@layerswap/widget 1.1.0 → 1.1.1
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/dist/esm/components/ErrorFallback.js +1 -1
- package/dist/esm/components/Icons/CircularLoader.js +5 -0
- package/dist/esm/components/Icons/FailIcon.js +2 -2
- package/dist/esm/components/Icons/GlobeIcon.js +3 -0
- package/dist/esm/components/Icons/MenuIcon.js +5 -0
- package/dist/esm/components/Icons/TokenIcon.js +1 -1
- package/dist/esm/components/Icons/Wallets/index.js +0 -2
- package/dist/esm/components/Input/Address/AddressNote.js +2 -2
- package/dist/esm/components/Input/Address/AddressPicker/AddressWithIcon.js +5 -2
- package/dist/esm/components/Input/Address/ContractAddressNote.js +17 -0
- package/dist/esm/components/Input/Address/UrlAddressNote.js +10 -0
- package/dist/esm/components/Input/Amount/ExchangeReceiveAmount.js +1 -1
- package/dist/esm/components/Input/Amount/PriceImpact.js +3 -5
- package/dist/esm/components/Input/Amount/ReceiveAmount.js +1 -1
- package/dist/esm/components/Input/RoutePicker/Content.js +17 -1
- package/dist/esm/components/Input/RoutePicker/RouteTokenSwitch.js +4 -4
- package/dist/esm/components/Input/RoutePicker/Routes.js +12 -11
- package/dist/esm/components/Input/RoutePicker/TokenTitleDetails.js +10 -0
- package/dist/esm/components/Input/RoutePicker/index.js +1 -1
- package/dist/esm/components/Menu/MenuList.js +11 -19
- package/dist/esm/components/Menu/index.js +16 -7
- package/dist/esm/components/Modal/modalWithoutAnimation.js +3 -3
- package/dist/esm/components/Pages/Campaigns/Details/index.js +1 -1
- package/dist/esm/components/Pages/Swap/Form/FeeDetails/Rate.js +3 -2
- package/dist/esm/components/Pages/Swap/Form/FeeDetails/Refuel.js +6 -1
- package/dist/esm/components/Pages/Swap/Form/FeeDetails/index.js +2 -2
- package/dist/esm/components/Pages/Swap/Form/FormWrapper.js +29 -2
- package/dist/esm/components/Pages/Swap/Form/NetworkForm.js +4 -3
- package/dist/esm/components/Pages/Swap/Form/SecondaryComponents/FormButton.js +1 -1
- package/dist/esm/components/Pages/Swap/Form/SecondaryComponents/validationError/ContractAddressValidationCache.js +19 -0
- package/dist/esm/components/Pages/Swap/Withdraw/Processing/Processing.js +9 -5
- package/dist/esm/components/Pages/Swap/Withdraw/Summary/Summary.js +2 -3
- package/dist/esm/components/Pages/Swap/Withdraw/Wallet/Common/buttons.js +13 -6
- package/dist/esm/components/Pages/Swap/Withdraw/WalletTransferButton.js +1 -1
- package/dist/esm/components/Pages/Swap/Withdraw/messages/Message.js +4 -4
- package/dist/esm/components/Pages/SwapHistory/History.js +1 -1
- package/dist/esm/components/Pages/SwapHistory/HistorySummary.js +1 -1
- package/dist/esm/components/Select/Selector/SelectItem.js +1 -1
- package/dist/esm/components/Wallet/WalletComponents/ConnectedWallets.js +4 -4
- package/dist/esm/components/Wallet/WalletModal/ConnectorsList.js +74 -125
- package/dist/esm/components/Wallet/WalletModal/InstalledExtensionNotFound.js +16 -0
- package/dist/esm/components/Wallet/WalletModal/LoadingConnect.js +27 -0
- package/dist/esm/components/Wallet/WalletModal/MultichainConnectorPicker.js +23 -0
- package/dist/esm/components/Wallet/WalletModal/ProviderPicker.js +26 -0
- package/dist/esm/components/Wallet/WalletModal/WalletQrCode.js +18 -0
- package/dist/esm/components/Wallet/WalletModal/index.js +1 -1
- package/dist/esm/components/Wallet/WalletProviders/index.js +1 -1
- package/dist/esm/components/Widget/Footer.js +20 -20
- package/dist/esm/components/Widget/Index.js +1 -1
- package/dist/esm/components/shadcn/checkbox.js +1 -1
- package/dist/esm/context/callbackProvider.js +6 -0
- package/dist/esm/context/resolverContext.js +5 -1
- package/dist/esm/hooks/useAllWithdrawalBalances.js +5 -0
- package/dist/esm/hooks/useConnectors.js +72 -0
- package/dist/esm/lib/address/contractAddressResolver.js +12 -0
- package/dist/esm/lib/apiClients/layerSwapApiClient.js +8 -1
- package/dist/esm/lib/balances/balanceResolver.js +52 -2
- package/dist/esm/lib/balances/errorUtils.js +13 -0
- package/dist/esm/lib/balances/nodeErrorClassifier.js +22 -0
- package/dist/esm/lib/fees.js +2 -2
- package/dist/esm/lib/generateSwapInitialValues.js +2 -2
- package/dist/esm/lib/isNewListed.js +8 -0
- package/dist/esm/lib/knownIds.js +1 -0
- package/dist/esm/lib/resolvers/resolverService.js +10 -1
- package/dist/esm/stores/balanceStore.js +39 -17
- package/dist/esm/stores/contractAddressStore.js +178 -0
- package/dist/esm/types/balance.js +15 -2
- package/dist/esm/types/contract.js +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/index.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/Models/Balance.d.ts +13 -1
- package/dist/types/Models/Balance.d.ts.map +1 -1
- package/dist/types/components/Icons/CircularLoader.d.ts +4 -0
- package/dist/types/components/Icons/CircularLoader.d.ts.map +1 -0
- package/dist/types/components/Icons/FailIcon.d.ts.map +1 -1
- package/dist/types/components/Icons/GasIcon.d.ts.map +1 -1
- package/dist/types/components/Icons/GlobeIcon.d.ts +4 -0
- package/dist/types/components/Icons/GlobeIcon.d.ts.map +1 -0
- package/dist/types/components/Icons/MenuIcon.d.ts +4 -0
- package/dist/types/components/Icons/MenuIcon.d.ts.map +1 -0
- package/dist/types/components/Icons/TokenIcon.d.ts.map +1 -1
- package/dist/types/components/Icons/Wallets/index.d.ts +0 -2
- package/dist/types/components/Icons/Wallets/index.d.ts.map +1 -1
- package/dist/types/components/Input/Address/AddressNote.d.ts +3 -3
- package/dist/types/components/Input/Address/AddressNote.d.ts.map +1 -1
- package/dist/types/components/Input/Address/AddressPicker/AddressWithIcon.d.ts +1 -0
- package/dist/types/components/Input/Address/AddressPicker/AddressWithIcon.d.ts.map +1 -1
- package/dist/types/components/Input/Address/ContractAddressNote.d.ts +9 -0
- package/dist/types/components/Input/Address/ContractAddressNote.d.ts.map +1 -0
- package/dist/types/components/Input/Address/UrlAddressNote.d.ts +10 -0
- package/dist/types/components/Input/Address/UrlAddressNote.d.ts.map +1 -0
- package/dist/types/components/Input/Amount/PriceImpact.d.ts +2 -1
- package/dist/types/components/Input/Amount/PriceImpact.d.ts.map +1 -1
- package/dist/types/components/Input/RoutePicker/Content.d.ts.map +1 -1
- package/dist/types/components/Input/RoutePicker/RouterPickerWalletConnect.d.ts.map +1 -1
- package/dist/types/components/Input/RoutePicker/Routes.d.ts.map +1 -1
- package/dist/types/components/Input/RoutePicker/TokenTitleDetails.d.ts +18 -0
- package/dist/types/components/Input/RoutePicker/TokenTitleDetails.d.ts.map +1 -0
- package/dist/types/components/Menu/MenuList.d.ts.map +1 -1
- package/dist/types/components/Menu/index.d.ts.map +1 -1
- package/dist/types/components/Modal/modalWithoutAnimation.d.ts +4 -2
- package/dist/types/components/Modal/modalWithoutAnimation.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/FeeDetails/Rate.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/FeeDetails/Refuel.d.ts +0 -1
- package/dist/types/components/Pages/Swap/Form/FeeDetails/Refuel.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/FeeDetails/index.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/FormWrapper.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/NetworkForm.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/SecondaryComponents/FormButton.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Form/SecondaryComponents/validationError/ContractAddressValidationCache.d.ts +10 -0
- package/dist/types/components/Pages/Swap/Form/SecondaryComponents/validationError/ContractAddressValidationCache.d.ts.map +1 -0
- package/dist/types/components/Pages/Swap/Withdraw/Processing/Processing.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Withdraw/Summary/Summary.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Withdraw/Wallet/Common/buttons.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Withdraw/WalletTransferButton.d.ts.map +1 -1
- package/dist/types/components/Pages/Swap/Withdraw/messages/Message.d.ts.map +1 -1
- package/dist/types/components/Pages/SwapHistory/HistorySummary.d.ts.map +1 -1
- package/dist/types/components/Select/Command/commandSelect.d.ts.map +1 -1
- package/dist/types/components/Select/Selector/SelectItem.d.ts.map +1 -1
- package/dist/types/components/Wallet/WalletModal/ConnectorsList.d.ts.map +1 -1
- package/dist/types/components/Wallet/WalletModal/InstalledExtensionNotFound.d.ts +7 -0
- package/dist/types/components/Wallet/WalletModal/InstalledExtensionNotFound.d.ts.map +1 -0
- package/dist/types/components/Wallet/WalletModal/LoadingConnect.d.ts +8 -0
- package/dist/types/components/Wallet/WalletModal/LoadingConnect.d.ts.map +1 -0
- package/dist/types/components/Wallet/WalletModal/MultichainConnectorPicker.d.ts +12 -0
- package/dist/types/components/Wallet/WalletModal/MultichainConnectorPicker.d.ts.map +1 -0
- package/dist/types/components/Wallet/WalletModal/ProviderPicker.d.ts +8 -0
- package/dist/types/components/Wallet/WalletModal/ProviderPicker.d.ts.map +1 -0
- package/dist/types/components/Wallet/WalletModal/WalletQrCode.d.ts +6 -0
- package/dist/types/components/Wallet/WalletModal/WalletQrCode.d.ts.map +1 -0
- package/dist/types/components/Wallet/WalletModal/index.d.ts +1 -0
- package/dist/types/components/Wallet/WalletModal/index.d.ts.map +1 -1
- package/dist/types/components/Widget/Footer.d.ts.map +1 -1
- package/dist/types/context/callbackProvider.d.ts +1 -0
- package/dist/types/context/callbackProvider.d.ts.map +1 -1
- package/dist/types/context/resolverContext.d.ts.map +1 -1
- package/dist/types/context/swapAccounts.d.ts.map +1 -1
- package/dist/types/context/walletProviders.d.ts.map +1 -1
- package/dist/types/hooks/useAllWithdrawalBalances.d.ts.map +1 -1
- package/dist/types/hooks/useConnectors.d.ts +28 -0
- package/dist/types/hooks/useConnectors.d.ts.map +1 -0
- package/dist/types/lib/address/contractAddressResolver.d.ts +7 -0
- package/dist/types/lib/address/contractAddressResolver.d.ts.map +1 -0
- package/dist/types/lib/apiClients/layerSwapApiClient.d.ts.map +1 -1
- package/dist/types/lib/balances/balanceResolver.d.ts.map +1 -1
- package/dist/types/lib/balances/errorUtils.d.ts +12 -0
- package/dist/types/lib/balances/errorUtils.d.ts.map +1 -0
- package/dist/types/lib/balances/nodeErrorClassifier.d.ts +4 -0
- package/dist/types/lib/balances/nodeErrorClassifier.d.ts.map +1 -0
- package/dist/types/lib/fees.d.ts +2 -2
- package/dist/types/lib/fees.d.ts.map +1 -1
- package/dist/types/lib/isNewListed.d.ts +4 -0
- package/dist/types/lib/isNewListed.d.ts.map +1 -0
- package/dist/types/lib/knownIds.d.ts +1 -0
- package/dist/types/lib/knownIds.d.ts.map +1 -1
- package/dist/types/lib/resolvers/resolverService.d.ts +5 -2
- package/dist/types/lib/resolvers/resolverService.d.ts.map +1 -1
- package/dist/types/stores/balanceStore.d.ts +3 -0
- package/dist/types/stores/balanceStore.d.ts.map +1 -1
- package/dist/types/stores/contractAddressStore.d.ts +43 -0
- package/dist/types/stores/contractAddressStore.d.ts.map +1 -0
- package/dist/types/types/balance.d.ts.map +1 -1
- package/dist/types/types/contract.d.ts +6 -0
- package/dist/types/types/contract.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/types/logEvents.d.ts +19 -1
- package/dist/types/types/logEvents.d.ts.map +1 -1
- package/dist/types/types/wallet.d.ts +6 -3
- package/dist/types/types/wallet.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/esm/components/Icons/Wallets/Keplr.js +0 -3
- package/dist/esm/components/Icons/Wallets/Xverse.js +0 -3
- package/dist/esm/components/Modal/popover.js +0 -15
- package/dist/esm/components/Wallet/WalletModal/utils.js +0 -23
- package/dist/esm/lib/sorting.js +0 -63
- package/dist/types/components/Icons/Wallets/Keplr.d.ts +0 -4
- package/dist/types/components/Icons/Wallets/Keplr.d.ts.map +0 -1
- package/dist/types/components/Icons/Wallets/Xverse.d.ts +0 -4
- package/dist/types/components/Icons/Wallets/Xverse.d.ts.map +0 -1
- package/dist/types/components/Modal/popover.d.ts +0 -12
- package/dist/types/components/Modal/popover.d.ts.map +0 -1
- package/dist/types/components/Wallet/WalletModal/utils.d.ts +0 -2
- package/dist/types/components/Wallet/WalletModal/utils.d.ts.map +0 -1
- package/dist/types/lib/sorting.d.ts +0 -22
- package/dist/types/lib/sorting.d.ts.map +0 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class ContractAddressResolver {
|
|
2
|
+
constructor(providers) {
|
|
3
|
+
this.providers = providers || [];
|
|
4
|
+
}
|
|
5
|
+
async isContractAddress(network, address) {
|
|
6
|
+
const provider = this.providers.find(p => p.supportsNetwork(network));
|
|
7
|
+
if (!provider) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return provider.isContractAddress(address, network);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -40,7 +40,14 @@ class LayerSwapApiClient {
|
|
|
40
40
|
return Promise.resolve(new EmptyApiResponse());
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
|
|
43
|
+
let error;
|
|
44
|
+
if (reason instanceof Error) {
|
|
45
|
+
error = reason;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
error = new Error(String(reason));
|
|
49
|
+
error.name = "APIError";
|
|
50
|
+
}
|
|
44
51
|
ErrorHandler({
|
|
45
52
|
type: 'APIError',
|
|
46
53
|
message: error.message,
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import { ErrorHandler } from "../../lib/ErrorHandler";
|
|
2
|
+
import { classifyNodeError } from "./nodeErrorClassifier";
|
|
3
|
+
import { extractErrorDetails } from "./errorUtils";
|
|
4
|
+
function formatErrorBalances(errorBalances) {
|
|
5
|
+
return errorBalances.map(b => ({
|
|
6
|
+
token: b.token,
|
|
7
|
+
error_message: b.error?.message,
|
|
8
|
+
error_name: b.error?.name,
|
|
9
|
+
error_code: b.error?.code,
|
|
10
|
+
error_category: b.error?.category,
|
|
11
|
+
response_status: b.error?.status,
|
|
12
|
+
response_status_text: b.error?.statusText,
|
|
13
|
+
request_url: b.error?.requestUrl,
|
|
14
|
+
// Include first 500 chars of stack trace for debugging
|
|
15
|
+
error_stack: b.error?.stack?.substring(0, 500),
|
|
16
|
+
// Include response data if available (truncated for size)
|
|
17
|
+
response_data: b.error?.responseData
|
|
18
|
+
? JSON.stringify(b.error.responseData).substring(0, 1000)
|
|
19
|
+
: undefined
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
2
22
|
export class BalanceResolver {
|
|
3
23
|
constructor(providers) {
|
|
4
24
|
this.providers = providers || [];
|
|
@@ -13,16 +33,46 @@ export class BalanceResolver {
|
|
|
13
33
|
if (!provider)
|
|
14
34
|
throw new Error(`No balance provider found for network ${network.name}`);
|
|
15
35
|
const balances = await provider.fetchBalance(address, network, { timeoutMs: options?.timeoutMs, retryCount: options?.retryCount });
|
|
36
|
+
const errorBalances = balances?.filter(b => b.error);
|
|
37
|
+
if (errorBalances?.length) {
|
|
38
|
+
const balanceError = new Error(`Could not fetch balance for ${errorBalances.map(t => t.token).join(", ")} in ${network.name}`);
|
|
39
|
+
ErrorHandler({
|
|
40
|
+
type: 'BalanceResolverError',
|
|
41
|
+
name: balanceError.name,
|
|
42
|
+
stack: balanceError.stack,
|
|
43
|
+
cause: balanceError.cause,
|
|
44
|
+
message: balanceError.message,
|
|
45
|
+
network: network.name,
|
|
46
|
+
node_url: network.node_url,
|
|
47
|
+
address: address,
|
|
48
|
+
error_categories: [...new Set(errorBalances.map(b => classifyNodeError(b.error)))],
|
|
49
|
+
error_codes: [...new Set(errorBalances.map(b => b.error?.code).filter(Boolean))],
|
|
50
|
+
http_statuses: [...new Set(errorBalances.map(b => b.error?.status).filter(Boolean))],
|
|
51
|
+
failed_tokens: formatErrorBalances(errorBalances),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
16
54
|
return { balances };
|
|
17
55
|
}
|
|
18
56
|
catch (e) {
|
|
19
|
-
const
|
|
57
|
+
const errorDetails = extractErrorDetails(e);
|
|
58
|
+
const error = new Error(errorDetails.message);
|
|
59
|
+
error.name = "BalanceError";
|
|
60
|
+
error.cause = e;
|
|
20
61
|
ErrorHandler({
|
|
21
62
|
type: 'BalanceResolverError',
|
|
22
63
|
message: error.message,
|
|
23
64
|
name: error.name,
|
|
24
65
|
stack: error.stack,
|
|
25
|
-
cause: error
|
|
66
|
+
cause: error.cause,
|
|
67
|
+
network: network.name,
|
|
68
|
+
node_url: network.node_url,
|
|
69
|
+
address: address,
|
|
70
|
+
error_category: classifyNodeError(e),
|
|
71
|
+
error_code: errorDetails.code,
|
|
72
|
+
response_status: errorDetails.status,
|
|
73
|
+
response_status_text: errorDetails.statusText,
|
|
74
|
+
response_data: errorDetails.responseData,
|
|
75
|
+
request_url: errorDetails.requestUrl,
|
|
26
76
|
});
|
|
27
77
|
return { balances: [] };
|
|
28
78
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function extractErrorDetails(error) {
|
|
2
|
+
const err = error;
|
|
3
|
+
return {
|
|
4
|
+
message: err?.message || String(error),
|
|
5
|
+
name: err?.name,
|
|
6
|
+
stack: err?.stack,
|
|
7
|
+
status: err?.response?.status,
|
|
8
|
+
statusText: err?.response?.statusText,
|
|
9
|
+
responseData: err?.response?.data,
|
|
10
|
+
requestUrl: err?.request?.url,
|
|
11
|
+
code: err?.code,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function classifyNodeError(error) {
|
|
2
|
+
// If it's already a structured error with category, return it
|
|
3
|
+
if (typeof error === 'object' && error !== null && 'category' in error) {
|
|
4
|
+
const category = error.category;
|
|
5
|
+
if (category) {
|
|
6
|
+
return category;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
// Otherwise classify from message
|
|
10
|
+
const message = (error?.message || String(error)).toLowerCase();
|
|
11
|
+
if (message.includes('timeout') || message.includes('timed out'))
|
|
12
|
+
return 'timeout';
|
|
13
|
+
if (message.includes('econnrefused') || message.includes('connection refused'))
|
|
14
|
+
return 'connection_refused';
|
|
15
|
+
if (message.includes('429') || message.includes('rate limit'))
|
|
16
|
+
return 'rate_limited';
|
|
17
|
+
if (message.includes('invalid json') || message.includes('unexpected token'))
|
|
18
|
+
return 'invalid_response';
|
|
19
|
+
if (message.includes('network') || message.includes('fetch failed'))
|
|
20
|
+
return 'network_error';
|
|
21
|
+
return 'unknown';
|
|
22
|
+
}
|
package/dist/esm/lib/fees.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export function CalculateMinimalAuthorizeAmount(usd_price, amount) {
|
|
2
2
|
return Math.ceil((usd_price * amount) + (usd_price * amount * 0.02));
|
|
3
3
|
}
|
|
4
|
-
export const resolvePriceImpactValues = (quote) => {
|
|
4
|
+
export const resolvePriceImpactValues = (quote, refuel) => {
|
|
5
5
|
const receiveAmount = quote?.receive_amount;
|
|
6
6
|
const requestedAmount = quote?.requested_amount;
|
|
7
7
|
const sourceTokenPriceUsd = quote?.source_token?.price_in_usd;
|
|
@@ -24,7 +24,7 @@ export const resolvePriceImpactValues = (quote) => {
|
|
|
24
24
|
? bridgeFee * sourceTokenPriceUsd
|
|
25
25
|
: undefined;
|
|
26
26
|
const marketImpact = priceImpact !== undefined && layerswapFees !== undefined && bridgeExpenses !== undefined
|
|
27
|
-
? priceImpact + Number(layerswapFees) + Number(bridgeExpenses)
|
|
27
|
+
? priceImpact + Number(layerswapFees) + Number(bridgeExpenses) + Number(refuel?.amount_in_usd || 0)
|
|
28
28
|
: undefined;
|
|
29
29
|
const priceImpactPercentage = requestedAmountUSD !== undefined && receiveAmountUSD !== undefined
|
|
30
30
|
? Number((((receiveAmountUSD - requestedAmountUSD) / requestedAmountUSD) * 100).toFixed(2))
|
|
@@ -24,11 +24,11 @@ export function generateSwapInitialValues(settings, queryParams, type) {
|
|
|
24
24
|
let initialAddress = destination_address && initialDestination && isValidAddress(destination_address, destinationNetwork) ? destination_address : "";
|
|
25
25
|
let initialSourceCurrency = filteredSourceCurrencies?.find(c => c.symbol?.toUpperCase() == fromAsset?.toUpperCase());
|
|
26
26
|
if (!initialSourceCurrency && !fromAsset && sourceNetwork) {
|
|
27
|
-
initialSourceCurrency = filteredSourceCurrencies?.
|
|
27
|
+
initialSourceCurrency = filteredSourceCurrencies?.sort((a, b) => a.symbol.localeCompare(b.symbol))?.find(c => c.status === "active");
|
|
28
28
|
}
|
|
29
29
|
let initialDestinationCurrency = filteredDestinationCurrencies?.find(c => c.symbol?.toUpperCase() == toAsset?.toUpperCase());
|
|
30
30
|
if (!initialDestinationCurrency && !toAsset && destinationNetwork) {
|
|
31
|
-
initialDestinationCurrency = filteredDestinationCurrencies?.
|
|
31
|
+
initialDestinationCurrency = filteredDestinationCurrencies?.sort((a, b) => a.symbol.localeCompare(b.symbol))?.find(c => c.status === "active");
|
|
32
32
|
}
|
|
33
33
|
//TODO this looks wrong
|
|
34
34
|
let initialAmount = (lockedDestinationCurrency && amount) || (initialDestinationCurrency ? amount : '');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
|
|
3
|
+
export const isNewListed = (date) => {
|
|
4
|
+
return new Date(date)?.getTime() >= new Date().getTime() - ONE_WEEK;
|
|
5
|
+
};
|
|
6
|
+
export const NewBadge = () => {
|
|
7
|
+
return (_jsx("div", { className: "text-primary-text text-xs py-0.5 px-1.5 bg-linear-90 from-primary-800 to-primary-600 rounded-md", children: "New" }));
|
|
8
|
+
};
|
package/dist/esm/lib/knownIds.js
CHANGED
|
@@ -140,6 +140,7 @@ KnownInternalNames.Networks = (_b = class {
|
|
|
140
140
|
_b.BitcoinTestnet = "BITCOIN_TESTNET",
|
|
141
141
|
_b.HyperliquidMainnet = "HYPERLIQUID_MAINNET",
|
|
142
142
|
_b.HyperliquidTestnet = "HYPERLIQUID_TESTNET",
|
|
143
|
+
_b.MonadMainnet = "MONAD_MAINNET",
|
|
143
144
|
_b);
|
|
144
145
|
KnownInternalNames.Currencies = (_c = class {
|
|
145
146
|
},
|
|
@@ -3,6 +3,7 @@ import { GasResolver } from "../../lib/gases/gasResolver";
|
|
|
3
3
|
import { AddressUtilsResolver } from '../../lib/address/addressUtilsResolver';
|
|
4
4
|
import { NftBalanceResolver } from "../nft/nftBalanceResolver";
|
|
5
5
|
import { TransferResolver } from "../transfers/transferResolver";
|
|
6
|
+
import { ContractAddressResolver } from "../../lib/address/contractAddressResolver";
|
|
6
7
|
class UtilsResolverService {
|
|
7
8
|
constructor() {
|
|
8
9
|
this.balanceResolver = null;
|
|
@@ -10,13 +11,15 @@ class UtilsResolverService {
|
|
|
10
11
|
this.addressUtilsResolver = null;
|
|
11
12
|
this.nftResolver = null;
|
|
12
13
|
this.transferResolver = null;
|
|
14
|
+
this.contractAddressResolver = null;
|
|
13
15
|
}
|
|
14
|
-
setProviders(balanceProviders, gasProviders, addressUtilsProviders, nftProviders, transferProviders) {
|
|
16
|
+
setProviders(balanceProviders, gasProviders, addressUtilsProviders, nftProviders, transferProviders, contractAddressProviders) {
|
|
15
17
|
this.balanceResolver = new BalanceResolver(balanceProviders);
|
|
16
18
|
this.gasResolver = new GasResolver(gasProviders);
|
|
17
19
|
this.addressUtilsResolver = new AddressUtilsResolver(addressUtilsProviders);
|
|
18
20
|
this.nftResolver = new NftBalanceResolver(nftProviders);
|
|
19
21
|
this.transferResolver = new TransferResolver(transferProviders);
|
|
22
|
+
this.contractAddressResolver = new ContractAddressResolver(contractAddressProviders);
|
|
20
23
|
}
|
|
21
24
|
getBalanceResolver() {
|
|
22
25
|
if (!this.balanceResolver) {
|
|
@@ -48,5 +51,11 @@ class UtilsResolverService {
|
|
|
48
51
|
}
|
|
49
52
|
return this.transferResolver;
|
|
50
53
|
}
|
|
54
|
+
getContractAddressResolver() {
|
|
55
|
+
if (!this.contractAddressResolver) {
|
|
56
|
+
throw new Error('ContractAddressResolver not initialized. Make sure to call setProviders first.');
|
|
57
|
+
}
|
|
58
|
+
return this.contractAddressResolver;
|
|
59
|
+
}
|
|
51
60
|
}
|
|
52
61
|
export const resolverService = new UtilsResolverService();
|
|
@@ -24,6 +24,19 @@ export const useBalanceStore = create()(subscribeWithSelector((set, get, api) =>
|
|
|
24
24
|
sortingDataIsLoading: false,
|
|
25
25
|
partialPublished: false,
|
|
26
26
|
startTimeOfInit: undefined,
|
|
27
|
+
sortingTimerId: undefined,
|
|
28
|
+
sortingUnsubscribe: undefined,
|
|
29
|
+
cleanupSortingBalances: () => {
|
|
30
|
+
const { sortingTimerId, sortingUnsubscribe } = get();
|
|
31
|
+
if (sortingTimerId) {
|
|
32
|
+
clearTimeout(sortingTimerId);
|
|
33
|
+
set({ sortingTimerId: undefined });
|
|
34
|
+
}
|
|
35
|
+
if (sortingUnsubscribe) {
|
|
36
|
+
sortingUnsubscribe();
|
|
37
|
+
set({ sortingUnsubscribe: undefined });
|
|
38
|
+
}
|
|
39
|
+
},
|
|
27
40
|
fetchBalance: (address, network, options) => {
|
|
28
41
|
const key = getKey(address, network);
|
|
29
42
|
const entry = get().balances[key];
|
|
@@ -80,6 +93,8 @@ export const useBalanceStore = create()(subscribeWithSelector((set, get, api) =>
|
|
|
80
93
|
return queuedPromise;
|
|
81
94
|
},
|
|
82
95
|
initSortingBalances: pairs => {
|
|
96
|
+
get().cleanupSortingBalances();
|
|
97
|
+
// Setup initiated balances and start fetches
|
|
83
98
|
const initiatedBalances = pairs.reduce((acc, { address, network }) => {
|
|
84
99
|
const key = getKey(address, network);
|
|
85
100
|
acc[network.name] = key;
|
|
@@ -93,29 +108,36 @@ export const useBalanceStore = create()(subscribeWithSelector((set, get, api) =>
|
|
|
93
108
|
set({ initiatedBalances });
|
|
94
109
|
set({ startTimeOfInit: Date.now() });
|
|
95
110
|
set({ partialPublished: false });
|
|
96
|
-
|
|
111
|
+
// Active timer - fires at 3 seconds
|
|
112
|
+
const timerId = setTimeout(() => {
|
|
113
|
+
const state = get();
|
|
114
|
+
// Only publish if not already published and still loading
|
|
115
|
+
if (!state.partialPublished && state.sortingDataIsLoading) {
|
|
116
|
+
const partial = {};
|
|
117
|
+
const balances = state.balances;
|
|
118
|
+
Object.entries(state.initiatedBalances || {}).forEach(([networkName, key]) => {
|
|
119
|
+
if (balances[key]?.data) {
|
|
120
|
+
partial[networkName] = key;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
set({ balanceKeysForSorting: partial });
|
|
124
|
+
set({ partialPublished: true });
|
|
125
|
+
}
|
|
126
|
+
}, 3000);
|
|
127
|
+
set({ sortingTimerId: timerId });
|
|
128
|
+
//Subscribe for completion detection
|
|
129
|
+
const unsubscribe = api.subscribe(state => state.balances, balances => {
|
|
97
130
|
const keysArray = Object.entries(get().initiatedBalances || {});
|
|
98
|
-
const done = keysArray.every(([_, key]) => balances[key]
|
|
131
|
+
const done = keysArray.every(([_, key]) => balances[key]?.data);
|
|
99
132
|
if (done) {
|
|
133
|
+
// All complete - cleanup and finalize
|
|
134
|
+
get().cleanupSortingBalances();
|
|
100
135
|
set({ sortingDataIsLoading: false });
|
|
101
136
|
set({ balanceKeysForSorting: get().initiatedBalances });
|
|
102
|
-
set({ partialPublished: false });
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
const startedAt = get().startTimeOfInit ?? 0;
|
|
106
|
-
const elapsed = Date.now() - startedAt;
|
|
107
|
-
if (!get().partialPublished && elapsed >= 3000) {
|
|
108
|
-
const partial = {};
|
|
109
|
-
keysArray.forEach(([networkName, key]) => {
|
|
110
|
-
if (balances[key]?.data) {
|
|
111
|
-
partial[networkName] = key;
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
set({ balanceKeysForSorting: partial });
|
|
115
|
-
set({ partialPublished: true });
|
|
116
|
-
}
|
|
137
|
+
set({ partialPublished: false }); // Reset for next time
|
|
117
138
|
}
|
|
118
139
|
}, { fireImmediately: true });
|
|
140
|
+
set({ sortingUnsubscribe: unsubscribe });
|
|
119
141
|
}
|
|
120
142
|
})));
|
|
121
143
|
export const selectResolvedSortingBalances = (state) => {
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
3
|
+
import { resolverService } from '../lib/resolvers/resolverService';
|
|
4
|
+
const isContractAddress = async (address, network) => {
|
|
5
|
+
if (!network || !address) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
const resolver = resolverService.getContractAddressResolver();
|
|
10
|
+
return await resolver.isContractAddress(network, address);
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
console.log(error);
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const useContractAddressStore = create()(persist((set, get) => ({
|
|
18
|
+
contractStatuses: [],
|
|
19
|
+
confirmedAddresses: [],
|
|
20
|
+
isChecking: false,
|
|
21
|
+
pendingChecks: new Map(),
|
|
22
|
+
checkContractStatus: async (address, sourceNetwork, destinationNetwork) => {
|
|
23
|
+
if (!address || !sourceNetwork || !destinationNetwork) {
|
|
24
|
+
return { sourceIsContract: false, destinationIsContract: false, isContractInAnyNetwork: false };
|
|
25
|
+
}
|
|
26
|
+
const { hasStatus, isContractInNetwork, isContractInAnyNetwork } = get();
|
|
27
|
+
// Check if we already have cached results for both networks
|
|
28
|
+
const hasSourceStatus = hasStatus(address, sourceNetwork.name);
|
|
29
|
+
const hasDestStatus = hasStatus(address, destinationNetwork.name);
|
|
30
|
+
if (hasSourceStatus && hasDestStatus) {
|
|
31
|
+
return {
|
|
32
|
+
sourceIsContract: isContractInNetwork(address, sourceNetwork.name),
|
|
33
|
+
destinationIsContract: isContractInNetwork(address, destinationNetwork.name),
|
|
34
|
+
isContractInAnyNetwork: isContractInAnyNetwork(address)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const checkKey = `${address.toLowerCase()}-${sourceNetwork.name}-${destinationNetwork.name}`;
|
|
38
|
+
// If there's already a pending check for these params, return that promise
|
|
39
|
+
const pendingCheck = get().pendingChecks.get(checkKey);
|
|
40
|
+
if (pendingCheck) {
|
|
41
|
+
return pendingCheck;
|
|
42
|
+
}
|
|
43
|
+
set({ isChecking: true });
|
|
44
|
+
const checkPromise = (async () => {
|
|
45
|
+
try {
|
|
46
|
+
// Check source network only if not already cached
|
|
47
|
+
let sourceIsContract = false;
|
|
48
|
+
if (hasSourceStatus) {
|
|
49
|
+
sourceIsContract = isContractInNetwork(address, sourceNetwork.name);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
sourceIsContract = await isContractAddress(address, sourceNetwork);
|
|
53
|
+
set((state) => {
|
|
54
|
+
const existingIndex = state.contractStatuses.findIndex((cs) => cs.address.toLowerCase() === address.toLowerCase() &&
|
|
55
|
+
cs.network === sourceNetwork.name);
|
|
56
|
+
if (existingIndex >= 0) {
|
|
57
|
+
const updated = [...state.contractStatuses];
|
|
58
|
+
updated[existingIndex] = { address, network: sourceNetwork.name, isContract: sourceIsContract };
|
|
59
|
+
return { contractStatuses: updated };
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
contractStatuses: [...state.contractStatuses, { address, network: sourceNetwork.name, isContract: sourceIsContract }]
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Check destination network only if not already cached
|
|
67
|
+
let destinationIsContract = false;
|
|
68
|
+
if (hasDestStatus) {
|
|
69
|
+
destinationIsContract = isContractInNetwork(address, destinationNetwork.name);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
destinationIsContract = await isContractAddress(address, destinationNetwork);
|
|
73
|
+
set((state) => {
|
|
74
|
+
const existingIndex = state.contractStatuses.findIndex((cs) => cs.address.toLowerCase() === address.toLowerCase() &&
|
|
75
|
+
cs.network === destinationNetwork.name);
|
|
76
|
+
if (existingIndex >= 0) {
|
|
77
|
+
const updated = [...state.contractStatuses];
|
|
78
|
+
updated[existingIndex] = { address, network: destinationNetwork.name, isContract: destinationIsContract };
|
|
79
|
+
return { contractStatuses: updated };
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
contractStatuses: [...state.contractStatuses, { address, network: destinationNetwork.name, isContract: destinationIsContract }]
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Check if contract in any network after updates
|
|
87
|
+
const isInAnyNetwork = get().isContractInAnyNetwork(address);
|
|
88
|
+
return { sourceIsContract, destinationIsContract, isContractInAnyNetwork: isInAnyNetwork };
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error('Error checking contract status:', error);
|
|
92
|
+
return { sourceIsContract: false, destinationIsContract: false, isContractInAnyNetwork: false };
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
set((state) => {
|
|
96
|
+
const newPendingChecks = new Map(state.pendingChecks);
|
|
97
|
+
newPendingChecks.delete(checkKey);
|
|
98
|
+
return { pendingChecks: newPendingChecks, isChecking: false };
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
set((state) => {
|
|
103
|
+
const newPendingChecks = new Map(state.pendingChecks);
|
|
104
|
+
newPendingChecks.set(checkKey, checkPromise);
|
|
105
|
+
return { pendingChecks: newPendingChecks };
|
|
106
|
+
});
|
|
107
|
+
return checkPromise;
|
|
108
|
+
},
|
|
109
|
+
hasStatus: (address, network) => {
|
|
110
|
+
return get().contractStatuses.some((cs) => cs.address.toLowerCase() === address.toLowerCase() &&
|
|
111
|
+
cs.network === network);
|
|
112
|
+
},
|
|
113
|
+
isContractInNetwork: (address, network) => {
|
|
114
|
+
const status = get().contractStatuses.find((cs) => cs.address.toLowerCase() === address.toLowerCase() &&
|
|
115
|
+
cs.network === network);
|
|
116
|
+
return status?.isContract ?? false;
|
|
117
|
+
},
|
|
118
|
+
isContractInAnyNetwork: (address) => {
|
|
119
|
+
return get().contractStatuses.some((cs) => cs.address.toLowerCase() === address.toLowerCase() &&
|
|
120
|
+
cs.isContract === true);
|
|
121
|
+
},
|
|
122
|
+
getContractNetworks: (address) => {
|
|
123
|
+
return get().contractStatuses
|
|
124
|
+
.filter((cs) => cs.address.toLowerCase() === address.toLowerCase() &&
|
|
125
|
+
cs.isContract === true)
|
|
126
|
+
.map((cs) => cs.network);
|
|
127
|
+
},
|
|
128
|
+
clearContractStatus: (address, network) => set((state) => {
|
|
129
|
+
if (network) {
|
|
130
|
+
return {
|
|
131
|
+
contractStatuses: state.contractStatuses.filter((cs) => !(cs.address.toLowerCase() === address.toLowerCase() &&
|
|
132
|
+
cs.network === network))
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
return {
|
|
137
|
+
contractStatuses: state.contractStatuses.filter((cs) => cs.address.toLowerCase() !== address.toLowerCase())
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}),
|
|
141
|
+
setConfirmed: (address, network) => set((state) => {
|
|
142
|
+
const exists = state.confirmedAddresses.some((ca) => ca.address.toLowerCase() === address.toLowerCase() &&
|
|
143
|
+
ca.network === network);
|
|
144
|
+
if (exists) {
|
|
145
|
+
return state;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
confirmedAddresses: [
|
|
149
|
+
...state.confirmedAddresses,
|
|
150
|
+
{ address, network }
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
}),
|
|
154
|
+
isConfirmed: (address, network) => {
|
|
155
|
+
return get().confirmedAddresses.some((ca) => ca.address.toLowerCase() === address.toLowerCase() &&
|
|
156
|
+
ca.network === network);
|
|
157
|
+
},
|
|
158
|
+
clearConfirmed: (address, network) => set((state) => {
|
|
159
|
+
if (network) {
|
|
160
|
+
return {
|
|
161
|
+
confirmedAddresses: state.confirmedAddresses.filter((ca) => !(ca.address.toLowerCase() === address.toLowerCase() &&
|
|
162
|
+
ca.network === network))
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
return {
|
|
167
|
+
confirmedAddresses: state.confirmedAddresses.filter((ca) => ca.address.toLowerCase() !== address.toLowerCase())
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}),
|
|
171
|
+
}), {
|
|
172
|
+
name: 'contractAddress',
|
|
173
|
+
storage: createJSONStorage(() => localStorage),
|
|
174
|
+
partialize: (state) => ({
|
|
175
|
+
contractStatuses: state.contractStatuses,
|
|
176
|
+
confirmedAddresses: state.confirmedAddresses,
|
|
177
|
+
}),
|
|
178
|
+
}));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ErrorHandler } from "../lib/ErrorHandler";
|
|
2
|
+
import { extractErrorDetails } from "../lib/balances/errorUtils";
|
|
3
|
+
import { classifyNodeError } from "../lib/balances/nodeErrorClassifier";
|
|
2
4
|
export class BalanceProvider {
|
|
3
5
|
constructor() {
|
|
4
6
|
this.resolveTokenBalanceFetchError = (err, token, network, isNativeCurrency) => {
|
|
5
|
-
const errorMessage = `${err.message || err}`;
|
|
6
7
|
ErrorHandler({
|
|
7
8
|
type: 'BalanceProviderError',
|
|
8
9
|
message: err.message,
|
|
@@ -10,6 +11,8 @@ export class BalanceProvider {
|
|
|
10
11
|
stack: err.stack,
|
|
11
12
|
cause: err
|
|
12
13
|
});
|
|
14
|
+
const errorDetails = extractErrorDetails(err);
|
|
15
|
+
const category = classifyNodeError(err);
|
|
13
16
|
const tokenBalance = {
|
|
14
17
|
network: network.name,
|
|
15
18
|
token: token.symbol,
|
|
@@ -17,7 +20,17 @@ export class BalanceProvider {
|
|
|
17
20
|
request_time: new Date().toJSON(),
|
|
18
21
|
decimals: Number(token?.decimals),
|
|
19
22
|
isNativeCurrency: isNativeCurrency ?? !token.contract,
|
|
20
|
-
error:
|
|
23
|
+
error: {
|
|
24
|
+
message: errorDetails.message,
|
|
25
|
+
name: errorDetails.name,
|
|
26
|
+
stack: errorDetails.stack,
|
|
27
|
+
code: errorDetails.code,
|
|
28
|
+
status: errorDetails.status,
|
|
29
|
+
statusText: errorDetails.statusText,
|
|
30
|
+
responseData: errorDetails.responseData,
|
|
31
|
+
requestUrl: errorDetails.requestUrl,
|
|
32
|
+
category: category
|
|
33
|
+
}
|
|
21
34
|
};
|
|
22
35
|
return tokenBalance;
|
|
23
36
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/esm/types/index.js
CHANGED