@runesx/api-client 0.1.0 → 0.3.0
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/package.json +1 -1
- package/src/index.mjs +5 -2
- package/src/socket.mjs +18 -2
- package/src/store/chainStore.mjs +92 -0
- package/src/utils/swapUtils.mjs +34 -58
- package/src/waitForStores.mjs +39 -2
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { createApi } from './api.mjs';
|
|
|
4
4
|
import { createConfig } from './config.mjs';
|
|
5
5
|
import { getPools, getPool } from './store/poolStore.mjs';
|
|
6
6
|
import { getCoins, getCoinByTicker } from './store/coinStore.mjs';
|
|
7
|
+
import { getChains, getChainByName } from './store/chainStore.mjs';
|
|
7
8
|
import { getWallets as getWalletsStore, getWalletByTicker } from './store/walletStore.mjs';
|
|
8
9
|
import { getUserShares, getUserShareByPoolId } from './store/userSharesStore.mjs';
|
|
9
10
|
import { waitForStores } from './waitForStores.mjs';
|
|
@@ -22,9 +23,9 @@ export function createRunesXClient(options = {}) {
|
|
|
22
23
|
throw new Error('API_KEY is required');
|
|
23
24
|
}
|
|
24
25
|
socket = setupSocket(config).socket;
|
|
25
|
-
const { pools, coins, wallets, userShares } = await waitForStores(socket);
|
|
26
|
+
const { pools, coins, chains, wallets, userShares } = await waitForStores(socket);
|
|
26
27
|
initialized = true;
|
|
27
|
-
return { pools, coins, wallets, userShares };
|
|
28
|
+
return { pools, coins, chains, wallets, userShares };
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
function ensureInitialized() {
|
|
@@ -43,6 +44,8 @@ export function createRunesXClient(options = {}) {
|
|
|
43
44
|
getPool,
|
|
44
45
|
getCoins,
|
|
45
46
|
getCoinByTicker,
|
|
47
|
+
getChains,
|
|
48
|
+
getChainByName,
|
|
46
49
|
getWallets: getWalletsStore,
|
|
47
50
|
getWalletByTicker,
|
|
48
51
|
getUserShares,
|
package/src/socket.mjs
CHANGED
|
@@ -3,12 +3,14 @@ import { io } from 'socket.io-client';
|
|
|
3
3
|
|
|
4
4
|
import { setInitialPools, updatePool, resetPools } from './store/poolStore.mjs';
|
|
5
5
|
import { setInitialCoins, updateCoin, resetCoins } from './store/coinStore.mjs';
|
|
6
|
+
import { setInitialChains, updateChain, resetChains } from './store/chainStore.mjs';
|
|
6
7
|
import { setInitialWallets, updateWallet, resetWallets } from './store/walletStore.mjs';
|
|
7
8
|
import { setInitialUserShares, updateUserShare, resetUserShares } from './store/userSharesStore.mjs';
|
|
8
9
|
|
|
9
10
|
export function setupSocket(config) {
|
|
10
11
|
const socket = io(config.socketUrl, {
|
|
11
12
|
auth: { authorization: `Bearer ${config.apiKey}` },
|
|
13
|
+
extraHeaders: { authorization: `Bearer ${config.apiKey}` },
|
|
12
14
|
transports: ['websocket'],
|
|
13
15
|
reconnection: true,
|
|
14
16
|
reconnectionAttempts: Infinity,
|
|
@@ -30,6 +32,7 @@ export function setupSocket(config) {
|
|
|
30
32
|
if (errorCount.count >= 3) {
|
|
31
33
|
resetPools();
|
|
32
34
|
resetCoins();
|
|
35
|
+
resetChains();
|
|
33
36
|
resetWallets();
|
|
34
37
|
resetUserShares();
|
|
35
38
|
}
|
|
@@ -39,6 +42,7 @@ export function setupSocket(config) {
|
|
|
39
42
|
console.log('Disconnected from Socket.IO server:', reason);
|
|
40
43
|
resetPools();
|
|
41
44
|
resetCoins();
|
|
45
|
+
resetChains();
|
|
42
46
|
resetWallets();
|
|
43
47
|
resetUserShares();
|
|
44
48
|
});
|
|
@@ -52,6 +56,7 @@ export function setupSocket(config) {
|
|
|
52
56
|
socket.emit('join_private');
|
|
53
57
|
resetPools();
|
|
54
58
|
resetCoins();
|
|
59
|
+
resetChains();
|
|
55
60
|
resetWallets();
|
|
56
61
|
resetUserShares();
|
|
57
62
|
});
|
|
@@ -62,6 +67,7 @@ export function setupSocket(config) {
|
|
|
62
67
|
if (errorCount.count >= 3) {
|
|
63
68
|
resetPools();
|
|
64
69
|
resetCoins();
|
|
70
|
+
resetChains();
|
|
65
71
|
resetWallets();
|
|
66
72
|
resetUserShares();
|
|
67
73
|
}
|
|
@@ -89,6 +95,15 @@ export function setupSocket(config) {
|
|
|
89
95
|
}
|
|
90
96
|
});
|
|
91
97
|
|
|
98
|
+
socket.on('chains_updated', ({ chains, isInitial }) => {
|
|
99
|
+
// console.log('Received chains_updated:', { chains, isInitial });
|
|
100
|
+
if (isInitial) {
|
|
101
|
+
setInitialChains(chains);
|
|
102
|
+
} else {
|
|
103
|
+
chains.forEach(chain => updateChain(chain));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
92
107
|
socket.on('wallets_updated', ({ wallets, isInitial }) => {
|
|
93
108
|
// console.log('Received wallets_updated:', { wallets, isInitial });
|
|
94
109
|
if (isInitial) {
|
|
@@ -130,8 +145,8 @@ export function setupSocket(config) {
|
|
|
130
145
|
// console.log('Status update:', data);
|
|
131
146
|
});
|
|
132
147
|
|
|
133
|
-
socket.on('deposit_address_generated', ({ requestId,
|
|
134
|
-
// console.log('Deposit address generated:', { requestId,
|
|
148
|
+
socket.on('deposit_address_generated', ({ requestId, chainName, address, memo }) => {
|
|
149
|
+
// console.log('Deposit address generated:', { requestId, chainName, address, memo });
|
|
135
150
|
});
|
|
136
151
|
|
|
137
152
|
socket.on('deposit_processed', (data) => {
|
|
@@ -227,6 +242,7 @@ export function setupSocket(config) {
|
|
|
227
242
|
clearInterval(heartbeatInterval);
|
|
228
243
|
resetPools();
|
|
229
244
|
resetCoins();
|
|
245
|
+
resetChains();
|
|
230
246
|
resetWallets();
|
|
231
247
|
resetUserShares();
|
|
232
248
|
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const chainStore = {
|
|
2
|
+
chains: new Map(), // Store chain data by name (lowercase)
|
|
3
|
+
isInitialReceived: false,
|
|
4
|
+
pendingUpdates: [],
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const setInitialChains = (chains) => {
|
|
8
|
+
chainStore.chains.clear();
|
|
9
|
+
chains.forEach(chain => {
|
|
10
|
+
chainStore.chains.set(chain.name.toLowerCase(), {
|
|
11
|
+
id: chain.id,
|
|
12
|
+
name: chain.name,
|
|
13
|
+
blockchainId: chain.blockchainId,
|
|
14
|
+
requiredConfirmations: chain.requiredConfirmations,
|
|
15
|
+
hasMemo: chain.hasMemo,
|
|
16
|
+
status: chain.status,
|
|
17
|
+
chainType: chain.chainType,
|
|
18
|
+
nativeTicker: chain.nativeTicker,
|
|
19
|
+
explorerTxUrl: chain.explorerTxUrl,
|
|
20
|
+
updatedAt: chain.updatedAt,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
chainStore.isInitialReceived = true;
|
|
24
|
+
|
|
25
|
+
if (chainStore.pendingUpdates.length > 0) {
|
|
26
|
+
chainStore.pendingUpdates.forEach(({ chains }) => {
|
|
27
|
+
chains.forEach(chain => updateChain(chain));
|
|
28
|
+
});
|
|
29
|
+
chainStore.pendingUpdates = [];
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const updateChain = (chain) => {
|
|
34
|
+
if (!chainStore.isInitialReceived) {
|
|
35
|
+
chainStore.pendingUpdates.push({ chains: [chain] });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const key = chain.name.toLowerCase();
|
|
40
|
+
const existingChain = chainStore.chains.get(key);
|
|
41
|
+
const incomingUpdatedAt = new Date(chain.updatedAt).getTime();
|
|
42
|
+
|
|
43
|
+
if (existingChain) {
|
|
44
|
+
const existingUpdatedAt = new Date(existingChain.updatedAt).getTime();
|
|
45
|
+
if (incomingUpdatedAt <= existingUpdatedAt) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
chainStore.chains.set(key, {
|
|
50
|
+
...existingChain,
|
|
51
|
+
blockchainId: chain.blockchainId,
|
|
52
|
+
requiredConfirmations: chain.requiredConfirmations,
|
|
53
|
+
hasMemo: chain.hasMemo,
|
|
54
|
+
status: chain.status,
|
|
55
|
+
chainType: chain.chainType,
|
|
56
|
+
nativeTicker: chain.nativeTicker,
|
|
57
|
+
explorerTxUrl: chain.explorerTxUrl,
|
|
58
|
+
updatedAt: chain.updatedAt,
|
|
59
|
+
});
|
|
60
|
+
} else if (chain.name && chain.status) {
|
|
61
|
+
chainStore.chains.set(key, {
|
|
62
|
+
id: chain.id,
|
|
63
|
+
name: chain.name,
|
|
64
|
+
blockchainId: chain.blockchainId,
|
|
65
|
+
requiredConfirmations: chain.requiredConfirmations,
|
|
66
|
+
hasMemo: chain.hasMemo,
|
|
67
|
+
status: chain.status,
|
|
68
|
+
chainType: chain.chainType,
|
|
69
|
+
nativeTicker: chain.nativeTicker,
|
|
70
|
+
explorerTxUrl: chain.explorerTxUrl,
|
|
71
|
+
updatedAt: chain.updatedAt,
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
console.warn(`Ignoring update for unknown chain ${chain.name} with incomplete data`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const getChains = () => {
|
|
79
|
+
return Array.from(chainStore.chains.values());
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const getChainByName = (name) => {
|
|
83
|
+
return chainStore.chains.get(name.toLowerCase());
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const resetChains = () => {
|
|
87
|
+
chainStore.chains.clear();
|
|
88
|
+
chainStore.isInitialReceived = false;
|
|
89
|
+
chainStore.pendingUpdates = [];
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export { chainStore, setInitialChains, updateChain, getChains, getChainByName, resetChains };
|
package/src/utils/swapUtils.mjs
CHANGED
|
@@ -10,9 +10,11 @@ export const validatePositiveNumber = (value, fieldName) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// Get RUNES price in USD using RUNES/USDC pool
|
|
13
|
-
export const getRunesPriceUSD =
|
|
13
|
+
export const getRunesPriceUSD = (pools) => {
|
|
14
14
|
try {
|
|
15
|
-
const runesUsdcPool = pools.find((p) =>
|
|
15
|
+
const runesUsdcPool = pools.find((p) =>
|
|
16
|
+
(p.coinA.ticker === 'RUNES' && p.coinB.ticker === 'USDC') ||
|
|
17
|
+
(p.coinA.ticker === 'USDC' && p.coinB.ticker === 'RUNES'));
|
|
16
18
|
|
|
17
19
|
if (!runesUsdcPool) {
|
|
18
20
|
console.warn('RUNES/USDC pool not found, using fallback price of $0.01');
|
|
@@ -63,8 +65,8 @@ export const getTokenPriceInRunes = (token, pools) => {
|
|
|
63
65
|
const reserveB = new BigNumber(pool.reserveB).shiftedBy(-pool.coinB.dp);
|
|
64
66
|
|
|
65
67
|
const priceInRunes = isRunesA
|
|
66
|
-
? reserveA.div(reserveB).toString() // RUNES
|
|
67
|
-
: reserveB.div(reserveA).toString(); //
|
|
68
|
+
? reserveA.div(reserveB).toString() // RUNES is coinA: price = RUNES_reserve / TOKEN_reserve
|
|
69
|
+
: reserveB.div(reserveA).toString(); // RUNES is coinB: price = RUNES_reserve / TOKEN_reserve
|
|
68
70
|
|
|
69
71
|
return priceInRunes;
|
|
70
72
|
};
|
|
@@ -74,6 +76,18 @@ const findAllPathsDFS = (startCoin, endCoin, pools, maxHops = 6) => {
|
|
|
74
76
|
const paths = [];
|
|
75
77
|
const visited = new Set();
|
|
76
78
|
|
|
79
|
+
// Build adjacency map for O(1) lookups (matches BFS approach)
|
|
80
|
+
const poolMap = new Map();
|
|
81
|
+
pools.forEach((pool) => {
|
|
82
|
+
if (!pool.runesCompliant || new BigNumber(pool.reserveA).isZero() || new BigNumber(pool.reserveB).isZero()) {return;}
|
|
83
|
+
const keyA = pool.coinA.ticker;
|
|
84
|
+
const keyB = pool.coinB.ticker;
|
|
85
|
+
if (!poolMap.has(keyA)) {poolMap.set(keyA, []);}
|
|
86
|
+
if (!poolMap.has(keyB)) {poolMap.set(keyB, []);}
|
|
87
|
+
poolMap.get(keyA).push({ pool, nextCoin: pool.coinB });
|
|
88
|
+
poolMap.get(keyB).push({ pool, nextCoin: pool.coinA });
|
|
89
|
+
});
|
|
90
|
+
|
|
77
91
|
function dfs(currentCoin, currentPath, hops) {
|
|
78
92
|
if (hops > maxHops) {return;}
|
|
79
93
|
if (currentCoin.ticker === endCoin.ticker) {
|
|
@@ -81,13 +95,8 @@ const findAllPathsDFS = (startCoin, endCoin, pools, maxHops = 6) => {
|
|
|
81
95
|
return;
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const isCoinA = pool.coinA.ticker === currentCoin.ticker;
|
|
87
|
-
const isCoinB = pool.coinB.ticker === currentCoin.ticker;
|
|
88
|
-
if (!isCoinA && !isCoinB) {continue;}
|
|
89
|
-
|
|
90
|
-
const nextCoin = isCoinA ? pool.coinB : pool.coinA;
|
|
98
|
+
const connectedPools = poolMap.get(currentCoin.ticker) || [];
|
|
99
|
+
for (const { pool, nextCoin } of connectedPools) {
|
|
91
100
|
const poolKey = pool.id;
|
|
92
101
|
|
|
93
102
|
if (visited.has(poolKey)) {continue;}
|
|
@@ -175,7 +184,11 @@ export const simulateSwap = (pool, inputCoin, amountInBN, isCoinAInput) => {
|
|
|
175
184
|
const totalFeeRate = lpFeeRate.plus(treasuryFeeRate);
|
|
176
185
|
|
|
177
186
|
// Calculate total fee and split proportionally
|
|
178
|
-
|
|
187
|
+
let totalFeeAmount = amountInBN.times(totalFeeRate).integerValue(BigNumber.ROUND_DOWN);
|
|
188
|
+
// Minimum fee floor: match backend - ensure at least 1 smallest unit when fees are configured
|
|
189
|
+
if (totalFeeRate.gt(0) && totalFeeAmount.isZero()) {
|
|
190
|
+
totalFeeAmount = new BigNumber(1);
|
|
191
|
+
}
|
|
179
192
|
let treasuryFeeAmount = new BigNumber(0);
|
|
180
193
|
let lpFeeAmount = new BigNumber(0);
|
|
181
194
|
if (!totalFeeRate.eq(0)) {
|
|
@@ -197,7 +210,7 @@ export const simulateSwap = (pool, inputCoin, amountInBN, isCoinAInput) => {
|
|
|
197
210
|
}
|
|
198
211
|
amountOutBN = amountOutBN.integerValue(BigNumber.ROUND_DOWN);
|
|
199
212
|
|
|
200
|
-
if (amountOutBN.isNaN() || amountOutBN.lt(1)) {return null;}
|
|
213
|
+
if (amountOutBN.isNaN() || !amountOutBN.isFinite() || amountOutBN.lt(1)) {return null;}
|
|
201
214
|
|
|
202
215
|
// Simulate reserve updates (mimicking backend)
|
|
203
216
|
const updatedPool = { ...pool };
|
|
@@ -362,7 +375,7 @@ export const estimateSwap = async (
|
|
|
362
375
|
const runesPriceUSD = await getRunesPriceUSD(pools);
|
|
363
376
|
const priceAInRunes = getTokenPriceInRunes(inputCoinData, pools);
|
|
364
377
|
const priceBInRunes = getTokenPriceInRunes(outputCoinData, pools);
|
|
365
|
-
if (!priceAInRunes || !priceBInRunes) {
|
|
378
|
+
if (!priceAInRunes || priceAInRunes === '0' || !priceBInRunes || priceBInRunes === '0') {
|
|
366
379
|
throw new Error('Pool not initialized or invalid token');
|
|
367
380
|
}
|
|
368
381
|
|
|
@@ -375,48 +388,11 @@ export const estimateSwap = async (
|
|
|
375
388
|
.times(priceBUSD)
|
|
376
389
|
.toString();
|
|
377
390
|
|
|
378
|
-
//
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
let updatedPools = [...pools]; // Clone pools for after-swap price simulation
|
|
384
|
-
|
|
385
|
-
for (const step of bestPath) {
|
|
386
|
-
const poolIndex = updatedPools.findIndex(
|
|
387
|
-
(p) =>
|
|
388
|
-
(p.coinA.ticker === step.from && p.coinB.ticker === step.to) ||
|
|
389
|
-
(p.coinB.ticker === step.from && p.coinA.ticker === step.to)
|
|
390
|
-
);
|
|
391
|
-
const pool = updatedPools[poolIndex];
|
|
392
|
-
const isCoinAInput = pool.coinA.ticker === step.from;
|
|
393
|
-
const nextCoin = coins.find((c) => c.ticker === step.to);
|
|
394
|
-
const swapResult = simulateSwap(pool, currentCoin, currentAmount, isCoinAInput);
|
|
395
|
-
|
|
396
|
-
const reserveA = new BigNumber(pool.reserveA);
|
|
397
|
-
const reserveB = new BigNumber(pool.reserveB);
|
|
398
|
-
if (isCoinAInput) {
|
|
399
|
-
const newRunesReserve = reserveA.plus(currentAmount);
|
|
400
|
-
const newTokenReserve = reserveB.minus(swapResult.amountOut);
|
|
401
|
-
if (step.from === 'RUNES') {
|
|
402
|
-
priceAInRunesAfter = newRunesReserve.div(newTokenReserve);
|
|
403
|
-
} else if (step.to === 'RUNES') {
|
|
404
|
-
priceBInRunesAfter = newRunesReserve.div(newTokenReserve);
|
|
405
|
-
}
|
|
406
|
-
} else {
|
|
407
|
-
const newTokenReserve = reserveB.plus(currentAmount);
|
|
408
|
-
const newRunesReserve = reserveA.minus(swapResult.amountOut);
|
|
409
|
-
if (step.from === 'RUNES') {
|
|
410
|
-
priceAInRunesAfter = newRunesReserve.div(newTokenReserve);
|
|
411
|
-
} else if (step.to === 'RUNES') {
|
|
412
|
-
priceBInRunesAfter = newRunesReserve.div(newTokenReserve);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
currentAmount = swapResult.amountOut;
|
|
417
|
-
currentCoin = nextCoin;
|
|
418
|
-
updatedPools[poolIndex] = swapResult.updatedPool; // Update pool for next iteration
|
|
419
|
-
}
|
|
391
|
+
// After-swap prices: use the already-simulated updated pools from bestResult
|
|
392
|
+
// (estimatePath already tracks post-swap reserve states, no need to re-simulate)
|
|
393
|
+
const runesPriceUSDAfter = getRunesPriceUSD(bestResult.updatedPools);
|
|
394
|
+
const priceAInRunesAfter = new BigNumber(getTokenPriceInRunes(inputCoinData, bestResult.updatedPools));
|
|
395
|
+
const priceBInRunesAfter = new BigNumber(getTokenPriceInRunes(outputCoinData, bestResult.updatedPools));
|
|
420
396
|
|
|
421
397
|
return {
|
|
422
398
|
input: {
|
|
@@ -438,8 +414,8 @@ export const estimateSwap = async (
|
|
|
438
414
|
intermediateAmounts: bestResult.intermediateAmounts,
|
|
439
415
|
},
|
|
440
416
|
afterSwapPrices: {
|
|
441
|
-
[inputCoin.ticker]: priceAInRunesAfter.times(
|
|
442
|
-
[outputCoin.ticker]: priceBInRunesAfter.times(
|
|
417
|
+
[inputCoin.ticker]: priceAInRunesAfter.times(runesPriceUSDAfter).toString(),
|
|
418
|
+
[outputCoin.ticker]: priceBInRunesAfter.times(runesPriceUSDAfter).toString(),
|
|
443
419
|
},
|
|
444
420
|
path: bestPath,
|
|
445
421
|
algorithm, // Include algorithm in the response
|
package/src/waitForStores.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { poolStore, getPools } from './store/poolStore.mjs';
|
|
2
2
|
import { coinStore, getCoins } from './store/coinStore.mjs';
|
|
3
|
+
import { chainStore, getChains } from './store/chainStore.mjs';
|
|
3
4
|
import { walletStore, getWallets } from './store/walletStore.mjs';
|
|
4
5
|
import { userSharesStore, getUserShares } from './store/userSharesStore.mjs';
|
|
5
6
|
|
|
@@ -74,6 +75,41 @@ export function waitForStores(socket) {
|
|
|
74
75
|
});
|
|
75
76
|
};
|
|
76
77
|
|
|
78
|
+
// Function to wait for chainStore to be populated
|
|
79
|
+
const waitForChains = () => {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
if (chainStore.isInitialReceived) {
|
|
82
|
+
const chains = getChains();
|
|
83
|
+
resolve(chains);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const timeout = setTimeout(() => {
|
|
88
|
+
reject(new Error('Timeout waiting for initial chain data'));
|
|
89
|
+
}, 30000); // 30-second timeout
|
|
90
|
+
|
|
91
|
+
socket.on('chains_updated', ({ isInitial }) => {
|
|
92
|
+
if (isInitial) {
|
|
93
|
+
const chains = getChains();
|
|
94
|
+
clearTimeout(timeout);
|
|
95
|
+
resolve(chains);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
socket.on('connect_error', (err) => {
|
|
100
|
+
console.error('Socket connect error:', err.message);
|
|
101
|
+
clearTimeout(timeout);
|
|
102
|
+
reject(new Error('Socket connection failed'));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
socket.on('disconnect', (reason) => {
|
|
106
|
+
console.error('Socket disconnected:', reason);
|
|
107
|
+
clearTimeout(timeout);
|
|
108
|
+
reject(new Error('Socket disconnected before receiving initial chain data'));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
77
113
|
// Function to wait for walletStore to be populated
|
|
78
114
|
const waitForWallets = () => {
|
|
79
115
|
return new Promise((resolve, reject) => {
|
|
@@ -145,10 +181,11 @@ export function waitForStores(socket) {
|
|
|
145
181
|
};
|
|
146
182
|
|
|
147
183
|
// Return a promise that resolves when all stores are populated
|
|
148
|
-
return Promise.all([waitForPools(), waitForCoins(), waitForWallets(), waitForUserShares()])
|
|
149
|
-
.then(([pools, coins, wallets, userShares]) => ({
|
|
184
|
+
return Promise.all([waitForPools(), waitForCoins(), waitForChains(), waitForWallets(), waitForUserShares()])
|
|
185
|
+
.then(([pools, coins, chains, wallets, userShares]) => ({
|
|
150
186
|
pools,
|
|
151
187
|
coins,
|
|
188
|
+
chains,
|
|
152
189
|
wallets,
|
|
153
190
|
userShares,
|
|
154
191
|
}));
|