@dynamic-labs/sdk-react-core 4.91.0 → 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.
Files changed (35) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/package.cjs +2 -2
  3. package/package.js +2 -2
  4. package/package.json +13 -13
  5. package/src/lib/components/SendBalanceForm/SendBalanceForm.cjs +34 -6
  6. package/src/lib/components/SendBalanceForm/SendBalanceForm.d.ts +2 -1
  7. package/src/lib/components/SendBalanceForm/SendBalanceForm.js +35 -7
  8. package/src/lib/components/SendBalancePageLayout/SendBalancePageLayout.cjs +2 -2
  9. package/src/lib/components/SendBalancePageLayout/SendBalancePageLayout.js +2 -2
  10. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.cjs +8 -7
  11. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.d.ts +3 -1
  12. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.js +8 -7
  13. package/src/lib/modals/SignMessageConfirmationModal/getProperErrorMessage.cjs +3 -0
  14. package/src/lib/modals/SignMessageConfirmationModal/getProperErrorMessage.js +3 -0
  15. package/src/lib/styles/index.shadow.cjs +1 -1
  16. package/src/lib/styles/index.shadow.js +1 -1
  17. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.cjs +21 -3
  18. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.d.ts +7 -0
  19. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.js +21 -3
  20. package/src/lib/utils/hooks/useEmbeddedReveal/useEmbeddedReveal.cjs +5 -3
  21. package/src/lib/utils/hooks/useEmbeddedReveal/useEmbeddedReveal.d.ts +1 -1
  22. package/src/lib/utils/hooks/useEmbeddedReveal/useEmbeddedReveal.js +5 -3
  23. package/src/lib/utils/hooks/useSyncEmbeddedWalletFlow/useSyncEmbeddedWalletFlow.cjs +1 -1
  24. package/src/lib/utils/hooks/useSyncEmbeddedWalletFlow/useSyncEmbeddedWalletFlow.js +1 -1
  25. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.cjs +18 -11
  26. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.d.ts +1 -0
  27. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.js +18 -11
  28. package/src/lib/widgets/DynamicWidget/components/ActiveMidnightWalletBalance/ActiveMidnightWalletBalance.cjs +38 -11
  29. package/src/lib/widgets/DynamicWidget/components/ActiveMidnightWalletBalance/ActiveMidnightWalletBalance.js +38 -11
  30. package/src/lib/widgets/DynamicWidget/views/AccountAndSecuritySettingsView/EmbeddedWalletExportSection/EmbeddedWalletExportSection.cjs +5 -2
  31. package/src/lib/widgets/DynamicWidget/views/AccountAndSecuritySettingsView/EmbeddedWalletExportSection/EmbeddedWalletExportSection.js +5 -2
  32. package/src/lib/widgets/DynamicWidget/views/DepositView/DepositView.cjs +18 -2
  33. package/src/lib/widgets/DynamicWidget/views/DepositView/DepositView.js +18 -2
  34. package/src/lib/widgets/DynamicWidget/views/ExportAndRecoveryView/ExportAndRecoveryView.cjs +3 -1
  35. package/src/lib/widgets/DynamicWidget/views/ExportAndRecoveryView/ExportAndRecoveryView.js +3 -1
