@dynamic-labs/sdk-react-core 4.84.0 → 4.85.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/package.cjs +3 -3
  3. package/package.js +3 -3
  4. package/package.json +14 -14
  5. package/src/index.cjs +2 -0
  6. package/src/index.d.ts +2 -2
  7. package/src/index.js +1 -0
  8. package/src/lib/components/SendBalanceForm/SendBalanceForm.cjs +26 -1
  9. package/src/lib/components/SendBalanceForm/SendBalanceForm.js +26 -1
  10. package/src/lib/components/SendBalancePageLayout/SendBalancePageLayout.cjs +6 -1
  11. package/src/lib/components/SendBalancePageLayout/SendBalancePageLayout.js +6 -1
  12. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.cjs +5 -1
  13. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.js +5 -1
  14. package/src/lib/context/OnrampContext/utils/getOnrampProviders.cjs +2 -6
  15. package/src/lib/context/OnrampContext/utils/getOnrampProviders.js +4 -8
  16. package/src/lib/data/api/onramp/onramp.cjs +26 -1
  17. package/src/lib/data/api/onramp/onramp.d.ts +11 -1
  18. package/src/lib/data/api/onramp/onramp.js +26 -1
  19. package/src/lib/utils/functions/onrampProviders/index.cjs +1 -0
  20. package/src/lib/utils/functions/onrampProviders/index.js +1 -0
  21. package/src/lib/utils/hooks/index.d.ts +2 -0
  22. package/src/lib/utils/hooks/useAleoAutoShieldSponsoredTokens/pollOnShielded.cjs +24 -4
  23. package/src/lib/utils/hooks/useAleoAutoShieldSponsoredTokens/pollOnShielded.d.ts +10 -2
  24. package/src/lib/utils/hooks/useAleoAutoShieldSponsoredTokens/pollOnShielded.js +24 -4
  25. package/src/lib/utils/hooks/useAleoAutoShieldSponsoredTokens/useAleoAutoShieldSponsoredTokens.cjs +14 -3
  26. package/src/lib/utils/hooks/useAleoAutoShieldSponsoredTokens/useAleoAutoShieldSponsoredTokens.d.ts +5 -1
  27. package/src/lib/utils/hooks/useAleoAutoShieldSponsoredTokens/useAleoAutoShieldSponsoredTokens.js +14 -3
  28. package/src/lib/utils/hooks/useAleoShieldedBalances/useAleoShieldedBalances.cjs +95 -10
  29. package/src/lib/utils/hooks/useAleoShieldedBalances/useAleoShieldedBalances.d.ts +18 -2
  30. package/src/lib/utils/hooks/useAleoShieldedBalances/useAleoShieldedBalances.js +96 -11
  31. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.cjs +4 -4
  32. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.js +4 -4
  33. package/src/lib/utils/hooks/usePrivateTokenBalances/index.d.ts +2 -0
  34. package/src/lib/utils/hooks/usePrivateTokenBalances/usePrivateTokenBalances.cjs +27 -0
  35. package/src/lib/utils/hooks/usePrivateTokenBalances/usePrivateTokenBalances.d.ts +24 -0
  36. package/src/lib/utils/hooks/usePrivateTokenBalances/usePrivateTokenBalances.js +23 -0
  37. package/src/lib/utils/hooks/useSyncDynamicWaas/instrumentWalletCreation.cjs +60 -0
  38. package/src/lib/utils/hooks/useSyncDynamicWaas/instrumentWalletCreation.d.ts +29 -0
  39. package/src/lib/utils/hooks/useSyncDynamicWaas/instrumentWalletCreation.js +55 -0
  40. package/src/lib/utils/hooks/useSyncDynamicWaas/useSyncDynamicWaas.cjs +14 -24
  41. package/src/lib/utils/hooks/useSyncDynamicWaas/useSyncDynamicWaas.js +14 -24
  42. package/src/lib/utils/hooks/useWalletDelegation/useWalletDelegation.cjs +19 -16
  43. package/src/lib/utils/hooks/useWalletDelegation/useWalletDelegation.d.ts +8 -0
  44. package/src/lib/utils/hooks/useWalletDelegation/useWalletDelegation.js +19 -17
  45. package/src/lib/views/TransactionConfirmationView/TransactionConfirmationView.cjs +17 -1
  46. package/src/lib/views/TransactionConfirmationView/TransactionConfirmationView.js +17 -1
  47. package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/ActiveWalletBalance.cjs +138 -21
  48. package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/ActiveWalletBalance.js +139 -22
  49. package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/optimisticShield.cjs +150 -0
  50. package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/optimisticShield.d.ts +74 -0
  51. package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/optimisticShield.js +143 -0
