@reown/appkit-core-react-native 1.1.1 → 1.2.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.
Files changed (110) hide show
  1. package/lib/commonjs/controllers/ApiController.js +1 -1
  2. package/lib/commonjs/controllers/BlockchainApiController.js +107 -21
  3. package/lib/commonjs/controllers/BlockchainApiController.js.map +1 -1
  4. package/lib/commonjs/controllers/ConnectionController.js +4 -2
  5. package/lib/commonjs/controllers/ConnectionController.js.map +1 -1
  6. package/lib/commonjs/controllers/NetworkController.js +6 -0
  7. package/lib/commonjs/controllers/NetworkController.js.map +1 -1
  8. package/lib/commonjs/controllers/RouterController.js.map +1 -1
  9. package/lib/commonjs/controllers/SnackController.js +5 -0
  10. package/lib/commonjs/controllers/SnackController.js.map +1 -1
  11. package/lib/commonjs/controllers/SwapController.js +578 -6
  12. package/lib/commonjs/controllers/SwapController.js.map +1 -1
  13. package/lib/commonjs/controllers/ThemeController.js +1 -1
  14. package/lib/commonjs/controllers/ThemeController.js.map +1 -1
  15. package/lib/commonjs/index.js +14 -0
  16. package/lib/commonjs/index.js.map +1 -1
  17. package/lib/commonjs/utils/ConnectionUtil.js +33 -0
  18. package/lib/commonjs/utils/ConnectionUtil.js.map +1 -0
  19. package/lib/commonjs/utils/ConstantsUtil.js +29 -0
  20. package/lib/commonjs/utils/ConstantsUtil.js.map +1 -1
  21. package/lib/commonjs/utils/CoreHelperUtil.js +12 -12
  22. package/lib/commonjs/utils/CoreHelperUtil.js.map +1 -1
  23. package/lib/commonjs/utils/NetworkUtil.js +46 -0
  24. package/lib/commonjs/utils/NetworkUtil.js.map +1 -0
  25. package/lib/commonjs/utils/RouterUtil.js +1 -1
  26. package/lib/commonjs/utils/RouterUtil.js.map +1 -1
  27. package/lib/commonjs/utils/SwapApiUtil.js +58 -0
  28. package/lib/commonjs/utils/SwapApiUtil.js.map +1 -1
  29. package/lib/commonjs/utils/SwapCalculationUtil.js +73 -0
  30. package/lib/commonjs/utils/SwapCalculationUtil.js.map +1 -1
  31. package/lib/module/controllers/ApiController.js +1 -1
  32. package/lib/module/controllers/BlockchainApiController.js +107 -21
  33. package/lib/module/controllers/BlockchainApiController.js.map +1 -1
  34. package/lib/module/controllers/ConnectionController.js +4 -2
  35. package/lib/module/controllers/ConnectionController.js.map +1 -1
  36. package/lib/module/controllers/NetworkController.js +6 -0
  37. package/lib/module/controllers/NetworkController.js.map +1 -1
  38. package/lib/module/controllers/RouterController.js.map +1 -1
  39. package/lib/module/controllers/SnackController.js +5 -0
  40. package/lib/module/controllers/SnackController.js.map +1 -1
  41. package/lib/module/controllers/SwapController.js +578 -6
  42. package/lib/module/controllers/SwapController.js.map +1 -1
  43. package/lib/module/controllers/ThemeController.js +1 -1
  44. package/lib/module/controllers/ThemeController.js.map +1 -1
  45. package/lib/module/index.js +2 -0
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/utils/ConnectionUtil.js +27 -0
  48. package/lib/module/utils/ConnectionUtil.js.map +1 -0
  49. package/lib/module/utils/ConstantsUtil.js +29 -0
  50. package/lib/module/utils/ConstantsUtil.js.map +1 -1
  51. package/lib/module/utils/CoreHelperUtil.js +12 -12
  52. package/lib/module/utils/CoreHelperUtil.js.map +1 -1
  53. package/lib/module/utils/NetworkUtil.js +40 -0
  54. package/lib/module/utils/NetworkUtil.js.map +1 -0
  55. package/lib/module/utils/RouterUtil.js +1 -1
  56. package/lib/module/utils/RouterUtil.js.map +1 -1
  57. package/lib/module/utils/SwapApiUtil.js +58 -0
  58. package/lib/module/utils/SwapApiUtil.js.map +1 -1
  59. package/lib/module/utils/SwapCalculationUtil.js +73 -1
  60. package/lib/module/utils/SwapCalculationUtil.js.map +1 -1
  61. package/lib/typescript/controllers/ApiController.d.ts +1 -1
  62. package/lib/typescript/controllers/BlockchainApiController.d.ts +6 -1
  63. package/lib/typescript/controllers/BlockchainApiController.d.ts.map +1 -1
  64. package/lib/typescript/controllers/ConnectionController.d.ts +3 -1
  65. package/lib/typescript/controllers/ConnectionController.d.ts.map +1 -1
  66. package/lib/typescript/controllers/NetworkController.d.ts +1 -0
  67. package/lib/typescript/controllers/NetworkController.d.ts.map +1 -1
  68. package/lib/typescript/controllers/RouterController.d.ts +3 -2
  69. package/lib/typescript/controllers/RouterController.d.ts.map +1 -1
  70. package/lib/typescript/controllers/SnackController.d.ts +2 -1
  71. package/lib/typescript/controllers/SnackController.d.ts.map +1 -1
  72. package/lib/typescript/controllers/SwapController.d.ts +87 -0
  73. package/lib/typescript/controllers/SwapController.d.ts.map +1 -1
  74. package/lib/typescript/controllers/ThemeController.d.ts +2 -2
  75. package/lib/typescript/controllers/ThemeController.d.ts.map +1 -1
  76. package/lib/typescript/index.d.ts +2 -0
  77. package/lib/typescript/index.d.ts.map +1 -1
  78. package/lib/typescript/utils/ConnectionUtil.d.ts +4 -0
  79. package/lib/typescript/utils/ConnectionUtil.d.ts.map +1 -0
  80. package/lib/typescript/utils/ConstantsUtil.d.ts +4 -0
  81. package/lib/typescript/utils/ConstantsUtil.d.ts.map +1 -1
  82. package/lib/typescript/utils/CoreHelperUtil.d.ts +2 -2
  83. package/lib/typescript/utils/CoreHelperUtil.d.ts.map +1 -1
  84. package/lib/typescript/utils/NetworkUtil.d.ts +8 -0
  85. package/lib/typescript/utils/NetworkUtil.d.ts.map +1 -0
  86. package/lib/typescript/utils/RouterUtil.d.ts.map +1 -1
  87. package/lib/typescript/utils/SwapApiUtil.d.ts +8 -0
  88. package/lib/typescript/utils/SwapApiUtil.d.ts.map +1 -1
  89. package/lib/typescript/utils/SwapCalculationUtil.d.ts +19 -0
  90. package/lib/typescript/utils/SwapCalculationUtil.d.ts.map +1 -1
  91. package/lib/typescript/utils/TypeUtil.d.ts +146 -6
  92. package/lib/typescript/utils/TypeUtil.d.ts.map +1 -1
  93. package/package.json +2 -2
  94. package/src/controllers/ApiController.ts +1 -1
  95. package/src/controllers/BlockchainApiController.ts +114 -17
  96. package/src/controllers/ConnectionController.ts +6 -2
  97. package/src/controllers/NetworkController.ts +8 -0
  98. package/src/controllers/RouterController.ts +6 -1
  99. package/src/controllers/SnackController.ts +7 -1
  100. package/src/controllers/SwapController.ts +759 -6
  101. package/src/controllers/ThemeController.ts +3 -3
  102. package/src/index.ts +2 -0
  103. package/src/utils/ConnectionUtil.ts +27 -0
  104. package/src/utils/ConstantsUtil.ts +120 -0
  105. package/src/utils/CoreHelperUtil.ts +20 -15
  106. package/src/utils/NetworkUtil.ts +33 -0
  107. package/src/utils/RouterUtil.ts +4 -1
  108. package/src/utils/SwapApiUtil.ts +89 -0
  109. package/src/utils/SwapCalculationUtil.ts +125 -0
  110. package/src/utils/TypeUtil.ts +169 -10
