@rango-dev/queue-manager-rango-preset 0.5.1-next.8 → 0.6.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.
@@ -0,0 +1,257 @@
1
+ import mitt from 'mitt';
2
+ import {
3
+ MainEvents,
4
+ RemoveNameField,
5
+ Route,
6
+ RouteEvent,
7
+ RouteEventType,
8
+ RouteExecutionEvents,
9
+ EventSeverity,
10
+ Step,
11
+ StepEvent,
12
+ StepEventType,
13
+ StepExecutionEventStatus,
14
+ StepExecutionBlockedEventStatus,
15
+ } from '../types';
16
+ import { PendingSwap, PendingSwapStep } from 'rango-types/lib';
17
+ import { getCurrentBlockchainOfOrNull } from '../shared';
18
+ import {
19
+ getCurrentStepTx,
20
+ getFailedStep,
21
+ getLastSuccessfulStep,
22
+ isApprovalCurrentStepTx,
23
+ } from '../helpers';
24
+
25
+ type NotifierParams = {
26
+ swap: PendingSwap;
27
+ step: PendingSwapStep | null;
28
+ } & {
29
+ event: RemoveNameField<StepEvent, 'message' | 'messageSeverity'>;
30
+ };
31
+
32
+ function createSteps(swapSteps: PendingSwapStep[]): Step[] {
33
+ return swapSteps.map((swapStep) => {
34
+ const {
35
+ diagnosisUrl,
36
+ estimatedTimeInSeconds,
37
+ explorerUrl,
38
+ feeInUsd,
39
+ executedTransactionId,
40
+ executedTransactionTime,
41
+ expectedOutputAmountHumanReadable,
42
+ fromBlockchain,
43
+ toBlockchain,
44
+ fromSymbol,
45
+ toSymbol,
46
+ fromSymbolAddress,
47
+ toSymbolAddress,
48
+ swapperType,
49
+ swapperId,
50
+ outputAmount,
51
+ fromAmountMaxValue,
52
+ fromAmountMinValue,
53
+ fromAmountPrecision,
54
+ fromAmountRestrictionType,
55
+ fromDecimals,
56
+ status: stepStatus,
57
+ } = swapStep;
58
+
59
+ const step: Step = {
60
+ diagnosisUrl,
61
+ estimatedTimeInSeconds,
62
+ explorerUrl,
63
+ feeInUsd,
64
+ executedTransactionId,
65
+ executedTransactionTime,
66
+ expectedOutputAmountHumanReadable,
67
+ fromBlockchain,
68
+ toBlockchain,
69
+ fromSymbol,
70
+ toSymbol,
71
+ fromSymbolAddress,
72
+ toSymbolAddress,
73
+ swapperName: swapperId,
74
+ swapperType,
75
+ outputAmount,
76
+ fromAmountMaxValue,
77
+ fromAmountMinValue,
78
+ fromAmountPrecision,
79
+ fromAmountRestrictionType,
80
+ fromDecimals,
81
+ status: stepStatus,
82
+ transaction: getCurrentStepTx(swapStep),
83
+ };
84
+
85
+ return step;
86
+ });
87
+ }
88
+
89
+ function getEventPayload(
90
+ swap: PendingSwap,
91
+ type: StepEventType | RouteEventType,
92
+ swapStep?: PendingSwapStep
93
+ ): { route: Route; step: Step } {
94
+ const {
95
+ creationTime,
96
+ finishTime,
97
+ requestId,
98
+ inputAmount,
99
+ status,
100
+ wallets,
101
+ steps,
102
+ settings,
103
+ } = swap;
104
+
105
+ const routeSteps = createSteps(steps);
106
+ const route: Route = {
107
+ creationTime,
108
+ finishTime,
109
+ requestId,
110
+ inputAmount,
111
+ status,
112
+ wallets,
113
+ steps: routeSteps,
114
+ slippage: settings.slippage,
115
+ infiniteApproval: settings.infiniteApprove,
116
+ };
117
+
118
+ const result: { route: Route; step: Step } = {
119
+ route,
120
+ step: routeSteps[routeSteps.length - 1],
121
+ };
122
+ if (swapStep) result.step = createSteps([swapStep])[0];
123
+ else {
124
+ if (type === 'failed') {
125
+ const failedStep = getFailedStep(routeSteps);
126
+ if (failedStep) result.step = failedStep;
127
+ } else {
128
+ const lastSuccessfulStep = getLastSuccessfulStep(routeSteps);
129
+ if (lastSuccessfulStep) result.step = lastSuccessfulStep;
130
+ }
131
+ }
132
+
133
+ return result;
134
+ }
135
+
136
+ export const eventEmitter = mitt<RouteExecutionEvents>();
137
+
138
+ function emitRouteEvent(stepEvent: StepEvent, route: Route) {
139
+ let routeEvent: RouteEvent | undefined;
140
+ const { type } = stepEvent;
141
+ switch (type) {
142
+ case StepEventType.STARTED:
143
+ routeEvent = { ...stepEvent, type: RouteEventType.STARTED };
144
+ break;
145
+ case StepEventType.FAILED:
146
+ routeEvent = { ...stepEvent, type: RouteEventType.FAILED };
147
+ break;
148
+ case StepEventType.SUCCEEDED:
149
+ routeEvent = { ...stepEvent, type: RouteEventType.SUCCEEDED };
150
+ break;
151
+ default:
152
+ break;
153
+ }
154
+ if (routeEvent)
155
+ eventEmitter.emit(MainEvents.RouteEvent, { event: routeEvent, route });
156
+ }
157
+
158
+ function emitStepEvent(stepEvent: StepEvent, route: Route, step: Step) {
159
+ eventEmitter.emit(MainEvents.StepEvent, { event: stepEvent, route, step });
160
+ }
161
+
162
+ export function notifier(params: NotifierParams) {
163
+ const { event } = params;
164
+ const { type } = event;
165
+ const { route, step } = getEventPayload(
166
+ params.swap,
167
+ type,
168
+ params.step ?? undefined
169
+ );
170
+ const fromAsset = `${step.fromBlockchain}.${step.fromSymbol}`;
171
+ const toAsset = `${step.toBlockchain}.${step.toSymbol}`;
172
+ const outputAmount = step.outputAmount ?? '';
173
+ const currentFromBlockchain = !!params.step
174
+ ? getCurrentBlockchainOfOrNull(params.swap, params.step)
175
+ : null;
176
+ let message = '';
177
+ let messageSeverity: StepEvent['messageSeverity'] = EventSeverity.INFO;
178
+
179
+ switch (type) {
180
+ case StepEventType.STARTED:
181
+ message = 'Swap process started';
182
+ messageSeverity = EventSeverity.SUCCESS;
183
+ break;
184
+ case StepEventType.SUCCEEDED:
185
+ message = `You received ${outputAmount} ${toAsset}, hooray!`;
186
+ messageSeverity = EventSeverity.SUCCESS;
187
+ break;
188
+ case StepEventType.FAILED:
189
+ message = `Swap failed: ${
190
+ params.swap?.extraMessage ?? 'Reason is unknown'
191
+ }`;
192
+ messageSeverity = EventSeverity.ERROR;
193
+ break;
194
+ case StepEventType.TX_EXECUTION:
195
+ if (event.status === StepExecutionEventStatus.CREATE_TX) {
196
+ message = 'Please wait while the transaction is created ...';
197
+ messageSeverity = EventSeverity.INFO;
198
+ } else if (event.status === StepExecutionEventStatus.SEND_TX) {
199
+ if (params.step && isApprovalCurrentStepTx(params.step))
200
+ message = `Please confirm '${step.swapperName}' smart contract access to ${fromAsset}`;
201
+ else message = 'Please confirm transaction request in your wallet';
202
+ messageSeverity = EventSeverity.WARNING;
203
+ } else if (event.status === StepExecutionEventStatus.TX_SENT) {
204
+ message = 'Transaction sent successfully';
205
+ messageSeverity = EventSeverity.INFO;
206
+ }
207
+ break;
208
+ case StepEventType.CHECK_STATUS:
209
+ if (params.step && isApprovalCurrentStepTx(params.step))
210
+ message = 'Checking approve transacation status ...';
211
+ else message = 'Checking transacation status ...';
212
+ messageSeverity = EventSeverity.INFO;
213
+ break;
214
+ case StepEventType.APPROVAL_TX_SUCCEEDED:
215
+ message = 'Smart contract called successfully';
216
+ messageSeverity = EventSeverity.SUCCESS;
217
+ break;
218
+ case StepEventType.OUTPUT_REVEALED:
219
+ message = 'Transaction output amount revealed';
220
+ messageSeverity = EventSeverity.SUCCESS;
221
+ break;
222
+
223
+ case StepEventType.TX_EXECUTION_BLOCKED:
224
+ if (
225
+ event.status ===
226
+ StepExecutionBlockedEventStatus.WAITING_FOR_WALLET_CONNECT
227
+ ) {
228
+ message = 'Please connect your wallet.';
229
+ messageSeverity = EventSeverity.WARNING;
230
+ } else if (
231
+ event.status === StepExecutionBlockedEventStatus.WAITING_FOR_QUEUE
232
+ ) {
233
+ message = 'Waiting for other swaps to complete';
234
+ messageSeverity = EventSeverity.WARNING;
235
+ } else if (
236
+ event.status ===
237
+ StepExecutionBlockedEventStatus.WAITING_FOR_CHANGE_WALLET_ACCOUNT
238
+ ) {
239
+ message = 'Please change your wallet account.';
240
+ messageSeverity = EventSeverity.WARNING;
241
+ } else if (
242
+ event.status ===
243
+ StepExecutionBlockedEventStatus.WAITING_FOR_NETWORK_CHANGE
244
+ ) {
245
+ message = `Please change your wallet network to ${currentFromBlockchain}.`;
246
+ messageSeverity = EventSeverity.WARNING;
247
+ }
248
+ break;
249
+
250
+ default:
251
+ break;
252
+ }
253
+
254
+ if (params.step)
255
+ emitStepEvent({ ...event, message, messageSeverity }, route, step);
256
+ else emitRouteEvent({ ...event, message, messageSeverity }, route);
257
+ }
@@ -8,6 +8,7 @@ import {
8
8
  isSignerErrorCode,
9
9
  isAPIErrorCode,
10
10
  } from 'rango-types';
