@subwallet/extension-base 1.3.31-1 → 1.3.32-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 (127) hide show
  1. package/background/KoniTypes.d.ts +70 -3
  2. package/background/KoniTypes.js +14 -0
  3. package/background/errors/CardanoProviderError.d.ts +6 -0
  4. package/background/errors/CardanoProviderError.js +61 -0
  5. package/background/types.d.ts +2 -2
  6. package/cjs/background/KoniTypes.js +16 -1
  7. package/cjs/background/errors/CardanoProviderError.js +67 -0
  8. package/cjs/constants/index.js +4 -1
  9. package/cjs/core/logic-validation/request.js +50 -3
  10. package/cjs/koni/api/contract-handler/evm/web3.js +21 -0
  11. package/cjs/koni/api/staking/bonding/utils.js +24 -3
  12. package/cjs/koni/background/handlers/Extension.js +115 -107
  13. package/cjs/koni/background/handlers/State.js +228 -5
  14. package/cjs/koni/background/handlers/Tabs.js +277 -55
  15. package/cjs/packageInfo.js +1 -1
  16. package/cjs/page/cardano/cips/cip30.js +63 -0
  17. package/cjs/page/cardano/cips/index.js +20 -0
  18. package/cjs/page/cardano/index.js +41 -0
  19. package/cjs/page/{SubWalleEvmProvider.js → evm/index.js} +2 -2
  20. package/cjs/page/index.js +9 -4
  21. package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +6 -2
  22. package/cjs/services/balance-service/transfer/xcm/index.js +2 -0
  23. package/cjs/services/chain-service/handler/CardanoApi.js +33 -0
  24. package/cjs/services/chain-service/index.js +31 -0
  25. package/cjs/services/chain-service/utils/patch.js +1 -1
  26. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +3 -3
  27. package/cjs/services/earning-service/handlers/native-staking/dtao.js +2 -2
  28. package/cjs/services/earning-service/handlers/native-staking/mythos.js +42 -8
  29. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +1 -1
  30. package/cjs/services/earning-service/handlers/native-staking/tao.js +13 -13
  31. package/cjs/services/earning-service/handlers/nomination-pool/index.js +1 -1
  32. package/cjs/services/migration-service/scripts/MigrateAuthUrls.js +1 -1
  33. package/cjs/services/request-service/constants.js +3 -1
  34. package/cjs/services/request-service/handler/AuthRequestHandler.js +38 -5
  35. package/cjs/services/request-service/handler/CardanoRequestHandler.js +45 -3
  36. package/cjs/services/request-service/helper/index.js +419 -1
  37. package/cjs/services/swap-service/handler/asset-hub/handler.js +1 -1
  38. package/cjs/services/swap-service/handler/base-handler.js +81 -21
  39. package/cjs/services/swap-service/handler/hydradx-handler.js +1 -1
  40. package/cjs/services/swap-service/handler/uniswap-handler.js +274 -45
  41. package/cjs/services/swap-service/index.js +33 -11
  42. package/cjs/services/swap-service/utils.js +15 -2
  43. package/cjs/utils/auth.js +2 -1
  44. package/cjs/utils/cardano.js +20 -0
  45. package/cjs/utils/index.js +4 -4
  46. package/constants/index.d.ts +1 -0
  47. package/constants/index.js +1 -0
  48. package/core/logic-validation/request.d.ts +6 -2
  49. package/core/logic-validation/request.js +51 -5
  50. package/koni/api/contract-handler/evm/web3.d.ts +2 -0
  51. package/koni/api/contract-handler/evm/web3.js +19 -0
  52. package/koni/api/staking/bonding/utils.d.ts +2 -1
  53. package/koni/api/staking/bonding/utils.js +23 -3
  54. package/koni/background/handlers/Extension.js +7 -2
  55. package/koni/background/handlers/State.d.ts +6 -1
  56. package/koni/background/handlers/State.js +223 -4
  57. package/koni/background/handlers/Tabs.d.ts +11 -1
  58. package/koni/background/handlers/Tabs.js +242 -19
  59. package/package.json +62 -42
  60. package/packageInfo.js +1 -1
  61. package/page/cardano/cips/cip30.d.ts +22 -0
  62. package/page/cardano/cips/cip30.js +55 -0
  63. package/page/cardano/cips/index.d.ts +3 -0
  64. package/page/cardano/cips/index.js +7 -0
  65. package/page/cardano/index.d.ts +13 -0
  66. package/page/cardano/index.js +34 -0
  67. package/page/{SubWalleEvmProvider.d.ts → evm/index.d.ts} +3 -2
  68. package/page/{SubWalleEvmProvider.js → evm/index.js} +1 -1
  69. package/page/index.d.ts +3 -2
  70. package/page/index.js +6 -2
  71. package/page/{Accounts.d.ts → substrate/Accounts.d.ts} +1 -1
  72. package/page/{Metadata.d.ts → substrate/Metadata.d.ts} +1 -1
  73. package/page/{PostMessageProvider.d.ts → substrate/PostMessageProvider.d.ts} +1 -1
  74. package/page/{Signer.d.ts → substrate/Signer.d.ts} +1 -1
  75. package/page/{Injected.d.ts → substrate/index.d.ts} +1 -1
  76. package/services/balance-service/helpers/subscribe/cardano/types.d.ts +14 -0
  77. package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +4 -0
  78. package/services/balance-service/transfer/xcm/acrossBridge/index.js +4 -1
  79. package/services/balance-service/transfer/xcm/index.js +2 -0
  80. package/services/chain-service/handler/CardanoApi.d.ts +3 -1
  81. package/services/chain-service/handler/CardanoApi.js +33 -0
  82. package/services/chain-service/index.d.ts +5 -1
  83. package/services/chain-service/index.js +32 -1
  84. package/services/chain-service/utils/patch.js +1 -1
  85. package/services/earning-service/handlers/liquid-staking/stella-swap.js +3 -3
  86. package/services/earning-service/handlers/native-staking/dtao.js +2 -2
  87. package/services/earning-service/handlers/native-staking/mythos.js +42 -8
  88. package/services/earning-service/handlers/native-staking/relay-chain.js +1 -1
  89. package/services/earning-service/handlers/native-staking/tao.js +14 -14
  90. package/services/earning-service/handlers/nomination-pool/index.js +1 -1
  91. package/services/migration-service/scripts/MigrateAuthUrls.js +1 -1
  92. package/services/request-service/constants.js +3 -1
  93. package/services/request-service/handler/AuthRequestHandler.js +40 -7
  94. package/services/request-service/handler/CardanoRequestHandler.d.ts +2 -0
  95. package/services/request-service/handler/CardanoRequestHandler.js +45 -3
  96. package/services/request-service/helper/index.d.ts +54 -0
  97. package/services/request-service/helper/index.js +406 -1
  98. package/services/request-service/types.d.ts +3 -1
  99. package/services/swap-service/handler/asset-hub/handler.js +1 -1
  100. package/services/swap-service/handler/base-handler.d.ts +3 -1
  101. package/services/swap-service/handler/base-handler.js +82 -22
  102. package/services/swap-service/handler/hydradx-handler.js +1 -1
  103. package/services/swap-service/handler/uniswap-handler.d.ts +5 -0
  104. package/services/swap-service/handler/uniswap-handler.js +275 -46
  105. package/services/swap-service/index.js +34 -12
  106. package/services/swap-service/utils.d.ts +3 -2
  107. package/services/swap-service/utils.js +13 -1
  108. package/types/swap/index.d.ts +1 -0
  109. package/types/transaction/process.d.ts +2 -0
  110. package/utils/auth.js +3 -2
  111. package/utils/cardano.d.ts +2 -0
  112. package/utils/cardano.js +12 -0
  113. package/utils/index.d.ts +1 -1
  114. package/utils/index.js +1 -1
  115. package/cjs/utils/canDerive.js +0 -12
  116. package/utils/canDerive.d.ts +0 -2
  117. package/utils/canDerive.js +0 -6
  118. /package/cjs/page/{Accounts.js → substrate/Accounts.js} +0 -0
  119. /package/cjs/page/{Metadata.js → substrate/Metadata.js} +0 -0
  120. /package/cjs/page/{PostMessageProvider.js → substrate/PostMessageProvider.js} +0 -0
  121. /package/cjs/page/{Signer.js → substrate/Signer.js} +0 -0
  122. /package/cjs/page/{Injected.js → substrate/index.js} +0 -0
  123. /package/page/{Accounts.js → substrate/Accounts.js} +0 -0
  124. /package/page/{Metadata.js → substrate/Metadata.js} +0 -0
  125. /package/page/{PostMessageProvider.js → substrate/PostMessageProvider.js} +0 -0
  126. /package/page/{Signer.js → substrate/Signer.js} +0 -0
  127. /package/page/{Injected.js → substrate/index.js} +0 -0