package/CHANGELOG.md CHANGED
@@ -1,4 +1,47 @@
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
+
26
+ ### [4.91.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.0...v4.91.1) (2026-06-24)
27
+
28
+
29
+ ### Features
30
+
31
+ * **aleo:** update sendBalance with individual and marketplace logic ([#11709](https://github.com/dynamic-labs/dynamic-auth/issues/11709)) ([f8dfc48](https://github.com/dynamic-labs/dynamic-auth/commit/f8dfc488ae607fbbbcc3432a3ef69f746f0b7df0))
32
+ * **sdk-react-core:** surface shielded address in Midnight deposit view ([#11698](https://github.com/dynamic-labs/dynamic-auth/issues/11698)) ([79c5402](https://github.com/dynamic-labs/dynamic-auth/commit/79c54029b1d8f722cf9f1d8b4c11977898442ac0))
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * display actual error message for WaaS export failures instead of generic fallback ([#11498](https://github.com/dynamic-labs/dynamic-auth/issues/11498)) ([373c931](https://github.com/dynamic-labs/dynamic-auth/commit/373c931eb96c88e484c557ee8f2934660d028f97))
38
+ * **wallet-book:** guard replaceKey and remove stale override ([#11682](https://github.com/dynamic-labs/dynamic-auth/issues/11682)) ([13947d9](https://github.com/dynamic-labs/dynamic-auth/commit/13947d972ed1f8227712bfc01af9cc2be616a78a))
39
+
40
+
41
+ ### Performance Improvements
42
+
43
+ * **e2e:** prebuild Expo web bundle for RN e2e tests ([#11674](https://github.com/dynamic-labs/dynamic-auth/issues/11674)) ([16e002d](https://github.com/dynamic-labs/dynamic-auth/commit/16e002d59b2035e3f2c116879a78418a959da8bc))
44
+
2
45
  ## [4.91.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.90.0...v4.91.0) (2026-06-23)
3
46
 
4
47
 
package/package.cjs CHANGED
@@ -3,11 +3,11 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.91.0";
6
+ var version = "4.91.2";
7
7
  var dependencies = {
8
8
  "@dynamic-labs/sdk-api-core": "0.0.1046",
9
9
  "@dynamic-labs-sdk/client": "1.12.1",
10
- "@dynamic-labs-wallet/browser-wallet-client": "1.0.44",
10
+ "@dynamic-labs-wallet/browser-wallet-client": "1.0.48",
11
11
  "@dynamic-labs-wallet/forward-mpc-client": "0.12.0",
12
12
  "@hcaptcha/react-hcaptcha": "1.4.4",
13
13
  "@thumbmarkjs/thumbmarkjs": "0.16.0",
package/package.js CHANGED
@@ -1,9 +1,9 @@
1
1
  'use client'
2
- var version = "4.91.0";
2
+ var version = "4.91.2";
3
3
  var dependencies = {
4
4
  "@dynamic-labs/sdk-api-core": "0.0.1046",
5
5
  "@dynamic-labs-sdk/client": "1.12.1",
6
- "@dynamic-labs-wallet/browser-wallet-client": "1.0.44",
6
+ "@dynamic-labs-wallet/browser-wallet-client": "1.0.48",
7
7
  "@dynamic-labs-wallet/forward-mpc-client": "0.12.0",
8
8
  "@hcaptcha/react-hcaptcha": "1.4.4",
9
9
  "@thumbmarkjs/thumbmarkjs": "0.16.0",
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dynamic-labs/sdk-react-core",
3
- "version": "4.91.0",
3
+ "version": "4.91.2",
4
4
  "dependencies": {
5
5
  "@dynamic-labs/sdk-api-core": "0.0.1046",
6
6
  "@dynamic-labs-sdk/client": "1.12.1",
7
- "@dynamic-labs-wallet/browser-wallet-client": "1.0.44",
7
+ "@dynamic-labs-wallet/browser-wallet-client": "1.0.48",
8
8
  "@dynamic-labs-wallet/forward-mpc-client": "0.12.0",
9
9
  "@hcaptcha/react-hcaptcha": "1.4.4",
10
10
  "@thumbmarkjs/thumbmarkjs": "0.16.0",
@@ -17,17 +17,17 @@
17
17
  "yup": "0.32.11",
18
18
  "react-international-phone": "4.5.0",
19
19
  "bs58": "5.0.0",
20
- "@dynamic-labs/assert-package-version": "4.91.0",
21
- "@dynamic-labs/iconic": "4.91.0",
22
- "@dynamic-labs/locale": "4.91.0",
23
- "@dynamic-labs/logger": "4.91.0",
24
- "@dynamic-labs/multi-wallet": "4.91.0",
25
- "@dynamic-labs/rpc-providers": "4.91.0",
26
- "@dynamic-labs/store": "4.91.0",
27
- "@dynamic-labs/types": "4.91.0",
28
- "@dynamic-labs/utils": "4.91.0",
29
- "@dynamic-labs/wallet-book": "4.91.0",
30
- "@dynamic-labs/wallet-connector-core": "4.91.0",
20
+ "@dynamic-labs/assert-package-version": "4.91.2",
21
+ "@dynamic-labs/iconic": "4.91.2",
22
+ "@dynamic-labs/locale": "4.91.2",
23
+ "@dynamic-labs/logger": "4.91.2",
24
+ "@dynamic-labs/multi-wallet": "4.91.2",
25
+ "@dynamic-labs/rpc-providers": "4.91.2",
26
+ "@dynamic-labs/store": "4.91.2",
27
+ "@dynamic-labs/types": "4.91.2",
28
+ "@dynamic-labs/utils": "4.91.2",
29
+ "@dynamic-labs/wallet-book": "4.91.2",
30
+ "@dynamic-labs/wallet-connector-core": "4.91.2",
31
31
  "eventemitter3": "5.0.1"
32
32
  },
33
33
  "devDependencies": {
@@ -82,7 +82,7 @@ const getDisplayErrorMessage = (errors, t, field, decimals) => {
82
82
  }
83
83
  return '';
84
84
  };
85
- const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddress = () => true, validateAmount = () => true, currentToken, transaction, tokenBalances, setCurrentToken, isLoading, supportsFeeTokenSelection = false, feeTokenOptions, currentFeeToken, setCurrentFeeToken, }) => {
85
+ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddress = () => true, validateAmount = () => true, currentToken, transaction, tokenBalances, setCurrentToken, isLoading, supportsFeeTokenSelection = false, feeTokenOptions, currentFeeToken, setCurrentFeeToken, fallbackTokenIcon, }) => {
86
86
  var _a;
87
87
  const { t } = reactI18next.useTranslation();
88
88
  const { showFiat } = useInternalDynamicContext.useInternalDynamicContext();
@@ -114,12 +114,34 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
114
114
  var _a;
115
115
  setMergeAction((_a = transaction === null || transaction === void 0 ? void 0 : transaction.getRecordMergeAction) === null || _a === void 0 ? void 0 : _a.call(transaction));
116
116
  };
117
+ // With a mode toggle + per-token pool (Midnight), filter the picker to the
118
+ // selected pool. Chains without `getTokenPool` show the full list unchanged.
119
+ const filteredTokenBalances = React.useMemo(() => {
120
+ if (!hasModes || !selectedModeId || !(transaction === null || transaction === void 0 ? void 0 : transaction.getTokenPool)) {
121
+ return tokenBalances;
122
+ }
123
+ return tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.filter((token) => { var _a; return ((_a = transaction.getTokenPool) === null || _a === void 0 ? void 0 : _a.call(transaction, token.address)) === selectedModeId; });
124
+ }, [tokenBalances, hasModes, selectedModeId, transaction]);
117
125
  const handleModeChange = (modeId) => {
118
126
  var _a;
119
127
  setSelectedModeId(modeId);
128
+ // Set the mode + filter only — do NOT change `currentToken`, which would
129
+ // trip the Send view's transaction-recreation effect (reload). The picker
130
+ // resets to a placeholder + gates Preview until a valid token is picked.
120
131
  (_a = transaction === null || transaction === void 0 ? void 0 : transaction.setTransactionMode) === null || _a === void 0 ? void 0 : _a.call(transaction, modeId);
121
132
  refreshMergeAction();
122
133
  };
134
+ // The selected token must belong to the active pool; while it doesn't, the
135
+ // picker shows a placeholder and Preview is disabled so we never carry an
136
+ // incompatible token into a transfer.
137
+ const selectionMatchesMode = !hasModes ||
138
+ !selectedModeId ||
139
+ !(transaction === null || transaction === void 0 ? void 0 : transaction.getTokenPool) ||
140
+ (currentToken !== undefined &&
141
+ transaction.getTokenPool(currentToken.address) === selectedModeId);
142
+ // Token shown as "selected" in the picker — hidden when it doesn't match the
143
+ // active pool so the row reads as unset rather than showing the wrong token.
144
+ const pickerToken = selectionMatchesMode ? currentToken : undefined;
123
145
  const handleMergeAction = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
124
146
  if (!mergeAction || isMerging)
125
147
  return;
@@ -139,7 +161,10 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
139
161
  }
140
162
  }, [currentToken]);
141
163
  const sendBalanceFormValidationSchema = React.useMemo(() => {
142
- const decimalsRegex = new RegExp(`^\\d*(\\.\\d{1,${decimals}})?$`);
164
+ // For 0-decimal tokens (e.g. Midnight shielded tokens) only whole numbers
165
+ // are valid — a `\d{1,0}` quantifier is an invalid regex and throws, so
166
+ // build an integer-only pattern in that case.
167
+ const decimalsRegex = decimals > 0 ? new RegExp(`^\\d*(\\.\\d{1,${decimals}})?$`) : /^\d*$/;
143
168
  return yup.object().shape({
144
169
  amount: yup.string()
145
170
  .required('required')
@@ -173,7 +198,7 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
173
198
  }, [decimals, validateAddress, validateAmount]);
174
199
  return (jsxRuntime.jsx(formik.Formik, { initialValues: initialValues || sendBalanceFormInitialValues, validationSchema: sendBalanceFormValidationSchema, onSubmit: (values) => onSubmit(values), validateOnChange: false, validateOnBlur: false, children: ({ errors, touched, values, handleChange, setFieldValue, setErrors, handleBlur, setFieldTouched, validateField, }) => {
175
200
  var _a;
176
- return (jsxRuntime.jsxs(formik.Form, { className: 'send-balance-form', children: [jsxRuntime.jsxs("div", { className: 'send-balance-page-layout__balance-container', children: [jsxRuntime.jsx(FormFieldLabel.FormFieldLabel, { copykey: 'dyn_send_transaction.data.select_token', children: t('dyn_send_transaction.data.select_token') }), jsxRuntime.jsx(TokensBalanceDropdown.TokensBalanceDropdown, { tokenBalances: tokenBalances !== null && tokenBalances !== void 0 ? tokenBalances : (currentToken && [currentToken]), currentToken: currentToken, setCurrentToken: setCurrentToken, isLoading: isLoading, setFieldValue: setFieldValue, setErrors: setErrors })] }), jsxRuntime.jsxs("div", { className: 'send-balance-form__amount-container', children: [jsxRuntime.jsx(formik.Field, { variant: 'regular', className: `send-balance-form__amount-container__field ${showFiat ? 'fiat' : ''}`, name: 'amount', id: 'amount', onChange: (e) => {
201
+ return (jsxRuntime.jsxs(formik.Form, { className: 'send-balance-form', children: [jsxRuntime.jsxs("div", { className: 'send-balance-page-layout__balance-container', children: [jsxRuntime.jsx(FormFieldLabel.FormFieldLabel, { copykey: 'dyn_send_transaction.data.select_token', children: t('dyn_send_transaction.data.select_token') }), jsxRuntime.jsx(TokensBalanceDropdown.TokensBalanceDropdown, { tokenBalances: filteredTokenBalances !== null && filteredTokenBalances !== void 0 ? filteredTokenBalances : (pickerToken && [pickerToken]), currentToken: pickerToken, setCurrentToken: setCurrentToken, isLoading: isLoading, setFieldValue: setFieldValue, setErrors: setErrors, fallbackTokenIcon: fallbackTokenIcon, placeholder: t('dyn_send_transaction.data.select_token') })] }), jsxRuntime.jsxs("div", { className: 'send-balance-form__amount-container', children: [jsxRuntime.jsx(formik.Field, { variant: 'regular', className: `send-balance-form__amount-container__field ${showFiat ? 'fiat' : ''}`, name: 'amount', id: 'amount', onChange: (e) => {
177
202
  const newValue = e.target.value;
178
203
  // Matching 123, 123.45, .45, 123.
179
204
  if (newValue !== '' && !/^(?:\d+|\d*\.\d*|)$/.test(newValue)) {
@@ -200,8 +225,8 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
200
225
  }, placeholder: t('dyn_send_transaction.data.amount.placeholder'), as: Input.Input, error: errors['amount'], copykey: 'dyn_send_transaction.data.amount.label', message: touched['amount'] &&
201
226
  getDisplayErrorMessage(errors, t, 'amount', decimals), style: {
202
227
  paddingLeft: `${leftSymbolPadding}px`,
203
- } }), jsxRuntime.jsx("div", { className: 'send-balance-form__amount-container__floating_value', ref: floatingValueRef, children: jsxRuntime.jsx(Typography.Typography, { variant: 'title', weight: 'regular', color: 'secondary', children: currentToken === null || currentToken === void 0 ? void 0 : currentToken.symbol }) }), jsxRuntime.jsx("div", { className: 'send-balance-form__amount-container__balance', children: showFiat && !Number.isNaN(amount) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Typography.Typography, { variant: 'body_mini', weight: 'bold', color: 'secondary', children: "$" }), jsxRuntime.jsx(Typography.Typography, { variant: 'body_mini', weight: 'regular', color: 'secondary', children: utils.getDisplayFiatPrice(amount, currentToken) })] })) })] }), jsxRuntime.jsx(Typography.Typography, { className: 'send-balance-form__amount_available', variant: 'body_small', weight: 'regular', color: 'secondary', as: 'div', children: jsxRuntime.jsxs("div", { style: { display: 'flex', gap: '0.225rem' }, children: [jsxRuntime.jsx(Typography.Typography, { className: 'send-balance-form__amount_available__line', variant: 'body_small', weight: 'bold', color: 'primary', as: 'div', children: (_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.balance) !== null && _a !== void 0 ? _a : 0 }), t('dyn_send_transaction.data.symbol_available', {
204
- symbol: currentToken === null || currentToken === void 0 ? void 0 : currentToken.symbol,
228
+ } }), jsxRuntime.jsx("div", { className: 'send-balance-form__amount-container__floating_value', ref: floatingValueRef, children: jsxRuntime.jsx(Typography.Typography, { variant: 'title', weight: 'regular', color: 'secondary', children: currentToken === null || currentToken === void 0 ? void 0 : currentToken.symbol }) }), jsxRuntime.jsx("div", { className: 'send-balance-form__amount-container__balance', children: showFiat && !Number.isNaN(amount) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Typography.Typography, { variant: 'body_mini', weight: 'bold', color: 'secondary', children: "$" }), jsxRuntime.jsx(Typography.Typography, { variant: 'body_mini', weight: 'regular', color: 'secondary', children: utils.getDisplayFiatPrice(amount, currentToken) })] })) })] }), jsxRuntime.jsx(Typography.Typography, { className: 'send-balance-form__amount_available', variant: 'body_small', weight: 'regular', color: 'secondary', as: 'div', children: jsxRuntime.jsxs("div", { style: { display: 'flex', gap: '0.225rem' }, children: [jsxRuntime.jsx(Typography.Typography, { className: 'send-balance-form__amount_available__line', variant: 'body_small', weight: 'bold', color: 'primary', as: 'div', children: (_a = pickerToken === null || pickerToken === void 0 ? void 0 : pickerToken.balance) !== null && _a !== void 0 ? _a : 0 }), t('dyn_send_transaction.data.symbol_available', {
229
+ symbol: pickerToken === null || pickerToken === void 0 ? void 0 : pickerToken.symbol,
205
230
  })] }) }), supportsFeeTokenSelection &&
206
231
  feeTokenOptions &&
207
232
  feeTokenOptions.length > 0 &&
@@ -215,7 +240,10 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
215
240
  refreshMergeAction();
216
241
  } }), hasModes && (jsxRuntime.jsx(TransactionModeSegmentedControl.TransactionModeSegmentedControl, { options: transactionModes, selectedId: selectedModeId, onChange: handleModeChange, disabled: isMerging })), mergeAction && (jsxRuntime.jsx("div", { className: 'send-balance-form__inline-action', children: jsxRuntime.jsx(Alert.Alert, { icon: 'error', variant: 'warning', children: jsxRuntime.jsxs("div", { className: 'send-balance-form__inline-action-content', children: [jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', weight: 'regular', children: mergeAction.message }), jsxRuntime.jsx(TypographyButton.TypographyButton, { dataTestId: 'sendBalanceFormMergeRecordsButton', type: 'button', buttonVariant: 'secondary', buttonPadding: 'small', onClick: handleMergeAction, disabled: isMerging, children: isMerging
217
242
  ? t('dyn_send_transaction.merging', 'Merging…')
218
- : mergeAction.actionLabel })] }) }) })), jsxRuntime.jsx(TypographyButton.TypographyButton, { dataTestId: 'sendBalanceFormSubmitButton', expanded: true, type: 'submit', buttonVariant: 'primary', buttonPadding: 'small', buttonClassName: 'send-balance-form__button', copykey: 'dyn_send_transaction.preview_transaction', disabled: !modeReady || isMerging || Boolean(mergeAction), children: t('dyn_send_transaction.preview_transaction') })] }));
243
+ : mergeAction.actionLabel })] }) }) })), jsxRuntime.jsx(TypographyButton.TypographyButton, { dataTestId: 'sendBalanceFormSubmitButton', expanded: true, type: 'submit', buttonVariant: 'primary', buttonPadding: 'small', buttonClassName: 'send-balance-form__button', copykey: 'dyn_send_transaction.preview_transaction', disabled: !modeReady ||
244
+ !selectionMatchesMode ||
245
+ isMerging ||
246
+ Boolean(mergeAction), children: t('dyn_send_transaction.preview_transaction') })] }));
219
247
  } }));