@@ -6,28 +6,76 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.TO_AMOUNT_DECIMALS = exports.SwapController = exports.INITIAL_GAS_LIMIT = void 0;
7
7
  var _utils = require("valtio/utils");
8
8
  var _valtio = require("valtio");
9
+ var _appkitCommonReactNative = require("@reown/appkit-common-react-native");
9
10
  var _ConstantsUtil = require("../utils/ConstantsUtil");
10
11
  var _SwapApiUtil = require("../utils/SwapApiUtil");
11
12
  var _NetworkController = require("./NetworkController");
12
13
  var _BlockchainApiController = require("./BlockchainApiController");
13
14
  var _OptionsController = require("./OptionsController");
14
15
  var _SwapCalculationUtil = require("../utils/SwapCalculationUtil");
16
+ var _SnackController = require("./SnackController");
17
+ var _RouterController = require("./RouterController");
18
+ var _ConnectorController = require("./ConnectorController");
19
+ var _AccountController = require("./AccountController");
20
+ var _CoreHelperUtil = require("../utils/CoreHelperUtil");
21
+ var _ConnectionController = require("./ConnectionController");
22
+ var _TransactionsController = require("./TransactionsController");
23
+ var _EventsController = require("./EventsController");
15
24
  // -- Constants ---------------------------------------- //
16
25
  const INITIAL_GAS_LIMIT = exports.INITIAL_GAS_LIMIT = 150000;
17
26
  const TO_AMOUNT_DECIMALS = exports.TO_AMOUNT_DECIMALS = 6;