@@ -4,10 +4,14 @@
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { validateTypedSignMessageDataV3V4 } from '@subwallet/extension-base/core/logic-validation';
7
+ import { estimateTxFee, getERC20Allowance, getERC20SpendingApprovalTx } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
8
+ import { createAcrossBridgeExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
9
+ import { SpokePoolMapping } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
7
10
  import { BasicTxErrorType, CommonStepType, DynamicSwapType, FeeOptionKey, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
8
11
  import { _reformatAddressWithChain } from '@subwallet/extension-base/utils';
12
+ import { getId } from '@subwallet/extension-base/utils/getId';
9
13
  import BigNumber from 'bignumber.js';
10
- import { _getContractAddressOfToken, _isNativeToken } from "../../chain-service/utils/index.js";
14
+ import { _getAssetOriginChain, _getChainNativeTokenSlug, _getContractAddressOfToken, _getEvmChainId, _isNativeToken } from "../../chain-service/utils/index.js";
11
15
  import { calculateGasFeeParams } from "../../fee-service/utils/index.js";
12
16
  import { SwapBaseHandler } from "./base-handler.js";
13
17
  const API_URL = 'https://trade-api.gateway.uniswap.org/v1';
@@ -59,41 +63,121 @@ export class UniswapHandler {
59
63
  return this.swapBaseHandler.providerInfo;
60
64
  }
61
65
  generateOptimalProcessV2(params) {
62
- return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getApprovalStep.bind(this), this.getPermitStep.bind(this), this.getSubmitStep.bind(this)]);
66
+ const stepFuncList = [];
67
+ /**
68
+ * approve - permit - swap or
69
+ * approve - permit - swap - approve - bridge
70
+ */
71
+
72
+ params.path.forEach(step => {
73
+ if (step.action === DynamicSwapType.SWAP) {
74
+ stepFuncList.push(...[this.getApprovalStep.bind(this), this.getPermitStep.bind(this), this.getSubmitStep.bind(this)]);
75
+ return;
76
+ }
77
+ if (step.action === DynamicSwapType.BRIDGE) {
78
+ stepFuncList.push(...[this.getApprovalStep.bind(this), this.getBridgeStep.bind(this)]);
79
+ return;
80
+ }
81
+ throw new Error(`Error generating optimal process: Action ${step.action} is not supported`);
82
+ });
83
+ return this.swapBaseHandler.generateOptimalProcessV2(params, stepFuncList);
63
84
  }
