@subwallet/extension-base 1.3.36-0 → 1.3.38-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 (40) hide show
  1. package/background/KoniTypes.d.ts +7 -0
  2. package/background/types.d.ts +2 -1
  3. package/cjs/core/logic-validation/request.js +62 -13
  4. package/cjs/koni/background/handlers/Extension.js +168 -108
  5. package/cjs/koni/background/handlers/State.js +18 -17
  6. package/cjs/koni/background/handlers/Tabs.js +38 -5
  7. package/cjs/packageInfo.js +1 -1
  8. package/cjs/page/cardano/cips/cip30.js +21 -1
  9. package/cjs/page/cardano/index.js +5 -5
  10. package/cjs/services/request-service/handler/AuthRequestHandler.js +4 -1
  11. package/cjs/services/request-service/handler/CardanoRequestHandler.js +4 -3
  12. package/cjs/services/request-service/helper/index.js +19 -17
  13. package/cjs/services/swap-service/handler/base-handler.js +4 -2
  14. package/cjs/services/swap-service/handler/uniswap-handler.js +122 -57
  15. package/cjs/services/swap-service/index.js +1 -1
  16. package/cjs/utils/cardano.js +10 -2
  17. package/core/logic-validation/request.d.ts +1 -0
  18. package/core/logic-validation/request.js +63 -15
  19. package/koni/background/handlers/Extension.d.ts +1 -0
  20. package/koni/background/handlers/Extension.js +61 -2
  21. package/koni/background/handlers/State.js +20 -19
  22. package/koni/background/handlers/Tabs.d.ts +1 -0
  23. package/koni/background/handlers/Tabs.js +38 -5
  24. package/package.json +11 -11
  25. package/packageInfo.js +1 -1
  26. package/page/cardano/cips/cip30.d.ts +31 -17
  27. package/page/cardano/cips/cip30.js +17 -1
  28. package/page/cardano/index.d.ts +20 -4
  29. package/page/cardano/index.js +5 -5
  30. package/services/chain-service/types.d.ts +1 -1
  31. package/services/request-service/handler/AuthRequestHandler.js +4 -1
  32. package/services/request-service/handler/CardanoRequestHandler.js +4 -3
  33. package/services/request-service/helper/index.js +19 -17
  34. package/services/swap-service/handler/base-handler.js +4 -2
  35. package/services/swap-service/handler/uniswap-handler.d.ts +1 -1
  36. package/services/swap-service/handler/uniswap-handler.js +99 -34
  37. package/services/swap-service/index.js +1 -1
  38. package/types/service-base.d.ts +1 -0
  39. package/utils/cardano.d.ts +2 -0
  40. package/utils/cardano.js +7 -0
@@ -7,6 +7,7 @@ import { validateTypedSignMessageDataV3V4 } from '@subwallet/extension-base/core
7
7
  import { estimateTxFee, getERC20Allowance, getERC20SpendingApprovalTx } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
