@rango-dev/queue-manager-rango-preset 0.0.0-experimental-936229e8-20251208
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/CHANGELOG.md +353 -0
- package/dist/actions/checkStatus.d.ts +13 -0
- package/dist/actions/checkStatus.d.ts.map +1 -0
- package/dist/actions/common/checkEnvironmentBeforeExecuteTransaction.d.ts +8 -0
- package/dist/actions/common/checkEnvironmentBeforeExecuteTransaction.d.ts.map +1 -0
- package/dist/actions/common/produceNextStateForTransaction.d.ts +17 -0
- package/dist/actions/common/produceNextStateForTransaction.d.ts.map +1 -0
- package/dist/actions/common/utils.d.ts +5 -0
- package/dist/actions/common/utils.d.ts.map +1 -0
- package/dist/actions/createTransaction.d.ts +12 -0
- package/dist/actions/createTransaction.d.ts.map +1 -0
- package/dist/actions/executeTransaction/executeTransaction.d.ts +14 -0
- package/dist/actions/executeTransaction/executeTransaction.d.ts.map +1 -0
- package/dist/actions/executeTransaction/index.d.ts +2 -0
- package/dist/actions/executeTransaction/index.d.ts.map +1 -0
- package/dist/actions/scheduleNextStep.d.ts +14 -0
- package/dist/actions/scheduleNextStep.d.ts.map +1 -0
- package/dist/actions/start.d.ts +4 -0
- package/dist/actions/start.d.ts.map +1 -0
- package/dist/configs.d.ts +14 -0
- package/dist/configs.d.ts.map +1 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/helpers.d.ts +255 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/hooks.d.ts +19 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/migration.d.ts +15 -0
- package/dist/migration.d.ts.map +1 -0
- package/dist/numbers.d.ts +3 -0
- package/dist/numbers.d.ts.map +1 -0
- package/dist/queue-manager-rango-preset.build.json +1 -0
- package/dist/queueDef.d.ts +10 -0
- package/dist/queueDef.d.ts.map +1 -0
- package/dist/services/eventEmitter.d.ts +10 -0
- package/dist/services/eventEmitter.d.ts.map +1 -0
- package/dist/services/httpService.d.ts +3 -0
- package/dist/services/httpService.d.ts.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/shared-errors.d.ts +25 -0
- package/dist/shared-errors.d.ts.map +1 -0
- package/dist/shared.d.ts +81 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +45 -0
- package/readme.md +2 -0
- package/src/actions/checkStatus.ts +564 -0
- package/src/actions/common/checkEnvironmentBeforeExecuteTransaction.ts +157 -0
- package/src/actions/common/produceNextStateForTransaction.ts +167 -0
- package/src/actions/common/utils.ts +25 -0
- package/src/actions/createTransaction.ts +117 -0
- package/src/actions/executeTransaction/executeTransaction.ts +107 -0
- package/src/actions/executeTransaction/index.ts +1 -0
- package/src/actions/scheduleNextStep.ts +104 -0
- package/src/actions/start.ts +16 -0
- package/src/configs.ts +38 -0
- package/src/constants.ts +18 -0
- package/src/helpers.ts +1598 -0
- package/src/hooks.ts +94 -0
- package/src/index.ts +68 -0
- package/src/migration.ts +124 -0
- package/src/numbers.ts +68 -0
- package/src/queueDef.ts +39 -0
- package/src/services/eventEmitter.ts +290 -0
- package/src/services/httpService.ts +10 -0
- package/src/services/index.ts +1 -0
- package/src/shared-errors.ts +165 -0
- package/src/shared.ts +473 -0
- package/src/types.ts +305 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
APIErrorCode,
|
|
3
|
+
SignerErrorCode as SignerErrorCodeType,
|
|
4
|
+
} from 'rango-types';
|
|
5
|
+
import {
|
|
6
|
+
SignerErrorCode,
|
|
7
|
+
SignerError,
|
|
8
|
+
isSignerErrorCode,
|
|
9
|
+
isAPIErrorCode,
|
|
10
|
+
} from 'rango-types';
|
|
11
|
+
import { DEFAULT_ERROR_CODE } from './constants';
|
|
12
|
+
|
|
13
|
+
export type ErrorDetail = {
|
|
14
|
+
extraMessage: string;
|
|
15
|
+
extraMessageDetail?: string | null | undefined;
|
|
16
|
+
extraMessageErrorCode: SignerErrorCodeType | APIErrorCode | null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const ERROR_ASSERTION_FAILED = 'Assertion failed (Unexpected behaviour)';
|
|
20
|
+
const ERROR_CREATE_TRANSACTION = 'Create transaction failed in Rango Server';
|
|
21
|
+
const ERROR_INPUT_WALLET_NOT_FOUND = 'Input wallet not found';
|
|
22
|
+
|
|
23
|
+
type ErrorRoot = string | Record<string, string> | null;
|
|
24
|
+
|
|
25
|
+
export class PrettyError extends Error {
|
|
26
|
+
private readonly detail?: string;
|
|
27
|
+
private readonly root?: ErrorRoot;
|
|
28
|
+
private readonly code?: APIErrorCode;
|
|
29
|
+
public _isPrettyError = true;
|
|
30
|
+
|
|
31
|
+
constructor(
|
|
32
|
+
code: APIErrorCode,
|
|
33
|
+
m: string,
|
|
34
|
+
root?: ErrorRoot,
|
|
35
|
+
detail?: string
|
|
36
|
+
) {
|
|
37
|
+
super(m);
|
|
38
|
+
Object.setPrototypeOf(this, PrettyError.prototype);
|
|
39
|
+
PrettyError.prototype._isPrettyError = true;
|
|
40
|
+
this.code = code;
|
|
41
|
+
this.detail = detail;
|
|
42
|
+
this.root = root;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static isPrettyError(obj: unknown): obj is PrettyError {
|
|
46
|
+
return (
|
|
47
|
+
obj instanceof PrettyError ||
|
|
48
|
+
Object.prototype.hasOwnProperty.call(obj, '_isPrettyError')
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getErrorDetail(): ErrorDetail {
|
|
53
|
+
const rawMessage =
|
|
54
|
+
typeof this.root === 'object' && this.root && this.root.error
|
|
55
|
+
? this.root.error
|
|
56
|
+
: JSON.stringify(this.root);
|
|
57
|
+
const rootStr =
|
|
58
|
+
typeof this.root === 'string'
|
|
59
|
+
? this.root
|
|
60
|
+
: this.root instanceof Error
|
|
61
|
+
? this.root.message
|
|
62
|
+
: rawMessage;
|
|
63
|
+
return {
|
|
64
|
+
extraMessage: this.message,
|
|
65
|
+
extraMessageDetail: this.detail || rootStr,
|
|
66
|
+
extraMessageErrorCode: this.code || null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static AssertionFailed(m: string): PrettyError {
|
|
71
|
+
return new PrettyError(
|
|
72
|
+
'CLIENT_UNEXPECTED_BEHAVIOUR',
|
|
73
|
+
ERROR_ASSERTION_FAILED,
|
|
74
|
+
null,
|
|
75
|
+
m
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static BadStatusCode(
|
|
80
|
+
message: string,
|
|
81
|
+
statusCode: number | string
|
|
82
|
+
): PrettyError {
|
|
83
|
+
return new PrettyError(
|
|
84
|
+
'TX_FAIL',
|
|
85
|
+
message,
|
|
86
|
+
null,
|
|
87
|
+
`status code = ${statusCode}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static CreateTransaction(detail: string): PrettyError {
|
|
92
|
+
return new PrettyError(
|
|
93
|
+
'FETCH_TX_FAILED',
|
|
94
|
+
ERROR_CREATE_TRANSACTION,
|
|
95
|
+
null,
|
|
96
|
+
detail
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static WalletMissing(): PrettyError {
|
|
101
|
+
return new PrettyError(
|
|
102
|
+
'CLIENT_UNEXPECTED_BEHAVIOUR',
|
|
103
|
+
ERROR_INPUT_WALLET_NOT_FOUND,
|
|
104
|
+
null,
|
|
105
|
+
'Server requested for a blockchain or address not selected by user'
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static BlockchainMissing(): PrettyError {
|
|
110
|
+
return new PrettyError(
|
|
111
|
+
'CLIENT_UNEXPECTED_BEHAVIOUR',
|
|
112
|
+
ERROR_INPUT_WALLET_NOT_FOUND,
|
|
113
|
+
null,
|
|
114
|
+
'Server requested for a blockchain or address not selected by user'
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function mapAppErrorCodesToAPIErrorCode(
|
|
120
|
+
errorCode: string | null
|
|
121
|
+
): APIErrorCode {
|
|
122
|
+
try {
|
|
123
|
+
if (!errorCode) return DEFAULT_ERROR_CODE;
|
|
124
|
+
if (isAPIErrorCode(errorCode)) return errorCode;
|
|
125
|
+
if (isSignerErrorCode(errorCode)) {
|
|
126
|
+
const t: { [key in SignerErrorCodeType]: APIErrorCode } = {
|
|
127
|
+
[SignerErrorCode.REJECTED_BY_USER]: 'USER_REJECT',
|
|
128
|
+
[SignerErrorCode.SIGN_TX_ERROR]: 'CALL_WALLET_FAILED',
|
|
129
|
+
[SignerErrorCode.SEND_TX_ERROR]: 'SEND_TX_FAILED',
|
|
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,
|
|
134
|
+
};
|
|
135
|
+
return t[errorCode];
|
|
136
|
+
}
|
|
137
|
+
return DEFAULT_ERROR_CODE;
|
|
138
|
+
} catch (err) {
|
|
139
|
+
return DEFAULT_ERROR_CODE;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const prettifyErrorMessage = (obj: unknown): ErrorDetail => {
|
|
144
|
+
if (!obj) return { extraMessage: '', extraMessageErrorCode: null };
|
|
145
|
+
if (PrettyError.isPrettyError(obj)) return obj.getErrorDetail();
|
|
146
|
+
if (SignerError.isSignerError(obj)) {
|
|
147
|
+
const t = obj.getErrorDetail();
|
|
148
|
+
return {
|
|
149
|
+
extraMessage: t.message,
|
|
150
|
+
extraMessageDetail: t.detail,
|
|
151
|
+
extraMessageErrorCode: t.code,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (obj instanceof Error)
|
|
155
|
+
return {
|
|
156
|
+
extraMessage: obj.toString(),
|
|
157
|
+
extraMessageErrorCode: null,
|
|
158
|
+
};
|
|
159
|
+
if (typeof obj !== 'string')
|
|
160
|
+
return {
|
|
161
|
+
extraMessage: JSON.stringify(obj),
|
|
162
|
+
extraMessageErrorCode: null,
|
|
163
|
+
};
|
|
164
|
+
return { extraMessage: obj, extraMessageErrorCode: null };
|
|
165
|
+
};
|
package/src/shared.ts
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import type { NamespaceInputForConnect } from '@rango-dev/wallets-core/dist/legacy/types';
|
|
2
|
+
import type { Network, WalletType } from '@rango-dev/wallets-shared';
|
|
3
|
+
import type {
|
|
4
|
+
BlockchainMeta,
|
|
5
|
+
ConfirmRouteResponse,
|
|
6
|
+
MetaResponse,
|
|
7
|
+
SwapResult,
|
|
8
|
+
Token,
|
|
9
|
+
} from 'rango-sdk';
|
|
10
|
+
import type {
|
|
11
|
+
PendingSwap,
|
|
12
|
+
PendingSwapStep,
|
|
13
|
+
SwapSavedSettings,
|
|
14
|
+
SwapStepRoute,
|
|
15
|
+
WalletTypeAndAddress,
|
|
16
|
+
} from 'rango-types';
|
|
17
|
+
|
|
18
|
+
import BigNumber from 'bignumber.js';
|
|
19
|
+
|
|
20
|
+
import { numberToString } from './numbers';
|
|
21
|
+
import { PrettyError } from './shared-errors';
|
|
22
|
+
|
|
23
|
+
export interface PendingSwapWithQueueID {
|
|
24
|
+
id: string;
|
|
25
|
+
swap: PendingSwap;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type WalletBalance = {
|
|
29
|
+
chain: Network;
|
|
30
|
+
symbol: string;
|
|
31
|
+
ticker: string;
|
|
32
|
+
address: string | null;
|
|
33
|
+
rawAmount: string;
|
|
34
|
+
decimal: number | null;
|
|
35
|
+
amount: string;
|
|
36
|
+
logo: string | null;
|
|
37
|
+
usdPrice: number | null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type Account = {
|
|
41
|
+
address: string;
|
|
42
|
+
loading: boolean;
|
|
43
|
+
walletType: WalletType;
|
|
44
|
+
error: boolean;
|
|
45
|
+
explorerUrl: string | null;
|
|
46
|
+
isConnected?: boolean;
|
|
47
|
+
};
|
|
48
|
+
export type Blockchain = { name: string; accounts: Account[] };
|
|
49
|
+
export type Wallet = { blockchains: Blockchain[] };
|
|
50
|
+
|
|
51
|
+
export type EventType =
|
|
52
|
+
| 'swap_started'
|
|
53
|
+
| 'confirm_contract'
|
|
54
|
+
| 'confirm_transfer'
|
|
55
|
+
| 'task_failed'
|
|
56
|
+
| 'task_completed'
|
|
57
|
+
| 'task_canceled'
|
|
58
|
+
| 'task_paused'
|
|
59
|
+
| 'contract_confirmed'
|
|
60
|
+
| 'confirm_approve_contract'
|
|
61
|
+
| 'contract_rejected'
|
|
62
|
+
| 'check_tx_status'
|
|
63
|
+
| 'check_approve_tx_status'
|
|
64
|
+
| 'transfer_rejected'
|
|
65
|
+
| 'transfer_failed'
|
|
66
|
+
| 'calling_smart_contract'
|
|
67
|
+
| 'smart_contract_called'
|
|
68
|
+
| 'smart_contract_call_failed'
|
|
69
|
+
| 'step_completed_with_output'
|
|
70
|
+
| 'waiting_for_network_change'
|
|
71
|
+
| 'waiting_for_connecting_wallet'
|
|
72
|
+
| 'waiting_for_change_wallet_account'
|
|
73
|
+
| 'network_changed'
|
|
74
|
+
| 'not_enough_balance'
|
|
75
|
+
| 'not_enough_approval'
|
|
76
|
+
| 'waiting_for_queue'
|
|
77
|
+
| 'check_fee_failed'
|
|
78
|
+
| 'route_failed_to_find'
|
|
79
|
+
| 'transaction_expired';
|
|
80
|
+
|
|
81
|
+
export enum MessageSeverity {
|
|
82
|
+
error = 'error',
|
|
83
|
+
warning = 'warning',
|
|
84
|
+
info = 'info',
|
|
85
|
+
success = 'success',
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type SwapStatus = 'running' | 'failed' | 'success';
|
|
89
|
+
|
|
90
|
+
export interface TargetNamespace {
|
|
91
|
+
namespace: NamespaceInputForConnect['namespace'];
|
|
92
|
+
network: string;
|
|
93
|
+
}
|
|
94
|
+
export const getCurrentNamespaceOfOrNull = (
|
|
95
|
+
swap: PendingSwap,
|
|
96
|
+
step: PendingSwapStep
|
|
97
|
+
): TargetNamespace | null => {
|
|
98
|
+
try {
|
|
99
|
+
return getCurrentNamespaceOf(swap, step);
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const getCurrentNamespaceOf = (
|
|
106
|
+
swap: PendingSwap,
|
|
107
|
+
step: PendingSwapStep
|
|
108
|
+
): TargetNamespace => {
|
|
109
|
+
const evmNetwork =
|
|
110
|
+
step.evmTransaction?.blockChain || step.evmApprovalTransaction?.blockChain;
|
|
111
|
+
const starknetNetwork =
|
|
112
|
+
step.starknetTransaction?.blockChain ||
|
|
113
|
+
step.starknetApprovalTransaction?.blockChain;
|
|
114
|
+
const tronNetwork =
|
|
115
|
+
step.tronTransaction?.blockChain ||
|
|
116
|
+
step.tronApprovalTransaction?.blockChain;
|
|
117
|
+
const cosmosNetwork = step.cosmosTransaction?.blockChain;
|
|
118
|
+
const solanaNetwork = step.solanaTransaction?.blockChain;
|
|
119
|
+
const tonNetwork = step.tonTransaction?.blockChain;
|
|
120
|
+
const suiNetwork = step.suiTransaction?.blockChain;
|
|
121
|
+
|
|
122
|
+
if (evmNetwork) {
|
|
123
|
+
return {
|
|
124
|
+
namespace: 'EVM',
|
|
125
|
+
network: evmNetwork,
|
|
126
|
+
};
|
|
127
|
+
} else if (starknetNetwork) {
|
|
128
|
+
return {
|
|
129
|
+
namespace: 'Starknet',
|
|
130
|
+
network: starknetNetwork,
|
|
131
|
+
};
|
|
132
|
+
} else if (tronNetwork) {
|
|
133
|
+
return {
|
|
134
|
+
namespace: 'Tron',
|
|
135
|
+
network: tronNetwork,
|
|
136
|
+
};
|
|
137
|
+
} else if (cosmosNetwork) {
|
|
138
|
+
return {
|
|
139
|
+
namespace: 'Cosmos',
|
|
140
|
+
network: cosmosNetwork,
|
|
141
|
+
};
|
|
142
|
+
} else if (solanaNetwork) {
|
|
143
|
+
return {
|
|
144
|
+
namespace: 'Solana',
|
|
145
|
+
network: solanaNetwork,
|
|
146
|
+
};
|
|
147
|
+
} else if (tonNetwork) {
|
|
148
|
+
return {
|
|
149
|
+
namespace: 'Ton',
|
|
150
|
+
network: tonNetwork,
|
|
151
|
+
};
|
|
152
|
+
} else if (suiNetwork) {
|
|
153
|
+
return {
|
|
154
|
+
namespace: 'Sui',
|
|
155
|
+
network: suiNetwork,
|
|
156
|
+
};
|
|
157
|
+
} else if (!!step.transferTransaction) {
|
|
158
|
+
const transferAddress = step.transferTransaction.fromWalletAddress;
|
|
159
|
+
if (!transferAddress) {
|
|
160
|
+
throw PrettyError.BlockchainMissing();
|
|
161
|
+
}
|
|
162
|
+
const utxoNetwork = Object.keys(swap.wallets).find(
|
|
163
|
+
(network) => swap.wallets[network]?.address === transferAddress
|
|
164
|
+
);
|
|
165
|
+
if (!utxoNetwork) {
|
|
166
|
+
throw PrettyError.BlockchainMissing();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
namespace: 'UTXO',
|
|
171
|
+
network: utxoNetwork,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
throw new Error(
|
|
176
|
+
'Unsupported transaction type has been included in your swap.',
|
|
177
|
+
{
|
|
178
|
+
cause: step,
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const getScannerUrl = (
|
|
184
|
+
txHash: string,
|
|
185
|
+
network: Network,
|
|
186
|
+
blockchainMetaMap: { [key: string]: BlockchainMeta }
|
|
187
|
+
): string | undefined => {
|
|
188
|
+
const blockchainMeta = blockchainMetaMap[network];
|
|
189
|
+
const baseUrl = blockchainMeta.info?.transactionUrl;
|
|
190
|
+
if (!baseUrl) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (baseUrl.indexOf('/{txHash}') !== -1) {
|
|
194
|
+
return baseUrl.replace('{txHash}', txHash);
|
|
195
|
+
}
|
|
196
|
+
return `${baseUrl}/${txHash}`;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
export function getNextStep(
|
|
200
|
+
swap: PendingSwap,
|
|
201
|
+
currentStep: PendingSwapStep
|
|
202
|
+
): PendingSwapStep | null {
|
|
203
|
+
return (
|
|
204
|
+
swap.steps.find(
|
|
205
|
+
(step) =>
|
|
206
|
+
step.status !== 'failed' &&
|
|
207
|
+
step.status !== 'success' &&
|
|
208
|
+
step.id !== currentStep.id
|
|
209
|
+
) || null
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Returns the wallet type and address, based on the current step of `PendingSwap`.
|
|
215
|
+
*
|
|
216
|
+
* @param {PendingSwap} swap - The swap.
|
|
217
|
+
* @param {PendingSwapStep} step - The current step.
|
|
218
|
+
* @returns {WalletTypeAndAddress} Type and address related to the current step of the swap.
|
|
219
|
+
*/
|
|
220
|
+
export const getCurrentWalletTypeAndAddress = (
|
|
221
|
+
swap: PendingSwap,
|
|
222
|
+
step: PendingSwapStep
|
|
223
|
+
): WalletTypeAndAddress => {
|
|
224
|
+
const result =
|
|
225
|
+
swap.wallets[step.evmTransaction?.blockChain || ''] ||
|
|
226
|
+
swap.wallets[step.evmApprovalTransaction?.blockChain || ''] ||
|
|
227
|
+
swap.wallets[step.tronTransaction?.blockChain || ''] ||
|
|
228
|
+
swap.wallets[step.tronApprovalTransaction?.blockChain || ''] ||
|
|
229
|
+
swap.wallets[step.starknetTransaction?.blockChain || ''] ||
|
|
230
|
+
swap.wallets[step.starknetApprovalTransaction?.blockChain || ''] ||
|
|
231
|
+
swap.wallets[step.cosmosTransaction?.blockChain || ''] ||
|
|
232
|
+
swap.wallets[step.solanaTransaction?.blockChain || ''] ||
|
|
233
|
+
swap.wallets[step.tonTransaction?.blockChain || ''] ||
|
|
234
|
+
swap.wallets[step.suiTransaction?.blockChain || ''] ||
|
|
235
|
+
(step.transferTransaction?.fromWalletAddress
|
|
236
|
+
? {
|
|
237
|
+
address: step.transferTransaction.fromWalletAddress,
|
|
238
|
+
walletType: Object.values(swap.wallets).find(
|
|
239
|
+
(wallet) =>
|
|
240
|
+
wallet.address === step.transferTransaction?.fromWalletAddress
|
|
241
|
+
)?.walletType,
|
|
242
|
+
}
|
|
243
|
+
: null) ||
|
|
244
|
+
null;
|
|
245
|
+
if (result == null) {
|
|
246
|
+
throw PrettyError.WalletMissing();
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Returns the wallet address, based on the current step of `PendingSwap`.
|
|
253
|
+
*/
|
|
254
|
+
export const getCurrentAddressOf = (
|
|
255
|
+
swap: PendingSwap,
|
|
256
|
+
step: PendingSwapStep
|
|
257
|
+
): string => {
|
|
258
|
+
return getCurrentWalletTypeAndAddress(swap, step).address;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
export function getRelatedWallet(
|
|
262
|
+
swap: PendingSwap,
|
|
263
|
+
currentStep: PendingSwapStep
|
|
264
|
+
): WalletTypeAndAddress {
|
|
265
|
+
const { address, walletType: type } = getCurrentWalletTypeAndAddress(
|
|
266
|
+
swap,
|
|
267
|
+
currentStep
|
|
268
|
+
);
|
|
269
|
+
const walletKV =
|
|
270
|
+
Object.keys(swap.wallets)
|
|
271
|
+
.map((k) => ({ k, v: swap.wallets[k] }))
|
|
272
|
+
.find(({ v }) => v.address === address && v.walletType === type) || null;
|
|
273
|
+
const blockchain = walletKV?.k || null;
|
|
274
|
+
const wallet = walletKV?.v || null;
|
|
275
|
+
|
|
276
|
+
const walletType = wallet?.walletType;
|
|
277
|
+
if (wallet === null) {
|
|
278
|
+
throw PrettyError.AssertionFailed(
|
|
279
|
+
`Wallet for source ${blockchain} not passed: walletType: ${walletType}`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
return wallet;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export function getRelatedWalletOrNull(
|
|
286
|
+
swap: PendingSwap,
|
|
287
|
+
currentStep: PendingSwapStep | null
|
|
288
|
+
): WalletTypeAndAddress | null {
|
|
289
|
+
if (!currentStep) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
try {
|
|
293
|
+
return getRelatedWallet(swap, currentStep);
|
|
294
|
+
} catch {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export const getUsdPrice = (
|
|
300
|
+
blockchain: string,
|
|
301
|
+
symbol: string,
|
|
302
|
+
address: string | null,
|
|
303
|
+
allTokens: Token[]
|
|
304
|
+
): number | null => {
|
|
305
|
+
const token = allTokens?.find(
|
|
306
|
+
(t) =>
|
|
307
|
+
t.blockchain === blockchain &&
|
|
308
|
+
t.symbol?.toUpperCase() === symbol?.toUpperCase() &&
|
|
309
|
+
t.address === address
|
|
310
|
+
);
|
|
311
|
+
return token?.usdPrice || null;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
export function getUsdFeeOfStep(
|
|
315
|
+
step: SwapResult,
|
|
316
|
+
allTokens: Token[]
|
|
317
|
+
): BigNumber {
|
|
318
|
+
let totalFeeInUsd = new BigNumber(0);
|
|
319
|
+
for (let i = 0; i < step.fee.length; i++) {
|
|
320
|
+
const fee = step.fee[i];
|
|
321
|
+
if (fee.expenseType === 'DECREASE_FROM_OUTPUT') {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const unitPrice = getUsdPrice(
|
|
326
|
+
fee.asset.blockchain,
|
|
327
|
+
fee.asset.symbol,
|
|
328
|
+
fee.asset.address,
|
|
329
|
+
allTokens
|
|
330
|
+
);
|
|
331
|
+
totalFeeInUsd = totalFeeInUsd.plus(
|
|
332
|
+
new BigNumber(fee.amount).multipliedBy(unitPrice || 0)
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return totalFeeInUsd;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function mapSwapStepToPendingSwapStep(
|
|
340
|
+
swap: SwapResult,
|
|
341
|
+
meta: Pick<MetaResponse, 'blockchains' | 'tokens'> | null
|
|
342
|
+
): SwapStepRoute {
|
|
343
|
+
return {
|
|
344
|
+
// from
|
|
345
|
+
fromBlockchain: swap.from.blockchain,
|
|
346
|
+
fromBlockchainLogo: swap.from.blockchainLogo,
|
|
347
|
+
fromLogo: swap.from.logo,
|
|
348
|
+
fromSymbol: swap.from.symbol,
|
|
349
|
+
fromSymbolAddress: swap.from.address,
|
|
350
|
+
fromDecimals: swap.from.decimals,
|
|
351
|
+
fromAmountPrecision: swap.fromAmountPrecision,
|
|
352
|
+
fromAmountMinValue: swap.fromAmountMinValue,
|
|
353
|
+
fromAmountMaxValue: swap.fromAmountMaxValue,
|
|
354
|
+
fromAmountRestrictionType: swap.fromAmountRestrictionType,
|
|
355
|
+
fromUsdPrice: swap.from.usdPrice,
|
|
356
|
+
|
|
357
|
+
// to
|
|
358
|
+
toBlockchain: swap.to.blockchain,
|
|
359
|
+
toBlockchainLogo: swap.to.blockchainLogo,
|
|
360
|
+
toSymbol: swap.to.symbol,
|
|
361
|
+
toSymbolAddress: swap.to.address,
|
|
362
|
+
toDecimals: swap.to.decimals,
|
|
363
|
+
toLogo: swap.to.logo,
|
|
364
|
+
toUsdPrice: swap.to.usdPrice,
|
|
365
|
+
|
|
366
|
+
// swapper
|
|
367
|
+
swapperId: swap.swapperId,
|
|
368
|
+
swapperLogo: swap.swapperLogo,
|
|
369
|
+
swapperType: swap.swapperType,
|
|
370
|
+
|
|
371
|
+
// route
|
|
372
|
+
expectedOutputAmountHumanReadable: swap.toAmount,
|
|
373
|
+
feeInUsd: meta
|
|
374
|
+
? // eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
375
|
+
numberToString(getUsdFeeOfStep(swap, meta?.tokens), null, 8)
|
|
376
|
+
: null,
|
|
377
|
+
estimatedTimeInSeconds: swap.estimatedTimeInSeconds || null,
|
|
378
|
+
internalSteps: null,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function calculatePendingSwap(params: {
|
|
383
|
+
inputAmount: string;
|
|
384
|
+
bestRoute: NonNullable<ConfirmRouteResponse['result']>;
|
|
385
|
+
wallets: { [p: string]: WalletTypeAndAddress };
|
|
386
|
+
settings: SwapSavedSettings;
|
|
387
|
+
validateBalanceOrFee: boolean;
|
|
388
|
+
meta: Pick<MetaResponse, 'blockchains' | 'tokens'> | null;
|
|
389
|
+
swapMode?: 'swap' | 'refuel';
|
|
390
|
+
}): PendingSwap {
|
|
391
|
+
const {
|
|
392
|
+
inputAmount,
|
|
393
|
+
bestRoute,
|
|
394
|
+
wallets,
|
|
395
|
+
settings,
|
|
396
|
+
validateBalanceOrFee,
|
|
397
|
+
meta,
|
|
398
|
+
swapMode = 'swap',
|
|
399
|
+
} = params;
|
|
400
|
+
const simulationResult = bestRoute.result;
|
|
401
|
+
if (!simulationResult) {
|
|
402
|
+
throw Error('Simulation result should not be null');
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
creationTime: new Date().getTime().toString(),
|
|
407
|
+
finishTime: null,
|
|
408
|
+
requestId: bestRoute.requestId || '',
|
|
409
|
+
inputAmount: inputAmount,
|
|
410
|
+
wallets,
|
|
411
|
+
status: 'running',
|
|
412
|
+
mode: swapMode,
|
|
413
|
+
isPaused: false,
|
|
414
|
+
extraMessage: null,
|
|
415
|
+
extraMessageSeverity: null,
|
|
416
|
+
extraMessageDetail: null,
|
|
417
|
+
extraMessageErrorCode: null,
|
|
418
|
+
networkStatusExtraMessage: null,
|
|
419
|
+
networkStatusExtraMessageDetail: null,
|
|
420
|
+
lastNotificationTime: null,
|
|
421
|
+
settings: settings,
|
|
422
|
+
simulationResult: simulationResult,
|
|
423
|
+
validateBalanceOrFee,
|
|
424
|
+
steps:
|
|
425
|
+
bestRoute.result?.swaps?.map((swap, index) => {
|
|
426
|
+
const stepRoute = mapSwapStepToPendingSwapStep(swap, meta);
|
|
427
|
+
return {
|
|
428
|
+
id: index + 1,
|
|
429
|
+
|
|
430
|
+
// route
|
|
431
|
+
...stepRoute,
|
|
432
|
+
internalSwaps:
|
|
433
|
+
swap?.internalSwaps?.map((internalSwap) => {
|
|
434
|
+
const stepRoute = mapSwapStepToPendingSwapStep(
|
|
435
|
+
internalSwap,
|
|
436
|
+
meta
|
|
437
|
+
);
|
|
438
|
+
return stepRoute;
|
|
439
|
+
}) || null,
|
|
440
|
+
|
|
441
|
+
// status, tracking
|
|
442
|
+
outputAmount: '',
|
|
443
|
+
status: 'created',
|
|
444
|
+
networkStatus: null,
|
|
445
|
+
startTransactionTime: new Date().getTime(),
|
|
446
|
+
externalTransactionId: null,
|
|
447
|
+
executedTransactionId: null,
|
|
448
|
+
executedTransactionTime: null,
|
|
449
|
+
explorerUrl: null,
|
|
450
|
+
diagnosisUrl: null,
|
|
451
|
+
trackingCode: null,
|
|
452
|
+
internalSteps: null,
|
|
453
|
+
|
|
454
|
+
// transactions
|
|
455
|
+
evmTransaction: null,
|
|
456
|
+
evmApprovalTransaction: null,
|
|
457
|
+
starknetTransaction: null,
|
|
458
|
+
starknetApprovalTransaction: null,
|
|
459
|
+
tronTransaction: null,
|
|
460
|
+
tronApprovalTransaction: null,
|
|
461
|
+
cosmosTransaction: null,
|
|
462
|
+
solanaTransaction: null,
|
|
463
|
+
transferTransaction: null,
|
|
464
|
+
tonTransaction: null,
|
|
465
|
+
suiTransaction: null,
|
|
466
|
+
xrplTransaction: null,
|
|
467
|
+
|
|
468
|
+
// front fields
|
|
469
|
+
hasAlreadyProceededToSign: false,
|
|
470
|
+
};
|
|
471
|
+
}) || [],
|
|
472
|
+
};
|
|
473
|
+
}
|