220
248
  };
221
249
 
@@ -1,4 +1,4 @@
1
- import { Dispatch, FC, SetStateAction } from 'react';
1
+ import { Dispatch, FC, type ReactNode, SetStateAction } from 'react';
2
2
  import { TokenBalance } from '@dynamic-labs/sdk-api-core';
3
3
  import { IUITransaction } from '@dynamic-labs/types';
4
4
  export type SendBalanceFormValues = {
@@ -20,5 +20,6 @@ export type Props = {
20
20
  feeTokenOptions?: TokenBalance[];
21
21
  currentFeeToken?: TokenBalance;
22
22
  setCurrentFeeToken?: Dispatch<SetStateAction<TokenBalance | undefined>>;
23
+ fallbackTokenIcon?: ReactNode;
23
24
  };
24
25
  export declare const SendBalanceForm: FC<Props>;
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../_virtual/_tslib.js';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import { useRef, useState, useEffect, useMemo } from 'react';
4
+ import { useRef, useState, useMemo, useEffect } from 'react';
5
5
  import { Formik, Form, Field } from 'formik';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { object, string } from 'yup';
@@ -78,7 +78,7 @@ const getDisplayErrorMessage = (errors, t, field, decimals) => {
78
78
  }
79
79
  return '';
80
80
  };
