swap.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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 ..include.common import cfg, vmsg, make_burn_addr
  7. class unit_tests:
  8. def memo(self, name, ut, desc='Swap transaction memo'):
  9. from mmgen.protocol import init_proto
  10. from mmgen.amt import UniAmt
  11. from mmgen.swap.proto.thorchain import Memo
  12. for coin, addrtype in (
  13. ('ltc', 'bech32'),
  14. ('bch', 'compressed'),
  15. ('eth', None),
  16. ):
  17. proto = init_proto(cfg, coin, need_amt=True)
  18. addr = make_burn_addr(proto, addrtype)
  19. vmsg(f'\nTesting coin {cyan(coin.upper())}:')
  20. for limit, limit_chk in (
  21. ('123.4567', 12340000000),
  22. ('1.234567', 123400000),
  23. ('0.01234567', 1234000),
  24. ('0.00012345', 12345),
  25. (None, 0),
  26. ):
  27. vmsg('\nTesting memo initialization:')
  28. m = Memo(proto, addr, trade_limit=UniAmt(limit) if limit else None)
  29. vmsg(f'str(memo): {m}')
  30. vmsg(f'repr(memo): {m!r}')
  31. vmsg(f'limit: {limit}')
  32. p = Memo.parse(m)
  33. limit_dec = UniAmt(p.trade_limit, from_unit='satoshi')
  34. vmsg(f'limit_dec: {limit_dec.hl()}')
  35. vmsg('\nTesting memo parsing:')
  36. from pprint import pformat
  37. vmsg(pformat(p._asdict()))
  38. assert p.proto == 'THORChain'
  39. assert p.function == 'SWAP'
  40. assert p.chain == coin.upper()
  41. assert p.asset == coin.upper()
  42. assert p.address == addr.views[addr.view_pref]
  43. assert p.trade_limit == limit_chk
  44. assert p.stream_interval == 1
  45. assert p.stream_quantity == 0 # auto
  46. vmsg('\nTesting is_partial_memo():')
  47. for vec in (
  48. str(m),
  49. 'SWAP:xyz',
  50. '=:xyz',
  51. 's:xyz',
  52. 'a:xz',
  53. '+:xz',
  54. 'WITHDRAW:xz',
  55. 'LOAN+:xz:x:x',
  56. 'TRADE-:xz:x:x',
  57. 'BOND:xz',
  58. ):
  59. vmsg(f' pass: {vec}')
  60. assert Memo.is_partial_memo(vec.encode('ascii')), vec
  61. for vec in (
  62. '=',
  63. 'swap',
  64. 'swap:',
  65. 'swap:abc',
  66. 'SWAP:a',
  67. ):
  68. vmsg(f' fail: {vec}')
  69. assert not Memo.is_partial_memo(vec.encode('ascii')), vec
  70. vmsg('\nTesting error handling:')
  71. def bad(s):
  72. return lambda: Memo.parse(s)
  73. ut.process_bad_data((
  74. ('bad1', 'SwapMemoParseError', 'must contain', bad('x')),
  75. ('bad2', 'SwapMemoParseError', 'must contain', bad('y:z:x')),
  76. ('bad3', 'SwapMemoParseError', 'function abbrev', bad('z:l:foobar:0/1/0')),
  77. ('bad4', 'SwapMemoParseError', 'asset abbrev', bad('=:x:foobar:0/1/0')),
  78. ('bad5', 'SwapMemoParseError', 'failed to parse', bad('=:l:foobar:n')),
  79. ('bad6', 'SwapMemoParseError', 'invalid specifier', bad('=:l:foobar:x/1/0')),
  80. ('bad7', 'SwapMemoParseError', 'extra', bad('=:l:foobar:0/1/0:x')),
  81. ), pfx='')
  82. return True