|
|
@@ -0,0 +1,50 @@
|
|
|
+from __future__ import annotations
|
|
|
+
|
|
|
+from exec_mcp import bitstamp
|
|
|
+
|
|
|
+
|
|
|
+def test_next_nonce_advances_within_same_millisecond(monkeypatch):
|
|
|
+ bitstamp._LAST_NONCE_BY_SCOPE.clear()
|
|
|
+ monkeypatch.setattr(bitstamp, "_nonce_now_ms", lambda: 1_700_000_000_000)
|
|
|
+
|
|
|
+ first = bitstamp._next_nonce("acct-a:key-a")
|
|
|
+ second = bitstamp._next_nonce("acct-a:key-a")
|
|
|
+ third = bitstamp._next_nonce("acct-a:key-a")
|
|
|
+
|
|
|
+ assert first == 1_700_000_000_000
|
|
|
+ assert second == 1_700_000_000_001
|
|
|
+ assert third == 1_700_000_000_002
|
|
|
+
|
|
|
+
|
|
|
+def test_next_nonce_is_scoped_per_credentials(monkeypatch):
|
|
|
+ bitstamp._LAST_NONCE_BY_SCOPE.clear()
|
|
|
+ monkeypatch.setattr(bitstamp, "_nonce_now_ms", lambda: 1_700_000_000_000)
|
|
|
+
|
|
|
+ first_a = bitstamp._next_nonce("acct-a:key-a")
|
|
|
+ first_b = bitstamp._next_nonce("acct-b:key-b")
|
|
|
+ second_a = bitstamp._next_nonce("acct-a:key-a")
|
|
|
+
|
|
|
+ assert first_a == 1_700_000_000_000
|
|
|
+ assert first_b == 1_700_000_000_000
|
|
|
+ assert second_a == 1_700_000_000_001
|
|
|
+
|
|
|
+
|
|
|
+def test_lg_trading_instances_share_nonce_sequence(monkeypatch):
|
|
|
+ bitstamp._LAST_NONCE_BY_SCOPE.clear()
|
|
|
+ now_ms = [1_700_000_000_000]
|
|
|
+ monkeypatch.setattr(bitstamp, "_nonce_now_ms", lambda: now_ms[0])
|
|
|
+
|
|
|
+ first = bitstamp.LG_Trading.__new__(bitstamp.LG_Trading)
|
|
|
+ first._nonce_scope = "acct-a:key-a"
|
|
|
+
|
|
|
+ second = bitstamp.LG_Trading.__new__(bitstamp.LG_Trading)
|
|
|
+ second._nonce_scope = "acct-a:key-a"
|
|
|
+
|
|
|
+ nonce_1 = first.get_nonce()
|
|
|
+ nonce_2 = second.get_nonce()
|
|
|
+ now_ms[0] += 5
|
|
|
+ nonce_3 = first.get_nonce()
|
|
|
+
|
|
|
+ assert nonce_1 == 1_700_000_000_000
|
|
|
+ assert nonce_2 == 1_700_000_000_001
|
|
|
+ assert nonce_3 == 1_700_000_000_005
|