81
- const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddress = () => true, validateAmount = () => true, currentToken, transaction, tokenBalances, setCurrentToken, isLoading, supportsFeeTokenSelection = false, feeTokenOptions, currentFeeToken, setCurrentFeeToken, }) => {
81
+ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddress = () => true, validateAmount = () => true, currentToken, transaction, tokenBalances, setCurrentToken, isLoading, supportsFeeTokenSelection = false, feeTokenOptions, currentFeeToken, setCurrentFeeToken, fallbackTokenIcon, }) => {
82
82
  var _a;
83
83
  const { t } = useTranslation();
84
84
  const { showFiat } = useInternalDynamicContext();
@@ -110,12 +110,34 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
110
110
  var _a;
111
111
  setMergeAction((_a = transaction === null || transaction === void 0 ? void 0 : transaction.getRecordMergeAction) === null || _a === void 0 ? void 0 : _a.call(transaction));
112
112
  };
113
+ // With a mode toggle + per-token pool (Midnight), filter the picker to the
114
+ // selected pool. Chains without `getTokenPool` show the full list unchanged.
115
+ const filteredTokenBalances = useMemo(() => {
116
+ if (!hasModes || !selectedModeId || !(transaction === null || transaction === void 0 ? void 0 : transaction.getTokenPool)) {
117
+ return tokenBalances;
118
+ }
119
+ return tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.filter((token) => { var _a; return ((_a = transaction.getTokenPool) === null || _a === void 0 ? void 0 : _a.call(transaction, token.address)) === selectedModeId; });
120
+ }, [tokenBalances, hasModes, selectedModeId, transaction]);
113
121
  const handleModeChange = (modeId) => {
114
122
  var _a;
115
123
  setSelectedModeId(modeId);
124
+ // Set the mode + filter only — do NOT change `currentToken`, which would
125
+ // trip the Send view's transaction-recreation effect (reload). The picker
126
+ // resets to a placeholder + gates Preview until a valid token is picked.
116
127
  (_a = transaction === null || transaction === void 0 ? void 0 : transaction.setTransactionMode) === null || _a === void 0 ? void 0 : _a.call(transaction, modeId);
117
128
  refreshMergeAction();
118
129
  };
