@subwallet/extension-base 1.1.17-0 → 1.1.18-1

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 (57) 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/api/nft/acala_nft/index.js +1 -1
  7. package/cjs/koni/api/nft/config.js +21 -1
  8. package/cjs/koni/api/nft/karura_nft/index.js +1 -1
  9. package/cjs/koni/api/nft/vara_nft/index.js +19 -17
  10. package/cjs/koni/background/handlers/Extension.js +49 -1
  11. package/cjs/koni/background/handlers/State.js +25 -33
  12. package/cjs/koni/background/subscription.js +6 -2
  13. package/cjs/packageInfo.js +1 -1
  14. package/cjs/services/campaign-service/helpers.js +61 -0
  15. package/cjs/services/campaign-service/index.js +142 -0
  16. package/cjs/services/campaign-service/types.js +1 -0
  17. package/cjs/services/event-service/index.js +2 -0
  18. package/cjs/services/migration-service/index.js +4 -1
  19. package/cjs/services/notification-service/NotificationService.js +20 -6
  20. package/cjs/services/storage-service/DatabaseService.js +18 -1
  21. package/cjs/services/storage-service/databases/index.js +3 -0
  22. package/cjs/services/storage-service/db-stores/Campaign.js +35 -0
  23. package/constants/index.d.ts +1 -0
  24. package/constants/index.js +1 -0
  25. package/koni/api/dotsama/crowdloan.d.ts +7 -6
  26. package/koni/api/dotsama/crowdloan.js +103 -51
  27. package/koni/api/nft/acala_nft/index.js +1 -1
  28. package/koni/api/nft/config.d.ts +4 -0
  29. package/koni/api/nft/config.js +16 -0
  30. package/koni/api/nft/karura_nft/index.js +1 -1
  31. package/koni/api/nft/vara_nft/index.js +19 -17
  32. package/koni/background/handlers/Extension.d.ts +2 -0
  33. package/koni/background/handlers/Extension.js +49 -2
  34. package/koni/background/handlers/State.d.ts +2 -0
  35. package/koni/background/handlers/State.js +4 -11
  36. package/koni/background/subscription.js +6 -2
  37. package/package.json +27 -6
  38. package/packageInfo.js +1 -1
  39. package/services/campaign-service/helpers.d.ts +3 -0
  40. package/services/campaign-service/helpers.js +54 -0
  41. package/services/campaign-service/index.d.ts +11 -0
  42. package/services/campaign-service/index.js +134 -0
  43. package/services/campaign-service/types.d.ts +34 -0
  44. package/services/campaign-service/types.js +1 -0
  45. package/services/event-service/index.d.ts +2 -0
  46. package/services/event-service/index.js +2 -0
  47. package/services/event-service/types.d.ts +2 -0
  48. package/services/migration-service/index.d.ts +3 -1
  49. package/services/migration-service/index.js +4 -1
  50. package/services/notification-service/NotificationService.d.ts +2 -2
  51. package/services/notification-service/NotificationService.js +20 -6
  52. package/services/storage-service/DatabaseService.d.ts +7 -1
  53. package/services/storage-service/DatabaseService.js +18 -1
  54. package/services/storage-service/databases/index.d.ts +3 -1
  55. package/services/storage-service/databases/index.js +3 -0
  56. package/services/storage-service/db-stores/Campaign.d.ts +9 -0
  57. package/services/storage-service/db-stores/Campaign.js +27 -0
