@subwallet/extension-base 1.3.73-0 → 1.3.74-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 (108) hide show
  1. package/background/KoniTypes.d.ts +42 -5
  2. package/background/KoniTypes.js +14 -1
  3. package/cjs/background/KoniTypes.js +16 -2
  4. package/cjs/core/logic-validation/transfer.js +35 -57
  5. package/cjs/koni/background/handlers/Extension.js +599 -144
  6. package/cjs/koni/background/handlers/State.js +5 -2
  7. package/cjs/koni/background/handlers/Tabs.js +3 -2
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +0 -2
  10. package/cjs/services/chain-service/handler/SubstrateApi.js +6 -1
  11. package/cjs/services/chain-service/index.js +1 -0
  12. package/cjs/services/chain-service/utils/index.js +4 -0
  13. package/cjs/services/event-service/index.js +1 -0
  14. package/cjs/services/fee-service/utils/index.js +4 -4
  15. package/cjs/services/inapp-notification-service/consts.js +4 -2
  16. package/cjs/services/inapp-notification-service/index.js +51 -6
  17. package/cjs/services/inapp-notification-service/interfaces.js +2 -0
  18. package/cjs/services/inapp-notification-service/utils/common.js +4 -0
  19. package/cjs/services/keyring-service/context/account-context.js +44 -0
  20. package/cjs/services/keyring-service/context/handlers/Multisig.js +186 -0
  21. package/cjs/services/keyring-service/context/state.js +12 -0
  22. package/cjs/services/multisig-service/index.js +627 -0
  23. package/cjs/services/multisig-service/utils.js +242 -0
  24. package/cjs/services/request-service/handler/SubstrateRequestHandler.js +25 -0
  25. package/cjs/services/request-service/index.js +5 -1
  26. package/cjs/services/storage-service/DatabaseService.js +5 -2
  27. package/cjs/services/storage-service/db-stores/InappNotification.js +20 -2
  28. package/cjs/services/substrate-proxy-service/index.js +22 -7
  29. package/cjs/services/transaction-service/helpers/index.js +8 -0
  30. package/cjs/services/transaction-service/index.js +348 -147
  31. package/cjs/services/transaction-service/types.js +18 -1
  32. package/cjs/types/account/info/keyring.js +5 -0
  33. package/cjs/types/account/info/proxy.js +1 -0
  34. package/cjs/types/multisig/index.js +14 -0
  35. package/cjs/types/transaction/error.js +9 -2
  36. package/cjs/utils/account/transform.js +28 -4
  37. package/cjs/utils/logger/Logger.js +294 -0
  38. package/cjs/utils/logger/index.js +42 -0
  39. package/cjs/utils/logger/types.js +1 -0
  40. package/core/logic-validation/transfer.d.ts +2 -2
  41. package/core/logic-validation/transfer.js +10 -32
  42. package/koni/background/handlers/Extension.d.ts +7 -0
  43. package/koni/background/handlers/Extension.js +498 -43
  44. package/koni/background/handlers/State.d.ts +2 -0
  45. package/koni/background/handlers/State.js +5 -2
  46. package/koni/background/handlers/Tabs.js +3 -2
  47. package/package.json +42 -6
  48. package/packageInfo.js +1 -1
  49. package/services/balance-service/helpers/subscribe/substrate/index.js +0 -2
  50. package/services/chain-service/handler/SubstrateApi.js +7 -2
  51. package/services/chain-service/index.js +1 -0
  52. package/services/chain-service/types.d.ts +1 -1
  53. package/services/chain-service/utils/index.js +4 -0
  54. package/services/event-service/index.d.ts +1 -0
  55. package/services/event-service/index.js +1 -0
  56. package/services/event-service/types.d.ts +1 -0
  57. package/services/fee-service/utils/index.js +4 -4
  58. package/services/inapp-notification-service/consts.d.ts +3 -1
  59. package/services/inapp-notification-service/consts.js +5 -3
  60. package/services/inapp-notification-service/index.d.ts +3 -2
  61. package/services/inapp-notification-service/index.js +51 -6
  62. package/services/inapp-notification-service/interfaces.d.ts +18 -2
  63. package/services/inapp-notification-service/interfaces.js +2 -0
  64. package/services/inapp-notification-service/utils/common.d.ts +1 -0
  65. package/services/inapp-notification-service/utils/common.js +3 -0
  66. package/services/keyring-service/context/account-context.d.ts +9 -1
  67. package/services/keyring-service/context/account-context.js +44 -0
  68. package/services/keyring-service/context/handlers/Multisig.d.ts +18 -0
  69. package/services/keyring-service/context/handlers/Multisig.js +180 -0
  70. package/services/keyring-service/context/state.d.ts +2 -0
  71. package/services/keyring-service/context/state.js +12 -0
  72. package/services/multisig-service/index.d.ts +245 -0
  73. package/services/multisig-service/index.js +620 -0
  74. package/services/multisig-service/utils.d.ts +95 -0
  75. package/services/multisig-service/utils.js +227 -0
  76. package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -0
  77. package/services/request-service/handler/SubstrateRequestHandler.js +25 -0
  78. package/services/request-service/index.d.ts +2 -1
  79. package/services/request-service/index.js +5 -1
  80. package/services/storage-service/DatabaseService.d.ts +3 -2
  81. package/services/storage-service/DatabaseService.js +5 -2
  82. package/services/storage-service/db-stores/InappNotification.d.ts +3 -2
  83. package/services/storage-service/db-stores/InappNotification.js +20 -2
  84. package/services/substrate-proxy-service/index.d.ts +4 -1
  85. package/services/substrate-proxy-service/index.js +22 -8
  86. package/services/transaction-service/helpers/index.js +8 -0
  87. package/services/transaction-service/index.d.ts +31 -0
  88. package/services/transaction-service/index.js +270 -69
  89. package/services/transaction-service/types.d.ts +28 -3
  90. package/services/transaction-service/types.js +12 -1
  91. package/types/account/info/keyring.d.ts +14 -1
  92. package/types/account/info/keyring.js +6 -0
  93. package/types/account/info/proxy.d.ts +1 -0
  94. package/types/account/info/proxy.js +1 -0
  95. package/types/multisig/index.d.ts +76 -0
  96. package/types/multisig/index.js +8 -0
  97. package/types/notification/index.d.ts +8 -0
  98. package/types/substrateProxyAccount/index.d.ts +26 -1
  99. package/types/transaction/error.d.ts +6 -1
  100. package/types/transaction/error.js +7 -1
  101. package/types/transaction/request.d.ts +0 -1
  102. package/utils/account/transform.js +28 -4
  103. package/utils/logger/Logger.d.ts +31 -0
  104. package/utils/logger/Logger.js +267 -0
  105. package/utils/logger/index.d.ts +15 -0
  106. package/utils/logger/index.js +29 -0
  107. package/utils/logger/types.d.ts +23 -0
  108. package/utils/logger/types.js +1 -0
