@subwallet/extension-base 1.3.20-0 → 1.3.21-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 (88) hide show
  1. package/background/KoniTypes.d.ts +8 -1
  2. package/cjs/defaults.js +1 -1
  3. package/cjs/koni/background/handlers/Extension.js +519 -90
  4. package/cjs/packageInfo.js +1 -1
  5. package/cjs/services/chain-service/handler/EvmApi.js +1 -3
  6. package/cjs/services/chain-service/utils/patch.js +1 -1
  7. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +19 -8
  8. package/cjs/services/earning-service/handlers/special.js +16 -10
  9. package/cjs/services/history-service/helpers/recoverHistoryStatus.js +14 -5
  10. package/cjs/services/history-service/index.js +15 -3
  11. package/cjs/services/inapp-notification-service/index.js +78 -0
  12. package/cjs/services/inapp-notification-service/interfaces.js +2 -0
  13. package/cjs/services/keyring-service/context/state.js +2 -1
  14. package/cjs/services/request-service/handler/EvmRequestHandler.js +10 -0
  15. package/cjs/services/request-service/handler/SubstrateRequestHandler.js +4 -3
  16. package/cjs/services/request-service/index.js +2 -2
  17. package/cjs/services/setting-service/constants.js +5 -2
  18. package/cjs/services/storage-service/DatabaseService.js +98 -2
  19. package/cjs/services/storage-service/databases/index.js +3 -0
  20. package/cjs/services/storage-service/db-stores/ProcessTransaction.js +47 -0
  21. package/cjs/services/storage-service/db-stores/Transaction.js +2 -0
  22. package/cjs/services/storage-service/db-stores/index.js +8 -1
  23. package/cjs/services/swap-service/handler/asset-hub/handler.js +30 -11
  24. package/cjs/services/swap-service/handler/hydradx-handler.js +18 -10
  25. package/cjs/services/swap-service/index.js +3 -0
  26. package/cjs/services/swap-service/utils.js +1 -0
  27. package/cjs/services/transaction-service/index.js +218 -9
  28. package/cjs/types/index.js +11 -0
  29. package/cjs/types/setting.js +1 -0
  30. package/cjs/types/swap/index.js +4 -1
  31. package/cjs/types/transaction/index.js +11 -0
  32. package/cjs/types/transaction/process.js +28 -0
  33. package/cjs/types/yield/actions/join/submit.js +16 -1
  34. package/defaults.d.ts +1 -1
  35. package/defaults.js +1 -1
  36. package/koni/background/handlers/Extension.d.ts +5 -0
  37. package/koni/background/handlers/Extension.js +437 -12
  38. package/package.json +21 -6
  39. package/packageInfo.js +1 -1
  40. package/services/chain-service/handler/EvmApi.js +1 -3
  41. package/services/chain-service/utils/patch.js +1 -1
  42. package/services/earning-service/handlers/liquid-staking/stella-swap.js +19 -8
  43. package/services/earning-service/handlers/special.js +18 -12
  44. package/services/history-service/helpers/recoverHistoryStatus.js +14 -5
  45. package/services/history-service/index.d.ts +6 -5
  46. package/services/history-service/index.js +16 -5
  47. package/services/inapp-notification-service/index.d.ts +2 -0
  48. package/services/inapp-notification-service/index.js +79 -1
  49. package/services/inapp-notification-service/interfaces.d.ts +8 -1
  50. package/services/inapp-notification-service/interfaces.js +2 -0
  51. package/services/keyring-service/context/state.d.ts +1 -1
  52. package/services/keyring-service/context/state.js +3 -2
  53. package/services/request-service/handler/EvmRequestHandler.js +10 -0
  54. package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -1
  55. package/services/request-service/handler/SubstrateRequestHandler.js +4 -3
  56. package/services/request-service/index.d.ts +1 -1
  57. package/services/request-service/index.js +2 -2
  58. package/services/setting-service/constants.d.ts +1 -0
  59. package/services/setting-service/constants.js +3 -1
  60. package/services/storage-service/DatabaseService.d.ts +12 -3
  61. package/services/storage-service/DatabaseService.js +100 -4
  62. package/services/storage-service/databases/index.d.ts +2 -1
  63. package/services/storage-service/databases/index.js +3 -0
  64. package/services/storage-service/db-stores/ProcessTransaction.d.ts +14 -0
  65. package/services/storage-service/db-stores/ProcessTransaction.js +39 -0
  66. package/services/storage-service/db-stores/Transaction.js +2 -0
  67. package/services/storage-service/db-stores/index.d.ts +1 -0
  68. package/services/storage-service/db-stores/index.js +2 -1
  69. package/services/swap-service/handler/asset-hub/handler.js +30 -11
  70. package/services/swap-service/handler/hydradx-handler.js +18 -10
  71. package/services/swap-service/index.js +3 -0
  72. package/services/swap-service/utils.js +1 -0
  73. package/services/transaction-service/index.d.ts +19 -1
  74. package/services/transaction-service/index.js +220 -11
  75. package/services/transaction-service/types.d.ts +13 -4
  76. package/types/index.d.ts +1 -0
  77. package/types/index.js +1 -0
  78. package/types/setting.d.ts +3 -0
  79. package/types/setting.js +1 -0
  80. package/types/swap/index.d.ts +3 -2
  81. package/types/swap/index.js +4 -1
  82. package/types/transaction/index.d.ts +1 -0
  83. package/types/transaction/index.js +1 -0
  84. package/types/transaction/process.d.ts +84 -0
  85. package/types/transaction/process.js +20 -0
  86. package/types/transaction/request.d.ts +3 -1
  87. package/types/yield/actions/join/submit.d.ts +18 -3
  88. package/types/yield/actions/join/submit.js +11 -1
