@subwallet/extension-base 1.1.17-0 → 1.1.18-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 (48) hide show
  1. package/background/KoniTypes.d.ts +67 -1
  2. package/background/KoniTypes.js +5 -0
  3. package/cjs/background/KoniTypes.js +7 -1
  4. package/cjs/constants/index.js +6 -3
  5. package/cjs/koni/api/dotsama/crowdloan.js +106 -60
  6. package/cjs/koni/background/handlers/Extension.js +48 -0
  7. package/cjs/koni/background/handlers/State.js +25 -33
  8. package/cjs/koni/background/subscription.js +6 -2
  9. package/cjs/packageInfo.js +1 -1
  10. package/cjs/services/campaign-service/helpers.js +61 -0
  11. package/cjs/services/campaign-service/index.js +142 -0
  12. package/cjs/services/campaign-service/types.js +1 -0
  13. package/cjs/services/event-service/index.js +2 -0
  14. package/cjs/services/migration-service/index.js +4 -1
  15. package/cjs/services/notification-service/NotificationService.js +20 -6
  16. package/cjs/services/storage-service/DatabaseService.js +18 -1
  17. package/cjs/services/storage-service/databases/index.js +3 -0
  18. package/cjs/services/storage-service/db-stores/Campaign.js +35 -0
  19. package/constants/index.d.ts +1 -0
  20. package/constants/index.js +1 -0
  21. package/koni/api/dotsama/crowdloan.d.ts +7 -6
  22. package/koni/api/dotsama/crowdloan.js +103 -51
  23. package/koni/background/handlers/Extension.d.ts +2 -0
  24. package/koni/background/handlers/Extension.js +48 -1
  25. package/koni/background/handlers/State.d.ts +2 -0
  26. package/koni/background/handlers/State.js +4 -11
  27. package/koni/background/subscription.js +6 -2
  28. package/package.json +26 -6
  29. package/packageInfo.js +1 -1
  30. package/services/campaign-service/helpers.d.ts +3 -0
  31. package/services/campaign-service/helpers.js +54 -0
  32. package/services/campaign-service/index.d.ts +11 -0
  33. package/services/campaign-service/index.js +134 -0
  34. package/services/campaign-service/types.d.ts +34 -0
  35. package/services/campaign-service/types.js +1 -0
  36. package/services/event-service/index.d.ts +2 -0
  37. package/services/event-service/index.js +2 -0
  38. package/services/event-service/types.d.ts +2 -0
  39. package/services/migration-service/index.d.ts +3 -1
  40. package/services/migration-service/index.js +4 -1
  41. package/services/notification-service/NotificationService.d.ts +2 -2
  42. package/services/notification-service/NotificationService.js +20 -6
  43. package/services/storage-service/DatabaseService.d.ts +7 -1
  44. package/services/storage-service/DatabaseService.js +18 -1
  45. package/services/storage-service/databases/index.d.ts +3 -1
  46. package/services/storage-service/databases/index.js +3 -0
  47. package/services/storage-service/db-stores/Campaign.d.ts +9 -0
  48. package/services/storage-service/db-stores/Campaign.js +27 -0
