@rango-dev/widget-embedded 0.63.1-next.0 → 0.63.1-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/QueueManager.d.ts.map +1 -1
- package/dist/components/SwapDetails/SwapDetails.d.ts.map +1 -1
- package/dist/components/SwapDetailsModal/SwapDetailsModal.ConnectWallet.d.ts.map +1 -1
- package/dist/components/WalletStatefulConnect/NamespaceDetachedItem.d.ts.map +1 -1
- package/dist/constants/errors.d.ts +1 -0
- package/dist/constants/errors.d.ts.map +1 -1
- package/dist/hooks/useStatefulConnect/useStatefulConnect.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +4 -4
- package/dist/utils/errors.d.ts +14 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.test.d.ts +2 -0
- package/dist/utils/errors.test.d.ts.map +1 -0
- package/dist/utils/swap.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/QueueManager.tsx +8 -1
- package/src/components/SwapDetails/SwapDetails.tsx +4 -1
- package/src/components/SwapDetailsModal/SwapDetailsModal.ConnectWallet.tsx +2 -1
- package/src/components/WalletStatefulConnect/NamespaceDetachedItem.tsx +2 -1
- package/src/constants/errors.ts +3 -0
- package/src/hooks/useStatefulConnect/useStatefulConnect.ts +7 -3
- package/src/utils/errors.test.ts +78 -0
- package/src/utils/errors.ts +69 -0
- package/src/utils/swap.ts +7 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function isModuleLoadError(value: unknown): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Replace a failure we recognize with one worth showing to a user.
|
|
4
|
+
*
|
|
5
|
+
* Every place the widget calls into another package routes its failures through
|
|
6
|
+
* here, so a new class of failure only has to be taught to the widget once.
|
|
7
|
+
*
|
|
8
|
+
* @param error - a thrown error, or a message already stringified from one.
|
|
9
|
+
* @returns a user facing error keeping the original as `cause`, or `null` when
|
|
10
|
+
* the failure is not one we recognize.
|
|
11
|
+
*/
|
|
12
|
+
export declare function tryRefineError(error: unknown): Error | null;
|
|
13
|
+
export declare function tryRefineErrorMessage(error: unknown, fallback: string): string;
|
|
14
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAoCA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAM3D;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,CAER"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../../src/utils/errors.test.ts"],"names":[],"mappings":""}
|
package/dist/utils/swap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swap.d.ts","sourceRoot":"","sources":["../../src/utils/swap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,MAAM,EACP,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,OAAO,EACP,UAAU,EACV,KAAK,EACN,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,EAEL,KAAK,UAAU,EAEf,KAAK,SAAS,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,SAAS,MAAM,cAAc,CAAC;AAMrC,OAAO,EACL,KAAK,SAAS,EAMf,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"swap.d.ts","sourceRoot":"","sources":["../../src/utils/swap.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rango-dev/widget-embedded",
|
|
3
|
-
"version": "0.63.1-next.
|
|
3
|
+
"version": "0.63.1-next.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"@lingui/core": "4.2.1",
|
|
28
28
|
"@lingui/react": "4.2.1",
|
|
29
29
|
"@rango-dev/logging-core": "^0.14.0",
|
|
30
|
-
"@rango-dev/provider-all": "^0.65.1-next.
|
|
30
|
+
"@rango-dev/provider-all": "^0.65.1-next.2",
|
|
31
31
|
"@rango-dev/queue-manager-core": "^0.34.0",
|
|
32
|
-
"@rango-dev/queue-manager-rango-preset": "^0.64.1-next.
|
|
32
|
+
"@rango-dev/queue-manager-rango-preset": "^0.64.1-next.2",
|
|
33
33
|
"@rango-dev/queue-manager-react": "^0.34.0",
|
|
34
34
|
"@rango-dev/signer-solana": "^0.49.0",
|
|
35
|
-
"@rango-dev/ui": "^0.65.1-next.
|
|
35
|
+
"@rango-dev/ui": "^0.65.1-next.2",
|
|
36
36
|
"@rango-dev/wallets-core": "^0.61.0",
|
|
37
|
-
"@rango-dev/wallets-react": "^0.48.1-next.
|
|
38
|
-
"@rango-dev/wallets-shared": "^0.62.1-next.
|
|
37
|
+
"@rango-dev/wallets-react": "^0.48.1-next.2",
|
|
38
|
+
"@rango-dev/wallets-shared": "^0.62.1-next.2",
|
|
39
39
|
"bignumber.js": "^9.1.1",
|
|
40
40
|
"copy-to-clipboard": "^3.3.3",
|
|
41
41
|
"crypto-browserify": "^3.12.1",
|
package/src/QueueManager.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import { eventEmitter } from './services/eventEmitter';
|
|
|
19
19
|
import { useAppStore } from './store/AppStore';
|
|
20
20
|
import { useUiStore } from './store/ui';
|
|
21
21
|
import { getConfig } from './utils/configs';
|
|
22
|
+
import { tryRefineError } from './utils/errors';
|
|
22
23
|
import { walletAndSupportedChainsNames } from './utils/wallets';
|
|
23
24
|
|
|
24
25
|
function QueueManager(props: PropsWithChildren<{ apiKey?: string }>) {
|
|
@@ -92,7 +93,13 @@ function QueueManager(props: PropsWithChildren<{ apiKey?: string }>) {
|
|
|
92
93
|
convertEvmBlockchainMetaToEvmChainInfo(evmBasedChains),
|
|
93
94
|
getSupportedChainNames,
|
|
94
95
|
},
|
|
95
|
-
getSigners
|
|
96
|
+
getSigners: async (type: WalletType) => {
|
|
97
|
+
try {
|
|
98
|
+
return await getSigners(type);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
throw tryRefineError(error) ?? error;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
96
103
|
wallets,
|
|
97
104
|
providers: allProviders,
|
|
98
105
|
switchNetwork,
|
|
@@ -36,6 +36,7 @@ import { useNotificationStore } from '../../store/notification';
|
|
|
36
36
|
import { useQuoteStore } from '../../store/quote';
|
|
37
37
|
import { UiEventTypes } from '../../types';
|
|
38
38
|
import { getContainer } from '../../utils/common';
|
|
39
|
+
import { tryRefineError } from '../../utils/errors';
|
|
39
40
|
import { emitUiEvent } from '../../utils/events';
|
|
40
41
|
import {
|
|
41
42
|
numberToString,
|
|
@@ -185,7 +186,9 @@ export function SwapDetails(props: SwapDetailsProps) {
|
|
|
185
186
|
handleShowSwitchNetworkSucceeded();
|
|
186
187
|
})
|
|
187
188
|
.catch((error: unknown) => {
|
|
188
|
-
handleShowSwitchNetworkFailed(
|
|
189
|
+
handleShowSwitchNetworkFailed(
|
|
190
|
+
tryRefineError(error) ?? (error as Error)
|
|
191
|
+
);
|
|
189
192
|
});
|
|
190
193
|
}
|
|
191
194
|
};
|
|
@@ -16,6 +16,7 @@ import React, { useState } from 'react';
|
|
|
16
16
|
|
|
17
17
|
import { useWalletList } from '../../hooks/useWalletList';
|
|
18
18
|
import { useUiStore } from '../../store/ui';
|
|
19
|
+
import { tryRefineError } from '../../utils/errors';
|
|
19
20
|
import { getConciseAddress } from '../../utils/wallets';
|
|
20
21
|
import { NamespaceItem } from '../NamespaceItem';
|
|
21
22
|
|
|
@@ -89,7 +90,7 @@ export const ConnectWalletContent = (props: ConnectWalletContentProps) => {
|
|
|
89
90
|
: undefined
|
|
90
91
|
);
|
|
91
92
|
} catch (error) {
|
|
92
|
-
setError(error as Error);
|
|
93
|
+
setError(tryRefineError(error) ?? (error as Error));
|
|
93
94
|
}
|
|
94
95
|
};
|
|
95
96
|
|
|
@@ -4,6 +4,7 @@ import { i18n } from '@lingui/core';
|
|
|
4
4
|
import { Button, Spinner } from '@rango-dev/ui';
|
|
5
5
|
import React, { useLayoutEffect, useRef, useState } from 'react';
|
|
6
6
|
|
|
7
|
+
import { tryRefineError } from '../../utils/errors';
|
|
7
8
|
import { getConciseAddress } from '../../utils/wallets';
|
|
8
9
|
import { NamespaceItem } from '../NamespaceItem';
|
|
9
10
|
|
|
@@ -39,7 +40,7 @@ export function NamespaceDetachedItem(props: NamespaceDetachedItemPropTypes) {
|
|
|
39
40
|
processingConnectAttempt.current = true;
|
|
40
41
|
await handleConnect(options);
|
|
41
42
|
} catch (error) {
|
|
42
|
-
setError(error as Error);
|
|
43
|
+
setError(tryRefineError(error) ?? (error as Error));
|
|
43
44
|
} finally {
|
|
44
45
|
processingConnectAttempt.current = false;
|
|
45
46
|
}
|
package/src/constants/errors.ts
CHANGED
|
@@ -7,6 +7,9 @@ import { QuoteErrorType } from '../types';
|
|
|
7
7
|
export const errorMessages = () => {
|
|
8
8
|
return {
|
|
9
9
|
genericServerError: i18n.t('Failed Network, Please retry your swap.'),
|
|
10
|
+
moduleLoadError: i18n.t(
|
|
11
|
+
'A network error occurred while processing your request. Please check your internet connection or refresh the page and try again.'
|
|
12
|
+
),
|
|
10
13
|
liquiditySourcesError: {
|
|
11
14
|
title: i18n.t('Please reset your liquidity sources.'),
|
|
12
15
|
description: i18n.t(
|
|
@@ -8,6 +8,7 @@ import { useWallets } from '@rango-dev/wallets-react';
|
|
|
8
8
|
import { useReducer } from 'react';
|
|
9
9
|
|
|
10
10
|
import { isOnDetached } from '../../components/StatefulConnectModal';
|
|
11
|
+
import { tryRefineErrorMessage } from '../../utils/errors';
|
|
11
12
|
import { type ExtendedModalWalletInfo } from '../../utils/wallets';
|
|
12
13
|
|
|
13
14
|
import {
|
|
@@ -75,9 +76,12 @@ export function useStatefulConnect(): UseStatefulConnect {
|
|
|
75
76
|
return { status: ResultStatus.Connected };
|
|
76
77
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
78
|
} catch (e: any) {
|
|
78
|
-
const message =
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
const message = tryRefineErrorMessage(
|
|
80
|
+
e,
|
|
81
|
+
e?.message
|
|
82
|
+
? `Error: ${e.message}`
|
|
83
|
+
: 'An unknown error happened during connecting wallet.'
|
|
84
|
+
);
|
|
81
85
|
|
|
82
86
|
if (options?.disconnectOnError) {
|
|
83
87
|
try {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
isModuleLoadError,
|
|
5
|
+
tryRefineError,
|
|
6
|
+
tryRefineErrorMessage,
|
|
7
|
+
} from './errors';
|
|
8
|
+
|
|
9
|
+
describe('error refinement', () => {
|
|
10
|
+
describe('recognizing a failed dynamic import', () => {
|
|
11
|
+
test('should match a thrown error', () => {
|
|
12
|
+
const error = new TypeError(
|
|
13
|
+
'Failed to fetch dynamically imported module: https://cdn.example/signer.js'
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
expect(isModuleLoadError(error)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('should match webpack failures named instead of worded', () => {
|
|
20
|
+
const error = new Error('Loading failed');
|
|
21
|
+
error.name = 'ChunkLoadError';
|
|
22
|
+
|
|
23
|
+
expect(isModuleLoadError(error)).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('should match a message that was already stringified', () => {
|
|
27
|
+
expect(
|
|
28
|
+
isModuleLoadError('TypeError: importing a module script failed')
|
|
29
|
+
).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('leaving unrecognized failures alone', () => {
|
|
34
|
+
test('should not match an unrelated error', () => {
|
|
35
|
+
expect(
|
|
36
|
+
isModuleLoadError(new Error('User rejected the transaction'))
|
|
37
|
+
).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('should not match empty input', () => {
|
|
41
|
+
expect(isModuleLoadError(null)).toBe(false);
|
|
42
|
+
expect(isModuleLoadError(undefined)).toBe(false);
|
|
43
|
+
expect(isModuleLoadError('')).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('refining into a user facing error', () => {
|
|
48
|
+
test('should keep the original as the cause', () => {
|
|
49
|
+
const error = new TypeError('failed to load module script');
|
|
50
|
+
const refined = tryRefineError(error);
|
|
51
|
+
|
|
52
|
+
expect(refined).toBeInstanceOf(Error);
|
|
53
|
+
expect(refined?.cause).toBe(error);
|
|
54
|
+
expect(refined?.message).not.toBe(error.message);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('should return null for an unrecognized failure', () => {
|
|
58
|
+
expect(tryRefineError(new Error('boom'))).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('should fall back to the given message', () => {
|
|
62
|
+
const fallback = 'An unknown error happened during connecting wallet.';
|
|
63
|
+
|
|
64
|
+
expect(tryRefineErrorMessage(new Error('boom'), fallback)).toBe(fallback);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('should refine instead of falling back when recognized', () => {
|
|
68
|
+
const fallback = 'An unknown error happened during connecting wallet.';
|
|
69
|
+
|
|
70
|
+
expect(
|
|
71
|
+
tryRefineErrorMessage(
|
|
72
|
+
new TypeError('loading chunk 42 failed'),
|
|
73
|
+
fallback
|
|
74
|
+
)
|
|
75
|
+
).not.toBe(fallback);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { errorMessages } from '../constants/errors';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* A failed `import()` has no standard error, so each engine and bundler words
|
|
5
|
+
* it differently. Lowercase, they are matched against a lowercased message.
|
|
6
|
+
*/
|
|
7
|
+
const MODULE_LOAD_ERROR_MESSAGES = [
|
|
8
|
+
// Chromium
|
|
9
|
+
'failed to fetch dynamically imported module',
|
|
10
|
+
// Firefox
|
|
11
|
+
'error loading dynamically imported module',
|
|
12
|
+
// Safari
|
|
13
|
+
'importing a module script failed',
|
|
14
|
+
// A stale chunk answered with the index page instead of a module
|
|
15
|
+
'failed to load module script',
|
|
16
|
+
// Vite
|
|
17
|
+
'unable to preload css',
|
|
18
|
+
// Webpack
|
|
19
|
+
'loading chunk',
|
|
20
|
+
'loading css chunk',
|
|
21
|
+
'chunkloaderror',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
function toMessage(value: unknown): string {
|
|
25
|
+
if (typeof value === 'string') {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (value instanceof Error) {
|
|
30
|
+
// Webpack names its failures rather than wording them.
|
|
31
|
+
return `${value.name} ${value.message}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isModuleLoadError(value: unknown): boolean {
|
|
38
|
+
const message = toMessage(value).toLowerCase();
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
!!message &&
|
|
42
|
+
MODULE_LOAD_ERROR_MESSAGES.some((candidate) => message.includes(candidate))
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Replace a failure we recognize with one worth showing to a user.
|
|
48
|
+
*
|
|
49
|
+
* Every place the widget calls into another package routes its failures through
|
|
50
|
+
* here, so a new class of failure only has to be taught to the widget once.
|
|
51
|
+
*
|
|
52
|
+
* @param error - a thrown error, or a message already stringified from one.
|
|
53
|
+
* @returns a user facing error keeping the original as `cause`, or `null` when
|
|
54
|
+
* the failure is not one we recognize.
|
|
55
|
+
*/
|
|
56
|
+
export function tryRefineError(error: unknown): Error | null {
|
|
57
|
+
if (isModuleLoadError(error)) {
|
|
58
|
+
return new Error(errorMessages().moduleLoadError, { cause: error });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function tryRefineErrorMessage(
|
|
65
|
+
error: unknown,
|
|
66
|
+
fallback: string
|
|
67
|
+
): string {
|
|
68
|
+
return tryRefineError(error)?.message ?? fallback;
|
|
69
|
+
}
|
package/src/utils/swap.ts
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
TOKEN_AMOUNT_MIN_DECIMALS,
|
|
50
50
|
} from '../constants/routing';
|
|
51
51
|
|
|
52
|
+
import { tryRefineError } from './errors';
|
|
52
53
|
import { getBlockchainShortNameFor, isValidTokenAddress } from './meta';
|
|
53
54
|
import { numberToString } from './numbers';
|
|
54
55
|
import { getRequiredBalanceOfWallet } from './quote';
|
|
@@ -737,6 +738,12 @@ export function getSwapMessages(
|
|
|
737
738
|
}
|
|
738
739
|
detailedMessage = detailedMessage || '';
|
|
739
740
|
message = message || '';
|
|
741
|
+
const refined = tryRefineError(message) ?? tryRefineError(detailedMessage);
|
|
742
|
+
if (refined) {
|
|
743
|
+
detailedMessage = [message, detailedMessage].filter(Boolean).join('\n');
|
|
744
|
+
message = refined.message;
|
|
745
|
+
}
|
|
746
|
+
|
|
740
747
|
const isRpc =
|
|
741
748
|
message?.indexOf('code') !== -1 && message?.indexOf('reason') !== -1;
|
|
742
749
|
|