@subwallet/extension-base 1.1.6-1 → 1.1.6-2
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 +1 -0
- package/cjs/koni/background/handlers/Extension.js +5 -0
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/chain-service/handler/AbstractChainHandler.js +25 -11
- package/cjs/services/chain-service/handler/EvmApi.js +15 -5
- package/cjs/services/chain-service/handler/EvmChainHandler.js +2 -2
- package/cjs/services/chain-service/handler/SubstrateApi.js +36 -17
- package/cjs/services/chain-service/handler/SubstrateChainHandler.js +5 -5
- package/cjs/services/chain-service/index.js +12 -6
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +5 -0
- package/package.json +6 -6
- package/packageInfo.js +1 -1
- package/services/chain-service/handler/AbstractChainHandler.d.ts +5 -5
- package/services/chain-service/handler/AbstractChainHandler.js +24 -9
- package/services/chain-service/handler/EvmApi.d.ts +4 -2
- package/services/chain-service/handler/EvmApi.js +15 -5
- package/services/chain-service/handler/EvmChainHandler.js +2 -2
- package/services/chain-service/handler/SubstrateApi.d.ts +5 -2
- package/services/chain-service/handler/SubstrateApi.js +36 -17
- package/services/chain-service/handler/SubstrateChainHandler.js +6 -6
- package/services/chain-service/handler/types.d.ts +2 -1
- package/services/chain-service/index.d.ts +1 -0
- package/services/chain-service/index.js +12 -6
- package/services/chain-service/types.d.ts +1 -0
|
@@ -1533,6 +1533,7 @@ export interface KoniRequestSignatures {
|
|
|
1533
1533
|
'pri(chainService.upsertChain)': [_NetworkUpsertParams, boolean];
|
|
1534
1534
|
'pri(chainService.enableChains)': [EnableMultiChainParams, boolean];
|
|
1535
1535
|
'pri(chainService.enableChain)': [EnableChainParams, boolean];
|
|
1536
|
+
'pri(chainService.reconnectChain)': [string, boolean];
|
|
1536
1537
|
'pri(chainService.disableChains)': [string[], boolean];
|
|
1537
1538
|
'pri(chainService.disableChain)': [string, boolean];
|
|
1538
1539
|
'pri(chainService.removeChain)': [string, boolean];
|
|
@@ -1734,6 +1734,9 @@ class KoniExtension {
|
|
|
1734
1734
|
} = _ref43;
|
|
1735
1735
|
return await this.#koniState.enableChain(chainSlug, enableTokens);
|
|
1736
1736
|
}
|
|
1737
|
+
async reconnectChain(chainSlug) {
|
|
1738
|
+
return this.#koniState.chainService.reconnectChain(chainSlug);
|
|
1739
|
+
}
|
|
1737
1740
|
async validateNetwork(_ref44) {
|
|
1738
1741
|
let {
|
|
1739
1742
|
existedChainSlug,
|
|
@@ -3710,6 +3713,8 @@ class KoniExtension {
|
|
|
3710
3713
|
return this.getSupportedSmartContractTypes();
|
|
3711
3714
|
case 'pri(chainService.enableChain)':
|
|
3712
3715
|
return await this.enableChain(request);
|
|
3716
|
+
case 'pri(chainService.reconnectChain)':
|
|
3717
|
+
return await this.reconnectChain(request);
|
|
3713
3718
|
case 'pri(chainService.disableChain)':
|
|
3714
3719
|
return await this.disableChain(request);
|
|
3715
3720
|
case 'pri(chainService.removeChain)':
|
package/cjs/packageInfo.js
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.SHORT_RETRY_TIME = exports.
|
|
6
|
+
exports.SHORT_RETRY_TIME = exports.FIRST_RECONNECT_TIME = exports.AbstractChainHandler = void 0;
|
|
7
|
+
var _types = require("@subwallet/extension-base/services/chain-service/types");
|
|
7
8
|
var _rxjs = require("rxjs");
|
|
8
9
|
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
|
|
9
10
|
// SPDX-License-Identifier: Apache-2.0
|
|
10
11
|
|
|
11
|
-
const
|
|
12
|
+
const MAX_RECOVER_RETRY = 6;
|
|
12
13
|
const FIRST_RECONNECT_TIME = 3000;
|
|
13
14
|
exports.FIRST_RECONNECT_TIME = FIRST_RECONNECT_TIME;
|
|
14
|
-
const SHORT_RETRY_TIME =
|
|
15
|
+
const SHORT_RETRY_TIME = 20000;
|
|
16
|
+
// export const LONG_RETRY_TIME = 60000;
|
|
15
17
|
exports.SHORT_RETRY_TIME = SHORT_RETRY_TIME;
|
|
16
|
-
const LONG_RETRY_TIME = 60000;
|
|
17
|
-
exports.LONG_RETRY_TIME = LONG_RETRY_TIME;
|
|
18
18
|
class AbstractChainHandler {
|
|
19
19
|
apiStateMapSubject = new _rxjs.BehaviorSubject({});
|
|
20
20
|
// Recover retry times
|
|
@@ -24,20 +24,26 @@ class AbstractChainHandler {
|
|
|
24
24
|
this.parent = parent;
|
|
25
25
|
this.recoverMap = {};
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
handleConnection(chain, newStatus) {
|
|
28
|
+
let forceRecover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
28
29
|
const currentMap = this.apiStateMapSubject.getValue();
|
|
29
|
-
const
|
|
30
|
+
const oldStatus = currentMap[chain];
|
|
30
31
|
|
|
31
32
|
// Update api state
|
|
32
|
-
if (
|
|
33
|
+
if (oldStatus !== newStatus) {
|
|
33
34
|
this.apiStateMapSubject.next({
|
|
34
35
|
...currentMap,
|
|
35
|
-
[chain]:
|
|
36
|
+
[chain]: newStatus
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
// Reset retry when connected is successful
|
|
41
|
+
if (newStatus === _types._ChainConnectionStatus.CONNECTED) {
|
|
42
|
+
this.cancelRecover(chain);
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
// Handle connection change
|
|
40
|
-
if (!
|
|
46
|
+
if ((!this.isRecovering(chain) || forceRecover) && newStatus === _types._ChainConnectionStatus.DISCONNECTED) {
|
|
41
47
|
this.handleRecover(chain);
|
|
42
48
|
}
|
|
43
49
|
}
|
|
@@ -57,8 +63,13 @@ class AbstractChainHandler {
|
|
|
57
63
|
};
|
|
58
64
|
clearTimeout(retryRecord.timeout);
|
|
59
65
|
const retryTimes = retryRecord.retryTimes;
|
|
66
|
+
if (retryTimes >= MAX_RECOVER_RETRY) {
|
|
67
|
+
this.handleConnection(chain, _types._ChainConnectionStatus.UNSTABLE);
|
|
68
|
+
this.cancelRecover(chain); // Need manual recover
|
|
69
|
+
}
|
|
70
|
+
|
|
60
71
|
// Slow down recover frequency if increasing recover times
|
|
61
|
-
const retryTimeout = retryTimes === 0 ? FIRST_RECONNECT_TIME :
|
|
72
|
+
const retryTimeout = retryTimes === 0 ? FIRST_RECONNECT_TIME : SHORT_RETRY_TIME;
|
|
62
73
|
|
|
63
74
|
// Recover api after retry timeout
|
|
64
75
|
const timeout = setTimeout(() => {
|
|
@@ -77,6 +88,9 @@ class AbstractChainHandler {
|
|
|
77
88
|
timeout
|
|
78
89
|
};
|
|
79
90
|
}
|
|
91
|
+
isRecovering(chain) {
|
|
92
|
+
return !!this.recoverMap[chain];
|
|
93
|
+
}
|
|
80
94
|
cancelRecover(chain) {
|
|
81
95
|
const retryRecord = this.recoverMap[chain];
|
|
82
96
|
if (retryRecord) {
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.EvmApi = void 0;
|
|
8
8
|
require("@polkadot/types-augment");
|
|
9
|
+
var _types = require("@subwallet/extension-base/services/chain-service/types");
|
|
9
10
|
var _promise = require("@subwallet/extension-base/utils/promise");
|
|
10
11
|
var _rxjs = require("rxjs");
|
|
11
12
|
var _web = _interopRequireDefault(require("web3"));
|
|
@@ -15,15 +16,23 @@ var _web = _interopRequireDefault(require("web3"));
|
|
|
15
16
|
class EvmApi {
|
|
16
17
|
apiRetry = 0;
|
|
17
18
|
isApiConnectedSubject = new _rxjs.BehaviorSubject(false);
|
|
19
|
+
connectionStatusSubject = new _rxjs.BehaviorSubject(_types._ChainConnectionStatus.DISCONNECTED);
|
|
18
20
|
isApiReady = false;
|
|
19
21
|
isApiReadyOnce = false;
|
|
20
22
|
get isApiConnected() {
|
|
21
23
|
return this.isApiConnectedSubject.getValue();
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
get connectionStatus() {
|
|
26
|
+
return this.connectionStatusSubject.getValue();
|
|
27
|
+
}
|
|
28
|
+
updateConnectionStatus(status) {
|
|
29
|
+
const isConnected = status === _types._ChainConnectionStatus.CONNECTED;
|
|
24
30
|
if (isConnected !== this.isApiConnectedSubject.value) {
|
|
25
31
|
this.isApiConnectedSubject.next(isConnected);
|
|
26
32
|
}
|
|
33
|
+
if (status !== this.connectionStatusSubject.value) {
|
|
34
|
+
this.connectionStatusSubject.next(status);
|
|
35
|
+
}
|
|
27
36
|
}
|
|
28
37
|
get isReady() {
|
|
29
38
|
return this.isReadyHandler.promise;
|
|
@@ -80,6 +89,7 @@ class EvmApi {
|
|
|
80
89
|
// For websocket provider, connect it
|
|
81
90
|
const wsProvider = this.provider;
|
|
82
91
|
wsProvider.connect && wsProvider.connect();
|
|
92
|
+
this.updateConnectionStatus(_types._ChainConnectionStatus.CONNECTING);
|
|
83
93
|
// Check if api is ready
|
|
84
94
|
this.api.eth.net.isListening().then(() => {
|
|
85
95
|
this.isApiReadyOnce = true;
|
|
@@ -88,7 +98,7 @@ class EvmApi {
|
|
|
88
98
|
this.isApiReadyOnce = false;
|
|
89
99
|
this.isApiReady = false;
|
|
90
100
|
this.isReadyHandler.reject(error);
|
|
91
|
-
this.
|
|
101
|
+
this.updateConnectionStatus(_types._ChainConnectionStatus.DISCONNECTED);
|
|
92
102
|
console.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`);
|
|
93
103
|
});
|
|
94
104
|
|
|
@@ -102,7 +112,7 @@ class EvmApi {
|
|
|
102
112
|
// For websocket provider, disconnect it
|
|
103
113
|
const wsProvider = this.provider;
|
|
104
114
|
wsProvider.disconnect && wsProvider.disconnect();
|
|
105
|
-
this.
|
|
115
|
+
this.updateConnectionStatus(_types._ChainConnectionStatus.DISCONNECTED);
|
|
106
116
|
return Promise.resolve();
|
|
107
117
|
}
|
|
108
118
|
destroy() {
|
|
@@ -117,10 +127,10 @@ class EvmApi {
|
|
|
117
127
|
this.isReadyHandler.resolve(this);
|
|
118
128
|
}
|
|
119
129
|
}
|
|
120
|
-
this.
|
|
130
|
+
this.updateConnectionStatus(_types._ChainConnectionStatus.CONNECTED);
|
|
121
131
|
}
|
|
122
132
|
onDisconnect() {
|
|
123
|
-
this.
|
|
133
|
+
this.updateConnectionStatus(_types._ChainConnectionStatus.DISCONNECTED);
|
|
124
134
|
if (this.isApiConnected) {
|
|
125
135
|
console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl} (EVM)`);
|
|
126
136
|
this.isApiReady = false;
|
|
@@ -46,8 +46,8 @@ class EvmChainHandler extends _AbstractChainHandler.AbstractChainHandler {
|
|
|
46
46
|
const apiObject = new _EvmApi2.EvmApi(chainSlug, apiUrl, {
|
|
47
47
|
providerName
|
|
48
48
|
});
|
|
49
|
-
apiObject.
|
|
50
|
-
apiObject.
|
|
49
|
+
apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
|
|
50
|
+
apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
|
|
51
51
|
return Promise.resolve(apiObject);
|
|
52
52
|
}
|
|
53
53
|
async recoverApi(chainSlug) {
|
|
@@ -10,6 +10,7 @@ var _types = require("@oak-foundation/types");
|
|
|
10
10
|
var _constants = require("@subwallet/extension-base/services/chain-service/constants");
|
|
11
11
|
var _lightClient = require("@subwallet/extension-base/services/chain-service/handler/light-client");
|
|
12
12
|
var _SubstrateChainHandler = require("@subwallet/extension-base/services/chain-service/handler/SubstrateChainHandler");
|
|
13
|
+
var _types2 = require("@subwallet/extension-base/services/chain-service/types");
|
|
13
14
|
var _promise = require("@subwallet/extension-base/utils/promise");
|
|
14
15
|
var _availJsSdk = require("avail-js-sdk");
|
|
15
16
|
var _rxjs = require("rxjs");
|
|
@@ -26,13 +27,22 @@ class SubstrateApi {
|
|
|
26
27
|
isApiReady = false;
|
|
27
28
|
isApiReadyOnce = false;
|
|
28
29
|
isApiConnectedSubject = new _rxjs.BehaviorSubject(false);
|
|
30
|
+
connectionStatusSubject = new _rxjs.BehaviorSubject(_types2._ChainConnectionStatus.DISCONNECTED);
|
|
29
31
|
get isApiConnected() {
|
|
30
32
|
return this.isApiConnectedSubject.getValue();
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
substrateRetry = 0;
|
|
35
|
+
get connectionStatus() {
|
|
36
|
+
return this.connectionStatusSubject.getValue();
|
|
37
|
+
}
|
|
38
|
+
updateConnectionStatus(status) {
|
|
39
|
+
const isConnected = status === _types2._ChainConnectionStatus.CONNECTED;
|
|
33
40
|
if (isConnected !== this.isApiConnectedSubject.value) {
|
|
34
41
|
this.isApiConnectedSubject.next(isConnected);
|
|
35
42
|
}
|
|
43
|
+
if (status !== this.connectionStatusSubject.value) {
|
|
44
|
+
this.connectionStatusSubject.next(status);
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
47
|
specName = '';
|
|
38
48
|
specVersion = '';
|
|
@@ -60,12 +70,14 @@ class SubstrateApi {
|
|
|
60
70
|
[`${metadata.genesisHash}-${metadata.specVersion}`]: metadata.hexValue
|
|
61
71
|
};
|
|
62
72
|
}
|
|
73
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTING);
|
|
74
|
+
let api;
|
|
63
75
|
if (_constants._API_OPTIONS_CHAIN_GROUP.acala.includes(this.chainSlug)) {
|
|
64
|
-
|
|
76
|
+
api = new _api2.ApiPromise((0, _api.options)({
|
|
65
77
|
provider
|
|
66
78
|
}));
|
|
67
79
|
} else if (_constants._API_OPTIONS_CHAIN_GROUP.turing.includes(this.chainSlug)) {
|
|
68
|
-
|
|
80
|
+
api = new _api2.ApiPromise({
|
|
69
81
|
provider,
|
|
70
82
|
rpc: _types.rpc,
|
|
71
83
|
types: _types.types
|
|
@@ -78,8 +90,13 @@ class SubstrateApi {
|
|
|
78
90
|
signedExtensions: _availJsSdk.spec.signedExtensions
|
|
79
91
|
});
|
|
80
92
|
} else {
|
|
81
|
-
|
|
93
|
+
api = new _api2.ApiPromise(apiOption);
|
|
82
94
|
}
|
|
95
|
+
api.on('ready', this.onReady.bind(this));
|
|
96
|
+
api.on('connected', this.onConnect.bind(this));
|
|
97
|
+
api.on('disconnected', this.onDisconnect.bind(this));
|
|
98
|
+
api.on('error', this.onError.bind(this));
|
|
99
|
+
return api;
|
|
83
100
|
}
|
|
84
101
|
constructor(chainSlug, apiUrl) {
|
|
85
102
|
let {
|
|
@@ -95,10 +112,6 @@ class SubstrateApi {
|
|
|
95
112
|
this.provider = this.createProvider(apiUrl);
|
|
96
113
|
this.api = externalApiPromise || this.createApi(this.provider);
|
|
97
114
|
this.handleApiReady = (0, _promise.createPromiseHandler)();
|
|
98
|
-
this.api.on('ready', this.onReady.bind(this));
|
|
99
|
-
this.api.on('connected', this.onConnect.bind(this));
|
|
100
|
-
this.api.on('disconnected', this.onDisconnect.bind(this));
|
|
101
|
-
this.api.on('error', this.onError.bind(this));
|
|
102
115
|
}
|
|
103
116
|
get isReady() {
|
|
104
117
|
return this.handleApiReady.promise;
|
|
@@ -120,17 +133,16 @@ class SubstrateApi {
|
|
|
120
133
|
this.apiUrl = apiUrl;
|
|
121
134
|
this.provider = this.createProvider(apiUrl);
|
|
122
135
|
this.api = this.createApi(this.provider);
|
|
123
|
-
this.api.on('ready', this.onReady.bind(this));
|
|
124
|
-
this.api.on('connected', this.onConnect.bind(this));
|
|
125
|
-
this.api.on('disconnected', this.onDisconnect.bind(this));
|
|
126
|
-
this.api.on('error', this.onError.bind(this));
|
|
127
136
|
}
|
|
128
137
|
connect() {
|
|
129
138
|
if (this.api.isConnected) {
|
|
130
|
-
this.
|
|
139
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTED);
|
|
131
140
|
} else {
|
|
141
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTING);
|
|
132
142
|
this.api.connect().then(() => {
|
|
133
|
-
this.
|
|
143
|
+
this.api.isReady.then(() => {
|
|
144
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTED);
|
|
145
|
+
}).catch(console.error);
|
|
134
146
|
}).catch(console.error);
|
|
135
147
|
}
|
|
136
148
|
}
|
|
@@ -140,7 +152,7 @@ class SubstrateApi {
|
|
|
140
152
|
} catch (e) {
|
|
141
153
|
console.error(e);
|
|
142
154
|
}
|
|
143
|
-
this.
|
|
155
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.DISCONNECTED);
|
|
144
156
|
}
|
|
145
157
|
async recoverConnect() {
|
|
146
158
|
await this.disconnect();
|
|
@@ -162,7 +174,8 @@ class SubstrateApi {
|
|
|
162
174
|
});
|
|
163
175
|
}
|
|
164
176
|
onConnect() {
|
|
165
|
-
this.
|
|
177
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTED);
|
|
178
|
+
this.substrateRetry = 0;
|
|
166
179
|
console.log(`Connected to ${this.chainSlug || ''} at ${this.apiUrl}`);
|
|
167
180
|
if (this.isApiReadyOnce) {
|
|
168
181
|
this.handleApiReady.resolve(this);
|
|
@@ -171,8 +184,14 @@ class SubstrateApi {
|
|
|
171
184
|
onDisconnect() {
|
|
172
185
|
this.isApiReady = false;
|
|
173
186
|
console.log(`Disconnected from ${this.chainSlug} at ${this.apiUrl}`);
|
|
174
|
-
this.
|
|
187
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.DISCONNECTED);
|
|
175
188
|
this.handleApiReady = (0, _promise.createPromiseHandler)();
|
|
189
|
+
this.substrateRetry += 1;
|
|
190
|
+
if (this.substrateRetry > 9) {
|
|
191
|
+
this.disconnect().then(() => {
|
|
192
|
+
this.updateConnectionStatus(_types2._ChainConnectionStatus.UNSTABLE);
|
|
193
|
+
}).catch(console.error);
|
|
194
|
+
}
|
|
176
195
|
}
|
|
177
196
|
onError(e) {
|
|
178
197
|
console.warn(`${this.chainSlug} connection got error`, e);
|
|
@@ -41,12 +41,12 @@ class SubstrateChainHandler extends _AbstractChainHandler.AbstractChainHandler {
|
|
|
41
41
|
|
|
42
42
|
// Not found substrateInterface mean it active with evm interface
|
|
43
43
|
if (api) {
|
|
44
|
-
api
|
|
44
|
+
api.connect();
|
|
45
45
|
if (!api.useLightClient) {
|
|
46
46
|
// Manual fire handle connect to avoid some chain can not reconnect
|
|
47
47
|
setTimeout(() => {
|
|
48
|
-
this.
|
|
49
|
-
},
|
|
48
|
+
this.handleConnection(chain, api.connectionStatus);
|
|
49
|
+
}, 10000);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -202,8 +202,8 @@ class SubstrateChainHandler extends _AbstractChainHandler.AbstractChainHandler {
|
|
|
202
202
|
metadata,
|
|
203
203
|
externalApiPromise
|
|
204
204
|
});
|
|
205
|
-
apiObject.
|
|
206
|
-
onUpdateStatus && apiObject.
|
|
205
|
+
apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
|
|
206
|
+
onUpdateStatus && apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
|
|
207
207
|
|
|
208
208
|
// Update metadata to database with async methods
|
|
209
209
|
apiObject.isReady.then(api => {
|
|
@@ -395,7 +395,7 @@ class ChainService {
|
|
|
395
395
|
this.dataMap.assetRefMap = latestAssetRefMap;
|
|
396
396
|
await this.initChains();
|
|
397
397
|
this.chainInfoMapSubject.next(this.getChainInfoMap());
|
|
398
|
-
this.
|
|
398
|
+
this.updateChainStateMapSubscription();
|
|
399
399
|
this.assetRegistrySubject.next(this.getAssetRegistry());
|
|
400
400
|
this.xcmRefMapSubject.next(this.dataMap.assetRefMap);
|
|
401
401
|
await this.initApis();
|
|
@@ -423,14 +423,14 @@ class ChainService {
|
|
|
423
423
|
endpoint,
|
|
424
424
|
providerName
|
|
425
425
|
} = this.getChainCurrentProviderByKey(chainInfo.slug);
|
|
426
|
-
const onUpdateStatus =
|
|
426
|
+
const onUpdateStatus = status => {
|
|
427
427
|
const currentStatus = this.getChainStateByKey(chainInfo.slug).connectionStatus;
|
|
428
|
-
const newStatus = isConnected ? _types3._ChainConnectionStatus.CONNECTED : _types3._ChainConnectionStatus.DISCONNECTED;
|
|
429
428
|
|
|
430
429
|
// Avoid unnecessary update in case disable chain
|
|
431
|
-
if (currentStatus !==
|
|
432
|
-
|
|
433
|
-
this.
|
|
430
|
+
if (currentStatus !== status) {
|
|
431
|
+
console.log(chainInfo.name, currentStatus, status);
|
|
432
|
+
this.setChainConnectionStatus(chainInfo.slug, status);
|
|
433
|
+
this.updateChainStateMapSubscription();
|
|
434
434
|
}
|
|
435
435
|
};
|
|
436
436
|
if (chainInfo.substrateInfo !== null && chainInfo.substrateInfo !== undefined) {
|
|
@@ -515,6 +515,12 @@ class ChainService {
|
|
|
515
515
|
needUpdate && this.updateChainStateMapSubscription();
|
|
516
516
|
return needUpdate;
|
|
517
517
|
}
|
|
518
|
+
async reconnectChain(chain) {
|
|
519
|
+
var _this$getSubstrateApi, _this$getEvmApi;
|
|
520
|
+
await ((_this$getSubstrateApi = this.getSubstrateApi(chain)) === null || _this$getSubstrateApi === void 0 ? void 0 : _this$getSubstrateApi.recoverConnect());
|
|
521
|
+
await ((_this$getEvmApi = this.getEvmApi(chain)) === null || _this$getEvmApi === void 0 ? void 0 : _this$getEvmApi.recoverConnect());
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
518
524
|
disableChain(chainSlug) {
|
|
519
525
|
const chainInfo = this.getChainInfoByKey(chainSlug);
|
|
520
526
|
const chainStateMap = this.getChainStateMap();
|
|
@@ -1681,6 +1681,9 @@ export default class KoniExtension {
|
|
|
1681
1681
|
}) {
|
|
1682
1682
|
return await this.#koniState.enableChain(chainSlug, enableTokens);
|
|
1683
1683
|
}
|
|
1684
|
+
async reconnectChain(chainSlug) {
|
|
1685
|
+
return this.#koniState.chainService.reconnectChain(chainSlug);
|
|
1686
|
+
}
|
|
1684
1687
|
async validateNetwork({
|
|
1685
1688
|
existedChainSlug,
|
|
1686
1689
|
provider
|
|
@@ -3611,6 +3614,8 @@ export default class KoniExtension {
|
|
|
3611
3614
|
return this.getSupportedSmartContractTypes();
|
|
3612
3615
|
case 'pri(chainService.enableChain)':
|
|
3613
3616
|
return await this.enableChain(request);
|
|
3617
|
+
case 'pri(chainService.reconnectChain)':
|
|
3618
|
+
return await this.reconnectChain(request);
|
|
3614
3619
|
case 'pri(chainService.disableChain)':
|
|
3615
3620
|
return await this.disableChain(request);
|
|
3616
3621
|
case 'pri(chainService.removeChain)':
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"./cjs/detectPackage.js"
|
|
18
18
|
],
|
|
19
19
|
"type": "module",
|
|
20
|
-
"version": "1.1.6-
|
|
20
|
+
"version": "1.1.6-2",
|
|
21
21
|
"main": "./cjs/index.js",
|
|
22
22
|
"module": "./index.js",
|
|
23
23
|
"types": "./index.d.ts",
|
|
@@ -1188,11 +1188,11 @@
|
|
|
1188
1188
|
"@reduxjs/toolkit": "^1.9.1",
|
|
1189
1189
|
"@sora-substrate/type-definitions": "^1.17.7",
|
|
1190
1190
|
"@substrate/connect": "^0.7.26",
|
|
1191
|
-
"@subwallet/chain-list": "0.2.9
|
|
1192
|
-
"@subwallet/extension-base": "^1.1.6-
|
|
1193
|
-
"@subwallet/extension-chains": "^1.1.6-
|
|
1194
|
-
"@subwallet/extension-dapp": "^1.1.6-
|
|
1195
|
-
"@subwallet/extension-inject": "^1.1.6-
|
|
1191
|
+
"@subwallet/chain-list": "0.2.9",
|
|
1192
|
+
"@subwallet/extension-base": "^1.1.6-2",
|
|
1193
|
+
"@subwallet/extension-chains": "^1.1.6-2",
|
|
1194
|
+
"@subwallet/extension-dapp": "^1.1.6-2",
|
|
1195
|
+
"@subwallet/extension-inject": "^1.1.6-2",
|
|
1196
1196
|
"@subwallet/keyring": "^0.0.10",
|
|
1197
1197
|
"@subwallet/ui-keyring": "^0.0.10",
|
|
1198
1198
|
"@walletconnect/sign-client": "^2.8.4",
|
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.6-
|
|
10
|
+
version: '1.1.6-2'
|
|
11
11
|
};
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { ChainService } from '@subwallet/extension-base/services/chain-service';
|
|
3
3
|
import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types';
|
|
4
|
-
import { _ChainBaseApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
4
|
+
import { _ChainBaseApi, _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
|
|
5
5
|
import { BehaviorSubject } from 'rxjs';
|
|
6
6
|
export declare const FIRST_RECONNECT_TIME = 3000;
|
|
7
|
-
export declare const SHORT_RETRY_TIME =
|
|
8
|
-
export declare const LONG_RETRY_TIME = 60000;
|
|
7
|
+
export declare const SHORT_RETRY_TIME = 20000;
|
|
9
8
|
interface RetryObject {
|
|
10
9
|
retryTimes: number;
|
|
11
10
|
timeout?: NodeJS.Timer;
|
|
12
11
|
}
|
|
13
12
|
export declare abstract class AbstractChainHandler {
|
|
14
13
|
protected parent?: ChainService | undefined;
|
|
15
|
-
readonly apiStateMapSubject: BehaviorSubject<Record<string,
|
|
14
|
+
readonly apiStateMapSubject: BehaviorSubject<Record<string, _ChainConnectionStatus>>;
|
|
16
15
|
protected recoverMap: Record<string, RetryObject>;
|
|
17
16
|
protected isSleeping: boolean;
|
|
18
17
|
protected constructor(parent?: ChainService | undefined);
|
|
@@ -21,8 +20,9 @@ export declare abstract class AbstractChainHandler {
|
|
|
21
20
|
abstract recoverApi(chainSlug: string): void;
|
|
22
21
|
abstract sleep(): Promise<void>;
|
|
23
22
|
abstract wakeUp(): Promise<void>;
|
|
24
|
-
|
|
23
|
+
handleConnection(chain: string, newStatus: _ChainConnectionStatus, forceRecover?: boolean): void;
|
|
25
24
|
protected handleRecover(chain: string): void;
|
|
25
|
+
protected isRecovering(chain: string): boolean;
|
|
26
26
|
protected cancelRecover(chain: string): void;
|
|
27
27
|
cancelAllRecover(): void;
|
|
28
28
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
|
|
4
5
|
import { BehaviorSubject } from 'rxjs';
|
|
5
|
-
const
|
|
6
|
+
const MAX_RECOVER_RETRY = 6;
|
|
6
7
|
export const FIRST_RECONNECT_TIME = 3000;
|
|
7
|
-
export const SHORT_RETRY_TIME =
|
|
8
|
-
export const LONG_RETRY_TIME = 60000;
|
|
8
|
+
export const SHORT_RETRY_TIME = 20000;
|
|
9
|
+
// export const LONG_RETRY_TIME = 60000;
|
|
10
|
+
|
|
9
11
|
export class AbstractChainHandler {
|
|
10
12
|
apiStateMapSubject = new BehaviorSubject({});
|
|
11
13
|
// Recover retry times
|
|
@@ -15,20 +17,25 @@ export class AbstractChainHandler {
|
|
|
15
17
|
this.parent = parent;
|
|
16
18
|
this.recoverMap = {};
|
|
17
19
|
}
|
|
18
|
-
|
|
20
|
+
handleConnection(chain, newStatus, forceRecover = false) {
|
|
19
21
|
const currentMap = this.apiStateMapSubject.getValue();
|
|
20
|
-
const
|
|
22
|
+
const oldStatus = currentMap[chain];
|
|
21
23
|
|
|
22
24
|
// Update api state
|
|
23
|
-
if (
|
|
25
|
+
if (oldStatus !== newStatus) {
|
|
24
26
|
this.apiStateMapSubject.next({
|
|
25
27
|
...currentMap,
|
|
26
|
-
[chain]:
|
|
28
|
+
[chain]: newStatus
|
|
27
29
|
});
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
// Reset retry when connected is successful
|
|
33
|
+
if (newStatus === _ChainConnectionStatus.CONNECTED) {
|
|
34
|
+
this.cancelRecover(chain);
|
|
35
|
+
}
|
|
36
|
+
|
|
30
37
|
// Handle connection change
|
|
31
|
-
if (!
|
|
38
|
+
if ((!this.isRecovering(chain) || forceRecover) && newStatus === _ChainConnectionStatus.DISCONNECTED) {
|
|
32
39
|
this.handleRecover(chain);
|
|
33
40
|
}
|
|
34
41
|
}
|
|
@@ -48,8 +55,13 @@ export class AbstractChainHandler {
|
|
|
48
55
|
};
|
|
49
56
|
clearTimeout(retryRecord.timeout);
|
|
50
57
|
const retryTimes = retryRecord.retryTimes;
|
|
58
|
+
if (retryTimes >= MAX_RECOVER_RETRY) {
|
|
59
|
+
this.handleConnection(chain, _ChainConnectionStatus.UNSTABLE);
|
|
60
|
+
this.cancelRecover(chain); // Need manual recover
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
// Slow down recover frequency if increasing recover times
|
|
52
|
-
const retryTimeout = retryTimes === 0 ? FIRST_RECONNECT_TIME :
|
|
64
|
+
const retryTimeout = retryTimes === 0 ? FIRST_RECONNECT_TIME : SHORT_RETRY_TIME;
|
|
53
65
|
|
|
54
66
|
// Recover api after retry timeout
|
|
55
67
|
const timeout = setTimeout(() => {
|
|
@@ -68,6 +80,9 @@ export class AbstractChainHandler {
|
|
|
68
80
|
timeout
|
|
69
81
|
};
|
|
70
82
|
}
|
|
83
|
+
isRecovering(chain) {
|
|
84
|
+
return !!this.recoverMap[chain];
|
|
85
|
+
}
|
|
71
86
|
cancelRecover(chain) {
|
|
72
87
|
const retryRecord = this.recoverMap[chain];
|
|
73
88
|
if (retryRecord) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import '@polkadot/types-augment';
|
|
3
3
|
import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types';
|
|
4
|
-
import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
4
|
+
import { _ChainConnectionStatus, _EvmApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
5
5
|
import { PromiseHandler } from '@subwallet/extension-base/utils/promise';
|
|
6
6
|
import { BehaviorSubject } from 'rxjs';
|
|
7
7
|
import Web3 from 'web3';
|
|
@@ -14,13 +14,15 @@ export declare class EvmApi implements _EvmApi {
|
|
|
14
14
|
apiError?: string;
|
|
15
15
|
apiRetry: number;
|
|
16
16
|
readonly isApiConnectedSubject: BehaviorSubject<boolean>;
|
|
17
|
+
readonly connectionStatusSubject: BehaviorSubject<_ChainConnectionStatus>;
|
|
17
18
|
isApiReady: boolean;
|
|
18
19
|
isApiReadyOnce: boolean;
|
|
19
20
|
isReadyHandler: PromiseHandler<_EvmApi>;
|
|
20
21
|
intervalCheckApi: NodeJS.Timer;
|
|
21
22
|
providerName: string;
|
|
22
23
|
get isApiConnected(): boolean;
|
|
23
|
-
|
|
24
|
+
get connectionStatus(): _ChainConnectionStatus;
|
|
25
|
+
private updateConnectionStatus;
|
|
24
26
|
get isReady(): Promise<_EvmApi>;
|
|
25
27
|
updateApiUrl(apiUrl: string): Promise<void>;
|
|
26
28
|
recoverConnect(): Promise<void>;
|
|
@@ -2,21 +2,30 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import '@polkadot/types-augment';
|
|
5
|
+
import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
|
|
5
6
|
import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
|
|
6
7
|
import { BehaviorSubject } from 'rxjs';
|
|
7
8
|
import Web3 from 'web3';
|
|
8
9
|
export class EvmApi {
|
|
9
10
|
apiRetry = 0;
|
|
10
11
|
isApiConnectedSubject = new BehaviorSubject(false);
|
|
12
|
+
connectionStatusSubject = new BehaviorSubject(_ChainConnectionStatus.DISCONNECTED);
|
|
11
13
|
isApiReady = false;
|
|
12
14
|
isApiReadyOnce = false;
|
|
13
15
|
get isApiConnected() {
|
|
14
16
|
return this.isApiConnectedSubject.getValue();
|
|
15
17
|
}
|
|
16
|
-
|
|
18
|
+
get connectionStatus() {
|
|
19
|
+
return this.connectionStatusSubject.getValue();
|
|
20
|
+
}
|
|
21
|
+
updateConnectionStatus(status) {
|
|
22
|
+
const isConnected = status === _ChainConnectionStatus.CONNECTED;
|
|
17
23
|
if (isConnected !== this.isApiConnectedSubject.value) {
|
|
18
24
|
this.isApiConnectedSubject.next(isConnected);
|
|
19
25
|
}
|
|
26
|
+
if (status !== this.connectionStatusSubject.value) {
|
|
27
|
+
this.connectionStatusSubject.next(status);
|
|
28
|
+
}
|
|
20
29
|
}
|
|
21
30
|
get isReady() {
|
|
22
31
|
return this.isReadyHandler.promise;
|
|
@@ -72,6 +81,7 @@ export class EvmApi {
|
|
|
72
81
|
// For websocket provider, connect it
|
|
73
82
|
const wsProvider = this.provider;
|
|
74
83
|
wsProvider.connect && wsProvider.connect();
|
|
84
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTING);
|
|
75
85
|
// Check if api is ready
|
|
76
86
|
this.api.eth.net.isListening().then(() => {
|
|
77
87
|
this.isApiReadyOnce = true;
|
|
@@ -80,7 +90,7 @@ export class EvmApi {
|
|
|
80
90
|
this.isApiReadyOnce = false;
|
|
81
91
|
this.isApiReady = false;
|
|
82
92
|
this.isReadyHandler.reject(error);
|
|
83
|
-
this.
|
|
93
|
+
this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
|
|
84
94
|
console.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`);
|
|
85
95
|
});
|
|
86
96
|
|
|
@@ -94,7 +104,7 @@ export class EvmApi {
|
|
|
94
104
|
// For websocket provider, disconnect it
|
|
95
105
|
const wsProvider = this.provider;
|
|
96
106
|
wsProvider.disconnect && wsProvider.disconnect();
|
|
97
|
-
this.
|
|
107
|
+
this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
|
|
98
108
|
return Promise.resolve();
|
|
99
109
|
}
|
|
100
110
|
destroy() {
|
|
@@ -109,10 +119,10 @@ export class EvmApi {
|
|
|
109
119
|
this.isReadyHandler.resolve(this);
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
|
-
this.
|
|
122
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
|
|
113
123
|
}
|
|
114
124
|
onDisconnect() {
|
|
115
|
-
this.
|
|
125
|
+
this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
|
|
116
126
|
if (this.isApiConnected) {
|
|
117
127
|
console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl} (EVM)`);
|
|
118
128
|
this.isApiReady = false;
|
|
@@ -39,8 +39,8 @@ export class EvmChainHandler extends AbstractChainHandler {
|
|
|
39
39
|
const apiObject = new EvmApi(chainSlug, apiUrl, {
|
|
40
40
|
providerName
|
|
41
41
|
});
|
|
42
|
-
apiObject.
|
|
43
|
-
apiObject.
|
|
42
|
+
apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
|
|
43
|
+
apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
|
|
44
44
|
return Promise.resolve(apiObject);
|
|
45
45
|
}
|
|
46
46
|
async recoverApi(chainSlug) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@polkadot/types-augment';
|
|
2
2
|
import { MetadataItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
3
3
|
import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types';
|
|
4
|
-
import { _SubstrateApi, _SubstrateDefaultFormatBalance } from '@subwallet/extension-base/services/chain-service/types';
|
|
4
|
+
import { _ChainConnectionStatus, _SubstrateApi, _SubstrateDefaultFormatBalance } from '@subwallet/extension-base/services/chain-service/types';
|
|
5
5
|
import { BehaviorSubject } from 'rxjs';
|
|
6
6
|
import { ApiPromise } from '@polkadot/api';
|
|
7
7
|
import { SubmittableExtrinsicFunction } from '@polkadot/api/promise/types';
|
|
@@ -20,8 +20,11 @@ export declare class SubstrateApi implements _SubstrateApi {
|
|
|
20
20
|
apiError?: string;
|
|
21
21
|
private handleApiReady;
|
|
22
22
|
readonly isApiConnectedSubject: BehaviorSubject<boolean>;
|
|
23
|
+
readonly connectionStatusSubject: BehaviorSubject<_ChainConnectionStatus>;
|
|
23
24
|
get isApiConnected(): boolean;
|
|
24
|
-
|
|
25
|
+
substrateRetry: number;
|
|
26
|
+
get connectionStatus(): _ChainConnectionStatus;
|
|
27
|
+
private updateConnectionStatus;
|
|
25
28
|
apiDefaultTx?: SubmittableExtrinsicFunction;
|
|
26
29
|
apiDefaultTxSudo?: SubmittableExtrinsicFunction;
|
|
27
30
|
defaultFormatBalance?: _SubstrateDefaultFormatBalance;
|
|
@@ -7,6 +7,7 @@ import { rpc as oakRpc, types as oakTypes } from '@oak-foundation/types';
|
|
|
7
7
|
import { _API_OPTIONS_CHAIN_GROUP, API_AUTO_CONNECT_MS, API_CONNECT_TIMEOUT } from '@subwallet/extension-base/services/chain-service/constants';
|
|
8
8
|
import { getSubstrateConnectProvider } from '@subwallet/extension-base/services/chain-service/handler/light-client';
|
|
9
9
|
import { DEFAULT_AUX } from '@subwallet/extension-base/services/chain-service/handler/SubstrateChainHandler';
|
|
10
|
+
import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
|
|
10
11
|
import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
|
|
11
12
|
import { spec as availSpec } from 'avail-js-sdk';
|
|
12
13
|
import { BehaviorSubject } from 'rxjs';
|
|
@@ -20,13 +21,22 @@ export class SubstrateApi {
|
|
|
20
21
|
isApiReady = false;
|
|
21
22
|
isApiReadyOnce = false;
|
|
22
23
|
isApiConnectedSubject = new BehaviorSubject(false);
|
|
24
|
+
connectionStatusSubject = new BehaviorSubject(_ChainConnectionStatus.DISCONNECTED);
|
|
23
25
|
get isApiConnected() {
|
|
24
26
|
return this.isApiConnectedSubject.getValue();
|
|
25
27
|
}
|
|
26
|
-
|
|
28
|
+
substrateRetry = 0;
|
|
29
|
+
get connectionStatus() {
|
|
30
|
+
return this.connectionStatusSubject.getValue();
|
|
31
|
+
}
|
|
32
|
+
updateConnectionStatus(status) {
|
|
33
|
+
const isConnected = status === _ChainConnectionStatus.CONNECTED;
|
|
27
34
|
if (isConnected !== this.isApiConnectedSubject.value) {
|
|
28
35
|
this.isApiConnectedSubject.next(isConnected);
|
|
29
36
|
}
|
|
37
|
+
if (status !== this.connectionStatusSubject.value) {
|
|
38
|
+
this.connectionStatusSubject.next(status);
|
|
39
|
+
}
|
|
30
40
|
}
|
|
31
41
|
specName = '';
|
|
32
42
|
specVersion = '';
|
|
@@ -54,12 +64,14 @@ export class SubstrateApi {
|
|
|
54
64
|
[`${metadata.genesisHash}-${metadata.specVersion}`]: metadata.hexValue
|
|
55
65
|
};
|
|
56
66
|
}
|
|
67
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTING);
|
|
68
|
+
let api;
|
|
57
69
|
if (_API_OPTIONS_CHAIN_GROUP.acala.includes(this.chainSlug)) {
|
|
58
|
-
|
|
70
|
+
api = new ApiPromise(acalaOptions({
|
|
59
71
|
provider
|
|
60
72
|
}));
|
|
61
73
|
} else if (_API_OPTIONS_CHAIN_GROUP.turing.includes(this.chainSlug)) {
|
|
62
|
-
|
|
74
|
+
api = new ApiPromise({
|
|
63
75
|
provider,
|
|
64
76
|
rpc: oakRpc,
|
|
65
77
|
types: oakTypes
|
|
@@ -72,8 +84,13 @@ export class SubstrateApi {
|
|
|
72
84
|
signedExtensions: availSpec.signedExtensions
|
|
73
85
|
});
|
|
74
86
|
} else {
|
|
75
|
-
|
|
87
|
+
api = new ApiPromise(apiOption);
|
|
76
88
|
}
|
|
89
|
+
api.on('ready', this.onReady.bind(this));
|
|
90
|
+
api.on('connected', this.onConnect.bind(this));
|
|
91
|
+
api.on('disconnected', this.onDisconnect.bind(this));
|
|
92
|
+
api.on('error', this.onError.bind(this));
|
|
93
|
+
return api;
|
|
77
94
|
}
|
|
78
95
|
constructor(chainSlug, apiUrl, {
|
|
79
96
|
externalApiPromise,
|
|
@@ -88,10 +105,6 @@ export class SubstrateApi {
|
|
|
88
105
|
this.provider = this.createProvider(apiUrl);
|
|
89
106
|
this.api = externalApiPromise || this.createApi(this.provider);
|
|
90
107
|
this.handleApiReady = createPromiseHandler();
|
|
91
|
-
this.api.on('ready', this.onReady.bind(this));
|
|
92
|
-
this.api.on('connected', this.onConnect.bind(this));
|
|
93
|
-
this.api.on('disconnected', this.onDisconnect.bind(this));
|
|
94
|
-
this.api.on('error', this.onError.bind(this));
|
|
95
108
|
}
|
|
96
109
|
get isReady() {
|
|
97
110
|
return this.handleApiReady.promise;
|
|
@@ -113,17 +126,16 @@ export class SubstrateApi {
|
|
|
113
126
|
this.apiUrl = apiUrl;
|
|
114
127
|
this.provider = this.createProvider(apiUrl);
|
|
115
128
|
this.api = this.createApi(this.provider);
|
|
116
|
-
this.api.on('ready', this.onReady.bind(this));
|
|
117
|
-
this.api.on('connected', this.onConnect.bind(this));
|
|
118
|
-
this.api.on('disconnected', this.onDisconnect.bind(this));
|
|
119
|
-
this.api.on('error', this.onError.bind(this));
|
|
120
129
|
}
|
|
121
130
|
connect() {
|
|
122
131
|
if (this.api.isConnected) {
|
|
123
|
-
this.
|
|
132
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
|
|
124
133
|
} else {
|
|
134
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTING);
|
|
125
135
|
this.api.connect().then(() => {
|
|
126
|
-
this.
|
|
136
|
+
this.api.isReady.then(() => {
|
|
137
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
|
|
138
|
+
}).catch(console.error);
|
|
127
139
|
}).catch(console.error);
|
|
128
140
|
}
|
|
129
141
|
}
|
|
@@ -133,7 +145,7 @@ export class SubstrateApi {
|
|
|
133
145
|
} catch (e) {
|
|
134
146
|
console.error(e);
|
|
135
147
|
}
|
|
136
|
-
this.
|
|
148
|
+
this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
|
|
137
149
|
}
|
|
138
150
|
async recoverConnect() {
|
|
139
151
|
await this.disconnect();
|
|
@@ -155,7 +167,8 @@ export class SubstrateApi {
|
|
|
155
167
|
});
|
|
156
168
|
}
|
|
157
169
|
onConnect() {
|
|
158
|
-
this.
|
|
170
|
+
this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
|
|
171
|
+
this.substrateRetry = 0;
|
|
159
172
|
console.log(`Connected to ${this.chainSlug || ''} at ${this.apiUrl}`);
|
|
160
173
|
if (this.isApiReadyOnce) {
|
|
161
174
|
this.handleApiReady.resolve(this);
|
|
@@ -164,8 +177,14 @@ export class SubstrateApi {
|
|
|
164
177
|
onDisconnect() {
|
|
165
178
|
this.isApiReady = false;
|
|
166
179
|
console.log(`Disconnected from ${this.chainSlug} at ${this.apiUrl}`);
|
|
167
|
-
this.
|
|
180
|
+
this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
|
|
168
181
|
this.handleApiReady = createPromiseHandler();
|
|
182
|
+
this.substrateRetry += 1;
|
|
183
|
+
if (this.substrateRetry > 9) {
|
|
184
|
+
this.disconnect().then(() => {
|
|
185
|
+
this.updateConnectionStatus(_ChainConnectionStatus.UNSTABLE);
|
|
186
|
+
}).catch(console.error);
|
|
187
|
+
}
|
|
169
188
|
}
|
|
170
189
|
onError(e) {
|
|
171
190
|
console.warn(`${this.chainSlug} connection got error`, e);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { _AssetType } from '@subwallet/chain-list/types';
|
|
5
5
|
import { getDefaultWeightV2 } from '@subwallet/extension-base/koni/api/tokens/wasm/utils';
|
|
6
|
-
import { AbstractChainHandler
|
|
6
|
+
import { AbstractChainHandler } from '@subwallet/extension-base/services/chain-service/handler/AbstractChainHandler';
|
|
7
7
|
import { SubstrateApi } from '@subwallet/extension-base/services/chain-service/handler/SubstrateApi';
|
|
8
8
|
import { ContractPromise } from '@polkadot/api-contract';
|
|
9
9
|
import { BN } from '@polkadot/util';
|
|
@@ -34,12 +34,12 @@ export class SubstrateChainHandler extends AbstractChainHandler {
|
|
|
34
34
|
|
|
35
35
|
// Not found substrateInterface mean it active with evm interface
|
|
36
36
|
if (api) {
|
|
37
|
-
api
|
|
37
|
+
api.connect();
|
|
38
38
|
if (!api.useLightClient) {
|
|
39
39
|
// Manual fire handle connect to avoid some chain can not reconnect
|
|
40
40
|
setTimeout(() => {
|
|
41
|
-
this.
|
|
42
|
-
},
|
|
41
|
+
this.handleConnection(chain, api.connectionStatus);
|
|
42
|
+
}, 10000);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -194,8 +194,8 @@ export class SubstrateChainHandler extends AbstractChainHandler {
|
|
|
194
194
|
metadata,
|
|
195
195
|
externalApiPromise
|
|
196
196
|
});
|
|
197
|
-
apiObject.
|
|
198
|
-
onUpdateStatus && apiObject.
|
|
197
|
+
apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
|
|
198
|
+
onUpdateStatus && apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
|
|
199
199
|
|
|
200
200
|
// Update metadata to database with async methods
|
|
201
201
|
apiObject.isReady.then(api => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MetadataItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
|
+
import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
|
|
2
3
|
import { ApiPromise } from '@polkadot/api';
|
|
3
4
|
export interface _EvmChainSpec {
|
|
4
5
|
evmChainId: number;
|
|
@@ -19,7 +20,7 @@ export interface _SubstrateChainSpec {
|
|
|
19
20
|
export interface _ApiOptions {
|
|
20
21
|
providerName?: string;
|
|
21
22
|
metadata?: MetadataItem;
|
|
22
|
-
onUpdateStatus?: (
|
|
23
|
+
onUpdateStatus?: (status: _ChainConnectionStatus) => void;
|
|
23
24
|
externalApiPromise?: ApiPromise;
|
|
24
25
|
}
|
|
25
26
|
export declare enum _CHAIN_VALIDATION_ERROR {
|
|
@@ -73,6 +73,7 @@ export declare class ChainService {
|
|
|
73
73
|
private destroyApiForChain;
|
|
74
74
|
enableChain(chainSlug: string): Promise<boolean>;
|
|
75
75
|
enableChains(chainSlugs: string[]): Promise<boolean>;
|
|
76
|
+
reconnectChain(chain: string): Promise<boolean>;
|
|
76
77
|
disableChain(chainSlug: string): boolean;
|
|
77
78
|
private checkExistedPredefinedChain;
|
|
78
79
|
private fetchLatestData;
|
|
@@ -381,7 +381,7 @@ export class ChainService {
|
|
|
381
381
|
this.dataMap.assetRefMap = latestAssetRefMap;
|
|
382
382
|
await this.initChains();
|
|
383
383
|
this.chainInfoMapSubject.next(this.getChainInfoMap());
|
|
384
|
-
this.
|
|
384
|
+
this.updateChainStateMapSubscription();
|
|
385
385
|
this.assetRegistrySubject.next(this.getAssetRegistry());
|
|
386
386
|
this.xcmRefMapSubject.next(this.dataMap.assetRefMap);
|
|
387
387
|
await this.initApis();
|
|
@@ -407,14 +407,14 @@ export class ChainService {
|
|
|
407
407
|
endpoint,
|
|
408
408
|
providerName
|
|
409
409
|
} = this.getChainCurrentProviderByKey(chainInfo.slug);
|
|
410
|
-
const onUpdateStatus =
|
|
410
|
+
const onUpdateStatus = status => {
|
|
411
411
|
const currentStatus = this.getChainStateByKey(chainInfo.slug).connectionStatus;
|
|
412
|
-
const newStatus = isConnected ? _ChainConnectionStatus.CONNECTED : _ChainConnectionStatus.DISCONNECTED;
|
|
413
412
|
|
|
414
413
|
// Avoid unnecessary update in case disable chain
|
|
415
|
-
if (currentStatus !==
|
|
416
|
-
|
|
417
|
-
this.
|
|
414
|
+
if (currentStatus !== status) {
|
|
415
|
+
console.log(chainInfo.name, currentStatus, status);
|
|
416
|
+
this.setChainConnectionStatus(chainInfo.slug, status);
|
|
417
|
+
this.updateChainStateMapSubscription();
|
|
418
418
|
}
|
|
419
419
|
};
|
|
420
420
|
if (chainInfo.substrateInfo !== null && chainInfo.substrateInfo !== undefined) {
|
|
@@ -499,6 +499,12 @@ export class ChainService {
|
|
|
499
499
|
needUpdate && this.updateChainStateMapSubscription();
|
|
500
500
|
return needUpdate;
|
|
501
501
|
}
|
|
502
|
+
async reconnectChain(chain) {
|
|
503
|
+
var _this$getSubstrateApi, _this$getEvmApi;
|
|
504
|
+
await ((_this$getSubstrateApi = this.getSubstrateApi(chain)) === null || _this$getSubstrateApi === void 0 ? void 0 : _this$getSubstrateApi.recoverConnect());
|
|
505
|
+
await ((_this$getEvmApi = this.getEvmApi(chain)) === null || _this$getEvmApi === void 0 ? void 0 : _this$getEvmApi.recoverConnect());
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
502
508
|
disableChain(chainSlug) {
|
|
503
509
|
const chainInfo = this.getChainInfoByKey(chainSlug);
|
|
504
510
|
const chainStateMap = this.getChainStateMap();
|
|
@@ -38,6 +38,7 @@ export interface _ChainBaseApi {
|
|
|
38
38
|
isApiConnectedSubject: BehaviorSubject<boolean>;
|
|
39
39
|
isApiReadyOnce: boolean;
|
|
40
40
|
isApiConnected: boolean;
|
|
41
|
+
connectionStatus: _ChainConnectionStatus;
|
|
41
42
|
updateApiUrl: (apiUrl: string) => Promise<void>;
|
|
42
43
|
connect: () => void;
|
|
43
44
|
disconnect: () => Promise<void>;
|