@@ -0,0 +1,74 @@
1
+ import { TokenBalance } from '@dynamic-labs/sdk-api-core';
2
+ /**
3
+ * In-memory record of a shield operation that has been accepted by the
4
+ * prover/relay but not yet observed on-chain by either the public
5
+ * balance mapping (Provable's `/mapping/balances/...` endpoint) or
6
+ * the RecordScanner index. Until reconciliation drops it, the entry
7
+ * forces the widget to display the post-shield state — unshielded
8
+ * rawBalance reduced by `amount`, shielded rawBalance increased by
9
+ * the same — so the Shield Manually CTA disappears the moment the
10
+ * shield is broadcast instead of flickering back into view during
11
+ * the indexing tail and tempting the user into a second shield.
12
+ */
13
+ export type OptimisticShieldEntry = {
14
+ tokenAddress: string;
15
+ isNative: boolean;
16
+ amount: bigint;
17
+ preShieldUnshieldedRaw: bigint;
18
+ preShieldShieldedRaw: bigint;
19
+ symbol: string;
20
+ name: string;
21
+ decimals: number;
22
+ logoURI: string;
23
+ price?: number;
24
+ createdAtMs: number;
25
+ };
26
+ export declare const OPTIMISTIC_SHIELD_STALE_MS = 180000;
27
+ /**
28
+ * Reduce each unshielded token's `rawBalance` by the sum of pending
29
+ * optimistic shields for the same `(address, isNative)`, clamped to 0.
30
+ * `balance` and `marketValue` scale by the same ratio so the fiat
31
+ * column doesn't disagree with the optimistic raw balance.
32
+ *
33
+ * Rows that are zeroed by the deduction are dropped from the returned
34
+ * array so they disappear immediately from the unshielded list instead
35
+ * of lingering as a `<$0.01` ghost (the per-row fiat formatter renders
36
+ * any non-positive-but-non-undefined `marketValue` as `<$0.01`, which
37
+ * looks broken when the optimistic deduction has already taken the row
38
+ * to exactly 0). Rows untouched by the optimistic shield pass through
39
+ * by reference (no copy) so downstream memos / identity comparisons
40
+ * don't churn on every render.
41
+ */
42
+ export declare const applyOptimisticUnshieldedDeductions: (balances: TokenBalance[], optimisticShields: ReadonlyArray<OptimisticShieldEntry>) => TokenBalance[];
43
+ /**
44
+ * Apply optimistic shield additions to the shielded balance list. For
45
+ * each optimistic shield with a matching `(address, isNative)` entry
46
+ * already in `shielded`, bump that entry; otherwise prepend a fresh
47
+ * synthesized row built from the entry's captured metadata.
48
+ *
49
+ * Returns a fresh array only when at least one optimistic shield
50
+ * applies. When `optimisticShields` is empty we pass through the
51
+ * input array by reference so consumers that compare by identity
52
+ * don't churn.
53
+ */
54
+ export declare const applyOptimisticShieldedAdditions: (shielded: TokenBalance[], optimisticShields: ReadonlyArray<OptimisticShieldEntry>) => TokenBalance[];
55
+ /**
56
+ * Filter the optimistic shield list down to entries that are still
57
+ * relevant. An entry is dropped when any of:
58
+ *
59
+ * - the unshielded server feed reports a `rawBalance` strictly less
60
+ * than `preShieldUnshieldedRaw` for that token (the burn was
61
+ * observed on-chain),
62
+ * - the shielded server feed reports a `rawBalance` strictly greater
63
+ * than `preShieldShieldedRaw` for that token (the new record was
64
+ * indexed),
65
+ * - the unshielded server no longer lists the token at all (rare,
66
+ * but means the public balance is effectively zero — our
67
+ * optimistic deduct is moot),
68
+ * - the entry is older than `staleMs` (safety net for shields whose
69
+ * on-chain effect is masked by parallel inbound credits).
70
+ *
71
+ * Pure / module-scope so it's trivially unit-testable; the widget
72
+ * just calls it on every server-side balance update.
73
+ */
74
+ export declare const reconcileOptimisticShields: (optimisticShields: ReadonlyArray<OptimisticShieldEntry>, unshieldedTokenBalances: TokenBalance[], shieldedTokenBalances: TokenBalance[], nowMs: number, staleMs?: number) => OptimisticShieldEntry[];
@@ -0,0 +1,143 @@
1
+ 'use client'
2
+ // Default safety-net stale window for optimistic entries. Tuned to
3
+ // comfortably outlast the post-shield polling schedule (~106s) so
4
+ // reconciliation has a chance to fire on the real server-side state
5
+ // before the safety net trips.
6
+ const OPTIMISTIC_SHIELD_STALE_MS = 180000;
7
+ const matches = (entry, token) => {
8
+ if (entry.isNative)
9
+ return Boolean(token.isNative);
10
+ return !token.isNative && entry.tokenAddress === token.address;
11
+ };
12
+ /**
13
+ * Reduce each unshielded token's `rawBalance` by the sum of pending
14
+ * optimistic shields for the same `(address, isNative)`, clamped to 0.
15
+ * `balance` and `marketValue` scale by the same ratio so the fiat
16
+ * column doesn't disagree with the optimistic raw balance.
17
+ *
18
+ * Rows that are zeroed by the deduction are dropped from the returned
19
+ * array so they disappear immediately from the unshielded list instead
20
+ * of lingering as a `<$0.01` ghost (the per-row fiat formatter renders
21
+ * any non-positive-but-non-undefined `marketValue` as `<$0.01`, which
22
+ * looks broken when the optimistic deduction has already taken the row
23
+ * to exactly 0). Rows untouched by the optimistic shield pass through
24
+ * by reference (no copy) so downstream memos / identity comparisons
25
+ * don't churn on every render.
26
+ */
27
+ const applyOptimisticUnshieldedDeductions = (balances, optimisticShields) => {
28
+ var _a, _b;
29
+ if (optimisticShields.length === 0)
30
+ return balances;
31
+ const result = [];
32
+ for (const token of balances) {
33
+ const adjustments = optimisticShields.filter((o) => matches(o, token));
34
+ if (adjustments.length === 0) {
35
+ result.push(token);
36
+ continue;
37
+ }
38
+ const currentRaw = BigInt(Math.round((_a = token.rawBalance) !== null && _a !== void 0 ? _a : 0));
39
+ const totalAdjustment = adjustments.reduce((sum, o) => sum + o.amount, BigInt(0));
40
+ const newRaw = currentRaw > totalAdjustment ? currentRaw - totalAdjustment : BigInt(0);
41
+ // Zero-out drop: the optimistic deduction took this row to (or
42
+ // below) zero, so there is nothing useful to display. Filter it
43
+ // out rather than emit a synthetic 0-balance row — otherwise the
44
+ // `<$0.01` formatter renders it as a misleading dust value until
45
+ // the server catches up and reconciliation drops the entry.
46
+ if (newRaw <= BigInt(0))
47
+ continue;
48
+ // Ratio-scale display-units balance + fiat so they stay consistent
49
+ // with the optimistic raw value. `currentRaw === 0n` is
50
+ // unreachable here (already handled by the zero-out drop above
51
+ // via `newRaw <= 0`), but the guard remains as defence-in-depth.
52
+ const ratio = currentRaw > BigInt(0) ? Number(newRaw) / Number(currentRaw) : 0;
53
+ result.push(Object.assign(Object.assign({}, token), { balance: ((_b = token.balance) !== null && _b !== void 0 ? _b : 0) * ratio, marketValue: token.marketValue !== undefined ? token.marketValue * ratio : undefined, rawBalance: Number(newRaw), rawBalanceString: newRaw.toString() }));
54
+ }
55
+ return result;
56
+ };
57
+ /**
58
+ * Apply optimistic shield additions to the shielded balance list. For
59
+ * each optimistic shield with a matching `(address, isNative)` entry
60
+ * already in `shielded`, bump that entry; otherwise prepend a fresh
61
+ * synthesized row built from the entry's captured metadata.
62
+ *
63
+ * Returns a fresh array only when at least one optimistic shield
64
+ * applies. When `optimisticShields` is empty we pass through the
65
+ * input array by reference so consumers that compare by identity
66
+ * don't churn.
67
+ */
68
+ const applyOptimisticShieldedAdditions = (shielded, optimisticShields) => {
69
+ if (optimisticShields.length === 0)
70
+ return shielded;
71
+ const consumedIndices = new Set();
72
+ const merged = shielded.map((token) => {
73
+ var _a, _b;
74
+ const adjustments = optimisticShields.filter((o, idx) => {
75
+ if (!matches(o, token))
76
+ return false;
77
+ consumedIndices.add(idx);
78
+ return true;
79
+ });
80
+ if (adjustments.length === 0)
81
+ return token;
82
+ const totalAtomic = adjustments.reduce((sum, o) => sum + o.amount, BigInt(0));
83
+ const newRaw = BigInt(Math.round((_a = token.rawBalance) !== null && _a !== void 0 ? _a : 0)) + totalAtomic;
84
+ const decimals = (_b = token.decimals) !== null && _b !== void 0 ? _b : 0;
85
+ const denominator = Math.pow(10, decimals);
86
+ const newDisplay = Number(newRaw) / denominator;
87
+ return Object.assign(Object.assign({}, token), { balance: newDisplay, marketValue: token.price !== undefined
88
+ ? newDisplay * token.price
89
+ : token.marketValue, rawBalance: Number(newRaw), rawBalanceString: newRaw.toString() });
90
+ });
91
+ // Prepend synthesized rows for any optimistic shield that didn't
92
+ // fold into an existing shielded row above. New rows go to the top
93
+ // of the list so the just-shielded token is immediately visible.
94
+ const synthesized = [];
95
+ optimisticShields.forEach((entry, idx) => {
96
+ if (consumedIndices.has(idx))
97
+ return;
98
+ const denominator = Math.pow(10, entry.decimals);
99
+ const display = Number(entry.amount) / denominator;
100
+ const marketValue = entry.price !== undefined ? display * entry.price : undefined;
101
+ synthesized.push(Object.assign(Object.assign({ address: entry.tokenAddress, balance: display, decimals: entry.decimals, isNative: entry.isNative, logoURI: entry.logoURI, name: entry.name, rawBalance: Number(entry.amount), rawBalanceString: entry.amount.toString(), symbol: entry.symbol }, (entry.price !== undefined ? { price: entry.price } : {})), (marketValue !== undefined ? { marketValue } : {})));
102
+ });
103
+ return [...synthesized, ...merged];
104
+ };
105
+ /**
106
+ * Filter the optimistic shield list down to entries that are still
107
+ * relevant. An entry is dropped when any of:
108
+ *
109
+ * - the unshielded server feed reports a `rawBalance` strictly less
110
+ * than `preShieldUnshieldedRaw` for that token (the burn was
111
+ * observed on-chain),
112
+ * - the shielded server feed reports a `rawBalance` strictly greater
113
+ * than `preShieldShieldedRaw` for that token (the new record was
114
+ * indexed),
115
+ * - the unshielded server no longer lists the token at all (rare,
116
+ * but means the public balance is effectively zero — our
117
+ * optimistic deduct is moot),
118
+ * - the entry is older than `staleMs` (safety net for shields whose
119
+ * on-chain effect is masked by parallel inbound credits).
120
+ *
121
+ * Pure / module-scope so it's trivially unit-testable; the widget
122
+ * just calls it on every server-side balance update.
123
+ */
124
+ const reconcileOptimisticShields = (optimisticShields, unshieldedTokenBalances, shieldedTokenBalances, nowMs, staleMs = OPTIMISTIC_SHIELD_STALE_MS) => optimisticShields.filter((entry) => {
125
+ var _a, _b;
126
+ if (nowMs - entry.createdAtMs > staleMs)
127
+ return false;
128
+ const unshielded = unshieldedTokenBalances.find((t) => matches(entry, t));
129
+ if (!unshielded)
130
+ return false;
131
+ const serverUnshielded = BigInt(Math.round((_a = unshielded.rawBalance) !== null && _a !== void 0 ? _a : 0));
132
+ if (serverUnshielded < entry.preShieldUnshieldedRaw)
133
+ return false;
134
+ const shielded = shieldedTokenBalances.find((t) => matches(entry, t));
135
+ const serverShielded = shielded
136
+ ? BigInt(Math.round((_b = shielded.rawBalance) !== null && _b !== void 0 ? _b : 0))
137
+ : BigInt(0);
138
+ if (serverShielded > entry.preShieldShieldedRaw)
139
+ return false;
140
+ return true;
141
+ });
142
+
143
+ export { OPTIMISTIC_SHIELD_STALE_MS, applyOptimisticShieldedAdditions, applyOptimisticUnshieldedDeductions, reconcileOptimisticShields };