@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
@@ -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
  });
@@ -135,7 +135,7 @@ const getMetadata = metadataUrl => {
135
135
  if (!metadataUrl) {
136
136
  return null;
137
137
  }
138
- url = getRandomIpfsGateway() + metadataUrl + '/azero_domain_registry_abi.json';
138
+ url = getRandomIpfsGateway() + metadataUrl + '/metadata.json';
139
139
  return fetch(url, {
140
140
  method: 'GET',
141
141
  headers
@@ -22,6 +22,10 @@ export declare const IPFS_IO = "https://ipfs.io/ipfs/";
22
22
  export declare const DWEB_LINK = "https://dweb.link/ipfs/";
23
23
  export declare const IPFS_GATEWAY_4EVERLAND = "https://4everland.io/ipfs/";
24
24
  export declare const IPFS_FLEEK = "https://ipfs.fleek.co/ipfs/";
25
+ export declare const W3S_IPFS = "https://w3s.link/ipfs/";
26
+ export declare const IPFS2_RMRK = "https://ipfs2.rmrk.link/ipfs/";
27
+ export declare const IPFS_ETH_ARAGON = "https://ipfs.eth.aragon.network/ipfs/";
28
+ export declare const SUBWALLET_IPFS = "https://ipfs.subwallet.app/ipfs/";
25
29
  export declare enum SUPPORTED_NFT_NETWORKS {
26
30
  karura = "karura",
27
31
  acala = "acala",
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { RuntimeInfo } from '@subwallet/extension-base/utils';
5
+ import Bowser from 'bowser';
5
6
  export const SINGULAR_V1_ENDPOINT = 'https://singular.rmrk-api.xyz/api/account-rmrk1/';
6
7
  export const SINGULAR_V2_ENDPOINT = 'https://singular.rmrk-api.xyz/api/account/';
7
8
  export const KANARIA_ENDPOINT = 'https://kanaria.rmrk.app/api/rmrk2/';
@@ -29,6 +30,15 @@ export const IPFS_IO = 'https://ipfs.io/ipfs/';
29
30
  export const DWEB_LINK = 'https://dweb.link/ipfs/';
30
31
  export const IPFS_GATEWAY_4EVERLAND = 'https://4everland.io/ipfs/';
31
32
  export const IPFS_FLEEK = 'https://ipfs.fleek.co/ipfs/';
33
+ export const W3S_IPFS = 'https://w3s.link/ipfs/'; // 400
34
+ export const IPFS2_RMRK = 'https://ipfs2.rmrk.link/ipfs/'; // ????
35
+ export const IPFS_ETH_ARAGON = 'https://ipfs.eth.aragon.network/ipfs/'; // 400
36
+ export const SUBWALLET_IPFS = 'https://ipfs.subwallet.app/ipfs/'; // ???
37
+
38
+ const detectFirefox = () => {
39
+ return (localStorage.getItem('browserInfo') || Bowser.getParser(window.navigator.userAgent).getBrowserName()).toLowerCase() === 'firefox';
40
+ };
41
+ const isFirefox = detectFirefox();
32
42
  export let SUPPORTED_NFT_NETWORKS;
33
43
  (function (SUPPORTED_NFT_NETWORKS) {
34
44
  SUPPORTED_NFT_NETWORKS["karura"] = "karura";
@@ -93,6 +103,12 @@ const RANDOM_IPFS_GATEWAY_SETTING = [{
93
103
  provider: NFT_STORAGE_GATEWAY,
94
104
  weight: 50
95
105
  }];
106
+ if (isFirefox) {
107
+ RANDOM_IPFS_GATEWAY_SETTING.push({
108
+ provider: SUBWALLET_IPFS,
109
+ weight: 5000
110
+ });
111
+ }
96
112
  if (!RuntimeInfo.protocol || RuntimeInfo.protocol && !RuntimeInfo.protocol.startsWith('http')) {
97
113
  RANDOM_IPFS_GATEWAY_SETTING.push({
98
114
  provider: IPFS_FLEEK,
@@ -137,7 +137,7 @@ const getKaruraMetadata = metadataUrl => {
137
137
  if (!metadataUrl) {
138
138
  return null;
139
139
  }
140
- url = getRandomIpfsGateway() + metadataUrl + '/azero_domain_registry_abi.json';
140
+ url = getRandomIpfsGateway() + metadataUrl + '/metadata.json';
141
141
  return fetch(url, {
142
142
  method: 'GET',
143
143
  headers: {
@@ -65,23 +65,25 @@ export class VaraNftApi extends BaseNftApi {
65
65
  try {
66
66
  await Promise.all(this.addresses.map(async address => {
67
67
  const nfts = await this.getNftByAccount(address);
68
- for (const nft of nfts) {
69
- const parsedNft = {
70
- id: nft.tokenId,
71
- chain: this.chain,
72
- owner: address,
73
- name: nft.name,
74
- image: this.parseUrl(nft.mediaUrl),
75
- description: nft.description,
76
- collectionId: nft.collection.id
77
- };
78
- const parsedCollection = {
79
- collectionId: nft.collection.id,
80
- chain: this.chain,
81
- collectionName: nft.collection.name
82
- };
83
- params.updateItem(this.chain, parsedNft, address);
84
- params.updateCollection(this.chain, parsedCollection);
68
+ if (nfts) {
69
+ for (const nft of nfts) {
70
+ const parsedNft = {
71
+ id: nft.tokenId,
72
+ chain: this.chain,
73
+ owner: address,
74
+ name: nft.name,
75
+ image: this.parseUrl(nft.mediaUrl),
76
+ description: nft.description,
77
+ collectionId: nft.collection.id
78
+ };
79
+ const parsedCollection = {
80
+ collectionId: nft.collection.id,
81
+ chain: this.chain,
82
+ collectionName: nft.collection.name
83
+ };
84
+ params.updateItem(this.chain, parsedNft, address);
85
+ params.updateCollection(this.chain, parsedCollection);
86
+ }
85
87
  }
86
88
  }));
87
89
  } catch (e) {
@@ -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
  }
@@ -7,7 +7,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
7
7
  import { isJsonPayload, SEED_DEFAULT_LENGTH, SEED_LENGTHS } from '@subwallet/extension-base/background/handlers/Extension';
8
8
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
9
9
  import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
10
- import { AccountExternalErrorCode, BasicTxErrorType, BasicTxWarningCode, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, MantaPayEnableMessage, StakingType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
10
+ import { AccountExternalErrorCode, BasicTxErrorType, BasicTxWarningCode, CampaignDataType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, MantaPayEnableMessage, StakingType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
11
11
  import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning';
12
12
  import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
13
13
  import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
@@ -2702,7 +2702,7 @@ export default class KoniExtension {
2702
2702
  }) {
2703
2703
  try {
2704
2704
  // Remove isMasterPassword meta if createNew
2705
- if (createNew) {
2705
+ if (createNew && !keyring.keyring.hasMasterPassword) {
2706
2706
  const pairs = keyring.getPairs();
2707
2707
  for (const pair of pairs) {
2708
2708
  if (pair.meta.isInjected) {
@@ -3512,6 +3512,46 @@ export default class KoniExtension {
3512
3512
  return true;
3513
3513
  }
3514
3514
 
3515
+ /* Campaign */
3516
+
3517
+ async subscribeProcessingBanner(id, port) {
3518
+ const cb = createSubscription(id, port);
3519
+ const filterBanner = data => {
3520
+ const result = [];
3521
+ for (const item of data) {
3522
+ if (item.type === CampaignDataType.BANNER) {
3523
+ result.push(item);
3524
+ }
3525
+ }
3526
+ return result;
3527
+ };
3528
+ const callback = data => {
3529
+ cb(filterBanner(data));
3530
+ };
3531
+ const subscription = this.#koniState.campaignService.subscribeProcessingCampaign().subscribe({
3532
+ next: callback
3533
+ });
3534
+ this.createUnsubscriptionHandle(id, subscription.unsubscribe);
3535
+ port.onDisconnect.addListener(() => {
3536
+ this.cancelSubscription(id);
3537
+ });
3538
+ return filterBanner(await this.#koniState.campaignService.getProcessingCampaign());
3539
+ }
3540
+ async completeCampaignBanner({
3541
+ slug
3542
+ }) {
3543
+ const campaign = await this.#koniState.dbService.getCampaign(slug);
3544
+ if (campaign) {
3545
+ await this.#koniState.dbService.upsertCampaign({
3546
+ ...campaign,
3547
+ isDone: true
3548
+ });
3549
+ }
3550
+ return true;
3551
+ }
3552
+
3553
+ /* Campaign */
3554
+
3515
3555
  // --------------------------------------------------------------
3516
3556
  // eslint-disable-next-line @typescript-eslint/require-await
3517
3557
  async handle(id, type, request, port) {
@@ -3948,6 +3988,13 @@ export default class KoniExtension {
3948
3988
  // Metadata
3949
3989
  case 'pri(metadata.find)':
3950
3990
  return this.findRawMetadata(request);
3991
+
3992
+ /* Campaign */
3993
+ case 'pri(campaign.banner.subscribe)':
3994
+ return this.subscribeProcessingBanner(id, port);
3995
+ case 'pri(campaign.banner.complete)':
3996
+ return this.completeCampaignBanner(request);
3997
+ /* Campaign */
3951
3998
  // Default
3952
3999
  default:
3953
4000
  throw new Error(`Unable to handle message of type ${type}`);
@@ -3,6 +3,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from
3
3
  import { AddTokenRequestExternal, AmountData, ApiMap, AuthRequestV2, BalanceItem, BalanceJson, ChainStakingMetadata, ConfirmationsQueue, CrowdloanItem, CrowdloanJson, CurrentAccountInfo, EvmSendTransactionParams, ExternalRequestPromise, MantaPayConfig, MantaPaySyncState, NftCollection, NftItem, NftJson, NominatorMetadata, RequestAccountExportPrivateKey, RequestCheckPublicAndSecretKey, RequestConfirmationComplete, RequestSettingsType, ResponseAccountExportPrivateKey, ResponseCheckPublicAndSecretKey, ServiceInfo, SingleModeJson, StakingItem, StakingJson, StakingRewardItem, StakingRewardJson, StakingType, UiSettings } from '@subwallet/extension-base/background/KoniTypes';
4
4
  import { AccountJson, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestSign, ResponseRpcListProviders, ResponseSigning } from '@subwallet/extension-base/background/types';
5
5
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
6
+ import CampaignService from '@subwallet/extension-base/services/campaign-service';
6
7
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
7
8
  import { _ChainState, _NetworkUpsertParams, _ValidateCustomAssetRequest } from '@subwallet/extension-base/services/chain-service/types';
8
9
  import { EventService } from '@subwallet/extension-base/services/event-service';
@@ -62,6 +63,7 @@ export default class KoniState {
62
63
  readonly migrationService: MigrationService;
63
64
  readonly subscanService: SubscanService;
64
65
  readonly walletConnectService: WalletConnectService;
66
+ readonly campaignService: CampaignService;
65
67
  private generalStatus;
66
68
  private waitSleeping;
67
69
  private waitStarting;
@@ -1,7 +1,6 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { ChainInfoMap } from '@subwallet/chain-list';
5
4
  import { EvmProviderError } from '@subwallet/extension-base/background/errors/EvmProviderError';
6
5
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
7
6
  import { isSubscriptionRunning, unsubscribe } from '@subwallet/extension-base/background/handlers/subscriptions';
@@ -9,9 +8,10 @@ import { APIItemState, BasicTxErrorType, ChainType, EvmProviderErrorType, Extern
9
8
  import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, MANTA_PAY_BALANCE_INTERVAL } from '@subwallet/extension-base/constants';
10
9
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
11
10
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
11
+ import CampaignService from '@subwallet/extension-base/services/campaign-service';
12
12
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
13
13
  import { _DEFAULT_MANTA_ZK_CHAIN, _MANTA_ZK_CHAIN_GROUP, _PREDEFINED_SINGLE_MODES } from '@subwallet/extension-base/services/chain-service/constants';
14
- import { _getEvmChainId, _getSubstrateGenesisHash, _getTokenOnChainAssetId, _isAssetFungibleToken, _isChainEnabled, _isChainTestNet, _isSubstrateParaChain, _parseMetadataForSmartContractAsset } from '@subwallet/extension-base/services/chain-service/utils';
14
+ import { _getEvmChainId, _getSubstrateGenesisHash, _getTokenOnChainAssetId, _isAssetFungibleToken, _isChainEnabled, _isChainTestNet, _parseMetadataForSmartContractAsset } from '@subwallet/extension-base/services/chain-service/utils';
15
15
  import { EventService } from '@subwallet/extension-base/services/event-service';
16
16
  import { HistoryService } from '@subwallet/extension-base/services/history-service';
17
17
  import { KeyringService } from '@subwallet/extension-base/services/keyring-service';
@@ -51,14 +51,6 @@ const getSuri = (seed, type) => {
51
51
  };
52
52
  const generateDefaultCrowdloanMap = () => {
53
53
  const crowdloanMap = {};
54
- Object.entries(ChainInfoMap).forEach(([networkKey, chainInfo]) => {
55
- if (_isSubstrateParaChain(chainInfo)) {
56
- crowdloanMap[networkKey] = {
57
- state: APIItemState.PENDING,
58
- contribute: '0'
59
- };
60
- }
61
- });
62
54
  return crowdloanMap;
63
55
  };
64
56
  export default class KoniState {
@@ -101,7 +93,8 @@ export default class KoniState {
101
93
  this.historyService = new HistoryService(this.dbService, this.chainService, this.eventService, this.keyringService);
102
94
  this.transactionService = new TransactionService(this.chainService, this.eventService, this.requestService, this.balanceService, this.historyService, this.notificationService, this.dbService);
103
95
  this.walletConnectService = new WalletConnectService(this, this.requestService);
104
- this.migrationService = new MigrationService(this);
96
+ this.migrationService = new MigrationService(this, this.eventService);
97
+ this.campaignService = new CampaignService(this);
105
98
  this.subscription = new KoniSubscription(this, this.dbService);
106
99
  this.cron = new KoniCron(this, this.subscription, this.dbService);
107
100
  this.logger = createLogger('State');
@@ -165,11 +165,15 @@ export class KoniSubscription {
165
165
  this.state.setCrowdloanItem(networkKey, rs);
166
166
  }, this.state.getChainInfoMap());
167
167
  if (onlyRunOnFirstTime) {
168
- subscriptionPromise.then(unsub => unsub()).catch(this.logger.warn);
168
+ subscriptionPromise.then(unsub => {
169
+ unsub && unsub();
170
+ }).catch(this.logger.warn);
169
171
  return;
170
172
  }
171
173
  return () => {
172
- subscriptionPromise.then(unsub => unsub()).catch(this.logger.warn);
174
+ subscriptionPromise.then(unsub => {
175
+ unsub && unsub();
176
+ }).catch(this.logger.warn);
173
177
  };
174
178
  }
175
179
  subscribeNft(address, substrateApiMap, evmApiMap, smartContractNfts, chainInfoMap) {
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.1.17-0",
20
+ "version": "1.1.18-1",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -520,6 +520,21 @@
520
520
  "require": "./cjs/services/base/types.js",
521
521
  "default": "./services/base/types.js"
522
522
  },
523
+ "./services/campaign-service": {
524
+ "types": "./services/campaign-service/index.d.ts",
525
+ "require": "./cjs/services/campaign-service/index.js",
526
+ "default": "./services/campaign-service/index.js"
527
+ },
528
+ "./services/campaign-service/helpers": {
529
+ "types": "./services/campaign-service/helpers.d.ts",
530
+ "require": "./cjs/services/campaign-service/helpers.js",
531
+ "default": "./services/campaign-service/helpers.js"
532
+ },
533
+ "./services/campaign-service/types": {
534
+ "types": "./services/campaign-service/types.d.ts",
535
+ "require": "./cjs/services/campaign-service/types.js",
536
+ "default": "./services/campaign-service/types.js"
537
+ },
523
538
  "./services/chain-service": {
524
539
  "types": "./services/chain-service/index.d.ts",
525
540
  "require": "./cjs/services/chain-service/index.js",
@@ -903,6 +918,11 @@
903
918
  "require": "./cjs/services/storage-service/db-stores/BaseStoreWithChain.js",
904
919
  "default": "./services/storage-service/db-stores/BaseStoreWithChain.js"
905
920
  },
921
+ "./services/storage-service/db-stores/Campaign": {
922
+ "types": "./services/storage-service/db-stores/Campaign.d.ts",
923
+ "require": "./cjs/services/storage-service/db-stores/Campaign.js",
924
+ "default": "./services/storage-service/db-stores/Campaign.js"
925
+ },
906
926
  "./services/storage-service/db-stores/Chain": {
907
927
  "types": "./services/storage-service/db-stores/Chain.d.ts",
908
928
  "require": "./cjs/services/storage-service/db-stores/Chain.js",
@@ -1257,11 +1277,11 @@
1257
1277
  "@reduxjs/toolkit": "^1.9.1",
1258
1278
  "@sora-substrate/type-definitions": "^1.17.7",
1259
1279
  "@substrate/connect": "^0.7.26",
1260
- "@subwallet/chain-list": "0.2.16-beta.12",
1261
- "@subwallet/extension-base": "^1.1.17-0",
1262
- "@subwallet/extension-chains": "^1.1.17-0",
1263
- "@subwallet/extension-dapp": "^1.1.17-0",
1264
- "@subwallet/extension-inject": "^1.1.17-0",
1280
+ "@subwallet/chain-list": "0.2.18-beta.2",
1281
+ "@subwallet/extension-base": "^1.1.18-1",
1282
+ "@subwallet/extension-chains": "^1.1.18-1",
1283
+ "@subwallet/extension-dapp": "^1.1.18-1",
1284
+ "@subwallet/extension-inject": "^1.1.18-1",
1265
1285
  "@subwallet/keyring": "^0.1.1",
1266
1286
  "@subwallet/ui-keyring": "^0.1.1",
1267
1287
  "@walletconnect/sign-client": "^2.8.4",
@@ -1271,6 +1291,7 @@
1271
1291
  "axios": "^1.2.1",
1272
1292
  "bignumber.js": "^9.1.1",
1273
1293
  "bn.js": "^5.2.1",
1294
+ "bowser": "^2.11.0",
1274
1295
  "browser-passworder": "^2.0.3",
1275
1296
  "buffer": "^6.0.3",
1276
1297
  "cross-fetch": "^3.1.5",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.1.17-0'
10
+ version: '1.1.18-1'
11
11
  };
@@ -0,0 +1,3 @@
1
+ import { CampaignNotification } from '@subwallet/extension-base/background/KoniTypes';
2
+ import NotificationService from '@subwallet/extension-base/services/notification-service/NotificationService';
3
+ export declare const runCampaign: (notificationService: NotificationService, campaign: CampaignNotification) => void;
@@ -0,0 +1,54 @@
1
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { NotificationType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { t } from 'i18next';
6
+ export const runCampaign = (notificationService, campaign) => {
7
+ const {
8
+ action,
9
+ message,
10
+ metadata,
11
+ title
12
+ } = campaign.data;
13
+ const {
14
+ buttons
15
+ } = campaign;
16
+ const onClick = (action, metadata) => {
17
+ return () => {
18
+ switch (action) {
19
+ case 'open_url':
20
+ {
21
+ if (metadata) {
22
+ const url = metadata.url;
23
+ if (url) {
24
+ window.open(url);
25
+ }
26
+ }
27
+ break;
28
+ }
29
+ default:
30
+ break;
31
+ }
32
+ };
33
+ };
34
+ const onButtonClick = btnIndex => {
35
+ const {
36
+ metadata,
37
+ type
38
+ } = buttons[btnIndex];
39
+ onClick(type, metadata)();
40
+ };
41
+ notificationService.notify({
42
+ type: NotificationType.SUCCESS,
43
+ title: t(title),
44
+ message: t(message),
45
+ action: {
46
+ buttonClick: onButtonClick,
47
+ click: onClick(action, metadata)
48
+ },
49
+ notifyViaBrowser: true,
50
+ buttons: buttons.map(button => ({
51
+ title: button.name
52
+ }))
53
+ });
54
+ };
@@ -0,0 +1,11 @@
1
+ import { CampaignData } from '@subwallet/extension-base/background/KoniTypes';
2
+ import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
3
+ export default class CampaignService {
4
+ #private;
5
+ constructor(state: KoniState);
6
+ private fetchCampaign;
7
+ private runCampaign;
8
+ getProcessingCampaign(): Promise<CampaignData[]>;
9
+ subscribeProcessingCampaign(): import("dexie").Observable<CampaignData[]>;
10
+ private completeCampaignNotification;
11
+ }