130
+ // The selected token must belong to the active pool; while it doesn't, the
131
+ // picker shows a placeholder and Preview is disabled so we never carry an
132
+ // incompatible token into a transfer.
133
+ const selectionMatchesMode = !hasModes ||
134
+ !selectedModeId ||
135
+ !(transaction === null || transaction === void 0 ? void 0 : transaction.getTokenPool) ||
136
+ (currentToken !== undefined &&
137
+ transaction.getTokenPool(currentToken.address) === selectedModeId);
138
+ // Token shown as "selected" in the picker — hidden when it doesn't match the
139
+ // active pool so the row reads as unset rather than showing the wrong token.
140
+ const pickerToken = selectionMatchesMode ? currentToken : undefined;
119
141
  const handleMergeAction = () => __awaiter(void 0, void 0, void 0, function* () {
120
142
  if (!mergeAction || isMerging)
121
143
  return;
@@ -135,7 +157,10 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
135
157
  }
136
158
  }, [currentToken]);
137
159
  const sendBalanceFormValidationSchema = useMemo(() => {
138
- const decimalsRegex = new RegExp(`^\\d*(\\.\\d{1,${decimals}})?$`);
160
+ // For 0-decimal tokens (e.g. Midnight shielded tokens) only whole numbers
161
+ // are valid — a `\d{1,0}` quantifier is an invalid regex and throws, so
162
+ // build an integer-only pattern in that case.
163
+ const decimalsRegex = decimals > 0 ? new RegExp(`^\\d*(\\.\\d{1,${decimals}})?$`) : /^\d*$/;
139
164
  return object().shape({
140
165
  amount: string()
141
166
  .required('required')
@@ -169,7 +194,7 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
169
194
  }, [decimals, validateAddress, validateAmount]);
170
195
  return (jsx(Formik, { initialValues: initialValues || sendBalanceFormInitialValues, validationSchema: sendBalanceFormValidationSchema, onSubmit: (values) => onSubmit(values), validateOnChange: false, validateOnBlur: false, children: ({ errors, touched, values, handleChange, setFieldValue, setErrors, handleBlur, setFieldTouched, validateField, }) => {
171
196
  var _a;
172
- return (jsxs(Form, { className: 'send-balance-form', children: [jsxs("div", { className: 'send-balance-page-layout__balance-container', children: [jsx(FormFieldLabel, { copykey: 'dyn_send_transaction.data.select_token', children: t('dyn_send_transaction.data.select_token') }), jsx(TokensBalanceDropdown, { tokenBalances: tokenBalances !== null && tokenBalances !== void 0 ? tokenBalances : (currentToken && [currentToken]), currentToken: currentToken, setCurrentToken: setCurrentToken, isLoading: isLoading, setFieldValue: setFieldValue, setErrors: setErrors })] }), jsxs("div", { className: 'send-balance-form__amount-container', children: [jsx(Field, { variant: 'regular', className: `send-balance-form__amount-container__field ${showFiat ? 'fiat' : ''}`, name: 'amount', id: 'amount', onChange: (e) => {
197
+ return (jsxs(Form, { className: 'send-balance-form', children: [jsxs("div", { className: 'send-balance-page-layout__balance-container', children: [jsx(FormFieldLabel, { copykey: 'dyn_send_transaction.data.select_token', children: t('dyn_send_transaction.data.select_token') }), jsx(TokensBalanceDropdown, { tokenBalances: filteredTokenBalances !== null && filteredTokenBalances !== void 0 ? filteredTokenBalances : (pickerToken && [pickerToken]), currentToken: pickerToken, setCurrentToken: setCurrentToken, isLoading: isLoading, setFieldValue: setFieldValue, setErrors: setErrors, fallbackTokenIcon: fallbackTokenIcon, placeholder: t('dyn_send_transaction.data.select_token') })] }), jsxs("div", { className: 'send-balance-form__amount-container', children: [jsx(Field, { variant: 'regular', className: `send-balance-form__amount-container__field ${showFiat ? 'fiat' : ''}`, name: 'amount', id: 'amount', onChange: (e) => {
173
198
  const newValue = e.target.value;
174
199
  // Matching 123, 123.45, .45, 123.
175
200
  if (newValue !== '' && !/^(?:\d+|\d*\.\d*|)$/.test(newValue)) {
@@ -196,8 +221,8 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
196
221
  }, placeholder: t('dyn_send_transaction.data.amount.placeholder'), as: Input, error: errors['amount'], copykey: 'dyn_send_transaction.data.amount.label', message: touched['amount'] &&
197
222
  getDisplayErrorMessage(errors, t, 'amount', decimals), style: {
198
223
  paddingLeft: `${leftSymbolPadding}px`,
199
- } }), jsx("div", { className: 'send-balance-form__amount-container__floating_value', ref: floatingValueRef, children: jsx(Typography, { variant: 'title', weight: 'regular', color: 'secondary', children: currentToken === null || currentToken === void 0 ? void 0 : currentToken.symbol }) }), jsx("div", { className: 'send-balance-form__amount-container__balance', children: showFiat && !Number.isNaN(amount) && (jsxs(Fragment, { children: [jsx(Typography, { variant: 'body_mini', weight: 'bold', color: 'secondary', children: "$" }), jsx(Typography, { variant: 'body_mini', weight: 'regular', color: 'secondary', children: getDisplayFiatPrice(amount, currentToken) })] })) })] }), jsx(Typography, { className: 'send-balance-form__amount_available', variant: 'body_small', weight: 'regular', color: 'secondary', as: 'div', children: jsxs("div", { style: { display: 'flex', gap: '0.225rem' }, children: [jsx(Typography, { className: 'send-balance-form__amount_available__line', variant: 'body_small', weight: 'bold', color: 'primary', as: 'div', children: (_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.balance) !== null && _a !== void 0 ? _a : 0 }), t('dyn_send_transaction.data.symbol_available', {
200
- symbol: currentToken === null || currentToken === void 0 ? void 0 : currentToken.symbol,
224
+ } }), jsx("div", { className: 'send-balance-form__amount-container__floating_value', ref: floatingValueRef, children: jsx(Typography, { variant: 'title', weight: 'regular', color: 'secondary', children: currentToken === null || currentToken === void 0 ? void 0 : currentToken.symbol }) }), jsx("div", { className: 'send-balance-form__amount-container__balance', children: showFiat && !Number.isNaN(amount) && (jsxs(Fragment, { children: [jsx(Typography, { variant: 'body_mini', weight: 'bold', color: 'secondary', children: "$" }), jsx(Typography, { variant: 'body_mini', weight: 'regular', color: 'secondary', children: getDisplayFiatPrice(amount, currentToken) })] })) })] }), jsx(Typography, { className: 'send-balance-form__amount_available', variant: 'body_small', weight: 'regular', color: 'secondary', as: 'div', children: jsxs("div", { style: { display: 'flex', gap: '0.225rem' }, children: [jsx(Typography, { className: 'send-balance-form__amount_available__line', variant: 'body_small', weight: 'bold', color: 'primary', as: 'div', children: (_a = pickerToken === null || pickerToken === void 0 ? void 0 : pickerToken.balance) !== null && _a !== void 0 ? _a : 0 }), t('dyn_send_transaction.data.symbol_available', {
225
+ symbol: pickerToken === null || pickerToken === void 0 ? void 0 : pickerToken.symbol,
201
226
  })] }) }), supportsFeeTokenSelection &&
202
227
  feeTokenOptions &&
203
228
  feeTokenOptions.length > 0 &&
@@ -211,7 +236,10 @@ const SendBalanceForm = ({ initialValues, onSubmit, decimals = 18, validateAddre
211
236
  refreshMergeAction();
212
237
  } }), hasModes && (jsx(TransactionModeSegmentedControl, { options: transactionModes, selectedId: selectedModeId, onChange: handleModeChange, disabled: isMerging })), mergeAction && (jsx("div", { className: 'send-balance-form__inline-action', children: jsx(Alert, { icon: 'error', variant: 'warning', children: jsxs("div", { className: 'send-balance-form__inline-action-content', children: [jsx(Typography, { variant: 'body_small', weight: 'regular', children: mergeAction.message }), jsx(TypographyButton, { dataTestId: 'sendBalanceFormMergeRecordsButton', type: 'button', buttonVariant: 'secondary', buttonPadding: 'small', onClick: handleMergeAction, disabled: isMerging, children: isMerging
213
238
  ? t('dyn_send_transaction.merging', 'Merging…')
214
- : mergeAction.actionLabel })] }) }) })), jsx(TypographyButton, { dataTestId: 'sendBalanceFormSubmitButton', expanded: true, type: 'submit', buttonVariant: 'primary', buttonPadding: 'small', buttonClassName: 'send-balance-form__button', copykey: 'dyn_send_transaction.preview_transaction', disabled: !modeReady || isMerging || Boolean(mergeAction), children: t('dyn_send_transaction.preview_transaction') })] }));
239
+ : mergeAction.actionLabel })] }) }) })), jsx(TypographyButton, { dataTestId: 'sendBalanceFormSubmitButton', expanded: true, type: 'submit', buttonVariant: 'primary', buttonPadding: 'small', buttonClassName: 'send-balance-form__button', copykey: 'dyn_send_transaction.preview_transaction', disabled: !modeReady ||
240
+ !selectionMatchesMode ||
241
+ isMerging ||
242
+ Boolean(mergeAction), children: t('dyn_send_transaction.preview_transaction') })] }));
215
243
  } }));
