capitalisk-dex 17.3.1 → 18.0.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.
@@ -5,7 +5,7 @@ module.exports = {
5
5
  multisigExpiry: 86400000,
6
6
  multisigExpiryCheckInterval: 60000,
7
7
  multisigFlushInterval: 15000,
8
- multisigReadyDelay: 5000,
8
+ multisigReadyDelay: 15000,
9
9
  multisigMaxBatchSize: 25,
10
10
  multisigRetryInterval: 60000,
11
11
  recentTransfersExpiry: 1800000,
package/index.js CHANGED
@@ -95,6 +95,7 @@ module.exports = class CapitaliskDEXModule {
95
95
  this.isQuoteChainForked = false;
96
96
  this.lastSnapshot = null;
97
97
  this.finalizedSnapshot = null;
98
+ this.scheduledTransferInfos = [];
98
99
  this.pendingTransfers = new Map();
99
100
  this.chainSymbols.forEach((chainSymbol) => {
100
101
  this.multisigWalletInfo[chainSymbol] = {
@@ -1442,23 +1443,17 @@ module.exports = class CapitaliskDEXModule {
1442
1443
  ) {
1443
1444
  let currentOrderBook = this.tradeEngine.getSnapshot();
1444
1445
  this.tradeEngine.clear();
1445
- try {
1446
- await this.refundOrderBook(
1447
- {
1448
- orderBook: currentOrderBook,
1449
- chainHeights: {...latestChainHeights}
1450
- },
1451
- latestBlockTimestamp,
1452
- {
1453
- [this.baseChainSymbol]: this.options.chains[this.baseChainSymbol].dexMovedToAddress,
1454
- [this.quoteChainSymbol]: this.options.chains[this.quoteChainSymbol].dexMovedToAddress
1455
- }
1456
- );
1457
- } catch (error) {
1458
- this.logger.error(
1459
- `Failed to refund the order book according to config because of error: ${error.message}`
1460
- );
1461
- }
1446
+ this.scheduleRefundOrderBook(
1447
+ {
1448
+ orderBook: currentOrderBook,
1449
+ chainHeights: {...latestChainHeights}
1450
+ },
1451
+ latestBlockTimestamp,
1452
+ {
1453
+ [this.baseChainSymbol]: this.options.chains[this.baseChainSymbol].dexMovedToAddress,
1454
+ [this.quoteChainSymbol]: this.options.chains[this.quoteChainSymbol].dexMovedToAddress
1455
+ }
1456
+ );
1462
1457
  }
1463
1458
  }
1464
1459
 
@@ -1732,103 +1727,93 @@ module.exports = class CapitaliskDEXModule {
1732
1727
  let disabledOrders = orders.filter(orderTxn => orderTxn.type === 'disabled');
1733
1728
 
1734
1729
  if (!this.passiveMode) {
1735
- movedOrders.forEach(async (orderTxn) => {
1730
+ movedOrders.forEach((orderTxn) => {
1736
1731
  let protocolMessage = this._computeProtocolMessage(orderTxn.sourceChain, 'r5', [orderTxn.id, orderTxn.movedToAddress], 'DEX has moved');
1737
- try {
1738
- await this.execRefundTransaction(orderTxn, latestBlockTimestamp, protocolMessage, {type: 'r5', originOrderId: orderTxn.id});
1739
- } catch (error) {
1740
- this.logger.error(
1741
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for moved DEX order ID ${
1742
- orderTxn.id
1743
- } to ${
1744
- orderTxn.sourceWalletAddress
1745
- } on chain ${
1746
- orderTxn.sourceChain
1747
- } because of error: ${
1748
- error.message
1749
- }`
1750
- );
1751
- }
1732
+ this.scheduleRefundTransaction(
1733
+ orderTxn,
1734
+ latestBlockTimestamp,
1735
+ protocolMessage,
1736
+ {type: 'r5', originOrderId: orderTxn.id},
1737
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for moved DEX order ID ${
1738
+ orderTxn.id
1739
+ } to ${
1740
+ orderTxn.sourceWalletAddress
1741
+ } on chain ${
1742
+ orderTxn.sourceChain
1743
+ }`
1744
+ );
1752
1745
  });
1753
1746
 
1754
- disabledOrders.forEach(async (orderTxn) => {
1747
+ disabledOrders.forEach((orderTxn) => {
1755
1748
  let protocolMessage = this._computeProtocolMessage(orderTxn.sourceChain, 'r6', [orderTxn.id], 'DEX has been disabled');
1756
- try {
1757
- await this.execRefundTransaction(orderTxn, latestBlockTimestamp, protocolMessage, {type: 'r6', originOrderId: orderTxn.id});
1758
- } catch (error) {
1759
- this.logger.error(
1760
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for disabled DEX order ID ${
1761
- orderTxn.id
1762
- } to ${
1763
- orderTxn.sourceWalletAddress
1764
- } on chain ${
1765
- orderTxn.sourceChain
1766
- } because of error: ${
1767
- error.message
1768
- }`
1769
- );
1770
- }
1749
+ this.scheduleRefundTransaction(
1750
+ orderTxn,
1751
+ latestBlockTimestamp,
1752
+ protocolMessage,
1753
+ {type: 'r6', originOrderId: orderTxn.id},
1754
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for disabled DEX order ID ${
1755
+ orderTxn.id
1756
+ } to ${
1757
+ orderTxn.sourceWalletAddress
1758
+ } on chain ${
1759
+ orderTxn.sourceChain
1760
+ }`
1761
+ );
1771
1762
  });
1772
1763
 
1773
- invalidOrders.forEach(async (orderTxn) => {
1764
+ invalidOrders.forEach((orderTxn) => {
1774
1765
  let reasonMessage = 'Invalid order';
1775
1766
  if (orderTxn.reason) {
1776
1767
  reasonMessage += ` - ${orderTxn.reason}`;
1777
1768
  }
1778
1769
  let protocolMessage = this._computeProtocolMessage(orderTxn.sourceChain, 'r1', [orderTxn.id], reasonMessage);
1779
- try {
1780
- await this.execRefundTransaction(orderTxn, latestBlockTimestamp, protocolMessage, {type: 'r1', originOrderId: orderTxn.id});
1781
- } catch (error) {
1782
- this.logger.error(
1783
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for invalid order ID ${
1784
- orderTxn.id
1785
- } to ${
1786
- orderTxn.sourceWalletAddress
1787
- } on chain ${
1788
- orderTxn.sourceChain
1789
- } because of error: ${
1790
- error.message
1791
- }`
1792
- );
1793
- }
1770
+ this.scheduleRefundTransaction(
1771
+ orderTxn,
1772
+ latestBlockTimestamp,
1773
+ protocolMessage,
1774
+ {type: 'r1', originOrderId: orderTxn.id},
1775
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for invalid order ID ${
1776
+ orderTxn.id
1777
+ } to ${
1778
+ orderTxn.sourceWalletAddress
1779
+ } on chain ${
1780
+ orderTxn.sourceChain
1781
+ }`
1782
+ );
1794
1783
  });
1795
1784
 
1796
- oversizedOrders.forEach(async (orderTxn) => {
1785
+ oversizedOrders.forEach((orderTxn) => {
1797
1786
  let protocolMessage = this._computeProtocolMessage(orderTxn.sourceChain, 'r1', [orderTxn.id], 'Oversized order');
1798
- try {
1799
- await this.execRefundTransaction(orderTxn, latestBlockTimestamp, protocolMessage, {type: 'r1', originOrderId: orderTxn.id});
1800
- } catch (error) {
1801
- this.logger.error(
1802
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for oversized order ID ${
1803
- orderTxn.id
1804
- } to ${
1805
- orderTxn.sourceWalletAddress
1806
- } on chain ${
1807
- orderTxn.sourceChain
1808
- } because of error: ${
1809
- error.message
1810
- }`
1811
- );
1812
- }
1787
+ this.scheduleRefundTransaction(
1788
+ orderTxn,
1789
+ latestBlockTimestamp,
1790
+ protocolMessage,
1791
+ {type: 'r1', originOrderId: orderTxn.id},
1792
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for oversized order ID ${
1793
+ orderTxn.id
1794
+ } to ${
1795
+ orderTxn.sourceWalletAddress
1796
+ } on chain ${
1797
+ orderTxn.sourceChain
1798
+ }`
1799
+ );
1813
1800
  });
1814
1801
 
1815
- undersizedOrders.forEach(async (orderTxn) => {
1802
+ undersizedOrders.forEach((orderTxn) => {
1816
1803
  let protocolMessage = this._computeProtocolMessage(orderTxn.sourceChain, 'r1', [orderTxn.id], 'Undersized order');
1817
- try {
1818
- await this.execRefundTransaction(orderTxn, latestBlockTimestamp, protocolMessage, {type: 'r1', originOrderId: orderTxn.id});
1819
- } catch (error) {
1820
- this.logger.error(
1821
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for undersized order ID ${
1822
- orderTxn.id
1823
- } to ${
1824
- orderTxn.sourceWalletAddress
1825
- } on chain ${
1826
- orderTxn.sourceChain
1827
- } because of error: ${
1828
- error.message
1829
- }`
1830
- );
1831
- }
1804
+ this.scheduleRefundTransaction(
1805
+ orderTxn,
1806
+ latestBlockTimestamp,
1807
+ protocolMessage,
1808
+ {type: 'r1', originOrderId: orderTxn.id},
1809
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for undersized order ID ${
1810
+ orderTxn.id
1811
+ } to ${
1812
+ orderTxn.sourceWalletAddress
1813
+ } on chain ${
1814
+ orderTxn.sourceChain
1815
+ }`
1816
+ );
1832
1817
  });
1833
1818
  }
1834
1819
 
@@ -1838,7 +1823,7 @@ module.exports = class CapitaliskDEXModule {
1838
1823
  } else {
1839
1824
  expiredOrders = this.tradeEngine.expireAskOrders(chainHeight);
1840
1825
  }
1841
- expiredOrders.forEach(async (expiredOrder) => {
1826
+ expiredOrders.forEach((expiredOrder) => {
1842
1827
  this.logger.info(
1843
1828
  `Chain ${chainSymbol}: Order ${expiredOrder.id} at height ${expiredOrder.height} expired`
1844
1829
  );
@@ -1846,30 +1831,23 @@ module.exports = class CapitaliskDEXModule {
1846
1831
  return;
1847
1832
  }
1848
1833
  let protocolMessage = this._computeProtocolMessage(expiredOrder.sourceChain, 'r2', [expiredOrder.id], 'Expired order');
1849
- try {
1850
- await this.refundOrder(
1851
- expiredOrder,
1852
- latestBlockTimestamp,
1853
- expiredOrder.expiryHeight,
1854
- protocolMessage,
1855
- {type: 'r2', originOrderId: expiredOrder.id}
1856
- );
1857
- } catch (error) {
1858
- this.logger.error(
1859
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for expired order ID ${
1860
- expiredOrder.id
1861
- } to ${
1862
- expiredOrder.sourceWalletAddress
1863
- } on chain ${
1864
- expiredOrder.sourceChain
1865
- } because of error: ${
1866
- error.message
1867
- }`
1868
- );
1869
- }
1834
+ this.scheduleRefundOrder(
1835
+ expiredOrder,
1836
+ latestBlockTimestamp,
1837
+ expiredOrder.expiryHeight,
1838
+ protocolMessage,
1839
+ {type: 'r2', originOrderId: expiredOrder.id},
1840
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for expired order ID ${
1841
+ expiredOrder.id
1842
+ } to ${
1843
+ expiredOrder.sourceWalletAddress
1844
+ } on chain ${
1845
+ expiredOrder.sourceChain
1846
+ }`
1847
+ );
1870
1848
  });
1871
1849
 
1872
- closeOrders.forEach(async (orderTxn) => {
1850
+ closeOrders.forEach((orderTxn) => {
1873
1851
  let targetOrder = this.tradeEngine.getOrder(orderTxn.orderIdToClose);
1874
1852
  if (!targetOrder) {
1875
1853
  this.logger.warn(
@@ -1901,29 +1879,22 @@ module.exports = class CapitaliskDEXModule {
1901
1879
  return;
1902
1880
  }
1903
1881
  let protocolMessage = this._computeProtocolMessage(refundTxn.sourceChain, 'r3', [targetOrder.id, orderTxn.id], 'Closed order');
1904
- try {
1905
- await this.execRefundTransaction(
1906
- refundTxn,
1907
- latestBlockTimestamp,
1908
- protocolMessage,
1909
- {type: 'r3', originOrderId: targetOrder.id, closerOrderId: orderTxn.id}
1910
- );
1911
- } catch (error) {
1912
- this.logger.error(
1913
- `Chain ${chainSymbol}: Failed to post multisig refund transaction for closed order ID ${
1914
- targetOrder.id
1915
- } to ${
1916
- targetOrder.sourceWalletAddress
1917
- } on chain ${
1918
- targetOrder.sourceChain
1919
- } because of error: ${
1920
- error.message
1921
- }`
1922
- );
1923
- }
1882
+ this.scheduleRefundTransaction(
1883
+ refundTxn,
1884
+ latestBlockTimestamp,
1885
+ protocolMessage,
1886
+ {type: 'r3', originOrderId: targetOrder.id, closerOrderId: orderTxn.id},
1887
+ `Chain ${chainSymbol}: Failed to post multisig refund transaction for closed order ID ${
1888
+ targetOrder.id
1889
+ } to ${
1890
+ targetOrder.sourceWalletAddress
1891
+ } on chain ${
1892
+ targetOrder.sourceChain
1893
+ }`
1894
+ );
1924
1895
  });
1925
1896
 
1926
- limitAndMarketOrders.forEach(async (orderTxn) => {
1897
+ limitAndMarketOrders.forEach((orderTxn) => {
1927
1898
  let result;
1928
1899
  try {
1929
1900
  result = this.tradeEngine.addOrder(orderTxn);
@@ -1950,7 +1921,7 @@ module.exports = class CapitaliskDEXModule {
1950
1921
 
1951
1922
  let makerCount = 0;
1952
1923
 
1953
- result.makers.forEach(async (makerOrder) => {
1924
+ result.makers.forEach((makerOrder) => {
1954
1925
  let makerChainOptions = this.options.chains[makerOrder.targetChain];
1955
1926
  let makerAddress = makerOrder.targetWalletAddress;
1956
1927
  let makerAmount = makerOrder.targetChain === this.baseChainSymbol ? makerOrder.lastValueTaken : makerOrder.lastSizeTaken;
@@ -1979,84 +1950,76 @@ module.exports = class CapitaliskDEXModule {
1979
1950
  [makerOrder.sourceChain, makerOrder.id, result.taker.id],
1980
1951
  'Order made'
1981
1952
  );
1982
- try {
1983
- await this.execMultisigTransaction(
1984
- makerOrder.targetChain,
1985
- makerTxn,
1986
- protocolMessage,
1987
- {type: 't2', originOrderId: makerOrder.id, makerOrderId: makerOrder.id, takerOrderId: result.taker.id}
1988
- );
1989
- } catch (error) {
1990
- this.logger.error(
1991
- `Chain ${chainSymbol}: Failed to post multisig transaction of maker ${makerAddress} on chain ${makerOrder.targetChain} because of error: ${error.message}`
1992
- );
1993
- }
1953
+ this.scheduleMultisigTransaction(
1954
+ makerOrder.targetChain,
1955
+ makerTxn,
1956
+ protocolMessage,
1957
+ {type: 't2', originOrderId: makerOrder.id, makerOrderId: makerOrder.id, takerOrderId: result.taker.id},
1958
+ `Chain ${chainSymbol}: Failed to post multisig transaction of maker ${makerAddress} on chain ${makerOrder.targetChain}`
1959
+ );
1994
1960
  });
1995
1961
 
1996
- (async () => {
1997
- if (!makerCount) {
1998
- return;
1999
- }
2000
- if (takerAmount <= 0n) {
2001
- this.logger.warn(
2002
- `Chain ${chainSymbol}: Did not post the taker trade order ${orderTxn.id} because the amount after fees was less than or equal to 0`
1962
+ if (makerCount) {
1963
+ if (takerAmount > 0n) {
1964
+ let takerTxn = {
1965
+ recipientAddress: takerAddress,
1966
+ amount: takerAmount.toString(),
1967
+ fee: takerChainOptions.exchangeFeeBase.toString(),
1968
+ timestamp: latestBlockTimestamp,
1969
+ height: latestChainHeights[takerTargetChain]
1970
+ };
1971
+ let protocolMessage = this._computeProtocolMessage(
1972
+ takerTargetChain,
1973
+ 't1',
1974
+ [result.taker.sourceChain, result.taker.id, makerCount],
1975
+ 'Orders taken'
2003
1976
  );
2004
- return;
2005
- }
2006
- let takerTxn = {
2007
- recipientAddress: takerAddress,
2008
- amount: takerAmount.toString(),
2009
- fee: takerChainOptions.exchangeFeeBase.toString(),
2010
- timestamp: latestBlockTimestamp,
2011
- height: latestChainHeights[takerTargetChain]
2012
- };
2013
- let protocolMessage = this._computeProtocolMessage(
2014
- takerTargetChain,
2015
- 't1',
2016
- [result.taker.sourceChain, result.taker.id, makerCount],
2017
- 'Orders taken'
2018
- );
2019
- try {
2020
- await this.execMultisigTransaction(
1977
+ this.scheduleMultisigTransaction(
2021
1978
  takerTargetChain,
2022
1979
  takerTxn,
2023
1980
  protocolMessage,
2024
- {type: 't1', originOrderId: result.taker.id, takerOrderId: result.taker.id, makerCount}
1981
+ {type: 't1', originOrderId: result.taker.id, takerOrderId: result.taker.id, makerCount},
1982
+ `Chain ${chainSymbol}: Failed to post multisig transaction of taker ${takerAddress} on chain ${takerTargetChain}`
2025
1983
  );
2026
- } catch (error) {
2027
- this.logger.error(
2028
- `Chain ${chainSymbol}: Failed to post multisig transaction of taker ${takerAddress} on chain ${takerTargetChain} because of error: ${error.message}`
1984
+ } else {
1985
+ this.logger.warn(
1986
+ `Chain ${chainSymbol}: Did not post the taker trade order ${orderTxn.id} because the amount after fees was less than or equal to 0`
2029
1987
  );
2030
1988
  }
2031
- })();
2032
-
2033
- (async () => {
2034
- if (orderTxn.type === 'market') {
2035
- let refundTxn = {
2036
- sourceChain: result.taker.sourceChain,
2037
- sourceWalletAddress: result.taker.sourceWalletAddress,
2038
- height: orderTxn.height
2039
- };
2040
- if (result.taker.sourceChain === this.baseChainSymbol) {
2041
- refundTxn.sourceChainAmount = result.taker.valueRemaining;
2042
- } else {
2043
- refundTxn.sourceChainAmount = result.taker.sizeRemaining;
2044
- }
2045
- if (refundTxn.sourceChainAmount <= 0n) {
2046
- return;
2047
- }
1989
+ }
1990
+
1991
+ if (orderTxn.type === 'market') {
1992
+ let refundTxn = {
1993
+ sourceChain: result.taker.sourceChain,
1994
+ sourceWalletAddress: result.taker.sourceWalletAddress,
1995
+ height: orderTxn.height
1996
+ };
1997
+ if (result.taker.sourceChain === this.baseChainSymbol) {
1998
+ refundTxn.sourceChainAmount = result.taker.valueRemaining;
1999
+ } else {
2000
+ refundTxn.sourceChainAmount = result.taker.sizeRemaining;
2001
+ }
2002
+ if (refundTxn.sourceChainAmount > 0n) {
2048
2003
  let protocolMessage = this._computeProtocolMessage(refundTxn.sourceChain, 'r4', [orderTxn.id], 'Unmatched market order part');
2049
- try {
2050
- await this.execRefundTransaction(refundTxn, latestBlockTimestamp, protocolMessage, {type: 'r4', originOrderId: orderTxn.id});
2051
- } catch (error) {
2052
- this.logger.error(
2053
- `Chain ${chainSymbol}: Failed to post multisig market order refund transaction of taker ${takerAddress} on chain ${takerTargetChain} because of error: ${error.message}`
2054
- );
2055
- }
2004
+ this.scheduleRefundTransaction(
2005
+ refundTxn,
2006
+ latestBlockTimestamp,
2007
+ protocolMessage,
2008
+ {type: 'r4', originOrderId: orderTxn.id},
2009
+ `Chain ${
2010
+ chainSymbol
2011
+ }: Failed to post multisig market order refund transaction of taker ${
2012
+ takerAddress
2013
+ } on chain ${
2014
+ takerTargetChain
2015
+ }`
2016
+ );
2056
2017
  }
2057
- })();
2018
+ }
2058
2019
  });
2059
2020
 
2021
+ await this.flushScheduledTransactions();
2022
+
2060
2023
  this.processedHeights = {...latestChainHeights};
2061
2024
  this.lastProcessedBlocks[blockData.chainSymbol] = blockData;
2062
2025
  }
@@ -2120,34 +2083,33 @@ module.exports = class CapitaliskDEXModule {
2120
2083
  fromHeight,
2121
2084
  toHeight
2122
2085
  });
2123
- await Promise.all(
2124
- dividendList.map(async (dividend) => {
2125
- let txnAmount = dividend.amount - BigInt(chainOptions.exchangeFeeBase);
2126
- if (txnAmount <= 0n) {
2127
- this.logger.debug(
2128
- `Chain ${chainSymbol}: Skipped dividend distribution to member address ${
2129
- dividend.walletAddress
2130
- } because the amount due after fees was less than or equal to 0`
2131
- );
2132
- return;
2133
- }
2134
- let dividendTxn = {
2135
- recipientAddress: dividend.walletAddress,
2136
- amount: txnAmount.toString(),
2137
- fee: chainOptions.exchangeFeeBase.toString(),
2138
- timestamp: latestBlockTimestamp,
2139
- height: chainHeight
2140
- };
2141
- let protocolMessage = this._computeProtocolMessage(chainSymbol, 'd1', [fromHeight + 1, toHeight], 'Member dividend');
2142
- try {
2143
- await this.execMultisigTransaction(chainSymbol, dividendTxn, protocolMessage);
2144
- } catch (error) {
2145
- this.logger.error(
2146
- `Chain ${chainSymbol}: Failed to post multisig dividend transaction to member address ${dividend.walletAddress} because of error: ${error.message}`
2147
- );
2148
- }
2149
- })
2150
- );
2086
+
2087
+ for (let dividend of dividendList) {
2088
+ let txnAmount = dividend.amount - BigInt(chainOptions.exchangeFeeBase);
2089
+ if (txnAmount <= 0n) {
2090
+ this.logger.debug(
2091
+ `Chain ${chainSymbol}: Skipped dividend distribution to member address ${
2092
+ dividend.walletAddress
2093
+ } because the amount due after fees was less than or equal to 0`
2094
+ );
2095
+ continue;
2096
+ }
2097
+ let dividendTxn = {
2098
+ recipientAddress: dividend.walletAddress,
2099
+ amount: txnAmount.toString(),
2100
+ fee: chainOptions.exchangeFeeBase.toString(),
2101
+ timestamp: latestBlockTimestamp,
2102
+ height: chainHeight
2103
+ };
2104
+ let protocolMessage = this._computeProtocolMessage(chainSymbol, 'd1', [fromHeight + 1, toHeight], 'Member dividend');
2105
+ this.scheduleMultisigTransaction(
2106
+ chainSymbol,
2107
+ dividendTxn,
2108
+ protocolMessage,
2109
+ null,
2110
+ `Chain ${chainSymbol}: Failed to post multisig dividend transaction to member address ${dividend.walletAddress}`
2111
+ );
2112
+ }
2151
2113
  };
2152
2114
 
2153
2115
  let baseChainForkTargetHeight = 0;
@@ -2638,37 +2600,36 @@ module.exports = class CapitaliskDEXModule {
2638
2600
  return block;
2639
2601
  }
2640
2602
 
2641
- async refundOrderBook(snapshot, timestamp, movedToAddresses) {
2603
+ scheduleRefundOrderBook(snapshot, timestamp, movedToAddresses) {
2642
2604
  let allOrders = snapshot.orderBook.bidLimitOrders.concat(snapshot.orderBook.askLimitOrders);
2643
- await Promise.all(
2644
- allOrders.map(async (order) => {
2645
- let movedToAddress = movedToAddresses[order.sourceChain];
2646
- if (movedToAddress) {
2647
- let protocolMessage = this._computeProtocolMessage(order.sourceChain, 'r5', [order.id, movedToAddress], 'DEX has moved');
2648
- await this.refundOrder(
2649
- order,
2650
- timestamp,
2651
- snapshot.chainHeights[order.sourceChain],
2652
- protocolMessage,
2653
- {type: 'r5', originOrderId: order.id}
2654
- );
2655
- } else {
2656
- let protocolMessage = this._computeProtocolMessage(order.sourceChain, 'r6', [order.id], 'DEX has been disabled');
2657
- allOrders.map(async (order) => {
2658
- await this.refundOrder(
2659
- order,
2660
- timestamp,
2661
- snapshot.chainHeights[order.sourceChain],
2662
- protocolMessage,
2663
- {type: 'r6', originOrderId: order.id}
2664
- );
2665
- })
2666
- }
2667
- })
2668
- );
2605
+ for (let order of allOrders) {
2606
+ let movedToAddress = movedToAddresses[order.sourceChain];
2607
+ let failureMessage = `Failed to post refund transaction for order ${order.id} as part of full order book refund`;
2608
+ if (movedToAddress) {
2609
+ let protocolMessage = this._computeProtocolMessage(order.sourceChain, 'r5', [order.id, movedToAddress], 'DEX has moved');
2610
+ this.scheduleRefundOrder(
2611
+ order,
2612
+ timestamp,
2613
+ snapshot.chainHeights[order.sourceChain],
2614
+ protocolMessage,
2615
+ {type: 'r5', originOrderId: order.id},
2616
+ failureMessage
2617
+ );
2618
+ } else {
2619
+ let protocolMessage = this._computeProtocolMessage(order.sourceChain, 'r6', [order.id], 'DEX has been disabled');
2620
+ this.scheduleRefundOrder(
2621
+ order,
2622
+ timestamp,
2623
+ snapshot.chainHeights[order.sourceChain],
2624
+ protocolMessage,
2625
+ {type: 'r6', originOrderId: order.id},
2626
+ failureMessage
2627
+ );
2628
+ }
2629
+ }
2669
2630
  }
2670
2631
 
2671
- async refundOrder(order, timestamp, refundHeight, reason, extraTransferData) {
2632
+ scheduleRefundOrder(order, timestamp, refundHeight, reason, extraTransferData, failureMessage) {
2672
2633
  let refundTxn = {
2673
2634
  sourceChain: order.sourceChain,
2674
2635
  sourceWalletAddress: order.sourceWalletAddress,
@@ -2679,7 +2640,7 @@ module.exports = class CapitaliskDEXModule {
2679
2640
  } else {
2680
2641
  refundTxn.sourceChainAmount = order.sizeRemaining;
2681
2642
  }
2682
- await this.execRefundTransaction(refundTxn, timestamp, reason, extraTransferData);
2643
+ this.scheduleRefundTransaction(refundTxn, timestamp, reason, extraTransferData, failureMessage);
2683
2644
  }
2684
2645
 
2685
2646
  _computeProtocolMessage(chainSymbol, code, args, reasonMessage) {
@@ -2696,15 +2657,16 @@ module.exports = class CapitaliskDEXModule {
2696
2657
  return messageParts.join(': ');
2697
2658
  }
2698
2659
 
2699
- async execRefundTransaction(txn, timestamp, reason, extraTransferData) {
2660
+ scheduleRefundTransaction(txn, timestamp, reason, extraTransferData, failureMessage) {
2700
2661
  let refundChainOptions = this.options.chains[txn.sourceChain];
2662
+ // Refunds do not charge the exchangeFeeRate.
2701
2663
  let refundAmount = txn.sourceChainAmount - BigInt(refundChainOptions.exchangeFeeBase);
2702
2664
 
2703
- // Refunds do not charge the exchangeFeeRate.
2704
2665
  if (refundAmount <= 0n) {
2705
- throw new Error(
2706
- 'Failed to make refund because amount was less than or equal to 0'
2666
+ this.logger.debug(
2667
+ `${failureMessage} because amount was less than or equal to 0`
2707
2668
  );
2669
+ return;
2708
2670
  }
2709
2671
 
2710
2672
  let refundTxn = {
@@ -2714,11 +2676,13 @@ module.exports = class CapitaliskDEXModule {
2714
2676
  timestamp,
2715
2677
  height: txn.height
2716
2678
  };
2717
- await this.execMultisigTransaction(
2679
+
2680
+ this.scheduleMultisigTransaction(
2718
2681
  txn.sourceChain,
2719
2682
  refundTxn,
2720
2683
  reason,
2721
- extraTransferData
2684
+ extraTransferData,
2685
+ failureMessage
2722
2686
  );
2723
2687
  }
2724
2688
 
@@ -2737,6 +2701,37 @@ module.exports = class CapitaliskDEXModule {
2737
2701
  }
2738
2702
  }
2739
2703
 
2704
+ scheduleMultisigTransaction(targetChain, transactionData, message, extraTransferData, failureMessage) {
2705
+ this.scheduledTransferInfos.push({
2706
+ targetChain,
2707
+ transactionData,
2708
+ message,
2709
+ extraTransferData,
2710
+ failureMessage
2711
+ });
2712
+ }
2713
+
2714
+ async flushScheduledTransactions() {
2715
+ for (let scheduledTransferInfo of this.scheduledTransferInfos) {
2716
+ let {
2717
+ targetChain,
2718
+ transactionData,
2719
+ message,
2720
+ extraTransferData,
2721
+ failureMessage
2722
+ } = scheduledTransferInfo;
2723
+
2724
+ try {
2725
+ await this.execMultisigTransaction(targetChain, transactionData, message, extraTransferData);
2726
+ } catch (error) {
2727
+ this.logger.debug(
2728
+ `${failureMessage} because of error: ${error.message}`
2729
+ );
2730
+ }
2731
+ }
2732
+ this.scheduledTransferInfos = [];
2733
+ }
2734
+
2740
2735
  async execMultisigTransaction(targetChain, transactionData, message, extraTransferData) {
2741
2736
  let chainTimestamp = this._denormalizeTimestamp(targetChain, transactionData.timestamp);
2742
2737
  let chainCrypto = this.chainCrypto[targetChain];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capitalisk-dex",
3
- "version": "17.3.1",
3
+ "version": "18.0.0",
4
4
  "description": "Decentralized exchange module.",
5
5
  "main": "index.js",
6
6
  "scripts": {