18
27
 
19
28
  // -- Types --------------------------------------------- //
20
29
 
30
+ class TransactionError extends Error {
31
+ constructor(message, shortMessage) {
32
+ super(message);
33
+ this.name = 'TransactionError';
34
+ this.shortMessage = shortMessage;
35
+ }
36
+ }
21
37
  // -- State --------------------------------------------- //
22
38
  const initialState = {
39
+ // Loading states
40
+ initializing: false,
41
+ initialized: false,
42
+ loadingPrices: false,
43
+ loadingQuote: false,
44
+ loadingApprovalTransaction: false,
45
+ loadingBuildTransaction: false,
46
+ loadingTransaction: false,
47
+ // Error states
48
+ fetchError: false,
49
+ // Approval & Swap transaction states
50
+ approvalTransaction: undefined,
51
+ swapTransaction: undefined,
52
+ transactionError: undefined,
23
53
  // Input values
54
+ sourceToken: undefined,
55
+ sourceTokenAmount: '',
56
+ sourceTokenPriceInUSD: 0,
57
+ toToken: undefined,
58
+ toTokenAmount: '',
59
+ toTokenPriceInUSD: 0,
24
60
  networkPrice: '0',
61
+ networkBalanceInUSD: '0',
25
62
  networkTokenSymbol: '',
63
+ inputError: undefined,
64
+ // Request values
65
+ slippage: _ConstantsUtil.ConstantsUtil.CONVERT_SLIPPAGE_TOLERANCE,
26
66
  // Tokens
67
+ tokens: undefined,
68
+ popularTokens: undefined,
69
+ suggestedTokens: undefined,
70
+ foundTokens: undefined,
71
+ myTokensWithBalance: undefined,
27
72
  tokensPriceMap: {},
28
73
  // Calculations
29
74
  gasFee: '0',
30
- gasPriceInUSD: 0
75
+ gasPriceInUSD: 0,
76
+ priceImpact: undefined,
77
+ maxSlippage: undefined,
78
+ providerFee: undefined
31
79
  };
32
80
  const state = (0, _valtio.proxy)(initialState);
33
81
 
@@ -41,18 +89,164 @@ const SwapController = exports.SwapController = {
41
89
  return (0, _utils.subscribeKey)(state, key, callback);
42
90
  },
43
91
  getParams() {
44
- const caipNetwork = _NetworkController.NetworkController.state.caipNetwork;
45
- const networkAddress = `${caipNetwork?.id}:${_ConstantsUtil.ConstantsUtil.NATIVE_TOKEN_ADDRESS}`;
92
+ const caipAddress = _AccountController.AccountController.state.caipAddress;
93
+ const address = _CoreHelperUtil.CoreHelperUtil.getPlainAddress(caipAddress);
94
+ const networkAddress = _NetworkController.NetworkController.getActiveNetworkTokenAddress();
95
+ const type = _ConnectorController.ConnectorController.state.connectedConnector;
96
+ if (!address) {
97
+ throw new Error('No address found to swap the tokens from.');
98
+ }
99
+ const invalidToToken = !state.toToken?.address || !state.toToken?.decimals;
100
+ const invalidSourceToken = !state.sourceToken?.address || !state.sourceToken?.decimals || state.sourceToken.address === state.toToken?.address || !_appkitCommonReactNative.NumberUtil.bigNumber(state.sourceTokenAmount).isGreaterThan(0);
101
+ const invalidSourceTokenAmount = !state.sourceTokenAmount;
46
102
  return {
47
- networkAddress
103
+ networkAddress,
104
+ fromAddress: address,
105
+ fromCaipAddress: caipAddress,
106
+ sourceTokenAddress: state.sourceToken?.address,
107
+ toTokenAddress: state.toToken?.address,
108
+ toTokenAmount: state.toTokenAmount,
109
+ toTokenDecimals: state.toToken?.decimals,
110
+ sourceTokenAmount: state.sourceTokenAmount,
111
+ sourceTokenDecimals: state.sourceToken?.decimals,
112
+ invalidToToken,
113
+ invalidSourceToken,
114
+ invalidSourceTokenAmount,
115
+ availableToSwap: caipAddress && !invalidToToken && !invalidSourceToken && !invalidSourceTokenAmount,
116
+ isAuthConnector: type === 'AUTH'
48
117
  };
49
118
  },