@@ -1,9 +1,9 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { APIItemState, StakingType } from '@subwallet/extension-base/background/KoniTypes';
4
+ import { APIItemState, ExtrinsicStatus, StakingType } from '@subwallet/extension-base/background/KoniTypes';
5
5
  import KoniDatabase from '@subwallet/extension-base/services/storage-service/databases';
6
- import { AssetStore, BalanceStore, ChainStore, CrowdloanStore, MetadataStore, MetadataV15Store, MigrationStore, NftCollectionStore, NftStore, PriceStore, StakingStore, TransactionStore } from '@subwallet/extension-base/services/storage-service/db-stores';
6
+ import { AssetStore, BalanceStore, ChainStore, CrowdloanStore, MetadataStore, MetadataV15Store, MigrationStore, NftCollectionStore, NftStore, PriceStore, ProcessTransactionStore, StakingStore, TransactionStore } from '@subwallet/extension-base/services/storage-service/db-stores';
7
7
  import CampaignStore from '@subwallet/extension-base/services/storage-service/db-stores/Campaign';
8
8
  import ChainStakingMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/ChainStakingMetadata';
9
9
  import InappNotificationStore from '@subwallet/extension-base/services/storage-service/db-stores/InappNotification';
@@ -11,6 +11,7 @@ import MantaPayStore from '@subwallet/extension-base/services/storage-service/db
11
11
  import NominatorMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/NominatorMetadata';
12
12
  import YieldPoolStore from '@subwallet/extension-base/services/storage-service/db-stores/YieldPoolStore';
13
13
  import YieldPositionStore from '@subwallet/extension-base/services/storage-service/db-stores/YieldPositionStore';
14
+ import { StepStatus } from '@subwallet/extension-base/types';
14
15
  import { BN_ZERO, reformatAddress } from '@subwallet/extension-base/utils';
15
16
  import keyring from '@subwallet/ui-keyring';
16
17
  import BigN from 'bignumber.js';
@@ -51,7 +52,9 @@ export default class DatabaseService {
51
52
  // assetRef: new AssetRefStore(this._db.assetRef)
52
53
 
53
54
  // inapp notification
54
- inappNotification: new InappNotificationStore(this._db.inappNotification)
55
+ inappNotification: new InappNotificationStore(this._db.inappNotification),
56
+ // process transaction
57
+ processTransactions: new ProcessTransactionStore(this._db.processTransactions)
55
58
  };