@@ -0,0 +1,134 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { CampaignDataType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { MARKETING_CAMPAIGN_URL } from '@subwallet/extension-base/constants';
6
+ import { TARGET_ENV } from '@subwallet/extension-base/utils';
7
+ import axios from 'axios';
8
+ import { runCampaign } from "./helpers.js";
9
+ export default class CampaignService {
10
+ #state;
11
+ constructor(state) {
12
+ this.#state = state;
13
+ this.fetchCampaign().catch(e => {
14
+ console.error('Error on fetch campaigns', e);
15
+ });
16
+ this.runCampaign().catch(e => {
17
+ console.error('Error on run campaigns', e);
18
+ });
19
+ }
20
+ async fetchCampaign() {
21
+ const response = await axios.request({
22
+ method: 'GET',
23
+ url: MARKETING_CAMPAIGN_URL
24
+ });
25
+ const respData = response.data;
26
+ const campaigns = [];
27
+ for (const data of respData) {
28
+ // eslint-disable-next-line camelcase
29
+ const {
30
+ condition,
31
+ end_time,
32
+ id: campaignId,
33
+ start_time
34
+ } = data;
35
+ const endTime = new Date(end_time).getTime();
36
+ const startTime = new Date(start_time).getTime();
37
+ for (const banner of data.banners) {
38
+ const {
39
+ buttons,
40
+ id,
41
+ ...baseData
42
+ } = banner;
43
+ const slug = `${campaignId}-banner-${id}`;
44
+ if (banner.environments.includes(TARGET_ENV)) {
45
+ campaigns.push({
46
+ slug,
47
+ endTime,
48
+ startTime,
49
+ isDone: false,
50
+ campaignId,
51
+ type: CampaignDataType.BANNER,
52
+ buttons,
53
+ data: baseData,
54
+ condition
55
+ });
56
+ }
57
+ }
58
+ for (const notification of data.notifications) {
59
+ const {
60
+ buttons,
61
+ id,
62
+ ...baseData
63
+ } = notification;
64
+ const slug = `${campaignId}-notification-${id}`;
65
+ campaigns.push({
66
+ slug,
67
+ endTime,
68
+ startTime,
69
+ isDone: false,
70
+ campaignId,
71
+ type: CampaignDataType.NOTIFICATION,
72
+ buttons,
73
+ data: baseData,
74
+ condition
75
+ });
76
+ }
77
+ }
78
+ for (const campaign of campaigns) {
79
+ const exists = await this.#state.dbService.getCampaign(campaign.slug);
80
+ if (!exists) {
81
+ await this.#state.dbService.upsertCampaign(campaign);
82
+ }
83
+ }
84
+ this.#state.eventService.emit('campaign.ready', true);
85
+ }
86
+ async runCampaign() {
87
+ await this.#state.eventService.waitCampaignReady;
88
+ const campaigns = (await this.getProcessingCampaign()).filter(data => data.type === CampaignDataType.NOTIFICATION);
89
+ campaigns.forEach(campaign => {
90
+ const {
91
+ isDone,
92
+ slug,
93
+ type
94
+ } = campaign;
95
+ if (isDone) {
96
+ return;
97
+ }
98
+ const onComplete = () => {
99
+ this.completeCampaignNotification(slug).catch(e => {
100
+ console.error('Error when complete campaign', slug, e);
101
+ });
102
+ };
103
+ try {
104
+ switch (type) {
105
+ case CampaignDataType.NOTIFICATION:
106
+ {
107
+ runCampaign(this.#state.notificationService, campaign);
108
+ onComplete();
109
+ break;
110
+ }
111
+ default:
112
+ throw new Error('Missing handle campaign');
113
+ }
114
+ } catch (e) {
115
+ console.error('Error on running campaigns', slug, e);
116
+ }
117
+ });
118
+ }
119
+ getProcessingCampaign() {
120
+ return this.#state.dbService.getProcessingCampaign();
121
+ }
122
+ subscribeProcessingCampaign() {
123
+ return this.#state.dbService.subscribeProcessingCampaign();
124
+ }
125
+ async completeCampaignNotification(slug) {
126
+ const campaign = await this.#state.dbService.getCampaign(slug);
127
+ if (campaign) {
128
+ await this.#state.dbService.upsertCampaign({
129
+ ...campaign,
130
+ isDone: true
131
+ });
132
+ }
133
+ }
134
+ }
@@ -0,0 +1,34 @@
1
+ import { CampaignAction, CampaignButton } from '@subwallet/extension-base/background/KoniTypes';
2
+ declare type Metadata = Record<string, any> | null;
3
+ interface _BannerData {
4
+ id: number;
5
+ alt: string;
6
+ action: CampaignAction;
7
+ metadata: Metadata;
8
+ environments: string[];
9
+ position: string[];
10
+ buttons: CampaignButton[];
11
+ media: string;
12
+ }
13
+ interface _NotificationData {
14
+ id: number;
15
+ title: string;
16
+ message: string;
17
+ repeat: number;
18
+ repeatAfter: number;
19
+ action: CampaignAction;
20
+ metadata: Metadata;
21
+ buttons: CampaignButton[];
22
+ }
23
+ interface _CampaignData {
24
+ id: number;
25
+ name: string;
26
+ description: null;
27
+ start_time: string;
28
+ end_time: string;
29
+ condition: Metadata;
30
+ banners: _BannerData[];
31
+ notifications: _NotificationData[];
32
+ }
33
+ export declare type ListCampaignResponse = _CampaignData[];
34
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -11,6 +11,8 @@ export declare class EventService extends EventEmitter<EventRegistry> {
11
11
  readonly waitAccountReady: Promise<boolean>;
12
12
  readonly waitChainReady: Promise<boolean>;
13
13
  readonly waitAssetReady: Promise<boolean>;
14
+ readonly waitMigrateReady: Promise<boolean>;
15
+ readonly waitCampaignReady: Promise<boolean>;
14
16
  constructor(options?: {
15
17
  lazyTime: number;
16
18
  });
@@ -19,6 +19,8 @@ export class EventService extends EventEmitter {
19
19
  this.waitAccountReady = this.generateWaitPromise('account.ready');
20
20
  this.waitChainReady = this.generateWaitPromise('chain.ready');
21
21
  this.waitAssetReady = this.generateWaitPromise('asset.ready');
22
+ this.waitMigrateReady = this.generateWaitPromise('migration.done');
23
+ this.waitCampaignReady = this.generateWaitPromise('campaign.ready');
22
24
  }
23
25
  generateWaitPromise(eventType) {
24
26
  return new Promise(resolve => {
@@ -23,6 +23,8 @@ export interface EventRegistry {
23
23
  'mantaPay.initSync': [string | undefined];
24
24
  'mantaPay.submitTransaction': [SWTransaction | undefined];
25
25
  'mantaPay.enable': [string];
26
+ 'migration.done': [boolean];
27
+ 'campaign.ready': [boolean];
26
28
  }
27
29
  export declare type EventType = keyof EventRegistry;
28
30
  export declare const COMMON_RELOAD_EVENTS: EventType[];
@@ -1,7 +1,9 @@
1
1
  import State from '@subwallet/extension-base/koni/background/handlers/State';
2
+ import { EventService } from '@subwallet/extension-base/services/event-service';
2
3
  export default class MigrationService {
4
+ #private;
3
5
  readonly state: State;
4
6
  private logger;
5
- constructor(state: State);
7
+ constructor(state: State, eventService: EventService);
6
8
  run(): Promise<void>;
7
9
  }
@@ -4,8 +4,10 @@
4
4
  import { logger as createLogger } from '@polkadot/util';
5
5
  import MigrationScripts, { EVERYTIME } from "./scripts/index.js";
6
6
  export default class MigrationService {
7
- constructor(state) {
7
+ #eventService;
8
+ constructor(state, eventService) {
8
9
  this.state = state;
10
+ this.#eventService = eventService;
9
11
  this.logger = createLogger('Migration');
10
12
  }
11
13
  async run() {
@@ -32,5 +34,6 @@ export default class MigrationService {
32
34
  this.logger.error('Migration error: ', MigrationScripts[keys[i]].name, error);
33
35
  }
34
36
  }
37
+ this.#eventService.emit('migration.done', true);
35
38
  }
36
39
  }
@@ -1,8 +1,8 @@
1
- import { Notification, NotificationParams } from '@subwallet/extension-base/background/KoniTypes';
1
+ import { Notification, NotificationButton, NotificationParams } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import { BehaviorSubject } from 'rxjs';
3
3
  export default class NotificationService {
4
4
  private notificationSubject;
5
5
  getNotificationSubject(): BehaviorSubject<Notification[]>;
6
6
  notify(notification: NotificationParams): void;
7
- static createBrowserNotification(title: string, message: string, link?: string): void;
7
+ static createBrowserNotification(title: string, message: string, action?: NotificationParams['action'], buttons?: NotificationButton[]): void;
8
8
  }
@@ -19,26 +19,40 @@ export default class NotificationService {
19
19
  });
20
20
  this.notificationSubject.next(notifications);
21
21
  if (notification.notifyViaBrowser) {
22
- var _notification$action;
23
- 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);
22
+ NotificationService.createBrowserNotification(notification.title, notification.message, notification.action, notification.buttons);
24
23
  }
25
24
  }
26
25
 
27
26
  // Create a new chrome notification with link
28
- static createBrowserNotification(title, message, link) {
27
+ static createBrowserNotification(title, message, action, buttons) {
29
28
  var _chrome, _chrome$notifications;
29
+ const link = action === null || action === void 0 ? void 0 : action.url;
30
+ const onClick = action === null || action === void 0 ? void 0 : action.click;
31
+ const onButtonClick = action === null || action === void 0 ? void 0 : action.buttonClick;
30
32
  (_chrome = chrome) === null || _chrome === void 0 ? void 0 : (_chrome$notifications = _chrome.notifications) === null || _chrome$notifications === void 0 ? void 0 : _chrome$notifications.create({
31
33
  type: 'basic',
32
34
  title,
33
35
  message,
34
36
  iconUrl: './images/icon-128.png',
35
37
  priority: 2,
36
- isClickable: !!link
38
+ isClickable: !!link || !!onClick,
39
+ buttons
37
40
  }, notificationId => {
38
- if (link) {
41
+ if (link || onClick) {
39
42
  chrome.notifications.onClicked.addListener(nId => {
40
43
  if (nId === notificationId) {
41
- window.open(link);
44
+ if (onClick) {
45
+ onClick();
46
+ } else {
47
+ window.open(link);
48
+ }
49
+ }
50
+ });
51
+ }
52
+ if (onButtonClick) {
53
+ chrome.notifications.onButtonClicked.addListener((nId, btnIndex) => {
54
+ if (nId === notificationId) {
55
+ onButtonClick(btnIndex);
42
56
  }
43
57
  });
44
58
  }
@@ -1,8 +1,9 @@
1
1
  import { _ChainAsset } from '@subwallet/chain-list/types';
2
2
  import { BalanceItem, ChainStakingMetadata, CrowdloanItem, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, StakingType, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { EventService } from '@subwallet/extension-base/services/event-service';
4
- import { IBalance, IChain, INft } from '@subwallet/extension-base/services/storage-service/databases';
4
+ import { IBalance, ICampaign, IChain, INft } from '@subwallet/extension-base/services/storage-service/databases';
5
5
  import { AssetStore, BalanceStore, ChainStore, CrowdloanStore, MetadataStore, MigrationStore, NftCollectionStore, NftStore, PriceStore, StakingStore, TransactionStore } from '@subwallet/extension-base/services/storage-service/db-stores';
6
+ import CampaignStore from '@subwallet/extension-base/services/storage-service/db-stores/Campaign';
6
7
  import ChainStakingMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/ChainStakingMetadata';
7
8
  import MantaPayStore from '@subwallet/extension-base/services/storage-service/db-stores/MantaPay';
8
9
  import NominatorMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/NominatorMetadata';
@@ -26,6 +27,7 @@ export default class DatabaseService {
26
27
  chainStakingMetadata: ChainStakingMetadataStore;
27
28
  nominatorMetadata: NominatorMetadataStore;
28
29
  mantaPay: MantaPayStore;
30
+ campaign: CampaignStore;
29
31
  };
30
32
  private logger;
31
33
  private nftSubscription;
@@ -77,4 +79,8 @@ export default class DatabaseService {
77
79
  subscribeMantaPayConfig(chain: string, callback: (data: MantaPayConfig[]) => void): void;
78
80
  getMantaPayConfig(chain: string): Promise<any[]>;
79
81
  getMantaPayFirstConfig(chain: string): Promise<any>;
82
+ subscribeProcessingCampaign(): import("dexie").Observable<import("@subwallet/extension-base/background/KoniTypes").CampaignData[]>;
83
+ getProcessingCampaign(): Promise<import("@subwallet/extension-base/background/KoniTypes").CampaignData[]>;
84
+ getCampaign(slug: string): Promise<import("@subwallet/extension-base/background/KoniTypes").CampaignData | undefined>;
85
+ upsertCampaign(campaign: ICampaign): import("dexie").PromiseExtended<unknown>;
80
86
  }
@@ -4,6 +4,7 @@
4
4
  import { APIItemState, StakingType } from '@subwallet/extension-base/background/KoniTypes';
5
5
  import KoniDatabase from '@subwallet/extension-base/services/storage-service/databases';
6
6
  import { AssetStore, BalanceStore, ChainStore, CrowdloanStore, MetadataStore, MigrationStore, NftCollectionStore, NftStore, PriceStore, StakingStore, TransactionStore } from '@subwallet/extension-base/services/storage-service/db-stores';
7
+ import CampaignStore from '@subwallet/extension-base/services/storage-service/db-stores/Campaign';
7
8
  import ChainStakingMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/ChainStakingMetadata';
8
9
  import MantaPayStore from '@subwallet/extension-base/services/storage-service/db-stores/MantaPay';
9
10
  import NominatorMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/NominatorMetadata';
@@ -34,7 +35,8 @@ export default class DatabaseService {
34
35
  // staking
35
36
  chainStakingMetadata: new ChainStakingMetadataStore(this._db.chainStakingMetadata),
36
37
  nominatorMetadata: new NominatorMetadataStore(this._db.nominatorMetadata),
37
- mantaPay: new MantaPayStore(this._db.mantaPay)
38
+ mantaPay: new MantaPayStore(this._db.mantaPay),
39
+ campaign: new CampaignStore(this._db.campaign)
38
40
  };
39
41
  }
40
42
  async updatePriceStore(priceData) {
@@ -262,4 +264,19 @@ export default class DatabaseService {
262
264
  async getMantaPayFirstConfig(chain) {
263
265
  return this.stores.mantaPay.getFirstConfig(chain);
264
266
  }
267
+
268
+ /* Campaign */
269
+
270
+ subscribeProcessingCampaign() {
271
+ return this.stores.campaign.subscribeProcessingCampaign();
272
+ }
273
+ getProcessingCampaign() {
274
+ return this.stores.campaign.getProcessingCampaign();
275
+ }
276
+ getCampaign(slug) {
277
+ return this.stores.campaign.getCampaign(slug);
278
+ }
279
+ upsertCampaign(campaign) {
280
+ return this.stores.campaign.upsertCampaign(campaign);
281
+ }
265
282
  }
@@ -1,5 +1,5 @@
1
1
  import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
- import { BalanceItem, ChainStakingMetadata, CrowdloanItem, MetadataItem, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { BalanceItem, CampaignData, ChainStakingMetadata, CrowdloanItem, MetadataItem, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import Dexie, { Table } from 'dexie';
4
4
  export interface DefaultChainDoc {
5
5
  chain: string;
@@ -29,6 +29,7 @@ export interface IMigration {
29
29
  export interface IMetadataItem extends MetadataItem, DefaultChainDoc {
30
30
  }
31
31
  export declare type IMantaPayLedger = any;
32
+ export declare type ICampaign = CampaignData;
32
33
  export default class KoniDatabase extends Dexie {
33
34
  price: Table<PriceJson, object>;
34
35
  balances: Table<IBalance, object>;
@@ -44,6 +45,7 @@ export default class KoniDatabase extends Dexie {
44
45
  chainStakingMetadata: Table<ChainStakingMetadata, object>;
45
46
  nominatorMetadata: Table<NominatorMetadata, object>;
46
47
  mantaPay: Table<IMantaPayLedger, object>;
48
+ campaign: Table<ICampaign, object>;
47
49
  private schemaVersion;
48
50
  constructor(name?: string, schemaVersion?: number);
49
51
  private conditionalVersion;
@@ -30,6 +30,9 @@ export default class KoniDatabase extends Dexie {
30
30
  this.conditionalVersion(3, {
31
31
  mantaPay: 'key, chain'
32
32
  });
33
+ this.conditionalVersion(4, {
34
+ campaign: 'slug'
35
+ });
33
36
  }
34
37
  conditionalVersion(version, schema, upgrade) {
35
38
  if (this.schemaVersion != null && this.schemaVersion < version) {
@@ -0,0 +1,9 @@
1
+ import { ICampaign } from '@subwallet/extension-base/services/storage-service/databases';
2
+ import BaseStore from '@subwallet/extension-base/services/storage-service/db-stores/BaseStore';
3
+ export default class CampaignStore extends BaseStore<ICampaign> {
4
+ getAll(): Promise<import("../../../background/KoniTypes").CampaignData[]>;
5
+ getCampaign(slug: string): Promise<import("../../../background/KoniTypes").CampaignData | undefined>;
6
+ getProcessingCampaign(): Promise<import("../../../background/KoniTypes").CampaignData[]>;
7
+ subscribeProcessingCampaign(): import("dexie").Observable<import("../../../background/KoniTypes").CampaignData[]>;
8
+ upsertCampaign(campaign: ICampaign): import("dexie").PromiseExtended<unknown>;
9
+ }
@@ -0,0 +1,27 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import BaseStore from '@subwallet/extension-base/services/storage-service/db-stores/BaseStore';
5
+ import { liveQuery } from 'dexie';
6
+ const filterProcessing = campaign => {
7
+ const now = new Date().getTime();
8
+ const isExpired = now <= campaign.startTime || now >= campaign.endTime;
9
+ return !(campaign.isDone || isExpired);
10
+ };
11
+ export default class CampaignStore extends BaseStore {
12
+ async getAll() {
13
+ return this.table.toArray();
14
+ }
15
+ async getCampaign(slug) {
16
+ return this.table.get(slug);
17
+ }
18
+ async getProcessingCampaign() {
19
+ return (await this.table.toArray()).filter(filterProcessing);
20
+ }
21
+ subscribeProcessingCampaign() {
22
+ return liveQuery(() => this.table.filter(filterProcessing).toArray());
23
+ }
24
+ upsertCampaign(campaign) {
25
+ return this.table.put(campaign);
26
+ }
27
+ }