119
+ switchTokens() {
120
+ if (state.initializing || !state.initialized) {
121
+ return;
122
+ }
123
+ let newSourceToken = state.toToken ? {
124
+ ...state.toToken
125
+ } : undefined;
126
+ const sourceTokenWithBalance = state.myTokensWithBalance?.find(token => token.address === newSourceToken?.address);
127
+ if (sourceTokenWithBalance) {
128
+ newSourceToken = sourceTokenWithBalance;
129
+ }
130
+ const newToToken = state.sourceToken ? {
131
+ ...state.sourceToken
132
+ } : undefined;
133
+ const newSourceTokenAmount = newSourceToken && state.toTokenAmount === '' ? '1' : state.toTokenAmount;
134
+ this.setSourceToken(newSourceToken);
135
+ this.setToToken(newToToken);
136
+ this.setSourceTokenAmount(newSourceTokenAmount);
137
+ this.setToTokenAmount('');
138
+ this.swapTokens();
139
+ },
50
140
  resetState() {
141
+ state.myTokensWithBalance = initialState.myTokensWithBalance;
51
142
  state.tokensPriceMap = initialState.tokensPriceMap;
143
+ state.initialized = initialState.initialized;
144
+ state.sourceToken = initialState.sourceToken;
145
+ state.sourceTokenAmount = initialState.sourceTokenAmount;
146
+ state.sourceTokenPriceInUSD = initialState.sourceTokenPriceInUSD;
147
+ state.toToken = initialState.toToken;
148
+ state.toTokenAmount = initialState.toTokenAmount;
149
+ state.toTokenPriceInUSD = initialState.toTokenPriceInUSD;
52
150
  state.networkPrice = initialState.networkPrice;
53
151
  state.networkTokenSymbol = initialState.networkTokenSymbol;
152
+ state.networkBalanceInUSD = initialState.networkBalanceInUSD;
153
+ state.inputError = initialState.inputError;
154
+ },
155
+ async fetchTokens() {
156
+ const {
157
+ networkAddress
158
+ } = this.getParams();
159
+ await this.getTokenList();
160
+ await this.getNetworkTokenPrice();
161
+ await this.getMyTokensWithBalance();
162
+ const networkToken = state.tokens?.find(token => token.address === networkAddress);
163
+ if (networkToken) {
164
+ state.networkTokenSymbol = networkToken.symbol;
165
+ }
166
+ const sourceToken = state.myTokensWithBalance?.find(token => token.address.startsWith(networkAddress)) || state.myTokensWithBalance?.[0];
167
+ this.setSourceToken(sourceToken);
168
+ this.setSourceTokenAmount('1');
169
+ },
170
+ async getTokenList() {
171
+ const tokens = await _SwapApiUtil.SwapApiUtil.getTokenList();
172
+ state.tokens = tokens;
173
+ state.popularTokens = tokens.sort((aTokenInfo, bTokenInfo) => {
174
+ if (aTokenInfo.symbol < bTokenInfo.symbol) {
175
+ return -1;
176
+ }
177
+ if (aTokenInfo.symbol > bTokenInfo.symbol) {
178
+ return 1;
179
+ }
180
+ return 0;
181
+ });
182
+ state.suggestedTokens = tokens.filter(token => {
183
+ if (_ConstantsUtil.ConstantsUtil.SWAP_SUGGESTED_TOKENS.includes(token.symbol)) {
184
+ return true;
185
+ }
186
+ return false;
187
+ }, {});
188
+ },
189
+ async getMyTokensWithBalance(forceUpdate) {
190
+ const balances = await _SwapApiUtil.SwapApiUtil.getMyTokensWithBalance(forceUpdate);
191
+ if (!balances) {
192
+ return;
193
+ }
194
+ await this.getInitialGasPrice();
195
+ this.setBalances(balances);
196
+ },
197
+ getFilteredPopularTokens() {
198
+ return state.popularTokens?.filter(token => !state.myTokensWithBalance?.some(t => t.address === token.address));
199
+ },
200
+ setSourceToken(sourceToken) {
201
+ if (!sourceToken) {
202
+ state.sourceToken = sourceToken;
203
+ state.sourceTokenAmount = '';
204
+ state.sourceTokenPriceInUSD = 0;
205
+ return;
206
+ }
207
+ state.sourceToken = sourceToken;
208
+ this.setTokenPrice(sourceToken.address, 'sourceToken');
209
+ },
210
+ setSourceTokenAmount(amount) {
211
+ state.sourceTokenAmount = amount;
212
+ if (amount === '') {
213
+ state.toTokenAmount = '';
214
+ }
215
+ },
216
+ async initializeState() {
217
+ if (state.initializing) {
218
+ return;
219
+ }
220
+ state.initializing = true;
221
+ if (!state.initialized) {
222
+ try {
223
+ await this.fetchTokens();
224
+ state.initialized = true;
225
+ } catch (error) {
226
+ state.initialized = false;
227
+ _SnackController.SnackController.showError('Failed to initialize swap');
228
+ _RouterController.RouterController.goBack();
229
+ }
230
+ }
231
+ state.initializing = false;
232
+ },
233
+ async getAddressPrice(address) {
234
+ const existPrice = state.tokensPriceMap[address];
235
+ if (existPrice) {
236
+ return existPrice;
237
+ }
238
+ const response = await _BlockchainApiController.BlockchainApiController.fetchTokenPrice({
239
+ projectId: _OptionsController.OptionsController.state.projectId,
240
+ addresses: [address]
241
+ });
242
+ const fungibles = response?.fungibles || [];
243
+ const allTokens = [...(state.tokens || []), ...(state.myTokensWithBalance || [])];
244
+ const symbol = allTokens?.find(token => token.address === address)?.symbol;
245
+ const price = fungibles.find(p => p.symbol.toLowerCase() === symbol?.toLowerCase())?.price || 0;
246
+ const priceAsFloat = parseFloat(price.toString());
247
+ state.tokensPriceMap[address] = priceAsFloat;
248
+ return priceAsFloat;
54
249
  },