8
8
  import { createAcrossBridgeExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
9
9
  import { getAcrossQuote } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
10
+ import { DEFAULT_EXCESS_AMOUNT_WEIGHT, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
10
11
  import { BasicTxErrorType, CommonStepType, DynamicSwapType, FeeOptionKey, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
11
12
  import { _reformatAddressWithChain } from '@subwallet/extension-base/utils';
12
13
  import { getId } from '@subwallet/extension-base/utils/getId';
@@ -94,7 +95,8 @@ export class UniswapHandler {
94
95
  const stepFuncList = [];
95
96
  /**
96
97
  * approve - permit - swap or
97
- * approve - permit - swap - approve - bridge
98
+ * approve - permit - swap - approve - bridge or
99
+ * approve - bridge - approve - permit - swap
98
100
  */
99
101
 
100
102
  params.path.forEach(step => {
@@ -111,11 +113,26 @@ export class UniswapHandler {
111
113
  return this.swapBaseHandler.generateOptimalProcessV2(params, stepFuncList);
112
114
  }
113
115
  async getApprovalStep(params, stepIndex) {
114
- if (stepIndex === 0) {
116
+ /**
117
+ * Explain: All processes will go through one of below processes. If a step do not have, it returns undefined and
118
+ * the stepIndex is still counted up
119
+ *
120
+ * Processes:
121
+ * approve - permit - swap or
122
+ * approve - permit - swap - approve - bridge or
123
+ * approve - bridge - approve - permit - swap
124
+ */
125
+ const actionList = JSON.stringify(params.path.map(step => step.action));
126
+ const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
127
+ const swapBridge = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
128
+ const bridgeSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
129
+ const isApproveBridge = stepIndex === 3 && swapBridge || stepIndex === 0 && bridgeSwap;
130
+ const isApproveSwap = stepIndex === 0 && swap || stepIndex === 0 && swapBridge || stepIndex === 2 && bridgeSwap;
131
+ if (isApproveSwap) {
115
132
  return this.getApproveSwap(params);
116
133
  }
117
- if (stepIndex === 3) {
118
- return this.getApproveBridge(params);
134
+ if (isApproveBridge) {
135
+ return this.getApproveBridge(params, bridgeSwap);
119
136
  }
120
137
  return Promise.resolve(undefined);
121
138
  }
@@ -196,20 +213,28 @@ export class UniswapHandler {
196
213
  };
197
214
  return Promise.resolve([submitStep, feeInfo]);
198
215
  }
199
- async getApproveBridge(params) {
200
- const quote = params.selectedQuote;
201
- if (!quote) {
216
+ async getApproveBridge(params, isBridgeFirst) {
217
+ const {
218
+ path,
219
+ request,
220
+ selectedQuote
221
+ } = params;
222
+ if (!selectedQuote) {
202
223
  return Promise.resolve(undefined);
203
224
  }
204
- console.log('params', params);
205
- const sendingAmount = quote.toAmount;
206
- const senderAddress = params.request.address;
207
- const fromTokenInfo = this.chainService.getAssetBySlug(quote.pair.to);
225
+ const bridgePairInfo = path.find(action => action.action === DynamicSwapType.BRIDGE);
226
+ if (!bridgePairInfo || !bridgePairInfo.pair) {
227
+ return Promise.resolve(undefined);
228
+ }
229
+ const _sendingAmount = isBridgeFirst ? request.fromAmount : selectedQuote.toAmount;
230
+ const sendingAmount = BigNumber(_sendingAmount).multipliedBy(2).toFixed(0, 1); // ensure approve enough amount
231
+ const senderAddress = request.address;
232
+ const fromTokenInfo = this.chainService.getAssetBySlug(bridgePairInfo.pair.from);
208
233
  const fromChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(fromTokenInfo));
209
234
  const fromChainId = _getEvmChainId(fromChainInfo);
210
235
  const evmApi = this.chainService.getEvmApi(fromChainInfo.slug);
211
236
  const tokenContract = _getContractAddressOfToken(fromTokenInfo);
212
- const toTokenInfo = this.chainService.getAssetBySlug(params.request.pair.to);
237
+ const toTokenInfo = this.chainService.getAssetBySlug(bridgePairInfo.pair.to);
213
238
  const toChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(toTokenInfo));
214
239
  if (_isNativeToken(fromTokenInfo)) {
215
240
  return Promise.resolve(undefined);
@@ -220,9 +245,10 @@ export class UniswapHandler {
220
245
  const inputData = {
221
246
  destinationTokenInfo: toTokenInfo,
222
247
  originTokenInfo: fromTokenInfo,
223
- sendingValue: sendingAmount,
248
+ sendingValue: _sendingAmount,
224
249
  sender: senderAddress,
225
250
  recipient: senderAddress,
251
+ // todo: there's a case swap - bridge to another address
226
252
  destinationChain: toChainInfo,
227
253
  originChain: fromChainInfo
228
254
  };
@@ -295,6 +321,10 @@ export class UniswapHandler {
295
321
  if (!selectedQuote) {
296
322
  return Promise.resolve(undefined);
297
323
  }
324
+ const actionList = JSON.stringify(path.map(step => step.action));
325
+ const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
326
+ const sendingValue = swapXcm ? BigNumber(request.fromAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT).toFixed(0, 1) : request.fromAmount;
327
+ const expectedReceive = swapXcm ? BigNumber(selectedQuote.toAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT).toFixed(0, 1) : selectedQuote.toAmount;
298
328
  const originTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
299
329
  const destinationTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.to);
300
330
  const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
@@ -304,8 +334,8 @@ export class UniswapHandler {
304
334
  type: SwapStepType.SWAP,
305
335
  // @ts-ignore
306
336
  metadata: {
307
- sendingValue: request.fromAmount.toString(),
308
- expectedReceive: selectedQuote.toAmount,
337
+ sendingValue,
338
+ expectedReceive,
309
339
  originTokenInfo,
310
340
  destinationTokenInfo,
311
341
  sender: _reformatAddressWithChain(request.address, originChain),
@@ -321,6 +351,20 @@ export class UniswapHandler {
321
351
  request,
322
352
  selectedQuote
323
353
  } = params;
354
+ /**
355
+ * Explain: All processes will go through one of below processes. If a step do not have, it returns undefined and
356
+ * the stepIndex is still counted up
357
+ *
358
+ * Processes:
359
+ * approve - permit - swap or
360
+ * approve - permit - swap - approve - bridge or
361
+ * approve - bridge - approve - permit - swap
362
+ */
363
+ const actionList = JSON.stringify(path.map(step => step.action));
364
+ const bridgeSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
365
+ const swapBridge = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
366
+ const isBridgeFirst = stepIndex === 1 && bridgeSwap;
367
+ const isBridgeSecond = stepIndex === 4 && swapBridge;
324
368
 
325
369
  // stepIndex is not corresponding index in path, because uniswap include approval and permit step
326
370
  const bridgePairInfo = path.find(action => action.action === DynamicSwapType.BRIDGE);
@@ -337,9 +381,18 @@ export class UniswapHandler {
337
381
  if (!fromChainInfo || !toChainInfo || !fromChainInfo || !toChainInfo) {
338
382
  throw Error('Token or chain not found');
339
383
  }
384
+ let receiverAddress;
385
+ let mockSendingValue;
340
386
  const senderAddress = _reformatAddressWithChain(request.address, fromChainInfo);
341
- const receiverAddress = _reformatAddressWithChain(request.recipient || request.address, toChainInfo);
342
- const sendingValue = BigNumber(selectedQuote.toAmount).div(1.02).toFixed(0, 1);
387
+ if (isBridgeFirst) {
388
+ receiverAddress = _reformatAddressWithChain(request.address, toChainInfo);
389
+ mockSendingValue = BigNumber(selectedQuote.fromAmount).toFixed(0, 1);
390
+ } else if (isBridgeSecond) {
391
+ receiverAddress = _reformatAddressWithChain(request.recipient || request.address, toChainInfo);
392
+ mockSendingValue = BigNumber(selectedQuote.toAmount).toFixed(0, 1);
393
+ } else {
394
+ return undefined;
395
+ }
343
396
  try {
344
397
  const evmApi = await this.chainService.getEvmApi(fromChainInfo.slug).isReady;
345
398
  const feeInfo = await this.feeService.subscribeChainFee(getId(), fromTokenInfo.originChain, 'evm');
@@ -351,25 +404,37 @@ export class UniswapHandler {
351
404
  evmApi,
352
405
  feeInfo,
353
406
  // Mock sending value to get payment info
354
- sendingValue,
407
+ sendingValue: mockSendingValue,
355
408
  sender: senderAddress,
356
409
  recipient: receiverAddress
357
410
  });
358
-
359
- // // todo: wait until this ready to get destination fee. the real receiveAmount is deduce by this fee
360
- // const acrossQuote = await getAcrossQuote({
361
- // destinationChain: toChainInfo,
362
- // destinationTokenInfo: toTokenInfo,
363
- // originChain: fromChainInfo,
364
- // originTokenInfo: fromTokenInfo,
365
- // recipient: receiverAddress,
366
- // sender: senderAddress,
367
- // sendingValue,
368
- // feeInfo
369
- // });
370
-
411
+ const acrossQuote = await getAcrossQuote({
412
+ destinationChain: toChainInfo,
413
+ destinationTokenInfo: toTokenInfo,
414
+ originChain: fromChainInfo,
415
+ originTokenInfo: fromTokenInfo,
416
+ recipient: receiverAddress,
417
+ sender: senderAddress,
418
+ sendingValue: mockSendingValue,
419
+ feeInfo
420
+ });
421
+ const acrossQuoteMetadata = acrossQuote.metadata;
371
422
  const estimatedBridgeFee = await estimateTxFee(tx, evmApi, feeInfo);
372
- const expectedReceive = BigNumber(sendingValue).minus(estimatedBridgeFee).toFixed(0, 1);
423
+ const estimatedDestinationFee = BigNumber(mockSendingValue).minus(acrossQuoteMetadata.outputAmount).toFixed(0, 1); // todo: should better handle on backend and return desFee metadata instead of minus like this
424
+
425
+ let sendingValue;
426
+ let expectedReceive;
427
+ if (isBridgeFirst) {
428
+ expectedReceive = selectedQuote.fromAmount;
429
+ sendingValue = BigNumber(estimatedDestinationFee).multipliedBy(FEE_RATE_MULTIPLIER.medium).plus(selectedQuote.fromAmount).toFixed(0, 1);
430
+ } else if (isBridgeSecond) {
431
+ expectedReceive = selectedQuote.toAmount;
432
+ sendingValue = BigNumber(selectedQuote.toAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT).toFixed(0, 1);
433
+ } else {
434
+ return undefined;
435
+ }
436
+ console.log('[i] estimatedBridgeFee', estimatedBridgeFee);
437
+ console.log('[i] estimatedDestinationFee', estimatedDestinationFee);
373
438
  const fee = {
374
439
  feeComponent: [{
375
440
  feeType: SwapFeeType.NETWORK_FEE,
@@ -738,7 +803,7 @@ export class UniswapHandler {
738
803
  if (swapIndex <= -1) {
739
804
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
740
805
  }
741
- if (swapXcm && bridgeIndex <= -1) {
806
+ if ((swapXcm || xcmSwap) && bridgeIndex <= -1) {
742
807
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
743
808
  }
744
809
  if (swap) {
@@ -749,7 +814,7 @@ export class UniswapHandler {
749
814
  return this.swapBaseHandler.validateSwapXcmProcess(params, swapIndex, bridgeIndex);
750
815
  }
751
816
  if (xcmSwap) {
752
- return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
817
+ return this.swapBaseHandler.validateXcmSwapProcess(params, swapIndex, bridgeIndex);
753
818
  }
754
819
  if (xcmSwapXcm) {
755
820
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
@@ -39,7 +39,7 @@ export class SwapService {
39
39
  var _subwalletApiSdk$swap;
40
40
  const availableQuotes = [];
41
41
 
42
- // hotfix
42
+ // hotfix // todo: remove later
43
43
  const request = {
44
44
  ..._request,
45
45
  isSupportKyberVersion: true
@@ -20,6 +20,7 @@ export interface CommonFeeComponent {
20
20
  feeType: BaseFeeType;
21
21
  amount: string;
22
22
  tokenSlug: string;
23
+ percentage?: number;
23
24
  }
24
25
  export interface CommonStepFeeInfo {
25
26
  feeComponent: CommonFeeComponent[];
@@ -1,2 +1,4 @@
1
+ import { _ChainInfo } from '@subwallet/chain-list/types';
1
2
  export declare const convertCardanoAddressToHex: (bech32Address: string) => string;
2
3
  export declare const convertCardanoHexToBech32: (hexAddress: string) => string;
4
+ export declare const validateAddressNetwork: (address: string, chainInfo?: _ChainInfo) => boolean;
package/utils/cardano.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { Address } from '@emurgo/cardano-serialization-lib-nodejs';
5
+ import { isCardanoMainnetAddress, isCardanoTestnetAddress } from '@subwallet/keyring';
5
6
  export const convertCardanoAddressToHex = bech32Address => {
6
7
  const addr = Address.from_bech32(bech32Address);
7
8
  return addr.to_hex();
@@ -9,4 +10,10 @@ export const convertCardanoAddressToHex = bech32Address => {
9
10
  export const convertCardanoHexToBech32 = hexAddress => {
10
11
  const addr = Address.from_hex(hexAddress);
11
12
  return addr.to_bech32();
13
+ };
14
+ export const validateAddressNetwork = (address, chainInfo) => {
15
+ if (!(chainInfo !== null && chainInfo !== void 0 && chainInfo.cardanoInfo) || !chainInfo.isTestnet) {
16
+ return isCardanoMainnetAddress(address);
17
+ }
18
+ return isCardanoTestnetAddress(address);
12
19
  };