swap.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/env python3
  2. """
  3. test.modtest_d.swap: swap unit tests for the MMGen suite
  4. """
  5. from mmgen.color import cyan
  6. from mmgen.cfg import Config
  7. from mmgen.amt import UniAmt
  8. from mmgen.swap.proto.thorchain import SwapAsset, Memo
  9. from mmgen.protocol import init_proto
  10. from ..include.common import cfg, vmsg, make_burn_addr
  11. class unit_tests:
  12. def asset(self, name, ut, desc='SwapAsset class'):
  13. for name, full_name, memo_name, chain, asset, direction in (
  14. ('BTC', 'BTC.BTC', 'b', 'BTC', None, 'recv'),
  15. ('LTC', 'LTC.LTC', 'l', 'LTC', None, 'recv'),
  16. ('BCH', 'BCH.BCH', 'c', 'BCH', None, 'recv'),
  17. ('ETH.USDT', 'ETH.USDT', 'ETH.USDT', 'ETH', 'USDT', 'recv'),
  18. ):
  19. a = SwapAsset(name, direction)
  20. vmsg(f' {a.name}')
  21. assert a.name == name
  22. assert a.full_name == full_name
  23. assert a.direction == direction
  24. assert a.asset == asset
  25. assert a.chain == chain
  26. assert a.memo_asset_name == memo_name
  27. return True
  28. def memo(self, name, ut, desc='Swap transaction memo'):
  29. for coin, addrtype, asset_name, token in (
  30. ('ltc', 'bech32', 'LTC', None),
  31. ('bch', 'compressed', 'BCH', None),
  32. ('eth', None, 'ETH', None),
  33. ('eth', None, 'ETH.USDT', 'USDT'),
  34. ):
  35. proto = init_proto(cfg, coin, tokensym=token, need_amt=True)
  36. addr = make_burn_addr(proto, addrtype)
  37. asset = SwapAsset(asset_name, 'recv')
  38. vmsg(f'\nTesting asset {cyan(asset_name)}:')
  39. for limit, limit_chk, suf in (
  40. ('123.4567', 12340000000, '1234e7/3/0'),
  41. ('1.234567', 123400000, '1234e5/3/0'),
  42. ('0.01234567', 1234000, '1234e3/3/0'),
  43. ('0.00012345', 12345, '12345/3/0'),
  44. (None, 0, '0/3/0'),
  45. ):
  46. vmsg('\nTesting memo initialization:')
  47. m = Memo(
  48. proto,
  49. asset,
  50. addr,
  51. trade_limit = None if limit is None else UniAmt(limit))
  52. vmsg(f'str(memo): {m}')
  53. vmsg(f'repr(memo): {m!r}')
  54. vmsg(f'limit: {limit}')
  55. assert str(m).endswith(':' + suf), f'{m} doesn’t end with {suf}'
  56. p = Memo.parse(m)
  57. limit_dec = UniAmt(p.trade_limit, from_unit='satoshi')
  58. vmsg(f'limit_dec: {limit_dec.hl()}')
  59. vmsg('\nTesting memo parsing:')
  60. from pprint import pformat
  61. vmsg(pformat(p._asdict()))
  62. assert p.proto == 'THORChain'
  63. assert p.function == 'SWAP'
  64. assert p.chain == coin.upper()
  65. assert p.asset == token or coin.upper()
  66. assert p.address == addr.views[addr.view_pref]
  67. assert p.trade_limit == limit_chk
  68. assert p.stream_interval == 3
  69. assert p.stream_quantity == 0 # auto
  70. vmsg('\nTesting is_partial_memo():')
  71. for vec in (
  72. str(m),
  73. 'SWAP:xyz',
  74. '=:xyz',
  75. 's:xyz',
  76. 'a:xz',
  77. '+:xz',
  78. 'WITHDRAW:xz',
  79. 'LOAN+:xz:x:x',
  80. 'TRADE-:xz:x:x',
  81. 'BOND:xz',
  82. ):
  83. vmsg(f' pass: {vec}')
  84. assert Memo.is_partial_memo(vec.encode('ascii')), vec
  85. for vec in (
  86. '=',
  87. 'swap',
  88. 'swap:',
  89. 'swap:abc',
  90. 'SWAP:a',
  91. ):
  92. vmsg(f' fail: {vec}')
  93. assert not Memo.is_partial_memo(vec.encode('ascii')), vec
  94. vmsg('\nTesting error handling:')
  95. def bad(s):
  96. return lambda: Memo.parse(s)
  97. def bad10():
  98. coin = 'BTC'
  99. proto = init_proto(cfg, coin, need_amt=True)
  100. addr = make_burn_addr(proto, 'C')
  101. asset = SwapAsset(coin, 'send')
  102. Memo(proto, asset, addr, trade_limit=None)
  103. def bad11():
  104. SwapAsset('XYZ', 'send')
  105. def bad12():
  106. SwapAsset('DOGE', 'send')
  107. ut.process_bad_data((
  108. ('bad1', 'SwapMemoParseError', 'must contain', bad('x')),
  109. ('bad2', 'SwapMemoParseError', 'must contain', bad('y:z:x')),
  110. ('bad3', 'SwapMemoParseError', 'function abbrev', bad('z:l:foobar:0/3/0')),
  111. ('bad4', 'SwapAssetError', 'unrecognized', bad('=:x:foobar:0/3/0')),
  112. ('bad5', 'SwapMemoParseError', 'failed to parse', bad('=:l:foobar:n')),
  113. ('bad6', 'SwapMemoParseError', 'invalid specifier', bad('=:l:foobar:x/3/0')),
  114. ('bad7', 'SwapMemoParseError', 'extra', bad('=:l:foobar:0/3/0:x')),
  115. ('bad10', 'AssertionError', 'recv', bad10),
  116. ('bad11', 'SwapAssetError', 'unrecognized', bad11),
  117. ('bad12', 'SwapAssetError', 'unsupported', bad12),
  118. ), pfx='')
  119. return True