216
244
  };
217
245
 
@@ -126,7 +126,7 @@ require('../../store/state/multichainBalances.cjs');
126
126
  require('@dynamic-labs/store');
127
127
  require('../../shared/utils/functions/getInitialUrl/getInitialUrl.cjs');
128
128
 
129
- const SendBalancePageLayout = ({ error, onClickClose, onClickBack, onSubmit, displayPoweredByDynamicFooter = false, transaction, networkCurrencyDecimals, tokenBalances, currentToken, setCurrentToken, isLoading, isNativeToken, }) => {
129
+ const SendBalancePageLayout = ({ error, onClickClose, onClickBack, onSubmit, displayPoweredByDynamicFooter = false, transaction, networkIcon, networkCurrencyDecimals, tokenBalances, currentToken, setCurrentToken, isLoading, isNativeToken, }) => {
130
130
  var _a, _b, _c;
131
131
  const { t } = reactI18next.useTranslation();
132
132
  const { primaryWallet, projectSettings, overrides } = useInternalDynamicContext.useInternalDynamicContext();
@@ -254,7 +254,7 @@ const SendBalancePageLayout = ({ error, onClickClose, onClickBack, onSubmit, dis
254
254
  return false;
255
255
  const amount = Number(transaction.parseNonNativeToken(amountText, (currentToken === null || currentToken === void 0 ? void 0 : currentToken.decimals) || 18));
256
256
  return amount <= currentToken.rawBalance;
257
- }, currentToken: currentToken, transaction: transaction }), displayPoweredByDynamicFooter && (jsxRuntime.jsx(PoweredByDynamic.PoweredByDynamic, { classNameRoot: 'send-balance-page-layout__footer' }))] })] }));
257
+ }, currentToken: currentToken, transaction: transaction, fallbackTokenIcon: networkIcon }), displayPoweredByDynamicFooter && (jsxRuntime.jsx(PoweredByDynamic.PoweredByDynamic, { classNameRoot: 'send-balance-page-layout__footer' }))] })] }));
258
258
  };
259
259
 
260
260
  exports.SendBalancePageLayout = SendBalancePageLayout;
@@ -122,7 +122,7 @@ import '../../store/state/multichainBalances.js';
122
122
  import '@dynamic-labs/store';
123
123
  import '../../shared/utils/functions/getInitialUrl/getInitialUrl.js';
124
124
 
125
- const SendBalancePageLayout = ({ error, onClickClose, onClickBack, onSubmit, displayPoweredByDynamicFooter = false, transaction, networkCurrencyDecimals, tokenBalances, currentToken, setCurrentToken, isLoading, isNativeToken, }) => {
125
+ const SendBalancePageLayout = ({ error, onClickClose, onClickBack, onSubmit, displayPoweredByDynamicFooter = false, transaction, networkIcon, networkCurrencyDecimals, tokenBalances, currentToken, setCurrentToken, isLoading, isNativeToken, }) => {
126
126
  var _a, _b, _c;
127
127
  const { t } = useTranslation();
128
128
  const { primaryWallet, projectSettings, overrides } = useInternalDynamicContext();
@@ -250,7 +250,7 @@ const SendBalancePageLayout = ({ error, onClickClose, onClickBack, onSubmit, dis
250
250
  return false;
251
251
  const amount = Number(transaction.parseNonNativeToken(amountText, (currentToken === null || currentToken === void 0 ? void 0 : currentToken.decimals) || 18));
252
252
  return amount <= currentToken.rawBalance;
253
- }, currentToken: currentToken, transaction: transaction }), displayPoweredByDynamicFooter && (jsx(PoweredByDynamic, { classNameRoot: 'send-balance-page-layout__footer' }))] })] }));
253
+ }, currentToken: currentToken, transaction: transaction, fallbackTokenIcon: networkIcon }), displayPoweredByDynamicFooter && (jsx(PoweredByDynamic, { classNameRoot: 'send-balance-page-layout__footer' }))] })] }));
254
254
  };