11
+ import { DEFAULT_ERROR_CODE } from './constants';
11
12
 
12
13
  export type ErrorDetail = {
13
14
  extraMessage: string;
@@ -70,6 +71,7 @@ export class PrettyError extends Error {
70
71
  return new PrettyError(
71
72
  'CLIENT_UNEXPECTED_BEHAVIOUR',
72
73
  ERROR_ASSERTION_FAILED,
74
+ null,
73
75
  m
74
76
  );
75
77
  }
@@ -117,24 +119,24 @@ export class PrettyError extends Error {
117
119
  export function mapAppErrorCodesToAPIErrorCode(
118
120
  errorCode: string | null
119
121
  ): APIErrorCode {
120
- const defaultErrorCode = 'CLIENT_UNEXPECTED_BEHAVIOUR';
121
122
  try {
122
- if (!errorCode) return defaultErrorCode;
123
+ if (!errorCode) return DEFAULT_ERROR_CODE;
123
124
  if (isAPIErrorCode(errorCode)) return errorCode;
124
125
  if (isSignerErrorCode(errorCode)) {
125
126
  const t: { [key in SignerErrorCodeType]: APIErrorCode } = {
126
127
  [SignerErrorCode.REJECTED_BY_USER]: 'USER_REJECT',
127
128
  [SignerErrorCode.SIGN_TX_ERROR]: 'CALL_WALLET_FAILED',
128
129
  [SignerErrorCode.SEND_TX_ERROR]: 'SEND_TX_FAILED',
129
- [SignerErrorCode.NOT_IMPLEMENTED]: defaultErrorCode,
130
- [SignerErrorCode.OPERATION_UNSUPPORTED]: defaultErrorCode,
131
- [SignerErrorCode.UNEXPECTED_BEHAVIOUR]: defaultErrorCode,
130
+ [SignerErrorCode.TX_FAILED_IN_BLOCKCHAIN]: 'TX_FAILED_IN_BLOCKCHAIN',
131
+ [SignerErrorCode.NOT_IMPLEMENTED]: DEFAULT_ERROR_CODE,
132
+ [SignerErrorCode.OPERATION_UNSUPPORTED]: DEFAULT_ERROR_CODE,
133
+ [SignerErrorCode.UNEXPECTED_BEHAVIOUR]: DEFAULT_ERROR_CODE,
132
134
  };
133
135
  return t[errorCode];
134
136
  }
135
- return defaultErrorCode;
137
+ return DEFAULT_ERROR_CODE;
136
138
  } catch (err) {
137
- return defaultErrorCode;
139
+ return DEFAULT_ERROR_CODE;
138
140
  }
139
141
  }
140
142
 
package/src/shared.ts CHANGED
@@ -19,6 +19,7 @@ import { PrettyError } from './shared-errors';
19
19
  import BigNumber from 'bignumber.js';
20
20
  import { numberToString } from './numbers';
21
21
  import {
22
+ TonTransaction,
22
23
  isCosmosBlockchain,
23
24
  isEvmBlockchain,
24
25
  isStarknetBlockchain,
@@ -30,12 +31,6 @@ export interface PendingSwapWithQueueID {
30
31
  swap: PendingSwap;
31
32
  }
32
33
 
33
- export type SwapProgressNotification = {
34
- eventType: EventType;
35
- swap: PendingSwap | null;
36
- step: PendingSwapStep | null;
37
- };
38
-
39
34
  export type WalletBalance = {
40
35
  chain: Network;
41
36
  symbol: string;
@@ -173,6 +168,7 @@ export type PendingSwapStep = {
173
168
  tronTransaction: TronTransaction | null;
174
169
  starknetApprovalTransaction: StarknetTransaction | null;
175
170
  starknetTransaction: StarknetTransaction | null;
171
+ tonTransaction: TonTransaction | null;
176
172
 
177
173
  // missing fields in older versions
178
174
  // keeping null for backward compatability
@@ -480,6 +476,7 @@ export function calculatePendingSwap(
480
476
  cosmosTransaction: null,
481
477
  solanaTransaction: null,
482
478
  transferTransaction: null,
479
+ tonTransaction: null,
483
480
 
484
481
  // front fields
485
482
  hasAlreadyProceededToSign: false,
package/src/types.ts CHANGED
@@ -7,8 +7,15 @@ import {
7
7
  WalletState,
8
8
  WalletType,
9
9
  } from '@rango-dev/wallets-shared';
10
- import { PendingSwap, SwapProgressNotification, Wallet } from './shared';
11
- import type { EvmBlockchainMeta, SignerFactory } from 'rango-types';
10
+ import { APIErrorCode, EvmBlockchainMeta, SignerFactory } from 'rango-types';
11
+ import { Transaction } from 'rango-sdk';
12
+ import { PendingSwap, PendingSwapStep, Wallet } from './shared';
13
+
14
+ export type RemoveNameField<T, U extends string> = {
15
+ [Property in keyof T as Exclude<Property, U>]: T[Property];
16
+ };
17
+
18
+ export type ArrayElement<A> = A extends readonly (infer T)[] ? T : never;
12
19
 
13
20
  export type SwapQueueDef = QueueDef<
14
21
  SwapStorage,
@@ -62,7 +69,6 @@ export interface SwapQueueContext extends QueueContext {
62
69
  ) => Promise<ConnectResult> | undefined;
63
70
  state: (type: WalletType) => WalletState;
64
71
  isMobileWallet: (type: WalletType) => boolean;
65
- notifier: (data: SwapProgressNotification) => void;
66
72
 
67
73
  // Dynamically will be added to context.
68
74
  claimedBy?: string;
@@ -74,6 +80,195 @@ export interface UseQueueManagerParams {
74
80
  disconnectedWallet: WalletType | undefined;
75
81
  clearDisconnectedWallet: () => void;
76
82
  evmChains: EvmBlockchainMeta[];
77
- notifier: SwapQueueContext['notifier'];
78
83
  canSwitchNetworkTo: (type: WalletType, network: Network) => boolean;
79
84
  }
85
+
86
+ export enum MainEvents {
87
+ RouteEvent = 'routeEvent',
88
+ StepEvent = 'stepEvent',
89
+ }
90
+
91
+ export type Step = Pick<
92
+ PendingSwapStep,
93
+ | 'diagnosisUrl'
94
+ | 'estimatedTimeInSeconds'
95
+ | 'explorerUrl'
96
+ | 'feeInUsd'
97
+ | 'executedTransactionId'
98
+ | 'executedTransactionTime'
99
+ | 'expectedOutputAmountHumanReadable'
100
+ | 'fromBlockchain'
101
+ | 'toBlockchain'
102
+ | 'fromSymbol'
103
+ | 'toSymbol'
104
+ | 'toSymbolAddress'
105
+ | 'fromSymbolAddress'
106
+ | 'swapperType'
107
+ | 'outputAmount'
108
+ | 'fromAmountMaxValue'
109
+ | 'fromAmountMinValue'
110
+ | 'fromAmountPrecision'
111
+ | 'fromAmountRestrictionType'
112
+ | 'fromDecimals'
113
+ | 'status'
114
+ > & { swapperName: string; transaction: Transaction | null };
115
+
116
+ export type Route = Pick<
117
+ PendingSwap,
118
+ | 'creationTime'
119
+ | 'finishTime'
120
+ | 'requestId'
121
+ | 'inputAmount'
122
+ | 'status'
123
+ | 'wallets'
124
+ > & { steps: Step[]; slippage: string; infiniteApproval?: boolean };
125
+
126
+ export type SwapEvent = RouteEvent | StepEvent;
127
+
128
+ export enum RouteEventType {
129
+ STARTED = 'started',
130
+ FAILED = 'failed',
131
+ SUCCEEDED = 'succeeded',
132
+ }
133
+
134
+ export enum StepExecutionEventStatus {
135
+ CREATE_TX = 'create_tx',
136
+ SEND_TX = 'send_tx',
137
+ TX_SENT = 'tx_sent',
138
+ }
139
+
140
+ export enum StepExecutionBlockedEventStatus {
141
+ WAITING_FOR_QUEUE = 'waiting_for_queue',
142
+ WAITING_FOR_WALLET_CONNECT = 'waiting_for_wallet_connect',
143
+ WAITING_FOR_NETWORK_CHANGE = 'waiting_for_network_change',
144
+ WAITING_FOR_CHANGE_WALLET_ACCOUNT = 'waiting_for_change_wallet_account',
145
+ }
146
+
147
+ export enum StepEventType {
148
+ STARTED = 'started',
149
+ FAILED = 'failed',
150
+ SUCCEEDED = 'succeeded',
151
+ TX_EXECUTION = 'tx_execution',
152
+ TX_EXECUTION_BLOCKED = 'tx_execution_blocked',
153
+ APPROVAL_TX_SUCCEEDED = 'approval_tx_succeeded',
154
+ CHECK_STATUS = 'check_status',
155
+ OUTPUT_REVEALED = 'output_revealed',
156
+ }
157
+
158
+ export enum EventSeverity {
159
+ ERROR = 'error',
160
+ SUCCESS = 'success',
161
+ WARNING = 'warning',
162
+ INFO = 'info',
163
+ }
164
+
165
+ export type Event<
166
+ T extends StepEventType | RouteEventType,
167
+ U extends Record<string, unknown> = Record<string, unknown>
168
+ > = {
169
+ type: T;
170
+ message: string;
171
+ messageSeverity: EventSeverity;
172
+ } & U;
173
+
174
+ export type FailedRouteEventPayload = {
175
+ reason?: string;
176
+ reasonCode: APIErrorCode;
177
+ };
178
+
179
+ export type FailedStepEventPayload = FailedRouteEventPayload;
180
+
181
+ export type SucceededRouteEventPayload = {
182
+ outputAmount: string;
183
+ };
184
+
185
+ export type SucceededStepEventPayload = SucceededRouteEventPayload;
186
+
187
+ export type OutputRevealedEventPayload = SucceededRouteEventPayload;
188
+
189
+ export type StepExecutionEventPayload = {
190
+ status:
191
+ | StepExecutionEventStatus.CREATE_TX
192
+ | StepExecutionEventStatus.SEND_TX
193
+ | StepExecutionEventStatus.TX_SENT;
194
+ };
195
+
196
+ export type StepBlockedEventPayload =
197
+ | { status: StepExecutionBlockedEventStatus.WAITING_FOR_QUEUE }
198
+ | {
199
+ status: StepExecutionBlockedEventStatus.WAITING_FOR_WALLET_CONNECT;
200
+ requiredWallet?: string;
201
+ requiredAccount?: string;
202
+ }
203
+ | {
204
+ status: StepExecutionBlockedEventStatus.WAITING_FOR_CHANGE_WALLET_ACCOUNT;
205
+ requiredAccount?: string;
206
+ }
207
+ | {
208
+ status: StepExecutionBlockedEventStatus.WAITING_FOR_NETWORK_CHANGE;
209
+ currentNetwork?: string;
210
+ requiredNetwork?: string;
211
+ };
212
+
213
+ export type RouteStartedEvent = Event<RouteEventType.STARTED>;
214
+
215
+ export type RouteFailedEvent = Event<
216
+ RouteEventType.FAILED,
217
+ FailedRouteEventPayload
218
+ >;
219
+
220
+ export type RouteSucceededEvent = Event<
221
+ RouteEventType.SUCCEEDED,
222
+ SucceededRouteEventPayload
223
+ >;
224
+
225
+ export type StepStartedEvent = Event<StepEventType.STARTED>;
226
+
227
+ export type StepSucceededEvent = Event<
228
+ StepEventType.SUCCEEDED,
229
+ SucceededStepEventPayload
230
+ >;
231
+ export type StepFailedEvent = Event<
232
+ StepEventType.FAILED,
233
+ FailedStepEventPayload
234
+ >;
235
+
236
+ export type StepTxExecutionUpdatedEvent = Event<
237
+ StepEventType.TX_EXECUTION,
238
+ StepExecutionEventPayload
239
+ >;
240
+
241
+ export type StepTxExecutionBlockedEvent = Event<
242
+ StepEventType.TX_EXECUTION_BLOCKED,
243
+ StepBlockedEventPayload
244
+ >;
245
+
246
+ export type StepCheckStatusEvent = Event<StepEventType.CHECK_STATUS>;
247
+
248
+ export type StepApprovalTxSucceededEvent =
249
+ Event<StepEventType.APPROVAL_TX_SUCCEEDED>;
250
+
251
+ export type StepOutputRevealedEvent = Event<
252
+ StepEventType.OUTPUT_REVEALED,
253
+ OutputRevealedEventPayload
254
+ >;
255
+
256
+ export type StepEvent =
257
+ | StepStartedEvent
258
+ | StepSucceededEvent
259
+ | StepFailedEvent
260
+ | StepTxExecutionUpdatedEvent
261
+ | StepTxExecutionBlockedEvent
262
+ | StepCheckStatusEvent
263
+ | StepApprovalTxSucceededEvent
264
+ | StepOutputRevealedEvent;
265
+
266
+ export type RouteEvent =
267
+ | RouteStartedEvent
268
+ | RouteSucceededEvent
269
+ | RouteFailedEvent;
270
+
271
+ export type RouteExecutionEvents = {
272
+ [MainEvents.RouteEvent]: { route: Route; event: RouteEvent };
273
+ [MainEvents.StepEvent]: { route: Route; step: Step; event: StepEvent };
274
+ };