55
- //this
56
250
  async getNetworkTokenPrice() {
57
251
  const {
58
252
  networkAddress
@@ -67,7 +261,6 @@ const SwapController = exports.SwapController = {
67
261
  state.networkTokenSymbol = token?.symbol || '';
68
262
  state.networkPrice = price;
69
263
  },
70
- //this
71
264
  async getInitialGasPrice() {
72
265
  const res = await _SwapApiUtil.SwapApiUtil.fetchGasPrice();
73
266
  if (!res) {
@@ -86,6 +279,385 @@ const SwapController = exports.SwapController = {
86
279
  gasPrice: gasFee,
87
280
  gasPriceInUSD: state.gasPriceInUSD
88
281
  };
282
+ },
283
+ getProviderFeePrice() {
284
+ return _SwapCalculationUtil.SwapCalculationUtil.getProviderFeePrice(state.sourceTokenAmount, state.sourceTokenPriceInUSD);
285
+ },
286
+ setBalances(balances) {
287
+ const {
288
+ networkAddress
289
+ } = this.getParams();
290
+ const caipNetwork = _NetworkController.NetworkController.state.caipNetwork;
291
+ if (!caipNetwork) {
292
+ return;
293
+ }
294
+ const networkToken = balances.find(token => token.address === networkAddress);
295
+ balances.forEach(token => {
296
+ state.tokensPriceMap[token.address] = token.price || 0;
297
+ });
298
+ state.myTokensWithBalance = balances.filter(token => token.address?.startsWith(caipNetwork.id));
299
+ state.networkBalanceInUSD = networkToken ? _appkitCommonReactNative.NumberUtil.multiply(networkToken.quantity.numeric, networkToken.price).toString() : '0';
300
+ },
301
+ setToToken(toToken) {
302
+ if (!toToken) {
303
+ state.toToken = toToken;
304
+ state.toTokenAmount = '';
305
+ state.toTokenPriceInUSD = 0;
306
+ return;
307
+ }
308
+ state.toToken = toToken;
309
+ this.setTokenPrice(toToken.address, 'toToken');
310
+ },
311
+ setToTokenAmount(amount) {
312
+ state.toTokenAmount = amount ? _appkitCommonReactNative.NumberUtil.formatNumberToLocalString(amount, TO_AMOUNT_DECIMALS) : '';
313
+ },
314
+ async setTokenPrice(address, target) {
315
+ let price = state.tokensPriceMap[address] || 0;
316
+ if (!price) {
317
+ state.loadingPrices = true;
318
+ price = await this.getAddressPrice(address);
319
+ }
320
+ if (target === 'sourceToken') {
321
+ state.sourceTokenPriceInUSD = price;
322
+ } else if (target === 'toToken') {
323
+ state.toTokenPriceInUSD = price;
324
+ }
325
+ if (state.loadingPrices) {
326
+ state.loadingPrices = false;
327
+ }
328
+ if (this.getParams().availableToSwap) {
329
+ this.swapTokens();
330
+ }
331
+ },
332
+ // -- Swap ---------------------------------------------- //
333
+ async swapTokens() {
334
+ const address = _AccountController.AccountController.state.address;
335
+ const sourceToken = state.sourceToken;
336
+ const toToken = state.toToken;
337
+ const haveSourceTokenAmount = _appkitCommonReactNative.NumberUtil.bigNumber(state.sourceTokenAmount).isGreaterThan(0);
338
+ if (!toToken || !sourceToken || state.loadingPrices || !haveSourceTokenAmount) {
339
+ return;
340
+ }
341
+ state.loadingQuote = true;
342
+ const amountDecimal = _appkitCommonReactNative.NumberUtil.bigNumber(state.sourceTokenAmount).multipliedBy(10 ** sourceToken.decimals).integerValue();
343
+ const quoteResponse = await _BlockchainApiController.BlockchainApiController.fetchSwapQuote({
344
+ userAddress: address,
345
+ projectId: _OptionsController.OptionsController.state.projectId,
346
+ from: sourceToken.address,
347
+ to: toToken.address,
348
+ gasPrice: state.gasFee,
349
+ amount: amountDecimal.toString()
350
+ });
351
+ state.loadingQuote = false;
352
+ const quoteToAmount = quoteResponse?.quotes?.[0]?.toAmount;
353
+ if (!quoteToAmount) {
354
+ return;
355
+ }
356
+ const toTokenAmount = _appkitCommonReactNative.NumberUtil.bigNumber(quoteToAmount).dividedBy(10 ** toToken.decimals).toString();
357
+ this.setToTokenAmount(toTokenAmount);
358
+ const isInsufficientToken = this.hasInsufficientToken(state.sourceTokenAmount, sourceToken.address);
359
+ if (isInsufficientToken) {
360
+ state.inputError = 'Insufficient balance';
361
+ } else {
362
+ state.inputError = undefined;
363
+ this.setTransactionDetails();
364
+ }
365
+ },
366
+ // -- Create Transactions -------------------------------------- //
367
+ async getTransaction() {
368
+ const {
369
+ fromCaipAddress,
370
+ availableToSwap
371
+ } = this.getParams();
372
+ const sourceToken = state.sourceToken;
373
+ const toToken = state.toToken;
374
+ if (!fromCaipAddress || !availableToSwap || !sourceToken || !toToken || state.loadingQuote) {
375
+ return undefined;
376
+ }
377
+ try {
378
+ state.loadingBuildTransaction = true;
379
+ const hasAllowance = await _SwapApiUtil.SwapApiUtil.fetchSwapAllowance({
380
+ userAddress: fromCaipAddress,
381
+ tokenAddress: sourceToken.address,
382
+ sourceTokenAmount: state.sourceTokenAmount,
383
+ sourceTokenDecimals: sourceToken.decimals
384
+ });
385
+ let transaction;
386
+ if (hasAllowance) {
387
+ transaction = await this.createSwapTransaction();
388
+ } else {
389
+ transaction = await this.createAllowanceTransaction();
390
+ }
391
+ state.loadingBuildTransaction = false;
392
+ state.fetchError = false;
393
+ return transaction;
394
+ } catch (error) {
395
+ _RouterController.RouterController.goBack();
396
+ _SnackController.SnackController.showError('Failed to check allowance');
397
+ state.loadingBuildTransaction = false;
398
+ state.approvalTransaction = undefined;
399
+ state.swapTransaction = undefined;
400
+ state.fetchError = true;
401
+ return undefined;
402
+ }
403
+ },
404
+ async createAllowanceTransaction() {
405
+ const {
406
+ fromCaipAddress,
407
+ fromAddress,
408
+ sourceTokenAddress,
409
+ toTokenAddress
410
+ } = this.getParams();
411
+ if (!fromCaipAddress || !toTokenAddress) {
412
+ return undefined;
413
+ }
414
+ if (!sourceTokenAddress) {
415
+ throw new Error('createAllowanceTransaction - No source token address found.');
416
+ }
417
+ try {
418
+ const response = await _BlockchainApiController.BlockchainApiController.generateApproveCalldata({
419
+ projectId: _OptionsController.OptionsController.state.projectId,
420
+ from: sourceTokenAddress,
421
+ to: toTokenAddress,
422
+ userAddress: fromCaipAddress
423
+ });
424
+ if (!response) {
425
+ throw new Error('createAllowanceTransaction - No response from generateApproveCalldata');
426
+ }
427
+ const gasLimit = await _ConnectionController.ConnectionController.estimateGas({
428
+ address: fromAddress,
429
+ to: _CoreHelperUtil.CoreHelperUtil.getPlainAddress(response.tx.to),
430
+ data: response.tx.data
431
+ });
432
+ const transaction = {
433
+ data: response.tx.data,
434
+ to: _CoreHelperUtil.CoreHelperUtil.getPlainAddress(response.tx.from),
435
+ gas: gasLimit,
436
+ gasPrice: BigInt(response.tx.eip155.gasPrice),
437
+ value: BigInt(response.tx.value),
438
+ toAmount: state.toTokenAmount
439
+ };
440
+ state.swapTransaction = undefined;
441
+ state.approvalTransaction = {
442
+ data: transaction.data,
443
+ to: transaction.to,
444
+ gas: transaction.gas ?? BigInt(0),
445
+ gasPrice: transaction.gasPrice,
446
+ value: transaction.value,
447
+ toAmount: transaction.toAmount
448
+ };
449
+ return {
450
+ data: transaction.data,
451
+ to: transaction.to,
452
+ gas: transaction.gas ?? BigInt(0),
453
+ gasPrice: transaction.gasPrice,
454
+ value: transaction.value,
455
+ toAmount: transaction.toAmount
456
+ };
457
+ } catch (error) {
458
+ _RouterController.RouterController.goBack();
459
+ _SnackController.SnackController.showError('Failed to create approval transaction');
460
+ state.approvalTransaction = undefined;
461
+ state.swapTransaction = undefined;
462
+ state.fetchError = true;
463
+ return undefined;
464
+ }
465
+ },
466
+ async createSwapTransaction() {
467
+ const {
468
+ networkAddress,
469
+ fromCaipAddress,
470
+ sourceTokenAmount
471
+ } = this.getParams();
472
+ const sourceToken = state.sourceToken;
473
+ const toToken = state.toToken;
474
+ if (!fromCaipAddress || !sourceTokenAmount || !sourceToken || !toToken) {
475
+ return undefined;
476
+ }
477
+ const amount = _ConnectionController.ConnectionController.parseUnits(sourceTokenAmount, sourceToken.decimals)?.toString();
478
+ try {
479
+ const response = await _BlockchainApiController.BlockchainApiController.generateSwapCalldata({
480
+ projectId: _OptionsController.OptionsController.state.projectId,
481
+ userAddress: fromCaipAddress,
482
+ from: sourceToken.address,
483
+ to: toToken.address,
484
+ amount: amount
485
+ });
486
+ if (!response) {
487
+ throw new Error('createSwapTransaction - No response from generateSwapCalldata');
488
+ }
489
+ const isSourceNetworkToken = sourceToken.address === networkAddress;
490
+ const gas = BigInt(response.tx.eip155.gas);
491
+ const gasPrice = BigInt(response.tx.eip155.gasPrice);
492
+ const transaction = {
493
+ data: response.tx.data,
494
+ to: _CoreHelperUtil.CoreHelperUtil.getPlainAddress(response.tx.to),
495
+ gas,
496
+ gasPrice,
497
+ value: isSourceNetworkToken ? BigInt(amount ?? '0') : BigInt('0'),
498
+ toAmount: state.toTokenAmount
499
+ };
500
+ state.gasPriceInUSD = _SwapCalculationUtil.SwapCalculationUtil.getGasPriceInUSD(state.networkPrice, gas, gasPrice);
501
+ state.approvalTransaction = undefined;
502
+ state.swapTransaction = transaction;
503
+ return transaction;
504
+ } catch (error) {
505
+ _RouterController.RouterController.goBack();
506
+ _SnackController.SnackController.showError('Failed to create transaction');
507
+ state.approvalTransaction = undefined;
508
+ state.swapTransaction = undefined;
509
+ state.fetchError = true;
510
+ return undefined;
511
+ }
512
+ },
513
+ async sendTransactionForApproval(data) {
514
+ const {
515
+ fromAddress,
516
+ isAuthConnector
517
+ } = this.getParams();
518
+ state.loadingApprovalTransaction = true;
519
+ const approveLimitMessage = `Approve limit increase in your wallet`;
520
+ if (isAuthConnector) {
521
+ _RouterController.RouterController.pushTransactionStack({
522
+ view: null,
523
+ goBack: true,
524
+ onSuccess() {
525
+ _SnackController.SnackController.showLoading(approveLimitMessage);
526
+ }
527
+ });
528
+ } else {
529
+ _SnackController.SnackController.showLoading(approveLimitMessage);
530
+ }
531
+ try {
532
+ await _ConnectionController.ConnectionController.sendTransaction({
533
+ address: fromAddress,
534
+ to: data.to,
535
+ data: data.data,
536
+ value: BigInt(data.value),
537
+ gasPrice: BigInt(data.gasPrice),
538
+ chainNamespace: 'eip155'
539
+ });
540
+ await this.swapTokens();
541
+ await this.getTransaction();
542
+ state.approvalTransaction = undefined;
543
+ state.loadingApprovalTransaction = false;
544
+ } catch (err) {
545
+ const error = err;
546
+ state.transactionError = error?.shortMessage;
547
+ state.loadingApprovalTransaction = false;
548
+ _SnackController.SnackController.showError(error?.shortMessage ?? 'Transaction error');
549
+ }
550
+ },
551
+ async sendTransactionForSwap(data) {
552
+ if (!data) {
553
+ return undefined;
554
+ }
555
+ const {
556
+ fromAddress,
557
+ toTokenAmount,
558
+ isAuthConnector
559
+ } = this.getParams();
560
+ state.loadingTransaction = true;
561
+ const snackbarPendingMessage = `Swapping ${state.sourceToken?.symbol} to ${_appkitCommonReactNative.NumberUtil.formatNumberToLocalString(toTokenAmount, 3)} ${state.toToken?.symbol}`;
562
+ const snackbarSuccessMessage = `Swapped ${state.sourceToken?.symbol} to ${_appkitCommonReactNative.NumberUtil.formatNumberToLocalString(toTokenAmount, 3)} ${state.toToken?.symbol}`;
563
+ if (isAuthConnector) {
564
+ _RouterController.RouterController.pushTransactionStack({
565
+ view: 'Account',
566
+ goBack: false,
567
+ onSuccess() {
568
+ _SnackController.SnackController.showLoading(snackbarPendingMessage);
569
+ SwapController.resetState();
570
+ }
571
+ });
572
+ } else {
573
+ _SnackController.SnackController.showLoading('Confirm transaction in your wallet');
574
+ }
575
+ try {
576
+ const forceUpdateAddresses = [state.sourceToken?.address, state.toToken?.address].join(',');
577
+ const transactionHash = await _ConnectionController.ConnectionController.sendTransaction({
578
+ address: fromAddress,
579
+ to: data.to,
580
+ data: data.data,
581
+ gas: data.gas,
582
+ gasPrice: BigInt(data.gasPrice),
583
+ value: data.value,
584
+ chainNamespace: 'eip155'
585
+ });
586
+ state.loadingTransaction = false;
587
+ _SnackController.SnackController.showSuccess(snackbarSuccessMessage);
588
+ _EventsController.EventsController.sendEvent({
589
+ type: 'track',
590
+ event: 'SWAP_SUCCESS',
591
+ properties: {
592
+ network: _NetworkController.NetworkController.state.caipNetwork?.id || '',
593
+ swapFromToken: this.state.sourceToken?.symbol || '',
594
+ swapToToken: this.state.toToken?.symbol || '',
595
+ swapFromAmount: this.state.sourceTokenAmount || '',
596
+ swapToAmount: this.state.toTokenAmount || '',
597
+ isSmartAccount: _AccountController.AccountController.state.preferredAccountType === 'smartAccount'
598
+ }
599
+ });
600
+ SwapController.resetState();
601
+ if (!isAuthConnector) {
602
+ _RouterController.RouterController.replace('AccountDefault');
603
+ }
604
+ SwapController.getMyTokensWithBalance(forceUpdateAddresses);
605
+ _AccountController.AccountController.fetchTokenBalance();
606
+ setTimeout(() => {
607
+ _TransactionsController.TransactionsController.fetchTransactions(_AccountController.AccountController.state.address, true);
608
+ }, 5000);
609
+ return transactionHash;
610
+ } catch (err) {
611
+ const error = err;
612
+ state.transactionError = error?.shortMessage;
613
+ state.loadingTransaction = false;
614
+ _SnackController.SnackController.showError(error?.shortMessage ?? 'Transaction error');
615
+ _EventsController.EventsController.sendEvent({
616
+ type: 'track',
617
+ event: 'SWAP_ERROR',
618
+ properties: {
619
+ message: error?.shortMessage ?? error?.message ?? 'Unknown',
620
+ network: _NetworkController.NetworkController.state.caipNetwork?.id || '',
621
+ swapFromToken: this.state.sourceToken?.symbol || '',
622
+ swapToToken: this.state.toToken?.symbol || '',
623
+ swapFromAmount: this.state.sourceTokenAmount || '',
624
+ swapToAmount: this.state.toTokenAmount || '',
625
+ isSmartAccount: _AccountController.AccountController.state.preferredAccountType === 'smartAccount'
626
+ }
627
+ });
628
+ return undefined;
629
+ }
630
+ },
631
+ // -- Checks -------------------------------------------- //
632
+ hasInsufficientToken(sourceTokenAmount, sourceTokenAddress) {
633
+ const isInsufficientSourceTokenForSwap = _SwapCalculationUtil.SwapCalculationUtil.isInsufficientSourceTokenForSwap(sourceTokenAmount, sourceTokenAddress, state.myTokensWithBalance);
634
+ let insufficientNetworkTokenForGas = true;
635
+ if (_AccountController.AccountController.state.preferredAccountType === 'smartAccount') {
636
+ // Smart Accounts may pay gas in any ERC20 token
637
+ insufficientNetworkTokenForGas = false;
638
+ } else {
639
+ insufficientNetworkTokenForGas = _SwapCalculationUtil.SwapCalculationUtil.isInsufficientNetworkTokenForGas(state.networkBalanceInUSD, state.gasPriceInUSD);
640
+ }
641
+ return insufficientNetworkTokenForGas || isInsufficientSourceTokenForSwap;
642
+ },
643
+ // -- Calculations -------------------------------------- //
644
+ setTransactionDetails() {
645
+ const {
646
+ toTokenAddress,
647
+ toTokenDecimals
648
+ } = this.getParams();
649
+ if (!toTokenAddress || !toTokenDecimals) {
650
+ return;
651
+ }
652
+ state.gasPriceInUSD = _SwapCalculationUtil.SwapCalculationUtil.getGasPriceInUSD(state.networkPrice, BigInt(state.gasFee), BigInt(INITIAL_GAS_LIMIT));
653
+ state.priceImpact = _SwapCalculationUtil.SwapCalculationUtil.getPriceImpact({
654
+ sourceTokenAmount: state.sourceTokenAmount,
655
+ sourceTokenPriceInUSD: state.sourceTokenPriceInUSD,
656
+ toTokenPriceInUSD: state.toTokenPriceInUSD,
657
+ toTokenAmount: state.toTokenAmount
658
+ });
659
+ state.maxSlippage = _SwapCalculationUtil.SwapCalculationUtil.getMaxSlippage(state.slippage, state.toTokenAmount);
660
+ state.providerFee = _SwapCalculationUtil.SwapCalculationUtil.getProviderFee(state.sourceTokenAmount);
89
661
  }
90
662
  };
91
663
  //# sourceMappingURL=SwapController.js.map