@@ -32,6 +32,7 @@ var _keyringService = require("@subwallet/extension-base/services/keyring-servic
32
32
  var _migrationService = _interopRequireDefault(require("@subwallet/extension-base/services/migration-service"));
33
33
  var _mintCampaignService = _interopRequireDefault(require("@subwallet/extension-base/services/mint-campaign-service"));
34
34
  var _mktCampaignService = _interopRequireDefault(require("@subwallet/extension-base/services/mkt-campaign-service"));
35
+ var _multisigService = require("@subwallet/extension-base/services/multisig-service");
35
36
  var _nftService = _interopRequireDefault(require("@subwallet/extension-base/services/nft-service"));
36
37
  var _NotificationService = _interopRequireDefault(require("@subwallet/extension-base/services/notification-service/NotificationService"));
37
38
  var _openGov = _interopRequireDefault(require("@subwallet/extension-base/services/open-gov"));
@@ -133,6 +134,7 @@ class KoniState {
133
134
  this.inappNotificationService = new _inappNotificationService.InappNotificationService(this.dbService, this.keyringService, this.eventService, this.chainService);
134
135
  this.chainOnlineService = new _chainOnlineService.ChainOnlineService(this.chainService, this.settingService, this.eventService, this.dbService);
135
136
  this.openGovService = new _openGov.default(this);
137
+ this.multisigService = new _multisigService.MultisigService(this.eventService, this.chainService, this.keyringService, this.inappNotificationService);
136
138
  this.substrateProxyAccountService = new _substrateProxyService.default(this);
137
139
  this.subscription = new _subscription.KoniSubscription(this, this.dbService);
138
140
  this.cron = new _cron.KoniCron(this, this.subscription, this.dbService);
@@ -239,6 +241,7 @@ class KoniState {
239
241
  await this.swapService.init();
240
242
  await this.inappNotificationService.init();
241
243
  await this.openGovService.init();
244
+ await this.multisigService.init();
242
245
 
243
246
  // this.onReady();
244
247
  this.onAccountAdd();
@@ -1694,7 +1697,7 @@ class KoniState {
1694
1697
  this.campaignService.stop();
1695
1698
  await Promise.all([this.cron.stop(), this.subscription.stop()]);
1696
1699
  await this.pauseAllNetworks(undefined, 'IDLE mode');
1697
- await Promise.all([this.historyService.stop(), this.priceService.stop(), this.balanceService.stop(), this.earningService.stop(), this.swapService.stop(), this.inappNotificationService.stop(), this.openGovService.stop()]);
1700
+ await Promise.all([this.historyService.stop(), this.priceService.stop(), this.balanceService.stop(), this.earningService.stop(), this.swapService.stop(), this.inappNotificationService.stop(), this.openGovService.stop(), this.multisigService.stop()]);
1698
1701
 
1699
1702
  // Complete sleeping
1700
1703
  sleeping.resolve();
@@ -1750,7 +1753,7 @@ class KoniState {
1750
1753
  this.generalStatus = _types.ServiceStatus.STARTING_FULL;
1751
1754
  const startingFull = (0, _promise.createPromiseHandler)();
1752
1755
  this.waitStartingFull = startingFull.promise;
1753
- await Promise.all([this.cron.start(), this.subscription.start(), this.historyService.start(), this.priceService.start(), this.balanceService.start(), this.earningService.start(), this.swapService.start(), this.inappNotificationService.start(), this.openGovService.start()]);
1756
+ await Promise.all([this.cron.start(), this.subscription.start(), this.historyService.start(), this.priceService.start(), this.balanceService.start(), this.earningService.start(), this.swapService.start(), this.inappNotificationService.start(), this.openGovService.start(), this.multisigService.start()]);
1754
1757
  this.eventService.emit('general.start_full', true);
1755
1758
  this.waitStartingFull = null;
1756
1759
  this.generalStatus = _types.ServiceStatus.STARTED_FULL;
@@ -83,11 +83,12 @@ function transformAccountsV2(accounts) {
83
83
  let {
84
84
  json: {
85
85
  meta: {
86
- isHidden
86
+ isHidden,
87
+ isMultisig
87
88
  }
88
89
  }
89
90
  } = _ref2;
90
- return !isHidden;
91
+ return !isHidden && !isMultisig;
91
92
  }).filter(authTypeFilter).filter(_ref3 => {
92
93
  let {
93
94
  json: {
@@ -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.3.73-0'
16
+ version: '1.3.74-1'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -144,8 +144,6 @@ const subscribeWithSystemAccountPallet = async _ref => {
144
144
  args: addresses
145
145
  });
146
146
  }
147
-
148
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
149
147
  const subscription = substrateApi.subscribeDataWithMulti(params, async rs => {
150
148
  const balances = rs[systemAccountKey];
151
149
  const poolMemberInfos = rs[poolMembersKey];
@@ -358,7 +358,12 @@ class SubstrateApi {
358
358
  subscriber.next([]);
359
359
  });
360
360
  } else {
361
- observables[key] = apiRx[section][module][method].multi(args).pipe((0, _rxjs.map)(codecs => codecs.map(codec => codec.toPrimitive())));
361
+ observables[key] = apiRx[section][module][method].multi(args).pipe(
362
+ // tap((codecs) => console.log('raw data', key, codecs)), // this line is used to debug data before transformation
363
+ (0, _rxjs.map)(codecs => codecs.map(codec => codec.toPrimitive())), (0, _rxjs.catchError)((error, caught) => {
364
+ console.error(`RxJS pipe() error for key ${key}`, error);
365
+ return (0, _rxjs.of)([]);
366
+ }));
362
367
  }
363
368
  });
364
369
  return (0, _rxjs.combineLatest)(observables).subscribe(callback);
@@ -1450,6 +1450,7 @@ class ChainService {
1450
1450
  hasNativeNft: false,
1451
1451
  supportStaking: params.chainSpec.paraId === null,
1452
1452
  supportProxy: false,
1453
+ supportMultisig: false,
1453
1454
  supportSmartContract: null
1454
1455
  };
1455
1456
  } else if (params.chainSpec.evmChainId !== null) {
@@ -876,6 +876,10 @@ const _isChainInfoCompatibleWithAccountInfo = (chainInfo, accountInfo) => {
876
876
  type: accountType
877
877
  } = accountInfo;
878
878
  if (accountChainType === _types3.AccountChainType.SUBSTRATE) {
879
+ var _chainInfo$substrateI19;
880
+ if (accountSignMode === _types3.AccountSignMode.MULTISIG && !((_chainInfo$substrateI19 = chainInfo.substrateInfo) !== null && _chainInfo$substrateI19 !== void 0 && _chainInfo$substrateI19.supportMultisig)) {
881
+ return false;
882
+ }
879
883
  return _isPureSubstrateChain(chainInfo) && _types4.AllSubstrateKeypairTypes.includes(accountType);
880
884
  }
881
885
  if (accountChainType === _types3.AccountChainType.ETHEREUM) {
@@ -41,6 +41,7 @@ class EventService extends _eventemitter.default {
41
41
  this.waitEarningReady = this.generateWaitPromise('earning.ready');
42
42
  this.waitLedgerReady = this.generateWaitPromise('ledger.ready');
43
43
  this.waitOpenGovReady = this.generateWaitPromise('open-gov.ready');
44
+ this.waitMultisigReady = this.generateWaitPromise('multisig-service.ready');
44
45
  }
45
46
  generateWaitPromise(eventType) {
46
47
  return new Promise(resolve => {
@@ -54,13 +54,13 @@ const parseInfuraFee = (info, threshold) => {
54
54
  exports.parseInfuraFee = parseInfuraFee;
55
55
  const fetchInfuraFeeData = async (chainId, infuraAuth) => {
56
56
  const baseUrl = 'https://gas.api.infura.io/networks/{{chainId}}/suggestedGasFees';
57
- const baseThressholdUrl = 'https://gas.api.infura.io/networks/{{chainId}}/busyThreshold';
57
+ const baseThresholdUrl = 'https://gas.api.infura.io/networks/{{chainId}}/busyThreshold';
58
58
  // const baseFeeHistoryUrl = 'https://gas.api.infura.io/networks/{{chainId}}/baseFeeHistory';
59
59
  // const baseFeePercentileUrl = 'https://gas.api.infura.io/networks/{{chainId}}/baseFeePercentile';
60
60
  const feeUrl = baseUrl.replaceAll('{{chainId}}', chainId.toString());
61
- const thressholdUrl = baseThressholdUrl.replaceAll('{{chainId}}', chainId.toString());
61
+ const thresholdUrl = baseThresholdUrl.replaceAll('{{chainId}}', chainId.toString());
62
62
  try {
63
- const [feeResp, thressholdResp] = await Promise.all([feeUrl, thressholdUrl].map(url => {
63
+ const [feeResp, thresholdResp] = await Promise.all([feeUrl, thresholdUrl].map(url => {
64
64
  return fetch(url, {
65
65
  method: 'GET',
66
66
  headers: {
@@ -70,7 +70,7 @@ const fetchInfuraFeeData = async (chainId, infuraAuth) => {
70
70
  }));
71
71
 
72
72
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
73
- const [feeInfo, thresholdInfo] = await Promise.all([feeResp.json(), thressholdResp.json()]);
73
+ const [feeInfo, thresholdInfo] = await Promise.all([feeResp.json(), thresholdResp.json()]);
74
74
  return parseInfuraFee(feeInfo, thresholdInfo);
75
75
  } catch (e) {
76
76
  console.warn(e);
@@ -16,7 +16,8 @@ const NotificationTitleMap = {
16
16
  [_interfaces.NotificationActionType.RECEIVE]: '[{{accountName}}] RECEIVE {{tokenSymbol}}',
17
17
  [_interfaces.NotificationActionType.CLAIM_AVAIL_BRIDGE_ON_AVAIL]: '[{{accountName}}] CLAIM {{tokenSymbol}}',
18
18
  [_interfaces.NotificationActionType.CLAIM_AVAIL_BRIDGE_ON_ETHEREUM]: '[{{accountName}}] CLAIM {{tokenSymbol}}',
19
- [_interfaces.NotificationActionType.CLAIM_POLYGON_BRIDGE]: '[{{accountName}}] CLAIM {{tokenSymbol}}'
19
+ [_interfaces.NotificationActionType.CLAIM_POLYGON_BRIDGE]: '[{{accountName}}] CLAIM {{tokenSymbol}}',
20
+ [_interfaces.NotificationActionType.MULTISIG_APPROVAL]: '[{{accountName}}] APPROVAL REQUIRED'
20
21
  };
21
22
  exports.NotificationTitleMap = NotificationTitleMap;
22
23
  const NotificationDescriptionMap = {
@@ -26,7 +27,8 @@ const NotificationDescriptionMap = {
26
27
  [_interfaces.NotificationActionType.RECEIVE]: _utils.getReceiveDescription,
27
28
  [_interfaces.NotificationActionType.CLAIM_AVAIL_BRIDGE_ON_AVAIL]: _utils.getAvailBridgeClaimDescription,
28
29
  [_interfaces.NotificationActionType.CLAIM_AVAIL_BRIDGE_ON_ETHEREUM]: _utils.getAvailBridgeClaimDescription,
29
- [_interfaces.NotificationActionType.CLAIM_POLYGON_BRIDGE]: _utils.getPolygonBridgeClaimDescription
30
+ [_interfaces.NotificationActionType.CLAIM_POLYGON_BRIDGE]: _utils.getPolygonBridgeClaimDescription,
31
+ [_interfaces.NotificationActionType.MULTISIG_APPROVAL]: _utils.getMultisigApprovalDescription
30
32
  };
31
33
  exports.NotificationDescriptionMap = NotificationDescriptionMap;
32
34
  const ONE_DAY_MILLISECOND = 1000 * 24 * 60 * 60;
@@ -35,8 +35,8 @@ class InappNotificationService {
35
35
  await this.start();
36
36
  this.onAccountProxyRemove();
37
37
  }
38
- async markAllRead(proxyId) {
39
- await this.dbService.markAllRead(proxyId);
38
+ async markAllRead(params) {
39
+ await this.dbService.markAllRead(params);
40
40
  }
41
41
  async switchReadStatus(params) {
42
42
  await this.dbService.switchReadStatus(params);
@@ -59,6 +59,9 @@ class InappNotificationService {
59
59
  let overdueTime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _consts.ONE_DAY_MILLISECOND * 60;
60
60
  return this.dbService.cleanUpOldNotifications(overdueTime);
61
61
  }
62
+ cleanUpNotificationByIds(ids) {
63
+ return this.dbService.cleanUpNotificationByIds(ids);
64
+ }
62
65
  passValidateNotification(candidateNotification, comparedNotifications, remindTimeConfigInHrs) {
63
66
  // todo: simplify condition !!
64
67
  if ([_interfaces.NotificationActionType.WITHDRAW, _interfaces.NotificationActionType.CLAIM].includes(candidateNotification.actionType)) {
@@ -94,6 +97,7 @@ class InappNotificationService {
94
97
  }
95
98
  if ([_interfaces.NotificationActionType.CLAIM_AVAIL_BRIDGE_ON_ETHEREUM, _interfaces.NotificationActionType.CLAIM_AVAIL_BRIDGE_ON_AVAIL].includes(candidateNotification.actionType)) {
96
99
  const {
100
+ actionType,
97
101
  address,
98
102
  metadata,
99
103
  time
@@ -104,6 +108,9 @@ class InappNotificationService {
104
108
  if (notification.address !== address) {
105
109
  continue;
106
110
  }
111
+ if (notification.actionType !== actionType) {
112
+ continue;
113
+ }
107
114
  if (time - notification.time >= remindTime) {
108
115
  continue;
109
116
  }
@@ -116,6 +123,7 @@ class InappNotificationService {
116
123
  }
117
124
  if ([_interfaces.NotificationActionType.CLAIM_POLYGON_BRIDGE].includes(candidateNotification.actionType)) {
118
125
  const {
126
+ actionType,
119
127
  address,
120
128
  metadata,
121
129
  time
@@ -126,6 +134,9 @@ class InappNotificationService {
126
134
  if (notification.address !== address) {
127
135
  continue;
128
136
  }
137
+ if (notification.actionType !== actionType) {
138
+ continue;
139
+ }
129
140
  if (time - notification.time >= remindTime) {
130
141
  continue;
131
142
  }
@@ -137,9 +148,16 @@ class InappNotificationService {
137
148
  }
138
149
  }
139
150
  if ([_interfaces.NotificationActionType.SWAP, _interfaces.NotificationActionType.EARNING].includes(candidateNotification.actionType)) {
140
- const candidateMetadata = candidateNotification.metadata;
151
+ const {
152
+ actionType,
153
+ metadata
154
+ } = candidateNotification;
155
+ const candidateMetadata = metadata;
141
156
  const processId = candidateMetadata.processId;
142
157
  for (const notification of comparedNotifications) {
158
+ if (notification.actionType !== actionType) {
159
+ continue;
160
+ }
143
161
  const comparedMetadata = notification.metadata;
144
162
  const _processId = comparedMetadata.processId;
145
163
  if (processId === _processId) {
@@ -147,10 +165,33 @@ class InappNotificationService {
147
165
  }
148
166
  }
149
167
  }
168
+ if ([_interfaces.NotificationActionType.MULTISIG_APPROVAL].includes(candidateNotification.actionType)) {
169
+ const {
170
+ actionType,
171
+ address,
172
+ metadata
173
+ } = candidateNotification;
174
+ const candidateMetadata = metadata;
175
+
176
+ // todo: experiment without notification reminder, remove this todo if no problems raised
177
+ for (const notification of comparedNotifications) {
178
+ if (notification.address !== address) {
179
+ continue;
180
+ }
181
+ if (notification.actionType !== actionType) {
182
+ continue;
183
+ }
184
+ const comparedMetadata = notification.metadata;
185
+ const sameNotification = candidateMetadata.multisigTxType === comparedMetadata.multisigTxType && candidateMetadata.multisigKey === comparedMetadata.multisigKey;
186
+ if (sameNotification) {
187
+ return false;
188
+ }
189
+ }
190
+ }
150
191
  return true;
151
192
  }
152
193
  async validateAndWriteNotificationsToDB(notifications, address) {
153
- const proxyId = this.keyringService.context.belongUnifiedAccount(address) || address;
194
+ const proxyId = this.keyringService.context.belongUnifiedAccount(address) || (0, _utils3.reformatAddress)(address);
154
195
  const accountName = this.keyringService.context.getCurrentAccountProxyName(proxyId);
155
196
  const passNotifications = [];
156
197
  const [comparedNotifications, remindTimeConfig] = await Promise.all([this.fetchNotificationsByParams({
@@ -429,7 +470,9 @@ class InappNotificationService {
429
470
  this.status = _types.ServiceStatus.STARTING;
430
471
  await this.startCron();
431
472
  this.status = _types.ServiceStatus.STARTED;
432
- } catch (e) {}
473
+ } catch (e) {
474
+ console.error('Failed to start InappNotificationService', e);
475
+ }
433
476
  }
434
477
  async startCron() {
435
478
  this.cleanUpOldNotifications().catch(console.error);
@@ -441,7 +484,9 @@ class InappNotificationService {
441
484
  this.status = _types.ServiceStatus.STOPPING;
442
485
  await this.stopCron();
443
486
  this.status = _types.ServiceStatus.STOPPED;
444
- } catch (e) {}
487
+ } catch (e) {
488
+ console.error('Failed to stop InappNotificationService', e);
489
+ }
445
490
  }
446
491
  stopCron() {
447
492
  return Promise.resolve(undefined);
@@ -32,6 +32,7 @@ exports.NotificationActionType = NotificationActionType;
32
32
  NotificationActionType["CLAIM_POLYGON_BRIDGE"] = "CLAIM_POLYGON_BRIDGE";
33
33
  NotificationActionType["SWAP"] = "SWAP";
34
34
  NotificationActionType["EARNING"] = "EARNING";
35
+ NotificationActionType["MULTISIG_APPROVAL"] = "MULTISIG_APPROVAL";
35
36
  })(NotificationActionType || (exports.NotificationActionType = NotificationActionType = {}));
36
37
  let NotificationTab;
37
38
  exports.NotificationTab = NotificationTab;
@@ -39,4 +40,5 @@ exports.NotificationTab = NotificationTab;
39
40
  NotificationTab["ALL"] = "ALL";
40
41
  NotificationTab["UNREAD"] = "UNREAD";
41
42
  NotificationTab["READ"] = "READ";
43
+ NotificationTab["MULTISIG"] = "MULTISIG";
42
44
  })(NotificationTab || (exports.NotificationTab = NotificationTab = {}));
@@ -7,6 +7,7 @@ exports.createClaimNotification = createClaimNotification;
7
7
  exports.createWithdrawNotifications = createWithdrawNotifications;
8
8
  exports.getClaimDescription = getClaimDescription;
9
9
  exports.getIsTabRead = getIsTabRead;
10
+ exports.getMultisigApprovalDescription = getMultisigApprovalDescription;
10
11
  exports.getReceiveDescription = getReceiveDescription;
11
12
  exports.getSendDescription = getSendDescription;
12
13
  exports.getWithdrawDescription = getWithdrawDescription;
@@ -36,6 +37,9 @@ function getSendDescription(amount, symbol) {
36
37
  function getReceiveDescription(amount, symbol) {
37
38
  return `You have just received ${amount} ${symbol}`;
38
39
  }
40
+ function getMultisigApprovalDescription() {
41
+ return 'A multisig transaction is waiting for your approval. Click to view details';
42
+ }
39
43
 
40
44
  /* Description */
41
45
 
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.AccountContext = void 0;
7
7
  var _Migration = require("@subwallet/extension-base/services/keyring-service/context/handlers/Migration");
8
+ var _Multisig = require("@subwallet/extension-base/services/keyring-service/context/handlers/Multisig");
9
+ var _utils = require("@subwallet/extension-base/utils");
8
10
  var _handlers = require("./handlers");
9
11
  var _state = require("./state");
10
12
  // Copyright 2019-2022 @subwallet/extension-base
@@ -23,6 +25,7 @@ class AccountContext {
23
25
  this.modifyHandler = new _handlers.AccountModifyHandler(this.parentService, this.state);
24
26
  this.secretHandler = new _handlers.AccountSecretHandler(this.parentService, this.state);
25
27
  this.migrationHandler = new _Migration.AccountMigrationHandler(this.parentService, this.state);
28
+ this.multisigHandler = new _Multisig.AccountMultisigHandler(this.parentService, this.state);
26
29
  }
27
30
 
28
31
  // TODO: Merge to value
@@ -147,6 +150,15 @@ class AccountContext {
147
150
  return this.secretHandler.accountsCreateExternalV2(request);
148
151
  }
149
152
 
153
+ /* Multisig */
154
+ async accountsCreateMultisig(request) {
155
+ return this.multisigHandler.accountsCreateMultisig(request);
156
+ }
157
+ getSignableAccountInfos(request) {
158
+ const chainInfo = this.koniState.chainService.getChainInfoByKey(request.chain);
159
+ return this.multisigHandler.getSignableAccountInfos(request, chainInfo);
160
+ }
161
+
150
162
  /* Import ethereum account with the private key */
151
163
  privateKeyValidateV2(request) {
152
164
  return this.secretHandler.privateKeyValidateV2(request);
@@ -262,6 +274,38 @@ class AccountContext {
262
274
 
263
275
  /* Migration */
264
276
 
277
+ /* Multisig */
278
+
279
+ getMultisigAccounts() {
280
+ return this.state.getMultisigAccounts();
281
+ }
282
+ getMultisigAccountByAddress(address) {
283
+ if (!address) {
284
+ return undefined;
285
+ }
286
+ const allMultisigAccounts = this.getMultisigAccounts();
287
+ return allMultisigAccounts.find(acc => acc.accounts[0].address === (0, _utils.reformatAddress)(address));
288
+ }
289
+ getMultisigAccountInfoByAddress(address) {
290
+ const accountProxy = this.getMultisigAccountByAddress(address);
291
+ if (!accountProxy) {
292
+ return undefined;
293
+ }
294
+ const threshold = accountProxy.accounts[0].threshold;
295
+ const signers = accountProxy.accounts[0].signers;
296
+ const multisigAddress = accountProxy.accounts[0].address;
297
+ return {
298
+ threshold,
299
+ signers,
300
+ multisigAddress
301
+ };
302
+ }
303
+ getMultisigAddresses() {
304
+ return this.state.getMultisigAddresses();
305
+ }
306
+
307
+ /* Multisig */
308
+
265
309
  /* Others */
266
310
 
267
311
  removeNoneHardwareGenesisHash() {
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AccountMultisigHandler = void 0;
7
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
8
+ var _Base = require("@subwallet/extension-base/services/keyring-service/context/handlers/Base");
9
+ var _types = require("@subwallet/extension-base/types");
10
+ var _utils = require("@subwallet/extension-base/utils");
11
+ var _keyring = require("@subwallet/keyring");
12
+ var _uiKeyring = require("@subwallet/ui-keyring");
13
+ var _i18next = require("i18next");
14
+ var _utilCrypto = require("@polkadot/util-crypto");
15
+ // Copyright 2019-2022 @subwallet/extension-base
16
+ // SPDX-License-Identifier: Apache-2.0
17
+
18
+ /**
19
+ * @class AccountMultisigHandler
20
+ * @extends AccountBaseHandler
21
+ * @description Handler for multisig account
22
+ * */
23
+ class AccountMultisigHandler extends _Base.AccountBaseHandler {
24
+ validateSigners(signers, threshold) {
25
+ const errors = [];
26
+ if (!signers || signers.length === 0) {
27
+ errors.push({
28
+ code: _KoniTypes.AccountMultisigErrorCode.INVALID_FILLED_ADDRESS,
29
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Multisig.signersRequired')
30
+ });
31
+ }
32
+ if (!signers || signers.length < 2) {
33
+ errors.push({
34
+ code: _KoniTypes.AccountMultisigErrorCode.INVALID_FILLED_ADDRESS,
35
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Multisig.multipleSignersRequired')
36
+ });
37
+ }
38
+ if (!threshold || threshold < 2 || threshold > signers.length) {
39
+ errors.push({
40
+ code: _KoniTypes.AccountMultisigErrorCode.INVALID_FILLED_THRESHOLD,
41
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Multisig.invalidThreshold')
42
+ });
43
+ }
44
+ for (const signer of signers) {
45
+ if (!signer || !(0, _keyring.isSubstrateAddress)(signer)) {
46
+ errors.push({
47
+ code: _KoniTypes.AccountMultisigErrorCode.INVALID_FILLED_ADDRESS,
48
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Multisig.mustBeSubstrateAddress')
49
+ });
50
+ break;
51
+ }
52
+ }
53
+ const distinctAddress = new Set();
54
+ for (const signer of signers) {
55
+ const rAddress = (0, _utils.reformatAddress)(signer);
56
+ if (distinctAddress.has(rAddress)) {
57
+ errors.push({
58
+ code: _KoniTypes.AccountMultisigErrorCode.DUPLICATE_FILLED_ADDRESS,
59
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Multisig.duplicateAddressFound')
60
+ });
61
+ break;
62
+ } else {
63
+ distinctAddress.add(rAddress);
64
+ }
65
+ }
66
+ return errors;
67
+ }
68
+ async accountsCreateMultisig(request) {
69
+ const {
70
+ name,
71
+ signers: _signer,
72
+ threshold
73
+ } = request;
74
+
75
+ // process signers
76
+ const signerError = this.validateSigners(_signer, threshold);
77
+ if (signerError.length > 0) {
78
+ return signerError;
79
+ }
80
+ const signers = _signer.map(address => (0, _utils.reformatAddress)(address));
81
+ const multisigKey = (0, _utilCrypto.createKeyMulti)(signers, threshold);
82
+ const multisigAddress = (0, _keyring.encodeAddress)(multisigKey);
83
+ try {
84
+ try {
85
+ const exists = _uiKeyring.keyring.getPair(multisigAddress);
86
+ if ((exists === null || exists === void 0 ? void 0 : exists.address) === (0, _utils.reformatAddress)(multisigAddress)) {
87
+ var _exists$meta;
88
+ const existingName = ((_exists$meta = exists.meta) === null || _exists$meta === void 0 ? void 0 : _exists$meta.name) || 'Unknown';
89
+ return [{
90
+ code: _KoniTypes.AccountMultisigErrorCode.INVALID_ADDRESS,
91
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Multisig.multisigAddressExists', {
92
+ replace: {
93
+ name: existingName
94
+ }
95
+ })
96
+ }];
97
+ }
98
+ } catch (e) {}
99
+ if (this.state.checkNameExists(name)) {
100
+ return [{
101
+ code: _KoniTypes.AccountMultisigErrorCode.INVALID_NAME,
102
+ message: (0, _i18next.t)('bg.ACCOUNT.services.keyring.handler.Secret.accountNameAlreadyExists')
103
+ }];
104
+ }
105
+ const meta = {
106
+ name,
107
+ threshold,
108
+ signers,
109
+ isExternal: true,
110
+ isMultisig: true,
111
+ genesisHash: ''
112
+ };
113
+ const multisigPair = _uiKeyring.keyring.keyring.addFromAddress(multisigAddress, meta);
114
+ _uiKeyring.keyring.saveAccount(multisigPair);
115
+ const address = multisigPair.address;
116
+ const modifiedPairs = this.state.modifyPairs;
117
+ modifiedPairs[address] = {
118
+ migrated: true,
119
+ key: address
120
+ };
121
+ this.state.upsertModifyPairs(modifiedPairs);
122
+ await new Promise(resolve => {
123
+ this.state.saveCurrentAccountProxyId(address, () => {
124
+ this.state._addAddressToAuthList(address, true);
125
+ resolve();
126
+ });
127
+ });
128
+ return [];
129
+ } catch (e) {
130
+ return [{
131
+ code: _KoniTypes.AccountMultisigErrorCode.KEYRING_ERROR,
132
+ message: e.message
133
+ }];
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Get 1-level signatories
139
+ * Ignore multisig accounts that are also signatories
140
+ */
141
+ getSignableAccountInfos(request, chainInfo) {
142
+ var _chainInfo$substrateI;
143
+ const {
144
+ extrinsicType,
145
+ multisigProxyId
146
+ } = request;
147
+ if (!((_chainInfo$substrateI = chainInfo.substrateInfo) !== null && _chainInfo$substrateI !== void 0 && _chainInfo$substrateI.supportMultisig)) {
148
+ return {
149
+ signableProxies: []
150
+ };
151
+ }
152
+ const allMultisigAccounts = this.state.getMultisigAccounts();
153
+ const allAccounts = this.state.accounts;
154
+ const targetMultisigAccount = allMultisigAccounts.find(acc => acc.id === multisigProxyId);
155
+ if (!targetMultisigAccount) {
156
+ return {
157
+ signableProxies: []
158
+ };
159
+ }
160
+ const signableAccountInfo = [];
161
+ const signers = targetMultisigAccount.accounts[0].signers;
162
+ const allMultisigAccountAddress = allMultisigAccounts.map(acc => acc.id);
163
+ for (const signer of signers) {
164
+ if (allMultisigAccountAddress.includes(signer)) {
165
+ continue;
166
+ }
167
+ const proxyId = this.state.belongUnifiedAccount(signer) || (0, _utils.reformatAddress)(signer);
168
+ const accountProxy = allAccounts[proxyId];
169
+ const substrateAccount = accountProxy === null || accountProxy === void 0 ? void 0 : accountProxy.accounts.find(acc => acc.chainType === _types.AccountChainType.SUBSTRATE);
170
+ if (substrateAccount) {
171
+ // Check if the account can sign the extrinsic type
172
+ // Only support 1 level signatories
173
+ if (substrateAccount.transactionActions.includes(extrinsicType) && !substrateAccount.isMultisig) {
174
+ signableAccountInfo.push({
175
+ proxyId,
176
+ address: signer
177
+ });
178
+ }
179
+ }
180
+ }
181
+ return {
182
+ signableProxies: signableAccountInfo
183
+ };
184
+ }
185
+ }
186
+ exports.AccountMultisigHandler = AccountMultisigHandler;
@@ -537,6 +537,18 @@ class AccountState {
537
537
  * Account ref
538
538
  * */
539
539
 
540
+ /* Multisig */
541
+
542
+ getMultisigAccounts() {
543
+ return Object.values(this.accounts).filter(acc => acc.accountType === _types.AccountProxyType.MULTISIG);
544
+ }
545
+ getMultisigAddresses() {
546
+ const allAccounts = this.getMultisigAccounts();
547
+ return allAccounts.map(acc => acc.id);
548
+ }
549
+
550
+ /* Multisig */
551
+
540
552
  /* Others */
541
553
 
542
554
  removeNoneHardwareGenesisHash() {