@@ -13,6 +13,6 @@ const packageInfo = {
13
13
  name: '@subwallet/extension-base',
14
14
  path: typeof __dirname === 'string' ? __dirname : 'auto',
15
15
  type: 'cjs',
16
- version: '1.1.17-0'
16
+ version: '1.1.18-0'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.runCampaign = void 0;
7
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
8
+ var _i18next = require("i18next");
9
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
10
+ // SPDX-License-Identifier: Apache-2.0
11
+
12
+ const runCampaign = (notificationService, campaign) => {
13
+ const {
14
+ action,
15
+ message,
16
+ metadata,
17
+ title
18
+ } = campaign.data;
19
+ const {
20
+ buttons
21
+ } = campaign;
22
+ const onClick = (action, metadata) => {
23
+ return () => {
24
+ switch (action) {
25
+ case 'open_url':
26
+ {
27
+ if (metadata) {
28
+ const url = metadata.url;
29
+ if (url) {
30
+ window.open(url);
31
+ }
32
+ }
33
+ break;
34
+ }
35
+ default:
36
+ break;
37
+ }
38
+ };
39
+ };
40
+ const onButtonClick = btnIndex => {
41
+ const {
42
+ metadata,
43
+ type
44
+ } = buttons[btnIndex];
45
+ onClick(type, metadata)();
46
+ };
47
+ notificationService.notify({
48
+ type: _KoniTypes.NotificationType.SUCCESS,
49
+ title: (0, _i18next.t)(title),
50
+ message: (0, _i18next.t)(message),
51
+ action: {
52
+ buttonClick: onButtonClick,
53
+ click: onClick(action, metadata)
54
+ },
55
+ notifyViaBrowser: true,
56
+ buttons: buttons.map(button => ({
57
+ title: button.name
58
+ }))
59
+ });
60
+ };
61
+ exports.runCampaign = runCampaign;
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
9
+ var _constants = require("@subwallet/extension-base/constants");
10
+ var _utils = require("@subwallet/extension-base/utils");
11
+ var _axios = _interopRequireDefault(require("axios"));
12
+ var _helpers = require("./helpers");
13
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
14
+ // SPDX-License-Identifier: Apache-2.0
15
+
16
+ class CampaignService {
17
+ #state;
18
+ constructor(state) {
19
+ this.#state = state;
20
+ this.fetchCampaign().catch(e => {
21
+ console.error('Error on fetch campaigns', e);
22
+ });
23
+ this.runCampaign().catch(e => {
24
+ console.error('Error on run campaigns', e);
25
+ });
26
+ }
27
+ async fetchCampaign() {
28
+ const response = await _axios.default.request({
29
+ method: 'GET',
30
+ url: _constants.MARKETING_CAMPAIGN_URL
31
+ });
32
+ const respData = response.data;
33
+ const campaigns = [];
34
+ for (const data of respData) {
35
+ // eslint-disable-next-line camelcase
36
+ const {
37
+ condition,
38
+ end_time,
39
+ id: campaignId,
40
+ start_time
41
+ } = data;
42
+ const endTime = new Date(end_time).getTime();
43
+ const startTime = new Date(start_time).getTime();
44
+ for (const banner of data.banners) {
45
+ const {
46
+ buttons,
47
+ id,
48
+ ...baseData
49
+ } = banner;
50
+ const slug = `${campaignId}-banner-${id}`;
51
+ if (banner.environments.includes(_utils.TARGET_ENV)) {
52
+ campaigns.push({
53
+ slug,
54
+ endTime,
55
+ startTime,
56
+ isDone: false,
57
+ campaignId,
58
+ type: _KoniTypes.CampaignDataType.BANNER,
59
+ buttons,
60
+ data: baseData,
61
+ condition
62
+ });
63
+ }
64
+ }
65
+ for (const notification of data.notifications) {
66
+ const {
67
+ buttons,
68
+ id,
69
+ ...baseData
70
+ } = notification;
71
+ const slug = `${campaignId}-notification-${id}`;
72
+ campaigns.push({
73
+ slug,
74
+ endTime,
75
+ startTime,
76
+ isDone: false,
77
+ campaignId,
78
+ type: _KoniTypes.CampaignDataType.NOTIFICATION,
79
+ buttons,
80
+ data: baseData,
81
+ condition
82
+ });
83
+ }
84
+ }
85
+ for (const campaign of campaigns) {
86
+ const exists = await this.#state.dbService.getCampaign(campaign.slug);
87
+ if (!exists) {
88
+ await this.#state.dbService.upsertCampaign(campaign);
89
+ }
90
+ }
91
+ this.#state.eventService.emit('campaign.ready', true);
92
+ }
93
+ async runCampaign() {
94
+ await this.#state.eventService.waitCampaignReady;
95
+ const campaigns = (await this.getProcessingCampaign()).filter(data => data.type === _KoniTypes.CampaignDataType.NOTIFICATION);
96
+ campaigns.forEach(campaign => {
97
+ const {
98
+ isDone,
99
+ slug,
100
+ type
101
+ } = campaign;
102
+ if (isDone) {
103
+ return;
104
+ }
105
+ const onComplete = () => {
106
+ this.completeCampaignNotification(slug).catch(e => {
107
+ console.error('Error when complete campaign', slug, e);
108
+ });
109
+ };
110
+ try {
111
+ switch (type) {
112
+ case _KoniTypes.CampaignDataType.NOTIFICATION:
113
+ {
114
+ (0, _helpers.runCampaign)(this.#state.notificationService, campaign);
115
+ onComplete();
116
+ break;
117
+ }
118
+ default:
119
+ throw new Error('Missing handle campaign');
120
+ }
121
+ } catch (e) {
122
+ console.error('Error on running campaigns', slug, e);
123
+ }
124
+ });
125
+ }
126
+ getProcessingCampaign() {
127
+ return this.#state.dbService.getProcessingCampaign();
128
+ }
129
+ subscribeProcessingCampaign() {
130
+ return this.#state.dbService.subscribeProcessingCampaign();
131
+ }
132
+ async completeCampaignNotification(slug) {
133
+ const campaign = await this.#state.dbService.getCampaign(slug);
134
+ if (campaign) {
135
+ await this.#state.dbService.upsertCampaign({
136
+ ...campaign,
137
+ isDone: true
138
+ });
139
+ }
140
+ }
141
+ }
142
+ exports.default = CampaignService;
@@ -0,0 +1 @@
1
+ "use strict";
@@ -27,6 +27,8 @@ class EventService extends _eventemitter.default {
27
27
  this.waitAccountReady = this.generateWaitPromise('account.ready');
28
28
  this.waitChainReady = this.generateWaitPromise('chain.ready');
29
29
  this.waitAssetReady = this.generateWaitPromise('asset.ready');
30
+ this.waitMigrateReady = this.generateWaitPromise('migration.done');
31
+ this.waitCampaignReady = this.generateWaitPromise('campaign.ready');
30
32
  }
