@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.
- package/background/KoniTypes.d.ts +67 -1
- package/background/KoniTypes.js +5 -0
- package/cjs/background/KoniTypes.js +7 -1
- package/cjs/constants/index.js +6 -3
- package/cjs/koni/api/dotsama/crowdloan.js +106 -60
- package/cjs/koni/background/handlers/Extension.js +48 -0
- package/cjs/koni/background/handlers/State.js +25 -33
- package/cjs/koni/background/subscription.js +6 -2
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/campaign-service/helpers.js +61 -0
- package/cjs/services/campaign-service/index.js +142 -0
- package/cjs/services/campaign-service/types.js +1 -0
- package/cjs/services/event-service/index.js +2 -0
- package/cjs/services/migration-service/index.js +4 -1
- package/cjs/services/notification-service/NotificationService.js +20 -6
- package/cjs/services/storage-service/DatabaseService.js +18 -1
- package/cjs/services/storage-service/databases/index.js +3 -0
- package/cjs/services/storage-service/db-stores/Campaign.js +35 -0
- package/constants/index.d.ts +1 -0
- package/constants/index.js +1 -0
- package/koni/api/dotsama/crowdloan.d.ts +7 -6
- package/koni/api/dotsama/crowdloan.js +103 -51
- package/koni/background/handlers/Extension.d.ts +2 -0
- package/koni/background/handlers/Extension.js +48 -1
- package/koni/background/handlers/State.d.ts +2 -0
- package/koni/background/handlers/State.js +4 -11
- package/koni/background/subscription.js +6 -2
- package/package.json +26 -6
- package/packageInfo.js +1 -1
- package/services/campaign-service/helpers.d.ts +3 -0
- package/services/campaign-service/helpers.js +54 -0
- package/services/campaign-service/index.d.ts +11 -0
- package/services/campaign-service/index.js +134 -0
- package/services/campaign-service/types.d.ts +34 -0
- package/services/campaign-service/types.js +1 -0
- package/services/event-service/index.d.ts +2 -0
- package/services/event-service/index.js +2 -0
- package/services/event-service/types.d.ts +2 -0
- package/services/migration-service/index.d.ts +3 -1
- package/services/migration-service/index.js +4 -1
- package/services/notification-service/NotificationService.d.ts +2 -2
- package/services/notification-service/NotificationService.js +20 -6
- package/services/storage-service/DatabaseService.d.ts +7 -1
- package/services/storage-service/DatabaseService.js +18 -1
- package/services/storage-service/databases/index.d.ts +3 -1
- package/services/storage-service/databases/index.js +3 -0
- package/services/storage-service/db-stores/Campaign.d.ts +9 -0
- package/services/storage-service/db-stores/Campaign.js +27 -0
package/cjs/packageInfo.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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;
|
package/constants/index.d.ts
CHANGED
|
@@ -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';
|
package/constants/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export declare
|
|
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
|
-
|
|
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,
|
|
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-
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
|
|
72
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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(
|
|
158
|
+
callback(chainSlug, rs);
|
|
104
159
|
};
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
}
|