@toruslabs/ethereum-controllers 5.11.0 → 6.0.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.
- package/dist/ethereumControllers.cjs.js +80 -431
- package/dist/ethereumControllers.esm.js +30 -349
- package/dist/ethereumControllers.umd.min.js +1 -1
- package/dist/ethereumControllers.umd.min.js.LICENSE.txt +7 -2
- package/dist/lib.cjs/Account/AccountTrackerController.js +160 -0
- package/dist/lib.cjs/Block/PollingBlockTracker.js +85 -0
- package/dist/lib.cjs/Currency/CurrencyController.js +111 -0
- package/dist/lib.cjs/Gas/GasFeeController.js +214 -0
- package/dist/lib.cjs/Gas/gasUtil.js +148 -0
- package/dist/lib.cjs/Keyring/KeyringController.js +93 -0
- package/dist/lib.cjs/Message/AbstractMessageController.js +107 -0
- package/dist/lib.cjs/Message/AddChainController.js +78 -0
- package/dist/lib.cjs/Message/MessageController.js +77 -0
- package/dist/lib.cjs/Message/PersonalMessageController.js +77 -0
- package/dist/lib.cjs/Message/SwitchChainController.js +78 -0
- package/dist/lib.cjs/Message/TypedMessageController.js +81 -0
- package/dist/lib.cjs/Message/utils.js +112 -0
- package/dist/lib.cjs/Network/NetworkController.js +201 -0
- package/dist/lib.cjs/Network/cacheIdentifier.js +112 -0
- package/dist/lib.cjs/Network/createEthereumMiddleware.js +302 -0
- package/dist/lib.cjs/Network/createJsonRpcClient.js +64 -0
- package/dist/lib.cjs/Nfts/NftHandler.js +180 -0
- package/dist/lib.cjs/Nfts/NftsController.js +213 -0
- package/dist/lib.cjs/Preferences/PreferencesController.js +476 -0
- package/dist/lib.cjs/Tokens/TokenHandler.js +51 -0
- package/dist/lib.cjs/Tokens/TokenRatesController.js +112 -0
- package/dist/lib.cjs/Tokens/TokensController.js +259 -0
- package/dist/lib.cjs/Transaction/NonceTracker.js +150 -0
- package/dist/lib.cjs/Transaction/PendingTransactionTracker.js +222 -0
- package/dist/lib.cjs/Transaction/TransactionController.js +515 -0
- package/dist/lib.cjs/Transaction/TransactionGasUtil.js +81 -0
- package/dist/lib.cjs/Transaction/TransactionStateHistoryHelper.js +42 -0
- package/dist/lib.cjs/Transaction/TransactionStateManager.js +296 -0
- package/dist/lib.cjs/Transaction/TransactionUtils.js +341 -0
- package/dist/lib.cjs/index.js +171 -0
- package/dist/lib.cjs/utils/abis.js +510 -0
- package/dist/lib.cjs/utils/constants.js +362 -0
- package/dist/lib.cjs/utils/contractAddresses.js +16 -0
- package/dist/lib.cjs/utils/conversionUtils.js +232 -0
- package/dist/lib.cjs/utils/helpers.js +244 -0
- package/dist/lib.cjs/utils/lodashUtils.js +25 -0
- package/dist/lib.esm/Account/AccountTrackerController.js +158 -0
- package/dist/lib.esm/Block/PollingBlockTracker.js +83 -0
- package/dist/lib.esm/Currency/CurrencyController.js +109 -0
- package/dist/lib.esm/Gas/GasFeeController.js +212 -0
- package/dist/lib.esm/Gas/gasUtil.js +141 -0
- package/dist/lib.esm/Keyring/KeyringController.js +91 -0
- package/dist/lib.esm/Message/AbstractMessageController.js +105 -0
- package/dist/lib.esm/Message/AddChainController.js +76 -0
- package/dist/lib.esm/Message/MessageController.js +75 -0
- package/dist/lib.esm/Message/PersonalMessageController.js +75 -0
- package/dist/lib.esm/Message/SwitchChainController.js +76 -0
- package/dist/lib.esm/Message/TypedMessageController.js +79 -0
- package/dist/lib.esm/Message/utils.js +105 -0
- package/dist/lib.esm/Network/NetworkController.js +199 -0
- package/dist/lib.esm/Network/cacheIdentifier.js +107 -0
- package/dist/lib.esm/Network/createEthereumMiddleware.js +289 -0
- package/dist/lib.esm/Network/createJsonRpcClient.js +60 -0
- package/dist/lib.esm/Nfts/NftHandler.js +178 -0
- package/dist/lib.esm/Nfts/NftsController.js +211 -0
- package/dist/lib.esm/Preferences/PreferencesController.js +474 -0
- package/dist/lib.esm/Tokens/TokenHandler.js +49 -0
- package/dist/lib.esm/Tokens/TokenRatesController.js +109 -0
- package/dist/lib.esm/Tokens/TokensController.js +257 -0
- package/dist/lib.esm/Transaction/NonceTracker.js +148 -0
- package/dist/lib.esm/Transaction/PendingTransactionTracker.js +220 -0
- package/dist/lib.esm/Transaction/TransactionController.js +513 -0
- package/dist/lib.esm/Transaction/TransactionGasUtil.js +79 -0
- package/dist/lib.esm/Transaction/TransactionStateHistoryHelper.js +38 -0
- package/dist/lib.esm/Transaction/TransactionStateManager.js +294 -0
- package/dist/lib.esm/Transaction/TransactionUtils.js +326 -0
- package/dist/lib.esm/index.js +33 -0
- package/dist/lib.esm/utils/abis.js +505 -0
- package/dist/lib.esm/utils/constants.js +323 -0
- package/dist/lib.esm/utils/contractAddresses.js +14 -0
- package/dist/lib.esm/utils/conversionUtils.js +218 -0
- package/dist/lib.esm/utils/helpers.js +227 -0
- package/dist/lib.esm/utils/lodashUtils.js +21 -0
- package/dist/types/Account/AccountTrackerController.d.ts +5 -5
- package/dist/types/Block/PollingBlockTracker.d.ts +1 -2
- package/dist/types/Currency/CurrencyController.d.ts +1 -1
- package/dist/types/Gas/GasFeeController.d.ts +3 -3
- package/dist/types/Gas/gasUtil.d.ts +1 -1
- package/dist/types/Keyring/KeyringController.d.ts +3 -5
- package/dist/types/Message/AbstractMessageController.d.ts +5 -6
- package/dist/types/Message/AddChainController.d.ts +4 -4
- package/dist/types/Message/MessageController.d.ts +4 -4
- package/dist/types/Message/PersonalMessageController.d.ts +4 -4
- package/dist/types/Message/SwitchChainController.d.ts +4 -4
- package/dist/types/Message/TypedMessageController.d.ts +6 -7
- package/dist/types/Message/utils.d.ts +2 -7
- package/dist/types/Network/NetworkController.d.ts +4 -4
- package/dist/types/Network/cacheIdentifier.d.ts +1 -1
- package/dist/types/Network/createEthereumMiddleware.d.ts +2 -18
- package/dist/types/Network/createJsonRpcClient.d.ts +2 -2
- package/dist/types/Nfts/NftsController.d.ts +2 -2
- package/dist/types/Preferences/PreferencesController.d.ts +4 -4
- package/dist/types/Tokens/TokensController.d.ts +3 -3
- package/dist/types/Transaction/NonceTracker.d.ts +5 -5
- package/dist/types/Transaction/PendingTransactionTracker.d.ts +5 -5
- package/dist/types/Transaction/TransactionController.d.ts +12 -12
- package/dist/types/Transaction/TransactionGasUtil.d.ts +4 -4
- package/dist/types/Transaction/TransactionStateManager.d.ts +3 -3
- package/dist/types/Transaction/TransactionUtils.d.ts +1 -1
- package/dist/types/index.d.ts +12 -14
- package/dist/types/utils/constants.d.ts +1 -5
- package/dist/types/utils/helpers.d.ts +4 -4
- package/dist/types/utils/interfaces.d.ts +43 -23
- package/package.json +10 -9
- package/dist/types/Message/DecryptMessageController.d.ts +0 -20
- package/dist/types/Message/EncryptionPublicKeyController.d.ts +0 -20
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
4
|
+
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
|
|
5
|
+
var baseControllers = require('@toruslabs/base-controllers');
|
|
6
|
+
var deepmerge = require('deepmerge');
|
|
7
|
+
var ethers = require('ethers');
|
|
8
|
+
var log = require('loglevel');
|
|
9
|
+
var constants = require('../utils/constants.js');
|
|
10
|
+
var helpers = require('../utils/helpers.js');
|
|
11
|
+
var NftHandler = require('./NftHandler.js');
|
|
12
|
+
|
|
13
|
+
const DEFAULT_INTERVAL = 180 * 1000;
|
|
14
|
+
class NftsController extends baseControllers.BaseController {
|
|
15
|
+
constructor({
|
|
16
|
+
config,
|
|
17
|
+
state,
|
|
18
|
+
provider,
|
|
19
|
+
getCustomNfts,
|
|
20
|
+
getSimpleHashNfts,
|
|
21
|
+
onPreferencesStateChange,
|
|
22
|
+
onNetworkStateChange
|
|
23
|
+
}) {
|
|
24
|
+
super({
|
|
25
|
+
config,
|
|
26
|
+
state
|
|
27
|
+
});
|
|
28
|
+
_defineProperty(this, "name", "NftsController");
|
|
29
|
+
_defineProperty(this, "provider", void 0);
|
|
30
|
+
_defineProperty(this, "ethersProvider", void 0);
|
|
31
|
+
_defineProperty(this, "_timer", void 0);
|
|
32
|
+
_defineProperty(this, "getCustomNfts", void 0);
|
|
33
|
+
_defineProperty(this, "getSimpleHashNfts", void 0);
|
|
34
|
+
this.provider = provider;
|
|
35
|
+
this.ethersProvider = new ethers.BrowserProvider(this.provider, "any");
|
|
36
|
+
this.getCustomNfts = getCustomNfts;
|
|
37
|
+
this.getSimpleHashNfts = getSimpleHashNfts;
|
|
38
|
+
this.defaultConfig = {
|
|
39
|
+
interval: DEFAULT_INTERVAL,
|
|
40
|
+
selectedAddress: "",
|
|
41
|
+
chainId: ""
|
|
42
|
+
};
|
|
43
|
+
this.defaultState = {
|
|
44
|
+
nfts: {}
|
|
45
|
+
};
|
|
46
|
+
this.initialize();
|
|
47
|
+
onPreferencesStateChange(preferencesState => {
|
|
48
|
+
if (preferencesState.selectedAddress !== this.config.selectedAddress) {
|
|
49
|
+
this.configure({
|
|
50
|
+
selectedAddress: preferencesState.selectedAddress
|
|
51
|
+
});
|
|
52
|
+
this.restartNftDetection();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
onNetworkStateChange(networkState => {
|
|
56
|
+
const {
|
|
57
|
+
chainId
|
|
58
|
+
} = networkState.providerConfig;
|
|
59
|
+
if (chainId !== this.config.chainId) {
|
|
60
|
+
this.configure({
|
|
61
|
+
chainId
|
|
62
|
+
});
|
|
63
|
+
this.restartNftDetection();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
get userSelectedAddress() {
|
|
68
|
+
return this.config.selectedAddress;
|
|
69
|
+
}
|
|
70
|
+
get userNfts() {
|
|
71
|
+
var _this$state$nfts$this;
|
|
72
|
+
if (!this.userSelectedAddress) return [];
|
|
73
|
+
return (_this$state$nfts$this = this.state.nfts[this.userSelectedAddress]) !== null && _this$state$nfts$this !== void 0 ? _this$state$nfts$this : [];
|
|
74
|
+
}
|
|
75
|
+
get interval() {
|
|
76
|
+
return this.config.interval;
|
|
77
|
+
}
|
|
78
|
+
set interval(interval) {
|
|
79
|
+
if (this._timer) window.clearInterval(this._timer);
|
|
80
|
+
if (!interval) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this._timer = window.setInterval(() => {
|
|
84
|
+
if (!helpers.idleTimeTracker.checkIfIdle()) {
|
|
85
|
+
this.detectNewNfts();
|
|
86
|
+
this.refreshNftBalances();
|
|
87
|
+
}
|
|
88
|
+
}, interval);
|
|
89
|
+
}
|
|
90
|
+
startNftDetection(selectedAddress) {
|
|
91
|
+
this.configure({
|
|
92
|
+
selectedAddress
|
|
93
|
+
});
|
|
94
|
+
this.restartNftDetection();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Restart nft detection polling period and call detectNewNfts
|
|
99
|
+
* in case of address change or user session initialization.
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
restartNftDetection() {
|
|
103
|
+
if (!this.userSelectedAddress) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.detectNewNfts();
|
|
107
|
+
this.refreshNftBalances();
|
|
108
|
+
this.config.interval = DEFAULT_INTERVAL;
|
|
109
|
+
}
|
|
110
|
+
detectNewNfts() {
|
|
111
|
+
const userAddress = this.userSelectedAddress;
|
|
112
|
+
if (!userAddress) return;
|
|
113
|
+
const currentChainId = this.config.chainId;
|
|
114
|
+
const nftsToDetect = []; // object[]
|
|
115
|
+
if (!currentChainId) {
|
|
116
|
+
this.update({
|
|
117
|
+
nfts: {
|
|
118
|
+
[userAddress]: [...nftsToDetect]
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (this.getCustomNfts) {
|
|
124
|
+
const customNfts = this.getCustomNfts(userAddress);
|
|
125
|
+
const reducedNfts = customNfts.reduce((acc, x) => {
|
|
126
|
+
// first aggregate by contract address
|
|
127
|
+
if (x.network === currentChainId) {
|
|
128
|
+
const newAsset = {
|
|
129
|
+
description: "",
|
|
130
|
+
image: "",
|
|
131
|
+
name: "",
|
|
132
|
+
tokenBalance: "",
|
|
133
|
+
tokenId: x.nft_id,
|
|
134
|
+
customNftId: x.id.toString()
|
|
135
|
+
};
|
|
136
|
+
if (acc[x.nft_address]) {
|
|
137
|
+
acc[x.nft_address].assets.push(newAsset);
|
|
138
|
+
} else {
|
|
139
|
+
const objToPush = {
|
|
140
|
+
assets: [newAsset],
|
|
141
|
+
chainId: x.network,
|
|
142
|
+
contractAddress: x.nft_address,
|
|
143
|
+
contractName: "",
|
|
144
|
+
contractSymbol: "",
|
|
145
|
+
contractImage: "",
|
|
146
|
+
nftStandard: x.nft_contract_standard,
|
|
147
|
+
contractDescription: ""
|
|
148
|
+
};
|
|
149
|
+
acc[x.nft_address] = objToPush;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return acc;
|
|
153
|
+
}, {});
|
|
154
|
+
nftsToDetect.push(...Object.values(reducedNfts));
|
|
155
|
+
}
|
|
156
|
+
this.update({
|
|
157
|
+
nfts: {
|
|
158
|
+
[userAddress]: [...nftsToDetect]
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async refreshNftBalances() {
|
|
163
|
+
const userAddress = this.userSelectedAddress;
|
|
164
|
+
if (userAddress === "") return;
|
|
165
|
+
const oldNfts = [...this.userNfts];
|
|
166
|
+
const nonZeroNfts = [];
|
|
167
|
+
try {
|
|
168
|
+
const currentChainId = this.config.chainId;
|
|
169
|
+
if (constants.SIMPLEHASH_SUPPORTED_CHAINS.includes(currentChainId)) {
|
|
170
|
+
const simpleHashBalances = await this.getSimpleHashNfts(userAddress, currentChainId);
|
|
171
|
+
nonZeroNfts.push(...simpleHashBalances);
|
|
172
|
+
this.update({
|
|
173
|
+
nfts: {
|
|
174
|
+
[userAddress]: nonZeroNfts
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (oldNfts.length > 0) {
|
|
179
|
+
this.getNftBalancesUsingHandler(oldNfts);
|
|
180
|
+
}
|
|
181
|
+
} catch (error) {
|
|
182
|
+
log.error(error, "unable to fetch nft balances");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async getNftBalancesUsingHandler(customNfts) {
|
|
186
|
+
if (!this.userSelectedAddress) return;
|
|
187
|
+
const userAddress = this.userSelectedAddress;
|
|
188
|
+
const currentNetworkNfts = customNfts;
|
|
189
|
+
const promiseSettledResult = await Promise.allSettled(currentNetworkNfts.map(async x => {
|
|
190
|
+
try {
|
|
191
|
+
const tokenInstance = new NftHandler.NftHandler(_objectSpread(_objectSpread({}, x), {}, {
|
|
192
|
+
provider: this.ethersProvider
|
|
193
|
+
}));
|
|
194
|
+
const contractData = await tokenInstance.getContractMetadata();
|
|
195
|
+
const assetData = await Promise.allSettled(x.assets.map(y => tokenInstance.getNftMetadata(userAddress, y)));
|
|
196
|
+
return _objectSpread(_objectSpread({}, contractData), {}, {
|
|
197
|
+
assets: assetData.filter(z => z.status === "fulfilled").map(z => z.value)
|
|
198
|
+
});
|
|
199
|
+
} catch (error) {
|
|
200
|
+
log.warn("Invalid contract address while fetching", error);
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
}));
|
|
204
|
+
const nonZeroTokens = promiseSettledResult.filter(x => x.status === "fulfilled").map(x => x.value);
|
|
205
|
+
this.update({
|
|
206
|
+
nfts: {
|
|
207
|
+
[userAddress]: deepmerge(this.userNfts, nonZeroTokens)
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
exports.NftsController = NftsController;
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
|
|
4
|
+
var util = require('@ethereumjs/util');
|
|
5
|
+
var baseControllers = require('@toruslabs/base-controllers');
|
|
6
|
+
var asyncMutex = require('async-mutex');
|
|
7
|
+
var log = require('loglevel');
|
|
8
|
+
var constants = require('../utils/constants.js');
|
|
9
|
+
var helpers = require('../utils/helpers.js');
|
|
10
|
+
|
|
11
|
+
class PreferencesController extends baseControllers.BasePreferencesController {
|
|
12
|
+
constructor({
|
|
13
|
+
config,
|
|
14
|
+
state,
|
|
15
|
+
provider,
|
|
16
|
+
signAuthMessage,
|
|
17
|
+
getProviderConfig,
|
|
18
|
+
setProviderConfig,
|
|
19
|
+
validateSignMessage
|
|
20
|
+
}) {
|
|
21
|
+
super({
|
|
22
|
+
config,
|
|
23
|
+
state,
|
|
24
|
+
defaultPreferences: {
|
|
25
|
+
formattedPastTransactions: [],
|
|
26
|
+
fetchedPastTx: [],
|
|
27
|
+
paymentTx: [],
|
|
28
|
+
etherscanTransactions: []
|
|
29
|
+
},
|
|
30
|
+
signAuthMessage,
|
|
31
|
+
validateSignMessage
|
|
32
|
+
});
|
|
33
|
+
_defineProperty(this, "_handle", void 0);
|
|
34
|
+
_defineProperty(this, "_mutex", new asyncMutex.Mutex());
|
|
35
|
+
_defineProperty(this, "getProviderConfig", void 0);
|
|
36
|
+
_defineProperty(this, "setProviderConfig", void 0);
|
|
37
|
+
_defineProperty(this, "provider", void 0);
|
|
38
|
+
this.provider = provider;
|
|
39
|
+
this.getProviderConfig = getProviderConfig;
|
|
40
|
+
this.setProviderConfig = setProviderConfig;
|
|
41
|
+
}
|
|
42
|
+
async poll(interval) {
|
|
43
|
+
var _this$getAddressState;
|
|
44
|
+
const releaseLock = await this._mutex.acquire();
|
|
45
|
+
if (interval) this.configure({
|
|
46
|
+
pollInterval: interval
|
|
47
|
+
});
|
|
48
|
+
if (this._handle) window.clearTimeout(this._handle);
|
|
49
|
+
// call here
|
|
50
|
+
const storeSelectedAddress = this.state.selectedAddress;
|
|
51
|
+
if (!storeSelectedAddress) return;
|
|
52
|
+
if (!((_this$getAddressState = this.getAddressState(storeSelectedAddress)) !== null && _this$getAddressState !== void 0 && _this$getAddressState.jwtToken)) return;
|
|
53
|
+
// This should never throw
|
|
54
|
+
await this.sync(storeSelectedAddress);
|
|
55
|
+
releaseLock();
|
|
56
|
+
this._handle = window.setTimeout(() => {
|
|
57
|
+
this.poll(this.config.pollInterval);
|
|
58
|
+
}, this.config.pollInterval);
|
|
59
|
+
}
|
|
60
|
+
async initPreferences(params) {
|
|
61
|
+
const {
|
|
62
|
+
address,
|
|
63
|
+
jwtToken,
|
|
64
|
+
calledFromEmbed,
|
|
65
|
+
userInfo,
|
|
66
|
+
rehydrate,
|
|
67
|
+
locale = "en",
|
|
68
|
+
type,
|
|
69
|
+
signatures,
|
|
70
|
+
web3AuthClientId,
|
|
71
|
+
web3AuthNetwork,
|
|
72
|
+
loginMode,
|
|
73
|
+
sessionPubKey
|
|
74
|
+
} = params;
|
|
75
|
+
await super.init({
|
|
76
|
+
address,
|
|
77
|
+
userInfo,
|
|
78
|
+
idToken: jwtToken,
|
|
79
|
+
type,
|
|
80
|
+
metadata: {
|
|
81
|
+
email: userInfo.email,
|
|
82
|
+
signatures,
|
|
83
|
+
network: web3AuthNetwork
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
const {
|
|
87
|
+
aggregateVerifier,
|
|
88
|
+
verifier,
|
|
89
|
+
verifierId
|
|
90
|
+
} = userInfo || {};
|
|
91
|
+
const userExists = await this.sync(address);
|
|
92
|
+
if (!userExists) {
|
|
93
|
+
const accountState = this.getAddressState(address);
|
|
94
|
+
await this.createUser({
|
|
95
|
+
selectedCurrency: accountState.selectedCurrency,
|
|
96
|
+
theme: accountState.theme,
|
|
97
|
+
verifier: aggregateVerifier || verifier,
|
|
98
|
+
verifierId,
|
|
99
|
+
locale,
|
|
100
|
+
address,
|
|
101
|
+
type,
|
|
102
|
+
web3AuthNetwork
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
this.storeUserLogin({
|
|
106
|
+
verifier: aggregateVerifier || verifier,
|
|
107
|
+
verifierId,
|
|
108
|
+
options: {
|
|
109
|
+
calledFromEmbed,
|
|
110
|
+
rehydrate
|
|
111
|
+
},
|
|
112
|
+
address,
|
|
113
|
+
web3AuthClientId,
|
|
114
|
+
web3AuthNetwork,
|
|
115
|
+
sessionPubKey,
|
|
116
|
+
loginMode
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
getSelectedAddress() {
|
|
120
|
+
return this.state.selectedAddress;
|
|
121
|
+
}
|
|
122
|
+
async sync(address) {
|
|
123
|
+
try {
|
|
124
|
+
const user = await this.getUser(address);
|
|
125
|
+
if (user) {
|
|
126
|
+
const {
|
|
127
|
+
default_currency: defaultCurrency,
|
|
128
|
+
contacts,
|
|
129
|
+
theme,
|
|
130
|
+
locale,
|
|
131
|
+
public_address: userPublicAddress,
|
|
132
|
+
default_public_address: defaultPublicAddress,
|
|
133
|
+
customNetworks,
|
|
134
|
+
customTokens,
|
|
135
|
+
customNfts,
|
|
136
|
+
account_type: accountType
|
|
137
|
+
} = user || {};
|
|
138
|
+
|
|
139
|
+
// update latest data in state.
|
|
140
|
+
this.updateState({
|
|
141
|
+
contacts,
|
|
142
|
+
theme,
|
|
143
|
+
selectedCurrency: defaultCurrency,
|
|
144
|
+
locale,
|
|
145
|
+
defaultPublicAddress: defaultPublicAddress || userPublicAddress,
|
|
146
|
+
customTokens,
|
|
147
|
+
customNfts,
|
|
148
|
+
customNetworks,
|
|
149
|
+
accountType: accountType
|
|
150
|
+
}, address);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (baseControllers.isUnauthorizedError(error)) {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
log.error(error);
|
|
159
|
+
return false;
|
|
160
|
+
} finally {
|
|
161
|
+
this.getWalletOrders(address).then(walletTx => {
|
|
162
|
+
// eslint-disable-next-line promise/always-return
|
|
163
|
+
if (walletTx && walletTx.length > 0) {
|
|
164
|
+
this.updateState({
|
|
165
|
+
fetchedPastTx: [...walletTx]
|
|
166
|
+
}, address);
|
|
167
|
+
this.calculatePastTx(walletTx, address);
|
|
168
|
+
}
|
|
169
|
+
}).catch(error => log.error(error));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async patchNewTx(tx, address) {
|
|
173
|
+
var _this$getAddressState2;
|
|
174
|
+
const formattedTx = helpers.formatPastTx({
|
|
175
|
+
transaction: tx,
|
|
176
|
+
blockExplorerUrl: this.getBlockExplorerUrl()
|
|
177
|
+
});
|
|
178
|
+
const storePastTx = ((_this$getAddressState2 = this.getAddressState(address)) === null || _this$getAddressState2 === void 0 ? void 0 : _this$getAddressState2.formattedPastTransactions) || [];
|
|
179
|
+
const duplicateIndex = storePastTx.findIndex(x => x.transaction_hash === tx.transaction_hash && x.chainId === tx.chain_id);
|
|
180
|
+
if (tx.status === baseControllers.TransactionStatus.submitted || tx.status === baseControllers.TransactionStatus.confirmed) {
|
|
181
|
+
if (duplicateIndex === -1) {
|
|
182
|
+
var _tx$to;
|
|
183
|
+
// No duplicate found
|
|
184
|
+
|
|
185
|
+
const finalTx = this.cancelTxCalculate([...storePastTx, formattedTx]);
|
|
186
|
+
tx.is_cancel = formattedTx.is_cancel;
|
|
187
|
+
tx.to = (_tx$to = tx.to) === null || _tx$to === void 0 ? void 0 : _tx$to.toLowerCase();
|
|
188
|
+
tx.from = tx.from.toLowerCase();
|
|
189
|
+
this.updateState({
|
|
190
|
+
formattedPastTransactions: finalTx
|
|
191
|
+
}, address);
|
|
192
|
+
this.postPastTx(tx, address);
|
|
193
|
+
} else {
|
|
194
|
+
// avoid overriding is_cancel
|
|
195
|
+
formattedTx.is_cancel = storePastTx[duplicateIndex].is_cancel;
|
|
196
|
+
storePastTx[duplicateIndex] = formattedTx;
|
|
197
|
+
this.updateState({
|
|
198
|
+
formattedPastTransactions: this.cancelTxCalculate([...storePastTx])
|
|
199
|
+
}, address);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
recalculatePastTx(address) {
|
|
204
|
+
// This triggers store update which calculates past Tx status for that network
|
|
205
|
+
const selectedAddress = address || this.state.selectedAddress;
|
|
206
|
+
const state = this.getAddressState(selectedAddress);
|
|
207
|
+
if (!(state !== null && state !== void 0 && state.fetchedPastTx)) return;
|
|
208
|
+
this.calculatePastTx(state.fetchedPastTx, selectedAddress);
|
|
209
|
+
}
|
|
210
|
+
async refetchEtherscanTx(address) {
|
|
211
|
+
var _this$getAddressState3;
|
|
212
|
+
const selectedAddress = address || this.state.selectedAddress;
|
|
213
|
+
if (!selectedAddress) return [];
|
|
214
|
+
const lowerCaseSelectedAddress = selectedAddress === null || selectedAddress === void 0 ? void 0 : selectedAddress.toLowerCase();
|
|
215
|
+
if ((_this$getAddressState3 = this.getAddressState(selectedAddress)) !== null && _this$getAddressState3 !== void 0 && _this$getAddressState3.jwtToken) {
|
|
216
|
+
const {
|
|
217
|
+
chainId
|
|
218
|
+
} = this.getProviderConfig();
|
|
219
|
+
if (constants.ETHERSCAN_SUPPORTED_CHAINS.includes(chainId)) {
|
|
220
|
+
const etherscanTxn = await this.fetchEtherscanTx({
|
|
221
|
+
selectedAddress,
|
|
222
|
+
chainId: this.getProviderConfig().chainId
|
|
223
|
+
});
|
|
224
|
+
const finalEthScanTxn = await helpers.addEtherscanTransactions({
|
|
225
|
+
txn: etherscanTxn,
|
|
226
|
+
lowerCaseSelectedAddress,
|
|
227
|
+
provider: this.provider,
|
|
228
|
+
chainId,
|
|
229
|
+
blockExplorerUrl: this.getBlockExplorerUrl()
|
|
230
|
+
});
|
|
231
|
+
log.info("Formatted Etherscan Response", finalEthScanTxn);
|
|
232
|
+
this.updateState({
|
|
233
|
+
etherscanTransactions: finalEthScanTxn
|
|
234
|
+
});
|
|
235
|
+
return etherscanTxn;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async fetchEtherscanTx(parameters) {
|
|
240
|
+
try {
|
|
241
|
+
const response = await this.wsApiClient.authGet(`etherscan?chainId=${parameters.chainId}`, this.authCredentials(parameters.selectedAddress));
|
|
242
|
+
log.info("Etherscan Response API", response);
|
|
243
|
+
return response.success ? response.data : [];
|
|
244
|
+
} catch (error) {
|
|
245
|
+
log.error("unable to fetch etherscan tx", error);
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async getEtherScanTokens(address, chainId) {
|
|
250
|
+
const selectedAddress = address;
|
|
251
|
+
const result = await this.wsApiClient.authGet(`tokens?chainId=${chainId}&address=${selectedAddress}`, this.authCredentials());
|
|
252
|
+
return result.data;
|
|
253
|
+
}
|
|
254
|
+
async getSimpleHashNfts(address, chainId) {
|
|
255
|
+
const selectedAddress = address;
|
|
256
|
+
const result = await this.wsApiClient.authGet(`nfts?chainId=${chainId}&address=${selectedAddress}`, this.authCredentials());
|
|
257
|
+
return result.data;
|
|
258
|
+
}
|
|
259
|
+
getCustomTokens(address) {
|
|
260
|
+
var _this$getAddressState4, _this$getAddressState5;
|
|
261
|
+
return (_this$getAddressState4 = (_this$getAddressState5 = this.getAddressState(address)) === null || _this$getAddressState5 === void 0 ? void 0 : _this$getAddressState5.customTokens) !== null && _this$getAddressState4 !== void 0 ? _this$getAddressState4 : [];
|
|
262
|
+
}
|
|
263
|
+
getCustomNfts(address) {
|
|
264
|
+
var _this$getAddressState6, _this$getAddressState7;
|
|
265
|
+
return (_this$getAddressState6 = (_this$getAddressState7 = this.getAddressState(address)) === null || _this$getAddressState7 === void 0 ? void 0 : _this$getAddressState7.customNfts) !== null && _this$getAddressState6 !== void 0 ? _this$getAddressState6 : [];
|
|
266
|
+
}
|
|
267
|
+
isChainIdSupported(address, chainId) {
|
|
268
|
+
const approveChainOptions = this.getChainOptions(address);
|
|
269
|
+
const providerConfig = approveChainOptions.find(x => util.stripHexPrefix(x.chainId) === chainId);
|
|
270
|
+
return !!providerConfig;
|
|
271
|
+
}
|
|
272
|
+
async addChain(network) {
|
|
273
|
+
const approveChainOptions = this.getChainOptions();
|
|
274
|
+
const providerConfig = approveChainOptions.find(x => x.chainId === network.chainId);
|
|
275
|
+
if (providerConfig) return;
|
|
276
|
+
const newNetwork = {
|
|
277
|
+
displayName: network.chainName,
|
|
278
|
+
rpcTarget: network.rpcUrls[0],
|
|
279
|
+
ticker: network.nativeCurrency.symbol,
|
|
280
|
+
chainId: network.chainId,
|
|
281
|
+
blockExplorerUrl: network.blockExplorerUrls[0],
|
|
282
|
+
tickerName: network.nativeCurrency.name,
|
|
283
|
+
logo: network.nativeCurrency.symbol
|
|
284
|
+
};
|
|
285
|
+
const isSuccess = await this.addCustomNetwork({
|
|
286
|
+
network: newNetwork
|
|
287
|
+
});
|
|
288
|
+
if (!isSuccess) throw new Error("unable to add custom network");
|
|
289
|
+
}
|
|
290
|
+
switchChain(data) {
|
|
291
|
+
const chainOptions = this.getChainOptions();
|
|
292
|
+
const providerConfig = chainOptions.find(x => x.chainId === data.chainId);
|
|
293
|
+
if (providerConfig) {
|
|
294
|
+
this.setProviderConfig(providerConfig);
|
|
295
|
+
} else {
|
|
296
|
+
throw new Error(`chainId ${data.chainId} is not supported`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Custom Network methods
|
|
301
|
+
async addCustomNetwork({
|
|
302
|
+
network
|
|
303
|
+
}) {
|
|
304
|
+
try {
|
|
305
|
+
const {
|
|
306
|
+
selectedAddress
|
|
307
|
+
} = this.state;
|
|
308
|
+
const payload = {
|
|
309
|
+
network_name: network.displayName,
|
|
310
|
+
rpc_url: network.rpcTarget,
|
|
311
|
+
chain_id: network.chainId,
|
|
312
|
+
symbol: network.ticker,
|
|
313
|
+
block_explorer_url: network.blockExplorerUrl || undefined,
|
|
314
|
+
is_testnet: network.isTestnet || false,
|
|
315
|
+
logo: network.logo,
|
|
316
|
+
symbol_name: network.tickerName
|
|
317
|
+
};
|
|
318
|
+
const res = await this.wsApiClient.authPost("customnetwork", payload, this.authCredentials(selectedAddress), {
|
|
319
|
+
useAPIKey: true
|
|
320
|
+
});
|
|
321
|
+
await this.sync(selectedAddress);
|
|
322
|
+
return res.data.id;
|
|
323
|
+
} catch {
|
|
324
|
+
log.error("error adding custom network");
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
async deleteCustomNetwork(id) {
|
|
329
|
+
try {
|
|
330
|
+
const {
|
|
331
|
+
selectedAddress
|
|
332
|
+
} = this.state;
|
|
333
|
+
await this.wsApiClient.authRemove(`customnetwork/${id}`, {}, this.authCredentials(selectedAddress), {
|
|
334
|
+
useAPIKey: true
|
|
335
|
+
});
|
|
336
|
+
await this.sync(selectedAddress);
|
|
337
|
+
return true;
|
|
338
|
+
} catch {
|
|
339
|
+
log.error("error deleting custom network");
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async editCustomNetwork({
|
|
344
|
+
network,
|
|
345
|
+
id
|
|
346
|
+
}) {
|
|
347
|
+
try {
|
|
348
|
+
const {
|
|
349
|
+
selectedAddress
|
|
350
|
+
} = this.state;
|
|
351
|
+
const payload = {
|
|
352
|
+
network_name: network.displayName,
|
|
353
|
+
rpc_url: network.rpcTarget,
|
|
354
|
+
chain_id: network.chainId,
|
|
355
|
+
symbol: network.ticker || undefined,
|
|
356
|
+
block_explorer_url: network.blockExplorerUrl || undefined,
|
|
357
|
+
is_testnet: network.isTestnet || false
|
|
358
|
+
};
|
|
359
|
+
await this.wsApiClient.authPatch(`customnetwork/${id}`, payload, this.authCredentials(selectedAddress), {
|
|
360
|
+
useAPIKey: true
|
|
361
|
+
});
|
|
362
|
+
await this.sync(selectedAddress);
|
|
363
|
+
return true;
|
|
364
|
+
} catch {
|
|
365
|
+
log.error("error editing custom network");
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
getChainOptions(address = this.state.selectedAddress) {
|
|
370
|
+
var _identities$address$c, _identities$address;
|
|
371
|
+
const {
|
|
372
|
+
identities
|
|
373
|
+
} = this.state;
|
|
374
|
+
const customNetworks = (_identities$address$c = (_identities$address = identities[address]) === null || _identities$address === void 0 ? void 0 : _identities$address.customNetworks) !== null && _identities$address$c !== void 0 ? _identities$address$c : [];
|
|
375
|
+
const custom = Object.values(customNetworks).reduce((chains, network) => {
|
|
376
|
+
const networkItem = {
|
|
377
|
+
blockExplorerUrl: network.block_explorer_url,
|
|
378
|
+
chainId: network.chain_id,
|
|
379
|
+
displayName: network.network_name,
|
|
380
|
+
logo: "eth.svg",
|
|
381
|
+
rpcTarget: network.rpc_url,
|
|
382
|
+
ticker: network.symbol,
|
|
383
|
+
tickerName: network.symbol.toUpperCase(),
|
|
384
|
+
isCustom: true,
|
|
385
|
+
id: network.id
|
|
386
|
+
};
|
|
387
|
+
if (Object.keys(constants.SUPPORTED_NETWORKS).includes(networkItem.chainId)) return chains;
|
|
388
|
+
chains.push(networkItem);
|
|
389
|
+
return chains;
|
|
390
|
+
}, []);
|
|
391
|
+
const supported = Object.values(constants.SUPPORTED_NETWORKS).reduce((chains, network) => {
|
|
392
|
+
chains.push(network);
|
|
393
|
+
return chains;
|
|
394
|
+
}, []);
|
|
395
|
+
return [...supported, ...custom];
|
|
396
|
+
}
|
|
397
|
+
getBlockExplorerUrl() {
|
|
398
|
+
const supportedNetworks = this.getChainOptions();
|
|
399
|
+
const network = supportedNetworks.find(x => x.chainId === this.getProviderConfig().chainId);
|
|
400
|
+
if (!network) return "";
|
|
401
|
+
return `${network.blockExplorerUrl}`;
|
|
402
|
+
}
|
|
403
|
+
async calculatePastTx(txs, address) {
|
|
404
|
+
const pastTx = [];
|
|
405
|
+
const pendingTx = [];
|
|
406
|
+
const lowerCaseSelectedAddress = address.toLowerCase();
|
|
407
|
+
const supportedNetworks = this.getChainOptions(address);
|
|
408
|
+
const supportedNetwork = supportedNetworks.find(x => x.chainId === this.getProviderConfig().chainId);
|
|
409
|
+
for (const x of txs) {
|
|
410
|
+
var _x$to;
|
|
411
|
+
if ((supportedNetwork === null || supportedNetwork === void 0 ? void 0 : supportedNetwork.chainId) === x.chain_id && x.to && x.from && (lowerCaseSelectedAddress === x.from.toLowerCase() || lowerCaseSelectedAddress === ((_x$to = x.to) === null || _x$to === void 0 ? void 0 : _x$to.toLowerCase()))) {
|
|
412
|
+
if (x.status !== "confirmed") {
|
|
413
|
+
pendingTx.push(x);
|
|
414
|
+
} else {
|
|
415
|
+
const finalObject = helpers.formatPastTx({
|
|
416
|
+
transaction: x,
|
|
417
|
+
lowerCaseSelectedAddress,
|
|
418
|
+
blockExplorerUrl: this.getBlockExplorerUrl()
|
|
419
|
+
});
|
|
420
|
+
pastTx.push(finalObject);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const pendingTxPromises = pendingTx.map(x => helpers.getEthTxStatus(x.transaction_hash, this.provider).catch(error => log.error(error)));
|
|
425
|
+
const resolvedTxStatuses = await Promise.all(pendingTxPromises);
|
|
426
|
+
for (const [index, element] of pendingTx.entries()) {
|
|
427
|
+
const finalObject = helpers.formatPastTx({
|
|
428
|
+
transaction: element,
|
|
429
|
+
lowerCaseSelectedAddress,
|
|
430
|
+
blockExplorerUrl: this.getBlockExplorerUrl()
|
|
431
|
+
});
|
|
432
|
+
finalObject.status = resolvedTxStatuses[index] || baseControllers.TransactionStatus.submitted;
|
|
433
|
+
pastTx.push(finalObject);
|
|
434
|
+
if (lowerCaseSelectedAddress === element.from.toLowerCase() && finalObject.status && finalObject.status !== element.status) this.patchPastTx({
|
|
435
|
+
id: element.id,
|
|
436
|
+
status: finalObject.status
|
|
437
|
+
}, address);
|
|
438
|
+
}
|
|
439
|
+
const finalTx = this.cancelTxCalculate(pastTx);
|
|
440
|
+
this.updateState({
|
|
441
|
+
formattedPastTransactions: [...finalTx]
|
|
442
|
+
}, address);
|
|
443
|
+
}
|
|
444
|
+
cancelTxCalculate(pastTx) {
|
|
445
|
+
const nonceMap = {};
|
|
446
|
+
for (const x of pastTx) {
|
|
447
|
+
if (!nonceMap[x.nonce]) nonceMap[x.nonce] = [x];else {
|
|
448
|
+
nonceMap[x.nonce].push(x);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
for (const [, value] of Object.entries(nonceMap)) {
|
|
452
|
+
// has duplicate
|
|
453
|
+
if (value.length > 1) {
|
|
454
|
+
// get latest and mark it as is_cancel
|
|
455
|
+
const latestTxs = value.sort((a, b) => {
|
|
456
|
+
const aDate = new Date(a.date).getTime();
|
|
457
|
+
const bDate = new Date(b.date).getTime();
|
|
458
|
+
return bDate - aDate;
|
|
459
|
+
});
|
|
460
|
+
const latestCancelTx = latestTxs[0];
|
|
461
|
+
latestCancelTx.is_cancel = true;
|
|
462
|
+
latestTxs.slice(1).forEach(x => {
|
|
463
|
+
x.hasCancel = true;
|
|
464
|
+
x.status = latestCancelTx.status === "confirmed" ? baseControllers.TransactionStatus.cancelled : baseControllers.TransactionStatus.cancelling;
|
|
465
|
+
x.cancelDateInitiated = `${helpers.formatTime(new Date(latestCancelTx.date).getTime())} - ${helpers.formatDate(latestCancelTx.date)}`;
|
|
466
|
+
x.etherscanLink = latestCancelTx.etherscanLink;
|
|
467
|
+
x.cancelGas = latestCancelTx.gas;
|
|
468
|
+
x.cancelGasPrice = latestCancelTx.gasPrice;
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return pastTx;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
exports.PreferencesController = PreferencesController;
|