31
33
  generateWaitPromise(eventType) {
32
34
  return new Promise(resolve => {
@@ -12,8 +12,10 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
12
12
  // SPDX-License-Identifier: Apache-2.0
13
13
 
14
14
  class MigrationService {
15
- constructor(state) {
15
+ #eventService;
16
+ constructor(state, eventService) {
16
17
  this.state = state;
18
+ this.#eventService = eventService;
17
19
  this.logger = (0, _util.logger)('Migration');
18
20
  }
19
21
  async run() {
@@ -40,6 +42,7 @@ class MigrationService {
40
42
  this.logger.error('Migration error: ', _scripts.default[keys[i]].name, error);
41
43
  }
42
44
  }
45
+ this.#eventService.emit('migration.done', true);
43
46
  }
44
47
  }
45
48
  exports.default = MigrationService;
@@ -25,26 +25,40 @@ class NotificationService {
25
25
  });
26
26
  this.notificationSubject.next(notifications);
27
27
  if (notification.notifyViaBrowser) {
28
- var _notification$action;
29
- NotificationService.createBrowserNotification(notification.title, notification.message, notification === null || notification === void 0 ? void 0 : (_notification$action = notification.action) === null || _notification$action === void 0 ? void 0 : _notification$action.url);
28
+ NotificationService.createBrowserNotification(notification.title, notification.message, notification.action, notification.buttons);
30
29
  }
31
30
  }
32
31
 
33
32
  // Create a new chrome notification with link
34
- static createBrowserNotification(title, message, link) {
33
+ static createBrowserNotification(title, message, action, buttons) {
35
34
  var _chrome, _chrome$notifications;
35
+ const link = action === null || action === void 0 ? void 0 : action.url;
36
+ const onClick = action === null || action === void 0 ? void 0 : action.click;
37
+ const onButtonClick = action === null || action === void 0 ? void 0 : action.buttonClick;
36
38
  (_chrome = chrome) === null || _chrome === void 0 ? void 0 : (_chrome$notifications = _chrome.notifications) === null || _chrome$notifications === void 0 ? void 0 : _chrome$notifications.create({
37
39
  type: 'basic',
38
40
  title,
39
41
  message,
40
42
  iconUrl: './images/icon-128.png',
41
43
  priority: 2,
42
- isClickable: !!link
44
+ isClickable: !!link || !!onClick,
45
+ buttons
43
46
  }, notificationId => {
44
- if (link) {
47
+ if (link || onClick) {
45
48
  chrome.notifications.onClicked.addListener(nId => {
46
49
  if (nId === notificationId) {
47
- window.open(link);
50
+ if (onClick) {
51
+ onClick();
52
+ } else {
53
+ window.open(link);
54
+ }
55
+ }
56
+ });
57
+ }
58
+ if (onButtonClick) {
59
+ chrome.notifications.onButtonClicked.addListener((nId, btnIndex) => {
60
+ if (nId === notificationId) {
61
+ onButtonClick(btnIndex);
48
62
  }
49
63
  });
50
64
  }
@@ -8,6 +8,7 @@ exports.default = void 0;
8
8
  var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
9
9
  var _databases = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/databases"));
10
10
  var _dbStores = require("@subwallet/extension-base/services/storage-service/db-stores");
11
+ var _Campaign = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/Campaign"));
11
12
  var _ChainStakingMetadata = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/ChainStakingMetadata"));
12
13
  var _MantaPay = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/MantaPay"));
13
14
  var _NominatorMetadata = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/NominatorMetadata"));
@@ -41,7 +42,8 @@ class DatabaseService {
41
42
  // staking
42
43
  chainStakingMetadata: new _ChainStakingMetadata.default(this._db.chainStakingMetadata),
43
44
  nominatorMetadata: new _NominatorMetadata.default(this._db.nominatorMetadata),
44
- mantaPay: new _MantaPay.default(this._db.mantaPay)
45
+ mantaPay: new _MantaPay.default(this._db.mantaPay),
46
+ campaign: new _Campaign.default(this._db.campaign)
45
47
  };
46
48
  }
47
49
  async updatePriceStore(priceData) {
@@ -270,5 +272,20 @@ class DatabaseService {
270
272
  async getMantaPayFirstConfig(chain) {
271
273
  return this.stores.mantaPay.getFirstConfig(chain);
272
274
  }
275
+
276
+ /* Campaign */
277
+
278
+ subscribeProcessingCampaign() {
279
+ return this.stores.campaign.subscribeProcessingCampaign();
280
+ }
281
+ getProcessingCampaign() {
282
+ return this.stores.campaign.getProcessingCampaign();
283
+ }
284
+ getCampaign(slug) {
285
+ return this.stores.campaign.getCampaign(slug);
286
+ }
287
+ upsertCampaign(campaign) {
288
+ return this.stores.campaign.upsertCampaign(campaign);
289
+ }
273
290
  }
274
291
  exports.default = DatabaseService;
@@ -39,6 +39,9 @@ class KoniDatabase extends _dexie.default {
39
39
  this.conditionalVersion(3, {
40
40
  mantaPay: 'key, chain'
41
41
  });
42
+ this.conditionalVersion(4, {
43
+ campaign: 'slug'
44
+ });
42
45
  }
43
46
  conditionalVersion(version, schema, upgrade) {
44
47
  if (this.schemaVersion != null && this.schemaVersion < version) {
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _BaseStore = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/BaseStore"));
9
+ var _dexie = require("dexie");
10
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
11
+ // SPDX-License-Identifier: Apache-2.0
12
+
13
+ const filterProcessing = campaign => {
14
+ const now = new Date().getTime();
15
+ const isExpired = now <= campaign.startTime || now >= campaign.endTime;
16
+ return !(campaign.isDone || isExpired);
17
+ };
18
+ class CampaignStore extends _BaseStore.default {
19
+ async getAll() {
20
+ return this.table.toArray();
21
+ }
22
+ async getCampaign(slug) {
23
+ return this.table.get(slug);
24
+ }
25
+ async getProcessingCampaign() {
26
+ return (await this.table.toArray()).filter(filterProcessing);
27
+ }
28
+ subscribeProcessingCampaign() {
29
+ return (0, _dexie.liveQuery)(() => this.table.filter(filterProcessing).toArray());
30
+ }
31
+ upsertCampaign(campaign) {
32
+ return this.table.put(campaign);
33
+ }
34
+ }
35
+ exports.default = CampaignStore;
@@ -20,5 +20,6 @@ export declare const ALL_GENESIS_HASH: null;
20
20
  export declare const IGNORE_GET_SUBSTRATE_FEATURES_LIST: string[];
21
21
  export declare const IGNORE_QR_SIGNER: string[];
22
22
  export declare const XCM_MIN_AMOUNT_RATIO = 1.2;
23
+ export declare const MARKETING_CAMPAIGN_URL: string;
23
24
  export * from './staking';
24
25
  export * from './storage';
@@ -23,5 +23,6 @@ export const ALL_GENESIS_HASH = null;
23
23
  export const IGNORE_GET_SUBSTRATE_FEATURES_LIST = ['astarEvm', 'ethereum', 'ethereum_goerli', 'binance', 'binance_test', 'boba_rinkeby', 'boba', 'bobabase', 'bobabeam'];
24
24
  export const IGNORE_QR_SIGNER = [];
25
25
  export const XCM_MIN_AMOUNT_RATIO = 1.2;
26
+ export const MARKETING_CAMPAIGN_URL = process.env.MARKETING_CAMPAIGN_URL || '';
26
27
  export * from "./staking.js";
27
28
  export * from "./storage.js";
@@ -1,7 +1,8 @@
1
- import { _ChainInfo } from '@subwallet/chain-list/types';
2
- import { CrowdloanItem, CrowdloanParaState } from '@subwallet/extension-base/background/KoniTypes';
1
+ import { _ChainInfo, _CrowdloanFund } from '@subwallet/chain-list/types';
2
+ import { CrowdloanItem } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
4
- import { ApiPromise } from '@polkadot/api';
5
- export declare const subscribeAcalaContributeInterval: (polkadotAddresses: string[], paraState: CrowdloanParaState, callback: (rs: CrowdloanItem) => void) => () => void;
6
- export declare function getCrowdloanFundsStatus(api: ApiPromise): Promise<Record<string, CrowdloanParaState>>;
7
- export declare function subscribeCrowdloan(addresses: string[], substrateApiMap: Record<string, _SubstrateApi>, callback: (networkKey: string, rs: CrowdloanItem) => void, chainInfoMap: Record<string, _ChainInfo>): Promise<() => void>;
4
+ export declare type CrowdloanFundInfo = _CrowdloanFund & {
5
+ chain: string;
6
+ };
7
+ export declare const subscribeAcalaContributeInterval: (polkadotAddresses: string[], fundInfo: _CrowdloanFund, callback: (rs: CrowdloanItem) => void) => () => void;
8
+ export declare function subscribeCrowdloan(addresses: string[], substrateApiMap: Record<string, _SubstrateApi>, callback: (networkKey: string, rs: CrowdloanItem) => void, chainInfoMap: Record<string, _ChainInfo>): Promise<(() => void) | undefined>;
@@ -2,14 +2,34 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
5
+ import { _FundStatus } from '@subwallet/chain-list/types';
5
6
  import { APIItemState, CrowdloanParaState } from '@subwallet/extension-base/background/KoniTypes';
6
7
  import { ACALA_REFRESH_CROWDLOAN_INTERVAL } from '@subwallet/extension-base/constants';
7
8
  import registry from '@subwallet/extension-base/koni/api/dotsama/typeRegistry';
8
- import { _getChainSubstrateAddressPrefix, _getSubstrateParaId, _getSubstrateRelayParent, _isChainEvmCompatible, _isSubstrateParaChain } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import { categoryAddresses, reformatAddress } from '@subwallet/extension-base/utils';
10
10
  import axios from 'axios';
11
11
  import { BN } from '@polkadot/util';
12
- function getRPCCrowdloan(parentAPI, paraId, hexAddresses, paraState, callback) {
12
+ const STATUS_MAP = {
13
+ [_FundStatus.IN_AUCTION]: CrowdloanParaState.ONGOING,
14
+ [_FundStatus.WITHDRAW]: CrowdloanParaState.FAILED,
15
+ [_FundStatus.FAILED]: CrowdloanParaState.FAILED,
16
+ [_FundStatus.WON]: CrowdloanParaState.COMPLETED
17
+ };
18
+ const getOnlineFundList = (async () => {
19
+ const request = await axios.get('https://static-data.subwallet.app/crowdloan-funds/list.json');
20
+ return request.data;
21
+ })();
22
+ function getRPCCrowdloan(parentAPI, fundInfo, hexAddresses, callback) {
23
+ const {
24
+ auctionIndex,
25
+ endTime,
26
+ firstPeriod,
27
+ fundId,
28
+ lastPeriod,
29
+ paraId,
30
+ startTime,
31
+ status
32
+ } = fundInfo;
13
33
  const unsubPromise = parentAPI.api.derive.crowdloan.ownContributions(paraId, hexAddresses, result => {
14
34
  let contribute = new BN(0);
15
35
  Object.values(result).forEach(item => {
@@ -17,8 +37,16 @@ function getRPCCrowdloan(parentAPI, paraId, hexAddresses, paraState, callback) {
17
37
  });
18
38
  const rs = {
19
39
  state: APIItemState.READY,
20
- paraState,
21
- contribute: contribute.toString()
40
+ paraState: STATUS_MAP[fundInfo.status],
41
+ contribute: contribute.toString(),
42
+ fundId,
43
+ paraId,
44
+ status,
45
+ startTime,
46
+ endTime,
47
+ auctionIndex,
48
+ firstPeriod,
49
+ lastPeriod
22
50
  };
23
51
  callback(rs);
24
52
  });
@@ -28,7 +56,18 @@ function getRPCCrowdloan(parentAPI, paraId, hexAddresses, paraState, callback) {
28
56
  }).catch(console.error);
29
57
  };
30
58
  }
31
- export const subscribeAcalaContributeInterval = (polkadotAddresses, paraState, callback) => {
59
+ export const subscribeAcalaContributeInterval = (polkadotAddresses, fundInfo, callback) => {
60
+ const {
61
+ auctionIndex,
62
+ endTime,
63
+ firstPeriod,
64
+ fundId,
65
+ lastPeriod,
66
+ paraId,
67
+ startTime,
68
+ status
69
+ } = fundInfo;
70
+ const paraState = STATUS_MAP[fundInfo.status];
32
71
  const acalaContributionApi = 'https://api.polkawallet.io/acala-distribution-v2/crowdloan?account=';
33
72
  const getContributeInfo = () => {
34
73
  Promise.all(polkadotAddresses.map(polkadotAddress => {
@@ -37,14 +76,21 @@ export const subscribeAcalaContributeInterval = (polkadotAddresses, paraState, c
37
76
  let contribute = new BN(0);
38
77
  resList.forEach(res => {
39
78
  var _res$data$data, _res$data$data$acala, _res$data$data$acala$;
40
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
79
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access
41
80
  contribute = contribute.add(new BN(((_res$data$data = res.data.data) === null || _res$data$data === void 0 ? void 0 : (_res$data$data$acala = _res$data$data.acala) === null || _res$data$data$acala === void 0 ? void 0 : (_res$data$data$acala$ = _res$data$data$acala[0]) === null || _res$data$data$acala$ === void 0 ? void 0 : _res$data$data$acala$.totalDOTLocked) || '0'));
42
81
  });
43
82
  const rs = {
44
83
  state: APIItemState.READY,
45
84
  paraState,
46
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
47
- contribute: contribute.toString()
85
+ contribute: contribute.toString(),
86
+ fundId,
87
+ paraId,
88
+ status,
89
+ startTime,
90
+ endTime,
91
+ auctionIndex,
92
+ firstPeriod,
93
+ lastPeriod
48
94
  };
49
95
  callback(rs);
50
96
  }).catch(console.error);
@@ -55,64 +101,70 @@ export const subscribeAcalaContributeInterval = (polkadotAddresses, paraState, c
55
101
  clearInterval(interval);
56
102
  };
57
103
  };
58
- export async function getCrowdloanFundsStatus(api) {
59
- const leases = await api.query.slots.leases.keys();
60
- const leasesParaIds = leases.map(({
61
- args: [paraId]
62
- }) => paraId.toString());
63
- const rs = await api.query.crowdloan.funds.entries();
64
- const newRaise = await api.query.crowdloan.newRaise();
65
- const newRaiseParaIds = newRaise.toJSON().map(p => p.toString());
66
- return rs.reduce((stateMap, [{
67
- args: [paraId]
68
- }, fundData]) => {
69
- const paraStr = paraId.toString();
70
104
 
71
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
72
- // const item = fundData.unwrap() as PolkadotRuntimeCommonCrowdloanFundInfo;
105
+ // export async function getCrowdloanFundsStatus (api: ApiPromise) {
106
+ // const leases = await api.query.slots.leases.keys<ParaId[]>();
107
+ // const leasesParaIds = leases.map(({ args: [paraId] }) => paraId.toString());
73
108
 
74
- if (leasesParaIds.indexOf(paraStr) > -1) {
75
- stateMap[paraStr] = CrowdloanParaState.COMPLETED;
76
- }
77
- if (newRaiseParaIds.indexOf(paraStr) > -1) {
78
- stateMap[paraStr] = CrowdloanParaState.ONGOING;
79
- }
80
- return stateMap;
81
- }, {});
82
- }
109
+ // const rs = await api.query.crowdloan.funds.entries<Option<any>, ParaId[]>();
110
+ // const newRaise = await api.query.crowdloan.newRaise<Vec<u32>>();
111
+
112
+ // const newRaiseParaIds = (newRaise.toJSON() as number[]).map((p) => p.toString());
113
+
114
+ // return rs.reduce((stateMap, [{ args: [paraId] }, fundData]) => {
115
+ // const paraStr = paraId.toString();
116
+ // // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
117
+ // // const item = fundData.unwrap() as PolkadotRuntimeCommonCrowdloanFundInfo;
118
+ // if (leasesParaIds.indexOf(paraStr) > -1) {
119
+ // stateMap[paraStr] = CrowdloanParaState.COMPLETED;
120
+ // }
121
+ // if (newRaiseParaIds.indexOf(paraStr) > -1) {
122
+ // stateMap[paraStr] = CrowdloanParaState.ONGOING;
123
+ // }
124
+ // return stateMap;
125
+ // }, {} as Record<string, CrowdloanParaState>);
126
+ // }
83
127
 
84
128
  // Get All crowdloan
85
129
  export async function subscribeCrowdloan(addresses, substrateApiMap, callback, chainInfoMap) {
86
130
  const unsubMap = {};
131
+ const latestMap = {};
132
+ const rawFundList = await getOnlineFundList;
133
+ rawFundList.forEach(fundInfo => {
134
+ const chainSlug = fundInfo.chain;
135
+ if (!latestMap[chainSlug] || fundInfo.auctionIndex > latestMap[chainSlug].auctionIndex) {
136
+ latestMap[chainSlug] = fundInfo;
137
+ }
138
+ });
87
139
  if (Object.keys(substrateApiMap).includes(COMMON_CHAIN_SLUGS.KUSAMA) && Object.keys(substrateApiMap).includes(COMMON_CHAIN_SLUGS.POLKADOT)) {
140
+ const now = Date.now();
88
141
  const polkadotAPI = await substrateApiMap[COMMON_CHAIN_SLUGS.POLKADOT].isReady;
89
- const polkadotFundsStatusMap = await getCrowdloanFundsStatus(polkadotAPI.api);
90
142
  const kusamaAPI = await substrateApiMap[COMMON_CHAIN_SLUGS.KUSAMA].isReady;
91
- const kusamaFundsStatusMap = await getCrowdloanFundsStatus(kusamaAPI.api);
92
-
93
- // TODO: find all crowdloan valid networks: parachains, in-crowdloan, crowdloan but failed
94
-
95
143
  const substrateAddresses = categoryAddresses(addresses)[0];
96
144
  const hexAddresses = substrateAddresses.map(address => {
97
145
  return registry.createType('AccountId', address).toHex();
98
146
  });
99
- Object.entries(chainInfoMap).forEach(([networkKey, chainInfo]) => {
100
- if (_isSubstrateParaChain(chainInfo)) {
101
- const parentChain = _getSubstrateRelayParent(chainInfo);
147
+ if (addresses.length === 0) {
148
+ return;
149
+ }
150
+ Object.values(latestMap).forEach(fundInfo => {
151
+ var _chainInfoMap$chainSl;
152
+ const chainSlug = fundInfo.chain;
153
+ const endTime = new Date(fundInfo.endTime).getTime();
154
+ const parentChain = fundInfo.relayChain;
155
+ const substrateInfo = (_chainInfoMap$chainSl = chainInfoMap[chainSlug]) === null || _chainInfoMap$chainSl === void 0 ? void 0 : _chainInfoMap$chainSl.substrateInfo;
156
+ if (chainSlug && parentChain && STATUS_MAP[fundInfo.status] && fundInfo.paraId && endTime > now && substrateInfo) {
102
157
  const crowdloanCb = rs => {
103
- callback(networkKey, rs);
158
+ callback(chainSlug, rs);
104
159
  };
105
- const paraId = _getSubstrateParaId(chainInfo);
106
- if (paraId <= -1 || addresses.length === 0 || parentChain.length === 0) {
107
- return;
108
- }
109
- if (networkKey === COMMON_CHAIN_SLUGS.ACALA) {
110
- const acalaAddresses = substrateAddresses.map(address => reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo), _isChainEvmCompatible(chainInfo)));
111
- unsubMap.acala = subscribeAcalaContributeInterval(acalaAddresses, CrowdloanParaState.COMPLETED, crowdloanCb);
112
- } else if (parentChain === COMMON_CHAIN_SLUGS.POLKADOT && polkadotFundsStatusMap[paraId]) {
113
- unsubMap[networkKey] = getRPCCrowdloan(polkadotAPI, paraId, hexAddresses, polkadotFundsStatusMap[paraId], crowdloanCb);
114
- } else if (parentChain === COMMON_CHAIN_SLUGS.KUSAMA && kusamaFundsStatusMap[paraId]) {
115
- unsubMap[networkKey] = getRPCCrowdloan(kusamaAPI, paraId, hexAddresses, kusamaFundsStatusMap[paraId], crowdloanCb);
160
+ fundInfo.paraId = substrateInfo.crowdloanParaId || substrateInfo.paraId || fundInfo.paraId;
161
+ if (chainSlug === COMMON_CHAIN_SLUGS.ACALA) {
162
+ const acalaAddresses = substrateAddresses.map(address => reformatAddress(address, 10, false));
163
+ unsubMap.acala = subscribeAcalaContributeInterval(acalaAddresses, fundInfo, crowdloanCb);
164
+ } else if (parentChain === COMMON_CHAIN_SLUGS.POLKADOT) {
165
+ unsubMap[chainSlug] = getRPCCrowdloan(polkadotAPI, fundInfo, hexAddresses, crowdloanCb);
166
+ } else if (parentChain === COMMON_CHAIN_SLUGS.KUSAMA) {
167
+ unsubMap[chainSlug] = getRPCCrowdloan(kusamaAPI, fundInfo, hexAddresses, crowdloanCb);
116
168
  }
117
169
  }
118
170
  });
@@ -213,5 +213,7 @@ export default class KoniExtension {
213
213
  private resolveAddressByDomain;
214
214
  private addInjects;
215
215
  private removeInjects;
216
+ private subscribeProcessingBanner;
217
+ private completeCampaignBanner;
216
218
  handle<TMessageType extends MessageTypes>(id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseType<TMessageType>>;
217
219
  }