@reown/appkit-core-react-native 0.0.0-feat-smart-account-20241016183051 → 0.0.0-feat-swaps-20241129153709

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