255
255
 
256
256
  export { SendBalancePageLayout };
@@ -121,7 +121,8 @@ require('../../../OverlayCard/OverlayCard.cjs');
121
121
  require('../../../Popper/Popper/Popper.cjs');
122
122
  require('../../../Popper/PopperContext/PopperContext.cjs');
123
123
 
124
- const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, isLoading, setFieldValue, setErrors, }) => {
124
+ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, isLoading, setFieldValue, setErrors, fallbackTokenIcon, placeholder, }) => {
125
+ var _a;
125
126
  const { t } = reactI18next.useTranslation();
126
127
  const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
127
128
  // Hide rows the user can't actually send from: anonymous tokens (no
@@ -155,7 +156,7 @@ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, i
155
156
  });
156
157
  [balance, decimals] = results.map((v) => Number(v.result));
157
158
  }
158
- catch (_a) {
159
+ catch (_b) {
159
160
  if (publicClient.readContract) {
160
161
  const [balanceResult, decimalsResult] = yield Promise.all([
161
162
  publicClient.readContract(Object.assign(Object.assign({}, erc20Contract), { args: [primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.address], functionName: 'balanceOf' })),
@@ -183,14 +184,14 @@ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, i
183
184
  }
184
185
  });
185
186
  const handleTokenClick = (selectedTokenName) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
186
- var _b, _c;
187
- const selectedToken = (_b = tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.find((t) => t.name === selectedTokenName)) !== null && _b !== void 0 ? _b : undefined;
187
+ var _c, _d;
188
+ const selectedToken = (_c = tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.find((t) => t.name === selectedTokenName)) !== null && _c !== void 0 ? _c : undefined;
188
189
  // we dont need to refetch solana balances because we simulate before sending
189
190
  if ((selectedToken === null || selectedToken === void 0 ? void 0 : selectedToken.address) && (selectedToken === null || selectedToken === void 0 ? void 0 : selectedToken.address.startsWith('0x'))) {
190
191
  fetchTokenData(selectedToken);
191
192
  }
192
193
  if (selectedToken) {
193
- if (tokenBalances && ((_c = tokenBalances[0]) === null || _c === void 0 ? void 0 : _c.price))
194
+ if (tokenBalances && ((_d = tokenBalances[0]) === null || _d === void 0 ? void 0 : _d.price))
194
195
  sendBalances.setSendBalanceVariable('nativePrice', tokenBalances[0].price);
195
196
  setCurrentToken(selectedToken);
196
197
  setFieldValue('amount', '');
@@ -204,8 +205,8 @@ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, i
204
205
  }
205
206
  const tokenLogo = (token, size) => (jsxRuntime.jsx(Image.Image, { src: token === null || token === void 0 ? void 0 : token.logoURI, alt: token === null || token === void 0 ? void 0 : token.name, className: 'token-balance-item__icon', dataTestId: 'token-balance-item-icon', fallback:
206
207
  // eslint-disable-next-line react/jsx-wrap-multilines
207
- jsxRuntime.jsx("div", { className: 'token-balance-item__skeleton-icon', "data-testid": 'token-balance-item__skeleton-icon', style: { height: `${size}px`, width: `${size}px` } }) }));
208
- return (jsxRuntime.jsxs("div", { className: 'tokens-balance-dropdown', ref: anchorRef, onClick: () => setIsDropdownOpen(!isDropdownOpen), "data-testid": 'tokens-balance-dropdown', children: [!isLoading && (jsxRuntime.jsxs("div", { className: 'tokens-balance-dropdown__selected', children: [tokenLogo(currentToken, '20'), jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', color: 'primary', children: currentToken === null || currentToken === void 0 ? void 0 : currentToken.name }), jsxRuntime.jsx(Icon.Icon, { color: 'text-primary', size: 'small', className: classNames.classNames('evm-network-control__arrow-icon', {
208
+ fallbackTokenIcon !== null && fallbackTokenIcon !== void 0 ? fallbackTokenIcon : (jsxRuntime.jsx("div", { className: 'token-balance-item__skeleton-icon', "data-testid": 'token-balance-item__skeleton-icon', style: { height: `${size}px`, width: `${size}px` } })) }));
209
+ return (jsxRuntime.jsxs("div", { className: 'tokens-balance-dropdown', ref: anchorRef, onClick: () => setIsDropdownOpen(!isDropdownOpen), "data-testid": 'tokens-balance-dropdown', children: [!isLoading && (jsxRuntime.jsxs("div", { className: 'tokens-balance-dropdown__selected', children: [tokenLogo(currentToken, '20'), jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', color: 'primary', children: (_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.name) !== null && _a !== void 0 ? _a : placeholder }), jsxRuntime.jsx(Icon.Icon, { color: 'text-primary', size: 'small', className: classNames.classNames('evm-network-control__arrow-icon', {
209
210
  'evm-network-control__arrow-icon--active': isDropdownOpen,
210
211
  }), children: jsxRuntime.jsx(stroke.ReactComponent, {}) })] })), jsxRuntime.jsx(MenuList.MenuList, { className: 'tokens-balance-dropdown__menu_list', isOpen: isDropdownOpen, popperProps: {
211
212
  anchorOrigin: 'bottom-left',
@@ -1,4 +1,4 @@
1
- import { Dispatch, FC, SetStateAction } from 'react';
1
+ import { Dispatch, FC, type ReactNode, SetStateAction } from 'react';
2
2
  import { TokenBalance } from '@dynamic-labs/sdk-api-core';
3
3
  type TokensBalanceDropdownProps = {
4
4
  tokenBalances: TokenBalance[] | undefined;
@@ -7,6 +7,8 @@ type TokensBalanceDropdownProps = {
7
7
  isLoading?: boolean;
8
8
  setFieldValue: (field: string, value: string) => void;
9
9
  setErrors: (errors: any) => void;
10
+ fallbackTokenIcon?: ReactNode;
11
+ placeholder?: string;
10
12
  };
11
13
  export declare const TokensBalanceDropdown: FC<TokensBalanceDropdownProps>;
12
14
  export {};
@@ -117,7 +117,8 @@ import '../../../OverlayCard/OverlayCard.js';
117
117
  import '../../../Popper/Popper/Popper.js';
118
118
  import '../../../Popper/PopperContext/PopperContext.js';
119
119
 
120
- const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, isLoading, setFieldValue, setErrors, }) => {
120
+ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, isLoading, setFieldValue, setErrors, fallbackTokenIcon, placeholder, }) => {
121
+ var _a;
121
122
  const { t } = useTranslation();
122
123
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
123
124
  // Hide rows the user can't actually send from: anonymous tokens (no
@@ -151,7 +152,7 @@ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, i
151
152
  });
152
153
  [balance, decimals] = results.map((v) => Number(v.result));
153
154
  }
154
- catch (_a) {
155
+ catch (_b) {
155
156
  if (publicClient.readContract) {
156
157
  const [balanceResult, decimalsResult] = yield Promise.all([
157
158
  publicClient.readContract(Object.assign(Object.assign({}, erc20Contract), { args: [primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.address], functionName: 'balanceOf' })),
@@ -179,14 +180,14 @@ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, i
179
180
  }
180
181
  });
181
182
  const handleTokenClick = (selectedTokenName) => __awaiter(void 0, void 0, void 0, function* () {
182
- var _b, _c;
183
- const selectedToken = (_b = tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.find((t) => t.name === selectedTokenName)) !== null && _b !== void 0 ? _b : undefined;
183
+ var _c, _d;
184
+ const selectedToken = (_c = tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.find((t) => t.name === selectedTokenName)) !== null && _c !== void 0 ? _c : undefined;
184
185
  // we dont need to refetch solana balances because we simulate before sending
185
186
  if ((selectedToken === null || selectedToken === void 0 ? void 0 : selectedToken.address) && (selectedToken === null || selectedToken === void 0 ? void 0 : selectedToken.address.startsWith('0x'))) {
186
187
  fetchTokenData(selectedToken);
187
188
  }
188
189
  if (selectedToken) {
189
- if (tokenBalances && ((_c = tokenBalances[0]) === null || _c === void 0 ? void 0 : _c.price))
190
+ if (tokenBalances && ((_d = tokenBalances[0]) === null || _d === void 0 ? void 0 : _d.price))
190
191
  setSendBalanceVariable('nativePrice', tokenBalances[0].price);
191
192
  setCurrentToken(selectedToken);
192
193
  setFieldValue('amount', '');
@@ -200,8 +201,8 @@ const TokensBalanceDropdown = ({ tokenBalances, currentToken, setCurrentToken, i
200
201
  }
201
202
  const tokenLogo = (token, size) => (jsx(Image, { src: token === null || token === void 0 ? void 0 : token.logoURI, alt: token === null || token === void 0 ? void 0 : token.name, className: 'token-balance-item__icon', dataTestId: 'token-balance-item-icon', fallback:
202
203
  // eslint-disable-next-line react/jsx-wrap-multilines
203
- jsx("div", { className: 'token-balance-item__skeleton-icon', "data-testid": 'token-balance-item__skeleton-icon', style: { height: `${size}px`, width: `${size}px` } }) }));
204
- return (jsxs("div", { className: 'tokens-balance-dropdown', ref: anchorRef, onClick: () => setIsDropdownOpen(!isDropdownOpen), "data-testid": 'tokens-balance-dropdown', children: [!isLoading && (jsxs("div", { className: 'tokens-balance-dropdown__selected', children: [tokenLogo(currentToken, '20'), jsx(Typography, { variant: 'body_normal', color: 'primary', children: currentToken === null || currentToken === void 0 ? void 0 : currentToken.name }), jsx(Icon, { color: 'text-primary', size: 'small', className: classNames('evm-network-control__arrow-icon', {
204
+ fallbackTokenIcon !== null && fallbackTokenIcon !== void 0 ? fallbackTokenIcon : (jsx("div", { className: 'token-balance-item__skeleton-icon', "data-testid": 'token-balance-item__skeleton-icon', style: { height: `${size}px`, width: `${size}px` } })) }));
205
+ return (jsxs("div", { className: 'tokens-balance-dropdown', ref: anchorRef, onClick: () => setIsDropdownOpen(!isDropdownOpen), "data-testid": 'tokens-balance-dropdown', children: [!isLoading && (jsxs("div", { className: 'tokens-balance-dropdown__selected', children: [tokenLogo(currentToken, '20'), jsx(Typography, { variant: 'body_normal', color: 'primary', children: (_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.name) !== null && _a !== void 0 ? _a : placeholder }), jsx(Icon, { color: 'text-primary', size: 'small', className: classNames('evm-network-control__arrow-icon', {
205
206
  'evm-network-control__arrow-icon--active': isDropdownOpen,
206
207
  }), children: jsx(SvgStroke, {}) })] })), jsx(MenuList, { className: 'tokens-balance-dropdown__menu_list', isOpen: isDropdownOpen, popperProps: {
207
208
  anchorOrigin: 'bottom-left',
@@ -63,6 +63,9 @@ const getProperErrorMessage = (originalError, user) => {
63
63
  reactNativePasskeyErrors[originalError.error]) {
64
64
  return reactNativePasskeyErrors[originalError.error];
65
65
  }
66
+ if (originalError instanceof Error && originalError.message) {
67
+ return originalError.message;
68
+ }
66
69
  return 'Something went wrong';
67
70
  };
68
71
 
@@ -59,6 +59,9 @@ const getProperErrorMessage = (originalError, user) => {
59
59
  reactNativePasskeyErrors[originalError.error]) {
60
60
  return reactNativePasskeyErrors[originalError.error];
61
61
  }
62
+ if (originalError instanceof Error && originalError.message) {
63
+ return originalError.message;
64
+ }
62
65
  return 'Something went wrong';
63
66
  };
64
67