64
85
  async getApprovalStep(params, stepIndex) {
65
- if (params.selectedQuote) {
66
- const walletAddress = params.request.address;
67
- const fromAmount = params.selectedQuote.fromAmount;
68
- const inputTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
69
- const {
70
- quote
71
- } = params.selectedQuote.metadata;
72
- const checkApprovalResponse = await fetchCheckApproval(walletAddress, fromAmount, quote);
73
- const approval = checkApprovalResponse.approval;
74
- if (approval) {
75
- let spender = '';
76
- try {
77
- const valueLength = 40;
78
- spender = approval.data.slice(-(valueLength * 2), -valueLength);
79
- } catch (e) {
80
- // Empty
81
- }
82
- const metadata = {
83
- tokenApprove: inputTokenInfo.slug,
84
- contractAddress: _getContractAddressOfToken(inputTokenInfo),
85
- spenderAddress: spender
86
- };
87
- const submitStep = {
88
- name: 'Approve token',
89
- type: CommonStepType.TOKEN_APPROVAL,
90
- metadata: metadata
91
- };
92
- return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
93
- }
86
+ if (stepIndex === 0) {
87
+ return this.getApproveSwap(params);
88
+ }
89
+ if (stepIndex === 3) {
90
+ return this.getApproveBridge(params);
94
91
  }
95
92
  return Promise.resolve(undefined);
96
93
  }
94
+ async getApproveSwap(params) {
95
+ const selectedQuote = params.selectedQuote;
96
+ if (!selectedQuote) {
97
+ return Promise.resolve(undefined);
98
+ }
99
+ const quoteMetadata = selectedQuote.metadata.quote;
100
+ const sender = quoteMetadata.swapper;
101
+ const sendingValue = quoteMetadata.input.amount;
102
+ const fromTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
103
+ const checkApprovalResponse = await fetchCheckApproval(sender, sendingValue, quoteMetadata);
104
+ const approval = checkApprovalResponse.approval;
105
+ if (!approval) {
106
+ return Promise.resolve(undefined);
107
+ }
108
+ let spender = '';
109
+ try {
110
+ const valueLength = 40;
111
+ spender = approval.data.slice(-(valueLength * 2), -valueLength);
112
+ } catch (e) {
113
+ // Empty
114
+ }
115
+ const submitStep = {
116
+ name: 'Approve token for swap',
117
+ type: CommonStepType.TOKEN_APPROVAL,
118
+ // @ts-ignore
119
+ metadata: {
120
+ tokenApprove: fromTokenInfo.slug,
121
+ contractAddress: _getContractAddressOfToken(fromTokenInfo),
122
+ spenderAddress: spender,
123
+ owner: sender,
124
+ amount: sendingValue,
125
+ isUniswapApprove: true
126
+ }
127
+ };
128
+ return Promise.resolve([submitStep, selectedQuote.feeInfo]); // todo: wrong feeInfo, please check
129
+ }
130
+
131
+ async getApproveBridge(params) {
132
+ const quote = params.selectedQuote;
133
+ if (!quote) {
134
+ return Promise.resolve(undefined);
135
+ }
136
+ const sendingAmount = quote.toAmount;
137
+ const senderAddress = params.request.address;
138
+ const fromTokenInfo = this.chainService.getAssetBySlug(quote.pair.to);
139
+ const fromChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(fromTokenInfo));
140
+ const fromChainId = _getEvmChainId(fromChainInfo);
141
+ const evmApi = this.chainService.getEvmApi(fromChainInfo.slug);
142
+ const tokenContract = _getContractAddressOfToken(fromTokenInfo);
143
+ if (_isNativeToken(fromTokenInfo)) {
144
+ return Promise.resolve(undefined);
145
+ }
146
+ if (!fromChainId) {
147
+ throw Error('Error getting Evm chain Id');
148
+ }
149
+ const spokePoolAddress = SpokePoolMapping[fromChainId].SpokePool.address;
150
+ const allowance = await getERC20Allowance(spokePoolAddress, senderAddress, tokenContract, evmApi);
151
+ if (allowance && BigNumber(allowance).gt(sendingAmount)) {
152
+ return Promise.resolve(undefined);
153
+ }
154
+ const tx = await getERC20SpendingApprovalTx(spokePoolAddress, senderAddress, tokenContract, evmApi);
155
+ const evmFeeInfo = await this.feeService.subscribeChainFee(getId(), fromTokenInfo.originChain, 'evm');
156
+ const estimatedFee = await estimateTxFee(tx, evmApi, evmFeeInfo);
157
+ const nativeTokenSlug = _getChainNativeTokenSlug(fromChainInfo);
158
+ const feeInfo = {
159
+ feeComponent: [{
160
+ feeType: SwapFeeType.NETWORK_FEE,
161
+ amount: estimatedFee,
162
+ tokenSlug: nativeTokenSlug
163
+ }],
164
+ defaultFeeToken: nativeTokenSlug,
165
+ feeOptions: [nativeTokenSlug]
166
+ };
167
+ const submitStep = {
168
+ name: 'Approve token for bridge',
169
+ type: CommonStepType.TOKEN_APPROVAL,
170
+ // @ts-ignore
171
+ metadata: {
172
+ tokenApprove: fromTokenInfo.slug,
173
+ contractAddress: tokenContract,
174
+ spenderAddress: spokePoolAddress,
175
+ amount: sendingAmount,
176
+ owner: senderAddress
177
+ }
178
+ };
179
+ return Promise.resolve([submitStep, feeInfo]);
180
+ }
97
181
  async getPermitStep(params, stepIndex) {
98
182
  if (params.selectedQuote && params.selectedQuote.metadata.permitData) {
99
183
  const submitStep = {
@@ -116,11 +200,22 @@ export class UniswapHandler {
116
200
  return Promise.resolve(undefined);
117
201
  }
118
202
  async getSubmitStep(params, stepIndex) {
119
- if (!params.selectedQuote) {
203
+ const {
204
+ path,
205
+ request,
206
+ selectedQuote
207
+ } = params;
208
+
209
+ // stepIndex is not corresponding index in path, because uniswap include approval and permit step
210
+ const stepData = path.find(action => action.action === DynamicSwapType.SWAP);
211
+ if (!stepData || !stepData.pair) {
212
+ return Promise.resolve(undefined);
213
+ }
214
+ if (!selectedQuote) {
120
215
  return Promise.resolve(undefined);
121
216
  }
122
- const originTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
123
- const destinationTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
217
+ const originTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
218
+ const destinationTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.to);
124
219
  const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
125
220
  const destinationChain = this.chainService.getChainInfoByKey(destinationTokenInfo.originChain);
126
221
  const submitStep = {
@@ -128,16 +223,99 @@ export class UniswapHandler {
128
223
  type: SwapStepType.SWAP,
129
224
  // @ts-ignore
130
225
  metadata: {
131
- sendingValue: params.request.fromAmount.toString(),
132
- expectedReceive: params.selectedQuote.toAmount,
226
+ sendingValue: request.fromAmount.toString(),
227
+ expectedReceive: selectedQuote.toAmount,
133
228
  originTokenInfo,
134
229
  destinationTokenInfo,
135
- sender: _reformatAddressWithChain(params.request.address, originChain),
136
- receiver: _reformatAddressWithChain(params.request.recipient || params.request.address, destinationChain),
230
+ sender: _reformatAddressWithChain(request.address, originChain),
231
+ receiver: _reformatAddressWithChain(request.recipient || request.address, destinationChain),
137
232
  version: 2
138
233
  }
139
234
  };
140
- return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
235
+ return Promise.resolve([submitStep, selectedQuote.feeInfo]);
236
+ }
237
+ async getBridgeStep(params, stepIndex) {
238
+ const {
239
+ path,
240
+ request,
241
+ selectedQuote
242
+ } = params;
243
+
244
+ // stepIndex is not corresponding index in path, because uniswap include approval and permit step
245
+ const bridgePairInfo = path.find(action => action.action === DynamicSwapType.BRIDGE);
246
+ if (!bridgePairInfo || !bridgePairInfo.pair) {
247
+ return Promise.resolve(undefined);
248
+ }
249
+ if (!selectedQuote) {
250
+ return Promise.resolve(undefined);
251
+ }
252
+ const fromTokenInfo = this.chainService.getAssetBySlug(bridgePairInfo.pair.from);
253
+ const toTokenInfo = this.chainService.getAssetBySlug(bridgePairInfo.pair.to);
254
+ const fromChainInfo = this.chainService.getChainInfoByKey(fromTokenInfo.originChain);
255
+ const toChainInfo = this.chainService.getChainInfoByKey(toTokenInfo.originChain);
256
+ if (!fromChainInfo || !toChainInfo || !fromChainInfo || !toChainInfo) {
257
+ throw Error('Token or chain not found');
258
+ }
259
+ const senderAddress = _reformatAddressWithChain(request.address, fromChainInfo);
260
+ const receiverAddress = _reformatAddressWithChain(request.recipient || request.address, toChainInfo);
261
+ const sendingValue = BigNumber(selectedQuote.toAmount).div(1.02).toFixed(0, 1);
262
+ try {
263
+ const evmApi = await this.chainService.getEvmApi(fromChainInfo.slug).isReady;
264
+ const feeInfo = await this.feeService.subscribeChainFee(getId(), fromTokenInfo.originChain, 'evm');
265
+ const tx = await createAcrossBridgeExtrinsic({
266
+ originTokenInfo: fromTokenInfo,
267
+ destinationTokenInfo: toTokenInfo,
268
+ originChain: fromChainInfo,
269
+ destinationChain: toChainInfo,
270
+ evmApi,
271
+ feeInfo,
272
+ // Mock sending value to get payment info
273
+ sendingValue,
274
+ sender: senderAddress,
275
+ recipient: receiverAddress
276
+ });
277
+
278
+ // // todo: wait until this ready to get destination fee. the real receiveAmount is deduce by this fee
279
+ // const acrossQuote = await getAcrossQuote({
280
+ // destinationChain: toChainInfo,
281
+ // destinationTokenInfo: toTokenInfo,
282
+ // originChain: fromChainInfo,
283
+ // originTokenInfo: fromTokenInfo,
284
+ // recipient: receiverAddress,
285
+ // sender: senderAddress,
286
+ // sendingValue,
287
+ // feeInfo
288
+ // });
289
+
290
+ const estimatedBridgeFee = await estimateTxFee(tx, evmApi, feeInfo);
291
+ const expectedReceive = BigNumber(sendingValue).minus(estimatedBridgeFee).toFixed(0, 1);
292
+ const fee = {
293
+ feeComponent: [{
294
+ feeType: SwapFeeType.NETWORK_FEE,
295
+ amount: estimatedBridgeFee,
296
+ tokenSlug: _getChainNativeTokenSlug(fromChainInfo)
297
+ }],
298
+ defaultFeeToken: _getChainNativeTokenSlug(fromChainInfo),
299
+ feeOptions: [_getChainNativeTokenSlug(fromChainInfo)]
300
+ };
301
+ const step = {
302
+ // @ts-ignore
303
+ metadata: {
304
+ sendingValue: sendingValue,
305
+ expectedReceive,
306
+ originTokenInfo: fromTokenInfo,
307
+ destinationTokenInfo: toTokenInfo,
308
+ receiver: receiverAddress,
309
+ sender: senderAddress
310
+ },
311
+ name: `Transfer ${fromTokenInfo.symbol} from ${fromChainInfo.name}`,
312
+ type: CommonStepType.XCM
313
+ };
314
+ return [step, fee];
315
+ } catch (e) {
316
+ console.error('Error creating bridge step', e);
317
+ throw new Error(e.message);
318
+ }
141
319
  }
142
320
  async handleSwapProcess(params) {
143
321
  const {
@@ -150,6 +328,8 @@ export class UniswapHandler {
150
328
  return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
151
329
  case CommonStepType.TOKEN_APPROVAL:
152
330
  return this.tokenApproveSpending(params);
331
+ case CommonStepType.XCM:
332
+ return this.swapBaseHandler.handleBridgeStep(params, 'across');
153
333
  case SwapStepType.SWAP:
154
334
  return this.handleSubmitStep(params);
155
335
  case SwapStepType.PERMIT:
@@ -159,13 +339,29 @@ export class UniswapHandler {
159
339
  }
160
340
  }
161
341
  async tokenApproveSpending(params) {
162
- const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
163
- const walletAddress = params.address;
164
- const fromAmount = params.quote.fromAmount;
342
+ const approveStep = params.process.steps[params.currentStep].metadata;
343
+ if (!approveStep || !approveStep.tokenApprove || !approveStep.contractAddress || !approveStep.spenderAddress) {
344
+ throw new Error('Approval spending metadata error');
345
+ }
346
+ if (approveStep.isUniswapApprove) {
347
+ return this.approveSpendingSwap(params, approveStep);
348
+ }
349
+ return this.approveSpendingBridge(approveStep);
350
+ }
351
+ async approveSpendingSwap(params, approveStep) {
352
+ const fromAsset = this.chainService.getAssetBySlug(approveStep.tokenApprove);
353
+ const sender = approveStep.owner;
354
+ const sendingValue = approveStep.amount;
355
+ if (!sender || !sendingValue) {
356
+ throw new Error('Sender or value is not found');
357
+ }
358
+
359
+ // todo: move quote param to metadata;
360
+
165
361
  const {
166
362
  quote
167
363
  } = params.quote.metadata;
168
- const checkApprovalResponse = await fetchCheckApproval(walletAddress, fromAmount, quote);
364
+ const checkApprovalResponse = await fetchCheckApproval(sender, sendingValue, quote);
169
365
  let transactionConfig = {};
170
366
  const approval = checkApprovalResponse.approval;
171
367
  if (approval) {
@@ -201,6 +397,34 @@ export class UniswapHandler {
201
397
  chainType: ChainType.EVM
202
398
  });
203
399
  }
400
+ async approveSpendingBridge(approveStep) {
401
+ const fromAsset = this.chainService.getAssetBySlug(approveStep.tokenApprove);
402
+ const fromChain = _getAssetOriginChain(fromAsset);
403
+ const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
404
+ const sender = approveStep.owner;
405
+ const sendingValue = approveStep.amount;
406
+ if (!sender) {
407
+ throw new Error('Sender or value is not found');
408
+ }
409
+ const spenderAddress = approveStep.spenderAddress;
410
+ const contractAddress = approveStep.contractAddress;
411
+ const transactionConfig = await getERC20SpendingApprovalTx(spenderAddress, sender, contractAddress, evmApi);
412
+ const _data = {
413
+ spenderAddress: approveStep.spenderAddress,
414
+ contractAddress: approveStep.contractAddress,
415
+ amount: sendingValue,
416
+ owner: sender,
417
+ chain: fromChain
418
+ };
419
+ return Promise.resolve({
420
+ txChain: fromChain,
421
+ extrinsicType: ExtrinsicType.TOKEN_SPENDING_APPROVAL,
422
+ extrinsic: transactionConfig,
423
+ txData: _data,
424
+ transferNativeAmount: '0',
425
+ chainType: ChainType.EVM
426
+ });
427
+ }
204
428
  async handleSubmitStep(params) {
205
429
  const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
206
430
  const {
@@ -234,6 +458,8 @@ export class UniswapHandler {
234
458
  const transactionResponse = await postTransactionResponse.json();
235
459
  extrinsic = transactionResponse.swap;
236
460
  } else if (routing === 'DUTCH_LIMIT' || routing === 'DUTCH_V2') {
461
+ // todo: update condition and add handle exception
462
+ // UniswapX, UniswapX_V2, and UniswapX_V3 are alternately referred to as DutchQuote, DutchQuoteV2, and DutchQuoteV3
237
463
  postTransactionResponse = await fetch(`${API_URL}/order`, {
238
464
  method: 'POST',
239
465
  headers: {
@@ -325,17 +551,20 @@ export class UniswapHandler {
325
551
  const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
326
552
  const xcmSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
327
553
  const xcmSwapXcm = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
328
- const swapIndex = params.process.steps.findIndex(step => step.type === SwapStepType.SWAP); // todo
329
-
554
+ const swapIndex = params.process.steps.findIndex(step => step.type === SwapStepType.SWAP);
555
+ const bridgeIndex = params.process.steps.findIndex(step => step.type === CommonStepType.XCM);
330
556
  if (swapIndex <= -1) {
331
557
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
332
558
  }
559
+ if (swapXcm && bridgeIndex <= -1) {
560
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
561
+ }
333
562
  if (swap) {
334
563
  return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex); // todo: create interface for input request
335
564
  }
336
565
 
337
566
  if (swapXcm) {
338
- return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
567
+ return this.swapBaseHandler.validateSwapXcmProcess(params, swapIndex, bridgeIndex);
339
568
  }
340
569
  if (xcmSwap) {
341
570
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
@@ -12,7 +12,7 @@ import { _getAssetOriginChain, _getChainSubstrateAddressPrefix } from '@subwalle
12
12
  import { AssetHubSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/asset-hub';
13
13
  import { ChainflipSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/chainflip-handler';
14
14
  import { HydradxHandler } from '@subwallet/extension-base/services/swap-service/handler/hydradx-handler';
15
- import { findAllBridgeDestinations, findBridgeTransitDestination, findSwapTransitDestination, getBridgeStep, getSupportSwapChain, getSwapAltToken, getSwapStep, getTokenPairFromStep, isChainsHasSameProvider, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
15
+ import { findAllBridgeDestinations, findBridgeTransitDestination, findSwapTransitDestination, getBridgeStep, getSupportedSwapChains, getSwapAltToken, getSwapStep, getTokenPairFromStep, isChainsHasSameProvider, processStepsToPathActions, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
16
16
  import { BasicTxErrorType, DynamicSwapType } from '@subwallet/extension-base/types';
17
17
  import { DEFAULT_FIRST_STEP, MOCK_STEP_FEE } from '@subwallet/extension-base/types/service-base';
18
18
  import { _SUPPORTED_SWAP_PROVIDERS, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
@@ -110,16 +110,22 @@ export class SwapService {
110
110
  path,
111
111
  swapQuoteResponse
112
112
  } = await this.getLatestQuoteFromSwapRequest(request);
113
- const optimalProcess = await this.generateOptimalProcessV2({
114
- request,
115
- selectedQuote: swapQuoteResponse.optimalQuote,
116
- path
117
- });
118
- console.log('-------');
113
+ console.group('Swap Logger');
114
+ console.log('path', path);
115
+ console.log('swapQuoteResponse', swapQuoteResponse);
116
+ let optimalProcess;
117
+ try {
118
+ optimalProcess = await this.generateOptimalProcessV2({
119
+ request,
120
+ selectedQuote: swapQuoteResponse.optimalQuote,
121
+ path
122
+ });
123
+ } catch (e) {
124
+ throw new Error(e.message);
125
+ }
119
126
  console.log('optimalProcess', optimalProcess);
120
- console.log('-------');
121
- if (optimalProcess.steps.length - 1 < optimalProcess.path.length) {
122
- // minus the fill info step
127
+ console.groupEnd();
128
+ if (JSON.stringify(processStepsToPathActions(optimalProcess.steps)) !== JSON.stringify(optimalProcess.path.map(e => e.action))) {
123
129
  throw new Error('Swap pair is not found');
124
130
  }
125
131
  return {
@@ -135,7 +141,7 @@ export class SwapService {
135
141
  pair
136
142
  } = request;
137
143
  // todo: control provider tighter
138
- const supportSwapChains = getSupportSwapChain();
144
+ const supportSwapChains = getSupportedSwapChains();
139
145
  const fromToken = this.chainService.getAssetBySlug(pair.from);
140
146
  const toToken = this.chainService.getAssetBySlug(pair.to);
141
147
  const fromChain = _getAssetOriginChain(fromToken);
@@ -237,10 +243,26 @@ export class SwapService {
237
243
  return [[], undefined];
238
244
  }
239
245
  async getLatestQuoteFromSwapRequest(request) {
240
- const [path, directSwapRequest] = this.getAvailablePath(request);
246
+ var _subwalletApiSdk$swap2;
247
+ const availablePath = await ((_subwalletApiSdk$swap2 = subwalletApiSdk.swapApi) === null || _subwalletApiSdk$swap2 === void 0 ? void 0 : _subwalletApiSdk$swap2.findAvailablePath(request));
248
+ if (!availablePath) {
249
+ throw Error('No available path');
250
+ }
251
+ const {
252
+ path
253
+ } = availablePath;
254
+ const swapAction = path.find(step => step.action === DynamicSwapType.SWAP);
255
+ const directSwapRequest = swapAction ? {
256
+ ...request,
257
+ address: _reformatAddressWithChain(request.address, this.chainService.getChainInfoByKey(_getAssetOriginChain(this.chainService.getAssetBySlug(swapAction.pair.from)))),
258
+ pair: swapAction.pair
259
+ } : undefined;
241
260
  if (!directSwapRequest) {
242
261
  throw Error('Swap pair is not found');
243
262
  }
263
+ if (path.length > 1 && path.map(action => action.action).includes(DynamicSwapType.BRIDGE)) {
264
+ directSwapRequest.isCrossChain = true;
265
+ }
244
266
  const swapQuoteResponse = await this.getLatestDirectQuotes(directSwapRequest);
245
267
  return {
246
268
  path,
@@ -1,5 +1,5 @@
1
1
  import { _AssetRef, _ChainAsset } from '@subwallet/chain-list/types';
2
- import { CommonStepDetail, DynamicSwapAction } from '@subwallet/extension-base/types';
2
+ import { CommonStepDetail, DynamicSwapAction, DynamicSwapType } from '@subwallet/extension-base/types';
3
3
  import { SwapPair } from '@subwallet/extension-base/types/swap';
4
4
  export declare const CHAIN_FLIP_TESTNET_EXPLORER = "https://blocks-perseverance.chainflip.io";
5
5
  export declare const CHAIN_FLIP_MAINNET_EXPLORER = "https://scan.chainflip.io";
@@ -8,7 +8,7 @@ export declare const SIMPLE_SWAP_SUPPORTED_TESTNET_ASSET_MAPPING: Record<string,
8
8
  export declare const SWAP_QUOTE_TIMEOUT_MAP: Record<string, number>;
9
9
  export declare const _PROVIDER_TO_SUPPORTED_PAIR_MAP: Record<string, string[]>;
10
10
  export declare const FEE_RATE_MULTIPLIER: Record<string, number>;
11
- export declare function getSupportSwapChain(): string[];
11
+ export declare function getSupportedSwapChains(): string[];
12
12
  export declare function getSwapAlternativeAsset(swapPair: SwapPair): string | undefined;
13
13
  export declare function getSwapAltToken(chainAsset: _ChainAsset): string | undefined;
14
14
  export declare function calculateSwapRate(fromAmount: string, toAmount: string, fromAsset: _ChainAsset, toAsset: _ChainAsset): number;
@@ -38,4 +38,5 @@ export declare function getFirstAmountFromSteps(steps: CommonStepDetail[]): stri
38
38
  export declare function getChainRouteFromSteps(steps: CommonStepDetail[]): string[];
39
39
  export declare function getTokenPairFromStep(steps: CommonStepDetail[]): SwapPair | undefined;
40
40
  export declare function getSwapChainsFromPath(path: DynamicSwapAction[]): string[];
41
+ export declare function processStepsToPathActions(steps: CommonStepDetail[]): DynamicSwapType[];
41
42
  export declare const DEFAULT_EXCESS_AMOUNT_WEIGHT = 1.04;
@@ -42,7 +42,7 @@ export const FEE_RATE_MULTIPLIER = {
42
42
  medium: 1.2,
43
43
  high: 2
44
44
  };
45
- export function getSupportSwapChain() {
45
+ export function getSupportedSwapChains() {
46
46
  return [...new Set(Object.values(_PROVIDER_TO_SUPPORTED_PAIR_MAP).flat())];
47
47
  }
48
48
  export function getSwapAlternativeAsset(swapPair) {
@@ -236,4 +236,16 @@ export function getSwapChainsFromPath(path) {
236
236
  });
237
237
  return swapChains;
238
238
  }
239
+ export function processStepsToPathActions(steps) {
240
+ const path = [];
241
+ for (const step of steps) {
242
+ if (step.type === CommonStepType.XCM) {
243
+ path.push(DynamicSwapType.BRIDGE);
244
+ }
245
+ if (step.type === SwapStepType.SWAP) {
246
+ path.push(DynamicSwapType.SWAP);
247
+ }
248
+ }
249
+ return path;
250
+ }
239
251
  export const DEFAULT_EXCESS_AMOUNT_WEIGHT = 1.04; // add 2%
@@ -137,6 +137,7 @@ export interface SwapRequestV2 {
137
137
  recipient?: string;
138
138
  feeToken?: string;
139
139
  preferredProvider?: SwapProviderId;
140
+ isCrossChain?: boolean;
140
141
  }
141
142
  export interface SwapRequestResult {
142
143
  process: CommonOptimalSwapPath;
@@ -84,6 +84,8 @@ export interface ApproveStepMetadata {
84
84
  contractAddress: string;
85
85
  spenderAddress: string;
86
86
  amount?: string;
87
+ owner?: string;
88
+ isUniswapApprove?: boolean;
87
89
  }
88
90
  export interface RequestSubscribeProcessById {
89
91
  processId: string;
package/utils/auth.js CHANGED
@@ -2,13 +2,14 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { getKeypairTypeByAddress } from '@subwallet/keyring';
5
- import { EthereumKeypairTypes, SubstrateKeypairTypes, TonKeypairTypes } from '@subwallet/keyring/types';
5
+ import { CardanoKeypairTypes, EthereumKeypairTypes, SubstrateKeypairTypes, TonKeypairTypes } from '@subwallet/keyring/types';
6
6
  export const isAddressValidWithAuthType = (address, accountAuthTypes) => {
7
7
  const keypairType = getKeypairTypeByAddress(address);
8
8
  const validTypes = {
9
9
  evm: EthereumKeypairTypes,
10
10
  substrate: SubstrateKeypairTypes,
11
- ton: TonKeypairTypes
11
+ ton: TonKeypairTypes,
12
+ cardano: CardanoKeypairTypes
12
13
  };
13
14
  return !!(accountAuthTypes !== null && accountAuthTypes !== void 0 && accountAuthTypes.some(authType => {
14
15
  var _validTypes$authType;
@@ -0,0 +1,2 @@
1
+ export declare const convertCardanoAddressToHex: (bech32Address: string) => string;
2
+ export declare const convertCardanoHexToBech32: (hexAddress: string) => string;
@@ -0,0 +1,12 @@
1
+ // Copyright 2019-2022 @polkadot/extension authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { Address } from '@emurgo/cardano-serialization-lib-nodejs';
5
+ export const convertCardanoAddressToHex = bech32Address => {
6
+ const addr = Address.from_bech32(bech32Address);
7
+ return addr.to_hex();
8
+ };
9
+ export const convertCardanoHexToBech32 = hexAddress => {
10
+ const addr = Address.from_hex(hexAddress);
11
+ return addr.to_bech32();
12
+ };
package/utils/index.d.ts CHANGED
@@ -4,9 +4,9 @@ import { CrowdloanParaState, NetworkJson } from '@subwallet/extension-base/backg
4
4
  import { AccountAuthType } from '@subwallet/extension-base/background/types';
5
5
  import { AccountJson } from '@subwallet/extension-base/types';
6
6
  import { BN } from '@polkadot/util';
7
- export { canDerive } from './canDerive';
8
7
  export * from './mv3';
9
8
  export * from './fetch';
9
+ export { convertCardanoAddressToHex } from './cardano';
10
10
  export declare const notDef: (x: any) => boolean;
11
11
  export declare const isDef: (x: any) => boolean;
12
12
  export declare const nonEmptyArr: (x: any) => boolean;
package/utils/index.js CHANGED
@@ -9,9 +9,9 @@ import { decodeAddress, encodeAddress, isCardanoAddress, isTonAddress } from '@s
9
9
  import { t } from 'i18next';
10
10
  import { assert, BN, hexToU8a, isHex } from '@polkadot/util';
11
11
  import { ethereumEncode, isEthereumAddress } from '@polkadot/util-crypto';
12
- export { canDerive } from "./canDerive.js";
13
12
  export * from "./mv3.js";
14
13
  export * from "./fetch.js";
14
+ export { convertCardanoAddressToHex } from "./cardano.js";
15
15
  export const notDef = x => x === null || typeof x === 'undefined';
16
16
  export const isDef = x => !notDef(x);
17
17
  export const nonEmptyArr = x => Array.isArray(x) && x.length > 0;
@@ -1,12 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.canDerive = canDerive;
7
- // Copyright 2019-2022 @polkadot/extension authors & contributors
8
- // SPDX-License-Identifier: Apache-2.0
9
-
10
- function canDerive(type) {
11
- return !!type && ['ed25519', 'sr25519', 'ecdsa', 'ethereum'].includes(type);
12
- }
@@ -1,2 +0,0 @@
1
- import type { KeypairType } from '@subwallet/keyring/types';
2
- export declare function canDerive(type?: KeypairType): boolean;
@@ -1,6 +0,0 @@
1
- // Copyright 2019-2022 @polkadot/extension authors & contributors
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- export function canDerive(type) {
5
- return !!type && ['ed25519', 'sr25519', 'ecdsa', 'ethereum'].includes(type);
6
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes