@rango-dev/queue-manager-rango-preset 0.1.10-next.77

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 (57) hide show
  1. package/dist/actions/checkStatus.d.ts +12 -0
  2. package/dist/actions/checkStatus.d.ts.map +1 -0
  3. package/dist/actions/createTransaction.d.ts +11 -0
  4. package/dist/actions/createTransaction.d.ts.map +1 -0
  5. package/dist/actions/executeTransaction.d.ts +13 -0
  6. package/dist/actions/executeTransaction.d.ts.map +1 -0
  7. package/dist/actions/scheduleNextStep.d.ts +13 -0
  8. package/dist/actions/scheduleNextStep.d.ts.map +1 -0
  9. package/dist/actions/start.d.ts +4 -0
  10. package/dist/actions/start.d.ts.map +1 -0
  11. package/dist/constants.d.ts +9 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/helpers.d.ts +159 -0
  14. package/dist/helpers.d.ts.map +1 -0
  15. package/dist/hooks.d.ts +19 -0
  16. package/dist/hooks.d.ts.map +1 -0
  17. package/dist/index.d.ts +10 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +8 -0
  20. package/dist/migration.d.ts +15 -0
  21. package/dist/migration.d.ts.map +1 -0
  22. package/dist/queue-manager-rango-preset.cjs.development.js +2249 -0
  23. package/dist/queue-manager-rango-preset.cjs.development.js.map +1 -0
  24. package/dist/queue-manager-rango-preset.cjs.production.min.js +2 -0
  25. package/dist/queue-manager-rango-preset.cjs.production.min.js.map +1 -0
  26. package/dist/queue-manager-rango-preset.esm.js +2242 -0
  27. package/dist/queue-manager-rango-preset.esm.js.map +1 -0
  28. package/dist/queueDef.d.ts +10 -0
  29. package/dist/queueDef.d.ts.map +1 -0
  30. package/dist/shared-api.d.ts +10 -0
  31. package/dist/shared-api.d.ts.map +1 -0
  32. package/dist/shared-errors.d.ts +56 -0
  33. package/dist/shared-errors.d.ts.map +1 -0
  34. package/dist/shared-sentry.d.ts +4 -0
  35. package/dist/shared-sentry.d.ts.map +1 -0
  36. package/dist/shared.d.ts +149 -0
  37. package/dist/shared.d.ts.map +1 -0
  38. package/dist/types.d.ts +46 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/package.json +59 -0
  41. package/readme.md +9 -0
  42. package/src/actions/checkStatus.ts +213 -0
  43. package/src/actions/createTransaction.ts +101 -0
  44. package/src/actions/executeTransaction.ts +117 -0
  45. package/src/actions/scheduleNextStep.ts +60 -0
  46. package/src/actions/start.ts +10 -0
  47. package/src/constants.ts +23 -0
  48. package/src/helpers.ts +1252 -0
  49. package/src/hooks.ts +75 -0
  50. package/src/index.ts +39 -0
  51. package/src/migration.ts +112 -0
  52. package/src/queueDef.ts +39 -0
  53. package/src/shared-api.ts +175 -0
  54. package/src/shared-errors.ts +156 -0
  55. package/src/shared-sentry.ts +24 -0
  56. package/src/shared.ts +333 -0
  57. package/src/types.ts +76 -0
package/src/hooks.ts ADDED
@@ -0,0 +1,75 @@
1
+ import { useManager } from '@rango-dev/queue-manager-react';
2
+ import { useEffect, useState } from 'react';
3
+ import {
4
+ checkWaitingForConnectWalletChange,
5
+ checkWaitingForNetworkChange,
6
+ retryOn,
7
+ } from './helpers';
8
+ import { migrated, migration } from './migration';
9
+ import { UseQueueManagerParams } from './types';
10
+
11
+ let isCalled = 0;
12
+
13
+ /**
14
+ *
15
+ * Runs a migration (old swaps from localstorage to queue manager's IndexedDB)
16
+ * It will be run only once on page load.
17
+ *
18
+ */
19
+ function useMigration(): {
20
+ status: boolean;
21
+ } {
22
+ const isMigrated = migrated();
23
+ const [status, setStatus] = useState<boolean>(isMigrated);
24
+
25
+ useEffect(() => {
26
+ (async () => {
27
+ // Preventing react to be called twice on Strict Mode (development)
28
+ if (isCalled) return;
29
+ isCalled = 1;
30
+
31
+ migration().finally(() => {
32
+ setStatus(true);
33
+ });
34
+ })();
35
+ }, []);
36
+
37
+ return {
38
+ status,
39
+ };
40
+ }
41
+
42
+ /**
43
+ *
44
+ * On initial load and also connect/disconnet we may need to update swap's notified message.
45
+ * And also if a new wallet is connected we will retry the queue to see we can resume it or not.
46
+ *
47
+ */
48
+ function useQueueManager(params: UseQueueManagerParams): void {
49
+ const { manager } = useManager();
50
+
51
+ useEffect(() => {
52
+ if (params.lastConnectedWallet) {
53
+ checkWaitingForConnectWalletChange({
54
+ evmChains: params.evmChains,
55
+ wallet_network: params.lastConnectedWallet,
56
+ manager,
57
+ });
58
+ retryOn(params.lastConnectedWallet, manager);
59
+ }
60
+ }, [params.lastConnectedWallet]);
61
+
62
+ useEffect(() => {
63
+ if (params.disconnectedWallet) {
64
+ checkWaitingForNetworkChange(manager);
65
+
66
+ /*
67
+ We need to reset the state value, so if a wallet disconnected twice (after reconnect),
68
+ this effect will be run properly.
69
+ */
70
+ params.clearDisconnectedWallet();
71
+ }
72
+ }, [params.disconnectedWallet]);
73
+ }
74
+
75
+ export { useQueueManager, useMigration };
package/src/index.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { BlockReason, SwapActionTypes, SwapQueueDef } from './types';
2
+ import { checkStatus } from './actions/checkStatus';
3
+ import { createTransaction } from './actions/createTransaction';
4
+ import { executeTransaction } from './actions/executeTransaction';
5
+ import { scheduleNextStep } from './actions/scheduleNextStep';
6
+ import { start } from './actions/start';
7
+ import {
8
+ onBlockForChangeNetwork,
9
+ onBlockForConnectWallet,
10
+ onDependsOnOtherQueues,
11
+ } from './helpers';
12
+
13
+ /**
14
+ *
15
+ * The idea behind this queue is to be able dynamically add some steps.
16
+ * After running a swap, it can be blocked (like on waiting for switch netwrok)
17
+ * or waits for something happend (like checking status of a transaction from server)
18
+ *
19
+ */
20
+ export const swapQueueDef: SwapQueueDef = {
21
+ name: 'swap',
22
+ actions: {
23
+ [SwapActionTypes.START]: start,
24
+ [SwapActionTypes.SCHEDULE_NEXT_STEP]: scheduleNextStep,
25
+ [SwapActionTypes.CREATE_TRANSACTION]: createTransaction,
26
+ [SwapActionTypes.EXECUTE_TRANSACTION]: executeTransaction,
27
+ [SwapActionTypes.CHECK_TRANSACTION_STATUS]: checkStatus,
28
+ },
29
+ run: [SwapActionTypes.START],
30
+ whenTaskBlocked: (event: any, meta: any) => {
31
+ if (event.reason.reason === BlockReason.WAIT_FOR_CONNECT_WALLET) {
32
+ onBlockForConnectWallet(event, meta);
33
+ } else if (event.reason.reason === BlockReason.WAIT_FOR_NETWORK_CHANGE) {
34
+ onBlockForChangeNetwork(event, meta);
35
+ } else if (event.reason.reason === BlockReason.DEPENDS_ON_OTHER_QUEUES) {
36
+ onDependsOnOtherQueues(event, meta);
37
+ }
38
+ },
39
+ };
@@ -0,0 +1,112 @@
1
+ import {
2
+ PersistedQueue,
3
+ Persistor,
4
+ Status,
5
+ } from '@rango-dev/queue-manager-core';
6
+ import { v4 as uuid } from 'uuid';
7
+ import { PendingSwap } from './shared';
8
+ import { SwapActionTypes } from './types';
9
+
10
+ const MIGRATED_KEY = 'migratedToQueueManager';
11
+
12
+ /**
13
+ *
14
+ * If `MIGRATED_KEY` is set, it means we already migrated data from localstorage.
15
+ *
16
+ */
17
+ function migrated(): boolean {
18
+ return !!window.localStorage.getItem(MIGRATED_KEY);
19
+ }
20
+
21
+ /**
22
+ *
23
+ * By calling this function, we first check if the data already migrated or not,
24
+ * If not, starting to migrating to IndexedDb with proper format that queue manager is understand.
25
+ *
26
+ */
27
+ async function migration(): Promise<boolean> {
28
+ const swapsFromStorage = window.localStorage.getItem('pendingSwaps');
29
+
30
+ // For new users or already migrated.
31
+ if (!swapsFromStorage || migrated()) {
32
+ return true;
33
+ }
34
+
35
+ // For old users, but they didn't do any swaps yet.
36
+ const swaps: PendingSwap[] = JSON.parse(swapsFromStorage);
37
+ const convertedSwaps: PersistedQueue[] = [];
38
+
39
+ swaps.forEach((swap) => {
40
+ /*
41
+ For running task we need to add some more work
42
+ We need to create a queue task to be run and resume the running task from queue manager.
43
+ */
44
+ if (swap.status === 'running') {
45
+ const taskId = uuid();
46
+
47
+ const convertedSwap: PersistedQueue = {
48
+ id: uuid(),
49
+ createdAt: Number(swap.creationTime),
50
+ name: 'swap',
51
+ status: Status.RUNNING,
52
+ storage: {
53
+ swapDetails: swap,
54
+ },
55
+ state: {
56
+ status: Status.RUNNING,
57
+ activeTaskIndex: 0,
58
+ tasks: {
59
+ [taskId]: {
60
+ blockedFor: null,
61
+ status: Status.RUNNING,
62
+ },
63
+ },
64
+ },
65
+ tasks: [
66
+ {
67
+ id: taskId,
68
+ action: SwapActionTypes.SCHEDULE_NEXT_STEP,
69
+ },
70
+ ],
71
+ };
72
+ convertedSwaps.push(convertedSwap);
73
+ } else {
74
+ /*
75
+ * For failed or successful swaps, we only move it to IndexedDB,
76
+ * And there is no need to consider them to be run.
77
+ */
78
+ const status = swap.status === 'success' ? Status.SUCCESS : Status.FAILED;
79
+
80
+ const convertedSwap: PersistedQueue = {
81
+ id: uuid(),
82
+ createdAt: Number(swap.creationTime),
83
+ name: 'swap',
84
+ status,
85
+ storage: {
86
+ swapDetails: swap,
87
+ },
88
+ state: {
89
+ status,
90
+ activeTaskIndex: 0,
91
+ tasks: {},
92
+ },
93
+ tasks: [],
94
+ };
95
+
96
+ convertedSwaps.push(convertedSwap);
97
+ }
98
+ });
99
+
100
+ // Getting an instance from persistor, so we can directly put our data inside it.
101
+ const persistor = new Persistor();
102
+
103
+ const promises = convertedSwaps.map((queue) => persistor.insertQueue(queue));
104
+ await Promise.all(promises);
105
+
106
+ // Mark as the data has been successfully migrated.
107
+ window.localStorage.setItem(MIGRATED_KEY, '1');
108
+
109
+ return true;
110
+ }
111
+
112
+ export { migration, migrated };
@@ -0,0 +1,39 @@
1
+ import { BlockReason, SwapActionTypes, SwapQueueDef } from './types';
2
+ import { checkStatus } from './actions/checkStatus';
3
+ import { createTransaction } from './actions/createTransaction';
4
+ import { executeTransaction } from './actions/executeTransaction';
5
+ import { scheduleNextStep } from './actions/scheduleNextStep';
6
+ import { start } from './actions/start';
7
+ import {
8
+ onBlockForChangeNetwork,
9
+ onBlockForConnectWallet,
10
+ onDependsOnOtherQueues,
11
+ } from './helpers';
12
+
13
+ /**
14
+ *
15
+ * The idea behind this queue is to be able dynamically add some steps.
16
+ * After running a swap, it can be blocked (like on waiting for switch netwrok)
17
+ * or waits for something happend (like checking status of a transaction from server)
18
+ *
19
+ */
20
+ export const swapQueueDef: SwapQueueDef = {
21
+ name: 'swap',
22
+ actions: {
23
+ [SwapActionTypes.START]: start,
24
+ [SwapActionTypes.SCHEDULE_NEXT_STEP]: scheduleNextStep,
25
+ [SwapActionTypes.CREATE_TRANSACTION]: createTransaction,
26
+ [SwapActionTypes.EXECUTE_TRANSACTION]: executeTransaction,
27
+ [SwapActionTypes.CHECK_TRANSACTION_STATUS]: checkStatus,
28
+ },
29
+ run: [SwapActionTypes.START],
30
+ whenTaskBlocked: (event, meta) => {
31
+ if (event.reason.reason === BlockReason.WAIT_FOR_CONNECT_WALLET) {
32
+ onBlockForConnectWallet(event, meta);
33
+ } else if (event.reason.reason === BlockReason.WAIT_FOR_NETWORK_CHANGE) {
34
+ onBlockForChangeNetwork(event, meta);
35
+ } else if (event.reason.reason === BlockReason.DEPENDS_ON_OTHER_QUEUES) {
36
+ onDependsOnOtherQueues(event, meta);
37
+ }
38
+ },
39
+ };
@@ -0,0 +1,175 @@
1
+ import {
2
+ isWalletErrorCode,
3
+ WalletErrorCode,
4
+ WalletType,
5
+ } from '@rango-dev/wallets-shared';
6
+ import { getCookieId, SwapperStatusResponse } from './shared';
7
+ import {
8
+ CheckApprovalResponse,
9
+ CheckTxStatusRequest,
10
+ CreateTransactionRequest,
11
+ CreateTransactionResponse,
12
+ } from 'rango-sdk';
13
+ import {
14
+ APIErrorCode,
15
+ ApiMethodName,
16
+ ERROR_COMMUNICATING_WITH_API,
17
+ PrettyError,
18
+ } from './shared-errors';
19
+ import { BigNumber } from 'bignumber.js';
20
+ import {
21
+ BASE_URL,
22
+ RANGO_COOKIE_HEADER,
23
+ RANGO_DAPP_ID_QUERY,
24
+ } from './constants';
25
+
26
+ export async function checkSwapStatus(
27
+ requestId: string,
28
+ txId: string,
29
+ step: number
30
+ ): Promise<SwapperStatusResponse | null> {
31
+ const url = `${BASE_URL}/tx/check-status?${RANGO_DAPP_ID_QUERY}`;
32
+ const body: CheckTxStatusRequest = { step, txId, requestId };
33
+
34
+ const response = await fetch(url, {
35
+ method: 'POST',
36
+ headers: {
37
+ [RANGO_COOKIE_HEADER]: getCookieId(),
38
+ 'content-type': 'application/json;charset=UTF-8',
39
+ },
40
+ body: JSON.stringify(body),
41
+ });
42
+
43
+ if (
44
+ (!!response.status && (response.status < 200 || response.status >= 400)) ||
45
+ !response.ok
46
+ ) {
47
+ const apiError = ERROR_COMMUNICATING_WITH_API(
48
+ ApiMethodName.CheckingTransactionStatus
49
+ );
50
+ throw PrettyError.BadStatusCode(apiError, response.status);
51
+ }
52
+
53
+ const res = await response.json();
54
+ return {
55
+ ...res,
56
+ outputAmount: res.outputAmount ? new BigNumber(res.outputAmount) : null,
57
+ };
58
+ }
59
+
60
+ export async function createTransaction(
61
+ request: CreateTransactionRequest
62
+ ): Promise<CreateTransactionResponse> {
63
+ const url = `${BASE_URL}/tx/create?${RANGO_DAPP_ID_QUERY}`;
64
+ try {
65
+ const response = await fetch(url, {
66
+ method: 'POST',
67
+ headers: {
68
+ 'content-type': 'application/json;charset=UTF-8',
69
+ [RANGO_COOKIE_HEADER]: getCookieId(),
70
+ },
71
+ body: JSON.stringify(request),
72
+ });
73
+
74
+ if (
75
+ (!!response.status &&
76
+ (response.status < 200 || response.status >= 400)) ||
77
+ !response.ok
78
+ ) {
79
+ throw PrettyError.CreateTransaction(
80
+ `Error creating the transaction, status code: ${response.status}`
81
+ );
82
+ }
83
+
84
+ const result: CreateTransactionResponse = await response.json();
85
+ if (!result.ok || !result.transaction)
86
+ throw PrettyError.CreateTransaction(
87
+ result.error || 'bad response from create tx endpoint'
88
+ );
89
+
90
+ return result;
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ } catch (error) {
93
+ if (error instanceof Error) {
94
+ throw PrettyError.CreateTransaction(error.message);
95
+ }
96
+ throw error;
97
+ }
98
+ }
99
+
100
+ export async function checkApproved(
101
+ requestId: string
102
+ ): Promise<CheckApprovalResponse> {
103
+ const url = `${BASE_URL}/tx/${requestId}/check-approval?${RANGO_DAPP_ID_QUERY}`;
104
+ const response = await fetch(url, {
105
+ method: 'GET',
106
+ headers: {
107
+ 'content-type': 'application/json;charset=UTF-8',
108
+ [RANGO_COOKIE_HEADER]: getCookieId(),
109
+ },
110
+ });
111
+
112
+ if (
113
+ (!!response.status && (response.status < 200 || response.status >= 400)) ||
114
+ !response.ok
115
+ ) {
116
+ const apiError = ERROR_COMMUNICATING_WITH_API(ApiMethodName.CheckApproval);
117
+ throw PrettyError.BadStatusCode(apiError, response.status);
118
+ }
119
+
120
+ return await response.json();
121
+ }
122
+
123
+ function isAPIErrorCode(value: string): value is APIErrorCode {
124
+ return (Object.values(APIErrorCode) as string[]).includes(value);
125
+ }
126
+
127
+ export function mapAppErrorCodesToAPIErrorCode(
128
+ errorCode: string | null
129
+ ): APIErrorCode {
130
+ const defaultErrorCode = APIErrorCode.CLIENT_UNEXPECTED_BEHAVIOUR;
131
+ try {
132
+ if (!errorCode) return defaultErrorCode;
133
+ if (isAPIErrorCode(errorCode)) return errorCode;
134
+ if (isWalletErrorCode(errorCode)) {
135
+ const t: { [key in WalletErrorCode]: APIErrorCode } = {
136
+ [WalletErrorCode.REJECTED_BY_USER]: APIErrorCode.USER_REJECT,
137
+ [WalletErrorCode.SIGN_TX_ERROR]: APIErrorCode.CALL_WALLET_FAILED,
138
+ [WalletErrorCode.SEND_TX_ERROR]: APIErrorCode.SEND_TX_FAILED,
139
+ [WalletErrorCode.NOT_IMPLEMENTED]: defaultErrorCode,
140
+ [WalletErrorCode.OPERATION_UNSUPPORTED]: defaultErrorCode,
141
+ [WalletErrorCode.UNEXPECTED_BEHAVIOUR]: defaultErrorCode,
142
+ };
143
+ return t[errorCode];
144
+ }
145
+ return defaultErrorCode;
146
+ } catch (err) {
147
+ return defaultErrorCode;
148
+ }
149
+ }
150
+
151
+ export async function reportFailed(
152
+ requestId: string,
153
+ step: number,
154
+ eventType: APIErrorCode,
155
+ reason: string,
156
+ walletType: WalletType | null
157
+ ): Promise<void> {
158
+ const url = `${BASE_URL}/tx/report-tx?${RANGO_DAPP_ID_QUERY}`;
159
+ await fetch(url, {
160
+ method: 'POST',
161
+ headers: {
162
+ 'content-type': 'application/json;charset=UTF-8',
163
+ [RANGO_COOKIE_HEADER]: getCookieId(),
164
+ },
165
+ body: JSON.stringify({
166
+ requestId,
167
+ step,
168
+ eventType,
169
+ reason,
170
+ tags: {
171
+ wallet: walletType,
172
+ },
173
+ }),
174
+ });
175
+ }
@@ -0,0 +1,156 @@
1
+ import { WalletType } from '@rango-dev/wallets-shared';
2
+
3
+ export type ErrorDetail = {
4
+ extraMessage: string;
5
+ extraMessageDetail?: string | null | undefined;
6
+ extraMessageErrorCode: string | null;
7
+ };
8
+
9
+ export enum APIErrorCode {
10
+ TX_FAIL = 'TX_FAIL',
11
+ FETCH_TX_FAILED = 'FETCH_TX_FAILED',
12
+ USER_REJECT = 'USER_REJECT',
13
+ CALL_WALLET_FAILED = 'CALL_WALLET_FAILED',
14
+ SEND_TX_FAILED = 'SEND_TX_FAILED',
15
+ CALL_OR_SEND_FAILED = 'CALL_OR_SEND_FAILED',
16
+ USER_CANCEL = 'USER_CANCEL',
17
+ CLIENT_UNEXPECTED_BEHAVIOUR = 'CLIENT_UNEXPECTED_BEHAVIOUR',
18
+ }
19
+
20
+ export enum ApiMethodName {
21
+ RequestingSwapTransaction = 'Requesting Swap Transaction',
22
+ CreatingSwap = 'Creating Swap',
23
+ CheckingTransactionStatus = 'Checking transaction status',
24
+ CreateTransaction = 'Create Transaction',
25
+ CheckApproval = 'Check TX Approval',
26
+ GettingSwapDetail = 'Getting Swap Detail',
27
+ GettingUserLimits = 'Getting user limits',
28
+ }
29
+
30
+ export enum TransactionName {
31
+ GenericTransaction = 'transaction',
32
+ SendingOneInchTransaction = '1inch transaction',
33
+ Approval = 'approve transaction',
34
+ }
35
+
36
+ export const ERROR_ASSERTION_FAILED = 'Assertion failed (Unexpected behaviour)';
37
+
38
+ export const ERROR_COMMUNICATING_WITH_API = (
39
+ apiMethodName: ApiMethodName
40
+ ): string => `Unexpected response from API (${apiMethodName})`;
41
+
42
+ export const ERROR_DESCRIPTION_UNSUPPORTED_TRANSACTION = (
43
+ method: string,
44
+ walletType: WalletType
45
+ ): string => `method: ${method} call is unsupported for wallet ${walletType}`;
46
+
47
+ export const ERROR_SIGNING_TRANSACTION = (
48
+ transactionName: TransactionName
49
+ ): string => `Error sending ${transactionName}`;
50
+ export const ERROR_REJECTING_TRANSACTION = 'User rejected the message signing';
51
+
52
+ export const ERROR_CREATE_TRANSACTION =
53
+ 'Create transaction failed in Rango Server';
54
+ export const ERROR_INPUT_WALLET_NOT_FOUND = 'Input wallet not found';
55
+
56
+ export const DEFAULT_WALLET_INJECTION_ERROR =
57
+ 'Failed to connect to wallet, if you have turned injection off (disable default wallet for xDefi), turn it on and refresh the page';
58
+
59
+ type ErrorRoot = string | Record<string, string> | null;
60
+
61
+ export class PrettyError extends Error {
62
+ private readonly detail?: string;
63
+ private readonly root?: ErrorRoot;
64
+ private readonly code?: APIErrorCode;
65
+
66
+ constructor(
67
+ code: APIErrorCode,
68
+ m: string,
69
+ root?: ErrorRoot,
70
+ detail?: string
71
+ ) {
72
+ super(m);
73
+ Object.setPrototypeOf(this, PrettyError.prototype);
74
+ this.code = code;
75
+ this.detail = detail;
76
+ this.root = root;
77
+ }
78
+
79
+ getErrorDetail(): ErrorDetail {
80
+ const rawMessage =
81
+ typeof this.root === 'object' && this.root && this.root.error
82
+ ? this.root.error
83
+ : JSON.stringify(this.root);
84
+ const rootStr =
85
+ typeof this.root === 'string'
86
+ ? this.root
87
+ : this.root instanceof Error
88
+ ? this.root.message
89
+ : rawMessage;
90
+ return {
91
+ extraMessage: this.message,
92
+ extraMessageDetail: this.detail || rootStr,
93
+ extraMessageErrorCode: this.code || null,
94
+ };
95
+ }
96
+
97
+ static AssertionFailed(m: string): PrettyError {
98
+ return new PrettyError(
99
+ APIErrorCode.CLIENT_UNEXPECTED_BEHAVIOUR,
100
+ ERROR_ASSERTION_FAILED,
101
+ m
102
+ );
103
+ }
104
+
105
+ static BadStatusCode(
106
+ message: string,
107
+ statusCode: number | string
108
+ ): PrettyError {
109
+ return new PrettyError(
110
+ APIErrorCode.TX_FAIL,
111
+ message,
112
+ null,
113
+ `status code = ${statusCode}`
114
+ );
115
+ }
116
+
117
+ static CreateTransaction(detail: string): PrettyError {
118
+ return new PrettyError(
119
+ APIErrorCode.FETCH_TX_FAILED,
120
+ ERROR_CREATE_TRANSACTION,
121
+ null,
122
+ detail
123
+ );
124
+ }
125
+
126
+ static WalletMissing(): PrettyError {
127
+ return new PrettyError(
128
+ APIErrorCode.CLIENT_UNEXPECTED_BEHAVIOUR,
129
+ ERROR_INPUT_WALLET_NOT_FOUND,
130
+ null,
131
+ 'Server requested for a blockchain or address not selected by user'
132
+ );
133
+ }
134
+
135
+ static BlockchainMissing(): PrettyError {
136
+ return new PrettyError(
137
+ APIErrorCode.CLIENT_UNEXPECTED_BEHAVIOUR,
138
+ ERROR_INPUT_WALLET_NOT_FOUND,
139
+ null,
140
+ 'Server requested for a blockchain or address not selected by user'
141
+ );
142
+ }
143
+ }
144
+
145
+ export const ERROR_GETTING_BEST_ROUTE = (status: number | string): string =>
146
+ `Failed to get best route (status: ${status}), please try again.`;
147
+
148
+ export const ERROR_CONFIRM_SWAP = (status?: number | string): string =>
149
+ `Failed to confirm swap (${!!status ? 'status' : 'route'}: ${
150
+ status || null
151
+ }), please try again.`;
152
+
153
+ export const WARNING_STARKNET_FOUND =
154
+ 'StarknNet blockchain is still an ALPHA version. As such, delays may occur, and catastrophic bugs may lurk.';
155
+
156
+
@@ -0,0 +1,24 @@
1
+ import { WalletType } from '@rango-dev/wallets-shared';
2
+ import * as Sentry from '@sentry/browser';
3
+ import { PendingSwap, PendingSwapStep } from './shared';
4
+
5
+ export function logRPCError(
6
+ error: unknown,
7
+ swap: PendingSwap,
8
+ currentStep: PendingSwapStep | undefined,
9
+ walletType: WalletType | undefined
10
+ ): void {
11
+ try {
12
+ Sentry.captureException(error, {
13
+ tags: {
14
+ requestId: swap.requestId,
15
+ rpc: true,
16
+ swapper: currentStep?.swapperId || '',
17
+ walletType: walletType || '',
18
+ },
19
+ level: 'warning',
20
+ });
21
+ } catch (e) {
22
+ console.log({ e });
23
+ }
24
+ }