56
59
  }
57
60
  async updatePriceStore(priceData) {
@@ -260,15 +263,90 @@ export default class DatabaseService {
260
263
  const cleanedHistory = histories.filter(x => x && x.address && x.chain && x.extrinsicHash);
261
264
  return this.stores.transaction.bulkUpsert(cleanedHistory);
262
265
  }
263
- async updateHistoryByExtrinsicHash(extrinsicHash, updateData) {
266
+ async updateHistoryByExtrinsicHash(extrinsicHash, updateData, isRecover) {
264
267
  const canUpdate = updateData && extrinsicHash;
265
268
  if (!canUpdate) {
266
269
  return;
267
270
  }
271
+ if (isRecover) {
272
+ await this.recoverProcessTransaction(extrinsicHash, updateData);
273
+ }
268
274
  return this.stores.transaction.updateWithQuery({
269
275
  extrinsicHash
270
276
  }, updateData);
271
277
  }
278
+ async restoreProcessTransaction() {
279
+ const processes = await this.stores.processTransactions.getSubmittingProcess();
280
+ const queuedProcesses = processes.filter(process => process.status === StepStatus.QUEUED);
281
+ const processingProcesses = processes.filter(process => process.status === StepStatus.PROCESSING);
282
+ await this.stores.processTransactions.bulkDelete(queuedProcesses.map(process => process.id));
283
+ for (const process of processingProcesses) {
284
+ const currentStepId = process.currentStepId;
285
+ const currentStep = process.steps.find(step => step.id === currentStepId);
286
+ if (currentStep) {
287
+ const currentStepStatus = currentStep.status;
288
+ if ([StepStatus.QUEUED, StepStatus.PREPARE].includes(currentStepStatus)) {
289
+ currentStep.status = StepStatus.CANCELLED;
290
+ process.status = StepStatus.CANCELLED;
291
+ } else if (currentStepStatus === StepStatus.TIMEOUT) {
292
+ currentStep.status = StepStatus.CANCELLED;
293
+ }
294
+ const nextSteps = process.steps.filter(step => step.id > currentStepId);
295
+ for (const step of nextSteps) {
296
+ step.status = StepStatus.CANCELLED;
297
+ }
298
+ }
299
+ }
300
+ await this.stores.processTransactions.bulkUpsert(processingProcesses);
301
+ }
302
+ async recoverProcessTransaction(extrinsicHash, updateData) {
303
+ const txs = await this.stores.transaction.queryHistory({
304
+ extrinsicHash
305
+ });
306
+ const map = new Map(txs.filter(x => !!x.processId && x.extrinsicHash === extrinsicHash).map(tx => [tx.processId || '', tx.transactionId || '']));
307
+ if (map.size && updateData.status) {
308
+ const processes = await this.stores.processTransactions.getByIds(Array.from(map.keys()));
309
+ for (const [processId, process] of Object.entries(processes)) {
310
+ const txId = map.get(processId);
311
+ if (txId) {
312
+ const currentStep = process.steps.find(tx => tx.transactionId === txId);
313
+ if (currentStep) {
314
+ const differentHash = txId !== extrinsicHash && currentStep.extrinsicHash !== extrinsicHash;
315
+ if (currentStep.status === StepStatus.PROCESSING || currentStep.status === StepStatus.SUBMITTING) {
316
+ switch (updateData.status) {
317
+ case ExtrinsicStatus.SUCCESS:
318
+ currentStep.status = StepStatus.COMPLETE;
319
+ if (differentHash) {
320
+ currentStep.extrinsicHash = extrinsicHash;
321
+ }
322
+ break;
323
+ case ExtrinsicStatus.FAIL:
324
+ currentStep.status = StepStatus.FAILED;
325
+ if (differentHash) {
326
+ currentStep.extrinsicHash = extrinsicHash;
327
+ }
328
+ break;
329
+ case ExtrinsicStatus.UNKNOWN:
330
+ currentStep.status = StepStatus.TIMEOUT;
331
+ break;
332
+ }
333
+ }
334
+ const isLastStep = process.steps[process.steps.length - 1].id === currentStep.id;
335
+ if (isLastStep) {
336
+ process.status = currentStep.status;
337
+ } else {
338
+ if (currentStep.status === StepStatus.TIMEOUT) {
339
+ process.status = StepStatus.TIMEOUT;
340
+ } else {
341
+ process.status = StepStatus.CANCELLED;
342
+ }
343
+ }
344
+ await this.stores.processTransactions.upsert(process);
345
+ }
346
+ }
347
+ }
348
+ }
349
+ }
272
350
 
273
351
  // NFT Collection
274
352
  async addNftCollection(collection) {
@@ -543,6 +621,24 @@ export default class DatabaseService {
543
621
  async getExportJson() {
544
622
  return JSON.parse(await this.exportDB());
545
623
  }
624
+ upsertProcessTransaction(processTransaction) {
625
+ return this.stores.processTransactions.upsert(processTransaction);
626
+ }
627
+ observableProcessTransactions() {
628
+ return this.stores.processTransactions.observableAll();
629
+ }
630
+ getProcessTransactions() {
631
+ return this.stores.processTransactions.getAll();
632
+ }
633
+ getProcessTransactionById(processId) {
634
+ return this.stores.processTransactions.getOne(processId);
635
+ }
636
+ observableProcessTransactionById(processId) {
637
+ return this.stores.processTransactions.observableOne(processId);
638
+ }
639
+ deleteProcessTransactionById(processId) {
640
+ return this.stores.processTransactions.delete(processId);
641
+ }
546
642
 
547
643
  // public setAssetRef (assetRef: Record<string, _AssetRef>) {
548
644
  // const assetRefList = Object.entries(assetRef).map(([slug, item]) => {
@@ -1,7 +1,7 @@
1
1
  import { _AssetRef, _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
2
  import { CampaignData, ChainStakingMetadata, CrowdloanItem, MetadataItem, MetadataV15Item, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { _NotificationInfo } from '@subwallet/extension-base/services/inapp-notification-service/interfaces';
4
- import { BalanceItem, YieldPoolInfo, YieldPositionInfo } from '@subwallet/extension-base/types';
4
+ import { BalanceItem, ProcessTransactionData, YieldPoolInfo, YieldPositionInfo } from '@subwallet/extension-base/types';
5
5
  import Dexie, { Table } from 'dexie';
6
6
  export declare const DEFAULT_DATABASE = "SubWalletDB_v2";
7
7
  export interface DefaultChainDoc {
@@ -64,6 +64,7 @@ export default class KoniDatabase extends Dexie {
64
64
  campaign: Table<ICampaign, object>;
65
65
  keyValue: Table<IKeyValue, object>;
66
66
  inappNotification: Table<_NotificationInfo, object>;
67
+ processTransactions: Table<ProcessTransactionData, object>;
67
68
  private schemaVersion;
68
69
  constructor(name?: string, schemaVersion?: number);
69
70
  private conditionalVersion;
@@ -46,6 +46,9 @@ export default class KoniDatabase extends Dexie {
46
46
  this.conditionalVersion(8, {
47
47
  metadataV15: 'genesisHash, chain'
48
48
  });
49
+ this.conditionalVersion(9, {
50
+ processTransactions: 'id, address'
51
+ });
49
52
  }
50
53
  conditionalVersion(version, schema, upgrade) {
51
54
  if (this.schemaVersion != null && this.schemaVersion < version) {
@@ -0,0 +1,14 @@
1
+ import { ProcessTransactionData } from '@subwallet/extension-base/types';
2
+ import BaseStoreWithAddress from './BaseStoreWithAddress';
3
+ export default class ProcessTransaction extends BaseStoreWithAddress<ProcessTransactionData> {
4
+ getAll(): Promise<Record<string, ProcessTransactionData>>;
5
+ observableAll(): import("dexie").Observable<Record<string, ProcessTransactionData>>;
6
+ getOne(id: string): Promise<ProcessTransactionData | undefined>;
7
+ observableOne(id: string): import("dexie").Observable<ProcessTransactionData | undefined>;
8
+ getByIds(ids: string[]): Promise<{
9
+ [k: string]: ProcessTransactionData;
10
+ }>;
11
+ delete(key: string): Promise<void>;
12
+ getSubmittingProcess(): import("dexie").PromiseExtended<ProcessTransactionData[]>;
13
+ bulkDelete(keys: string[]): Promise<void>;
14
+ }
@@ -0,0 +1,39 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { StepStatus } from '@subwallet/extension-base/types';
5
+ import { liveQuery } from 'dexie';
6
+ import BaseStoreWithAddress from "./BaseStoreWithAddress.js";
7
+ export default class ProcessTransaction extends BaseStoreWithAddress {
8
+ async getAll() {
9
+ const all = await this.table.toArray();
10
+ return Object.fromEntries(all.map(item => [item.id, item]));
11
+ }
12
+ observableAll() {
13
+ return liveQuery(async () => {
14
+ const all = await this.table.toArray();
15
+ return Object.fromEntries(all.map(item => [item.id, item]));
16
+ });
17
+ }
18
+ async getOne(id) {
19
+ return this.table.get(id);
20
+ }
21
+ observableOne(id) {
22
+ return liveQuery(async () => {
23
+ return this.table.get(id);
24
+ });
25
+ }
26
+ async getByIds(ids) {
27
+ const rs = await this.table.where('id').anyOf(ids).toArray();
28
+ return Object.fromEntries(rs.map(item => [item.id, item]));
29
+ }
30
+ delete(key) {
31
+ return this.table.delete(key);
32
+ }
33
+ getSubmittingProcess() {
34
+ return this.table.filter(item => [StepStatus.PROCESSING, StepStatus.QUEUED].includes(item.status)).toArray();
35
+ }
36
+ bulkDelete(keys) {
37
+ return this.table.bulkDelete(keys);
38
+ }
39
+ }
@@ -10,6 +10,8 @@ export default class TransactionStore extends BaseStoreWithAddressAndChain {
10
10
  }
11
11
  return this.table.where('address').equals(address).toArray();
12
12
  }
13
+
14
+ // TODO: This query is not exactly correct. It makes a lot of wrong assumptions, need to be fixed.
13
15
  async queryHistory(query) {
14
16
  if (!(query !== null && query !== void 0 && query.address) && !(query !== null && query !== void 0 && query.chain)) {
15
17
  return this.table.toArray();
@@ -10,3 +10,4 @@ export { default as MetadataStore } from './Metadata';
10
10
  export { default as MetadataV15Store } from './MetadataV15';
11
11
  export { default as ChainStore } from './Chain';
12
12
  export { default as AssetStore } from './Asset';
13
+ export { default as ProcessTransactionStore } from './ProcessTransaction';
@@ -12,4 +12,5 @@ export { default as MigrationStore } from "./Migration.js";
12
12
  export { default as MetadataStore } from "./Metadata.js";
13
13
  export { default as MetadataV15Store } from "./MetadataV15.js";
14
14
  export { default as ChainStore } from "./Chain.js";
15
- export { default as AssetStore } from "./Asset.js";
15
+ export { default as AssetStore } from "./Asset.js";
16
+ export { default as ProcessTransactionStore } from "./ProcessTransaction.js";
@@ -4,6 +4,7 @@
4
4
  import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
5
5
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
6
6
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
7
+ import { XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
7
8
  import { _getEarlyAssetHubValidationError, _validateBalanceToSwapOnAssetHub, _validateSwapRecipient } from '@subwallet/extension-base/core/logic-validation/swap';
8
9
  import { createXcmExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
9
10
  import { _getChainNativeTokenSlug, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
@@ -20,7 +21,18 @@ export class AssetHubSwapHandler {
20
21
  isReady = false;
21
22
  constructor(chainService, balanceService, feeService, chain) {
22
23
  const chainInfo = chainService.getChainInfoByKey(chain);
23
- const providerSlug = chain === 'statemint' ? SwapProviderId.POLKADOT_ASSET_HUB : chain === 'statemine' ? SwapProviderId.KUSAMA_ASSET_HUB : SwapProviderId.ROCOCO_ASSET_HUB;
24
+ const providerSlug = function () {
25
+ switch (chain) {
26
+ case 'statemint':
27
+ return SwapProviderId.POLKADOT_ASSET_HUB;
28
+ case 'statemine':
29
+ return SwapProviderId.KUSAMA_ASSET_HUB;
30
+ case 'westend_assethub':
31
+ return SwapProviderId.WESTEND_ASSET_HUB;
32
+ default:
33
+ return SwapProviderId.ROCOCO_ASSET_HUB;
34
+ }
35
+ }();
24
36
  this.swapBaseHandler = new SwapBaseHandler({
25
37
  balanceService,
26
38
  chainService,
@@ -78,21 +90,13 @@ export class AssetHubSwapHandler {
78
90
  try {
79
91
  const alternativeChainInfo = this.chainService.getChainInfoByKey(alternativeAsset.originChain);
80
92
  const originalChainInfo = this.chainService.getChainInfoByKey(this.chain);
81
- const step = {
82
- metadata: {
83
- sendingValue: bnAmount.toString(),
84
- originTokenInfo: alternativeAsset,
85
- destinationTokenInfo: fromAsset
86
- },
87
- name: `Transfer ${alternativeAsset.symbol} from ${alternativeChainInfo.name}`,
88
- type: CommonStepType.XCM
89
- };
90
93
  const xcmOriginSubstrateApi = await this.chainService.getSubstrateApi(alternativeAsset.originChain).isReady;
91
94
  const id = getId();
92
95
  const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(id, alternativeChainInfo.slug, 'substrate');
93
96
  const xcmTransfer = await createXcmExtrinsic({
94
97
  originTokenInfo: alternativeAsset,
95
98
  destinationTokenInfo: fromAsset,
99
+ // Mock sending value to get payment info
96
100
  sendingValue: bnAmount.toString(),
97
101
  recipient: params.request.address,
98
102
  sender: params.request.address,
@@ -106,12 +110,27 @@ export class AssetHubSwapHandler {
106
110
  const fee = {
107
111
  feeComponent: [{
108
112
  feeType: SwapFeeType.NETWORK_FEE,
109
- amount: Math.round(xcmFeeInfo.partialFee * 1.2).toString(),
113
+ amount: Math.round(xcmFeeInfo.partialFee * XCM_MIN_AMOUNT_RATIO).toString(),
110
114
  tokenSlug: _getChainNativeTokenSlug(alternativeChainInfo)
111
115
  }],
112
116
  defaultFeeToken: _getChainNativeTokenSlug(alternativeChainInfo),
113
117
  feeOptions: [_getChainNativeTokenSlug(alternativeChainInfo)]
114
118
  };
119
+ let bnTransferAmount = bnAmount.minus(bnFromAssetBalance);
120
+ if (_isNativeToken(alternativeAsset)) {
121
+ const bnXcmFee = new BigN(fee.feeComponent[0].amount); // xcm fee is paid in native token but swap token is not always native token
122
+
123
+ bnTransferAmount = bnTransferAmount.plus(bnXcmFee);
124
+ }
125
+ const step = {
126
+ metadata: {
127
+ sendingValue: bnTransferAmount.toString(),
128
+ originTokenInfo: alternativeAsset,
129
+ destinationTokenInfo: fromAsset
130
+ },
131
+ name: `Transfer ${alternativeAsset.symbol} from ${alternativeChainInfo.name}`,
132
+ type: CommonStepType.XCM
133
+ };
115
134
  return [step, fee];
116
135
  } catch (e) {
117
136
  console.error('Error creating xcm step', e);
@@ -7,6 +7,7 @@ import { _AssetType } from '@subwallet/chain-list/types';
7
7
  import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
8
8
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
9
9
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
10
+ import { XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
10
11
  import { _getEarlyHydradxValidationError } from '@subwallet/extension-base/core/logic-validation/swap';
11
12
  import { createXcmExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
12
13
  import { _getAssetDecimals, _getChainNativeTokenSlug, _getTokenOnChainAssetId, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
@@ -92,21 +93,13 @@ export class HydradxHandler {
92
93
  try {
93
94
  const alternativeChainInfo = this.chainService.getChainInfoByKey(alternativeAsset.originChain);
94
95
  const destChainInfo = this.chainService.getChainInfoByKey(this.chain());
95
- const step = {
96
- metadata: {
97
- sendingValue: bnAmount.toString(),
98
- originTokenInfo: alternativeAsset,
99
- destinationTokenInfo: fromAsset
100
- },
101
- name: `Transfer ${alternativeAsset.symbol} from ${alternativeChainInfo.name}`,
102
- type: CommonStepType.XCM
103
- };
104
96
  const xcmOriginSubstrateApi = await this.chainService.getSubstrateApi(alternativeAsset.originChain).isReady;
105
97
  const id = getId();
106
98
  const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(id, alternativeAsset.originChain, 'substrate');
107
99
  const xcmTransfer = await createXcmExtrinsic({
108
100
  originTokenInfo: alternativeAsset,
109
101
  destinationTokenInfo: fromAsset,
102
+ // Mock sending value to get payment info
110
103
  sendingValue: bnAmount.toString(),
111
104
  recipient: params.request.address,
112
105
  substrateApi: xcmOriginSubstrateApi,
@@ -120,12 +113,27 @@ export class HydradxHandler {
120
113
  const fee = {
121
114
  feeComponent: [{
122
115
  feeType: SwapFeeType.NETWORK_FEE,
123
- amount: Math.round(xcmFeeInfo.partialFee * 1.2).toString(),
116
+ amount: Math.round(xcmFeeInfo.partialFee * XCM_MIN_AMOUNT_RATIO).toString(),
124
117
  tokenSlug: _getChainNativeTokenSlug(alternativeChainInfo)
125
118
  }],
126
119
  defaultFeeToken: _getChainNativeTokenSlug(alternativeChainInfo),
127
120
  feeOptions: [_getChainNativeTokenSlug(alternativeChainInfo)]
128
121
  };
122
+ let bnTransferAmount = bnAmount.minus(bnFromAssetBalance);
123
+ if (_isNativeToken(alternativeAsset)) {
124
+ const bnXcmFee = new BigNumber(fee.feeComponent[0].amount); // xcm fee is paid in native token but swap token is not always native token
125
+
126
+ bnTransferAmount = bnTransferAmount.plus(bnXcmFee);
127
+ }
128
+ const step = {
129
+ metadata: {
130
+ sendingValue: bnTransferAmount.toString(),
131
+ originTokenInfo: alternativeAsset,
132
+ destinationTokenInfo: fromAsset
133
+ },
134
+ name: `Transfer ${alternativeAsset.symbol} from ${alternativeChainInfo.name}`,
135
+ type: CommonStepType.XCM
136
+ };
129
137
  return [step, fee];
130
138
  } catch (e) {
131
139
  console.error('Error creating xcm step', e);
@@ -158,6 +158,9 @@ export class SwapService {
158
158
  case SwapProviderId.ROCOCO_ASSET_HUB:
159
159
  this.handlers[providerId] = new AssetHubSwapHandler(this.chainService, this.state.balanceService, this.state.feeService, 'rococo_assethub');
160
160
  break;
161
+ case SwapProviderId.WESTEND_ASSET_HUB:
162
+ this.handlers[providerId] = new AssetHubSwapHandler(this.chainService, this.state.balanceService, this.state.feeService, 'westend_assethub');
163
+ break;
161
164
  case SwapProviderId.SIMPLE_SWAP:
162
165
  this.handlers[providerId] = new SimpleSwapHandler(this.chainService, this.state.balanceService, this.state.feeService);
163
166
  break;
@@ -51,6 +51,7 @@ export const _PROVIDER_TO_SUPPORTED_PAIR_MAP = {
51
51
  [SwapProviderId.POLKADOT_ASSET_HUB]: [COMMON_CHAIN_SLUGS.POLKADOT_ASSET_HUB],
52
52
  [SwapProviderId.KUSAMA_ASSET_HUB]: [COMMON_CHAIN_SLUGS.KUSAMA_ASSET_HUB],
53
53
  [SwapProviderId.ROCOCO_ASSET_HUB]: [COMMON_CHAIN_SLUGS.ROCOCO_ASSET_HUB],
54
+ [SwapProviderId.WESTEND_ASSET_HUB]: ['westend_assethub'],
54
55
  [SwapProviderId.SIMPLE_SWAP]: ['bittensor', COMMON_CHAIN_SLUGS.ETHEREUM, COMMON_CHAIN_SLUGS.POLKADOT]
55
56
  };
56
57
  export function getSwapAlternativeAsset(swapPair) {
@@ -1,17 +1,20 @@
1
1
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
2
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
3
3
  import { SWTransaction, SWTransactionInput, SWTransactionResponse, TransactionEmitter } from '@subwallet/extension-base/services/transaction-service/types';
4
+ import { BriefProcessStep, ProcessStep, ProcessTransactionData } from '@subwallet/extension-base/types';
4
5
  import { BehaviorSubject } from 'rxjs';
5
6
  import { TransactionConfig } from 'web3-core';
6
7
  import { HexString } from '@polkadot/util/types';
7
8
  export default class TransactionService {
8
9
  private readonly state;
9
- private readonly transactionSubject;
10
10
  private readonly eventService;
11
11
  private readonly historyService;
12
12
  private readonly notificationService;
13
13
  private readonly chainService;
14
14
  private readonly watchTransactionSubscribes;
15
+ private aliveProcessMap;
16
+ private readonly transactionSubject;
17
+ private readonly aliveProcessSubject;
15
18
  private get transactions();
16
19
  constructor(state: KoniState);
17
20
  private get allTransactions();
@@ -20,6 +23,15 @@ export default class TransactionService {
20
23
  private checkDuplicate;
21
24
  validateTransaction(transactionInput: SWTransactionInput): Promise<SWTransactionResponse>;
22
25
  getTransactionSubject(): BehaviorSubject<Record<string, SWTransaction>>;
26
+ get observables(): {
27
+ readonly transaction: import("rxjs").Observable<Record<string, SWTransaction>>;
28
+ readonly aliveProcess: import("rxjs").Observable<Record<string, ProcessTransactionData>>;
29
+ };
30
+ get values(): {
31
+ readonly transaction: Record<string, SWTransaction>;
32
+ readonly aliveProcess: Record<string, ProcessTransactionData>;
33
+ };
34
+ private updateAliveProcess;
23
35
  private fillTransactionDefaultInfo;
24
36
  addTransaction(inputTransaction: SWTransactionInput): Promise<TransactionEmitter>;
25
37
  generateBeforeHandleResponseErrors(errors: TransactionError[]): SWTransactionResponse;
@@ -42,5 +54,11 @@ export default class TransactionService {
42
54
  private signAndSendTonTransaction;
43
55
  private handleTransactionTimeout;
44
56
  private handlePostEarningTransaction;
57
+ createProcessIfNeed(process: ProcessTransactionData): Promise<void>;
58
+ checkProcessExist(processId: string): boolean;
59
+ private deleteProcess;
60
+ updateProcessStepStatus(step: BriefProcessStep, data: Pick<ProcessStep, 'status' | 'transactionId' | 'extrinsicHash' | 'chain'>): void;
61
+ updateProcessInfo(id: string, combineInfo: unknown, step?: ProcessStep): Promise<void>;
62
+ createProcessNotification(transactionId: string): Promise<void>;
45
63
  resetWallet(): void;
46
64
  }