test_transactions.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #!/usr/bin/env python3
  2. """
  3. Test suite for CDK FFI wallet database operations
  4. """
  5. import asyncio
  6. import os
  7. import sys
  8. import tempfile
  9. from pathlib import Path
  10. # Setup paths before importing cdk_ffi
  11. repo_root = Path(__file__).parent.parent.parent.parent
  12. bindings_path = repo_root / "target" / "bindings" / "python"
  13. lib_path = repo_root / "target" / "release"
  14. # Copy the library to the bindings directory so Python can find it
  15. import shutil
  16. lib_file = "libcdk_ffi.dylib" if sys.platform == "darwin" else "libcdk_ffi.so"
  17. src_lib = lib_path / lib_file
  18. dst_lib = bindings_path / lib_file
  19. if src_lib.exists() and not dst_lib.exists():
  20. shutil.copy2(src_lib, dst_lib)
  21. # Add target/bindings/python to path to load cdk_ffi module
  22. sys.path.insert(0, str(bindings_path))
  23. import cdk_ffi
  24. # Wallet Database Tests
  25. async def test_wallet_creation():
  26. """Test creating a wallet with SQLite backend"""
  27. print("\n=== Test: Wallet Creation ===")
  28. with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
  29. db_path = tmp.name
  30. try:
  31. backend = cdk_ffi.WalletDbBackend.SQLITE(path=db_path)
  32. db = cdk_ffi.create_wallet_db(backend)
  33. print("✓ Wallet database created")
  34. # Verify database is accessible
  35. mint_quotes = await db.get_mint_quotes()
  36. assert isinstance(mint_quotes, list), "get_mint_quotes should return a list"
  37. print("✓ Wallet database accessible")
  38. print("✓ Test passed: Wallet creation works")
  39. finally:
  40. if os.path.exists(db_path):
  41. os.unlink(db_path)
  42. async def test_wallet_mint_management():
  43. """Test adding and querying mints"""
  44. print("\n=== Test: Wallet Mint Management ===")
  45. with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
  46. db_path = tmp.name
  47. try:
  48. backend = cdk_ffi.WalletDbBackend.SQLITE(path=db_path)
  49. db = cdk_ffi.create_wallet_db(backend)
  50. mint_url = cdk_ffi.MintUrl(url="https://testmint.example.com")
  51. # Add mint
  52. await db.add_mint(mint_url, None)
  53. print("✓ Added mint to wallet")
  54. # Get specific mint
  55. await db.get_mint(mint_url)
  56. print("✓ Retrieved mint from database")
  57. # Remove mint
  58. await db.remove_mint(mint_url)
  59. print("✓ Removed mint from wallet")
  60. # Verify removal
  61. mint_info_after = await db.get_mint(mint_url)
  62. assert mint_info_after is None, "Mint should be removed"
  63. print("✓ Verified mint removal")
  64. print("✓ Test passed: Mint management works")
  65. finally:
  66. if os.path.exists(db_path):
  67. os.unlink(db_path)
  68. async def test_wallet_keyset_management():
  69. """Test adding and querying keysets"""
  70. print("\n=== Test: Wallet Keyset Management ===")
  71. with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
  72. db_path = tmp.name
  73. try:
  74. backend = cdk_ffi.WalletDbBackend.SQLITE(path=db_path)
  75. db = cdk_ffi.create_wallet_db(backend)
  76. mint_url = cdk_ffi.MintUrl(url="https://testmint.example.com")
  77. keyset_id = cdk_ffi.Id(hex="004146bdf4a9afab")
  78. # Add mint and keyset
  79. await db.add_mint(mint_url, None)
  80. keyset_info = cdk_ffi.KeySetInfo(
  81. id=keyset_id.hex,
  82. unit=cdk_ffi.CurrencyUnit.SAT(),
  83. active=True,
  84. input_fee_ppk=0
  85. )
  86. await db.add_mint_keysets(mint_url, [keyset_info])
  87. print("✓ Added mint and keyset")
  88. # Query keyset by ID
  89. keyset = await db.get_keyset_by_id(keyset_id)
  90. assert keyset is not None, "Keyset should exist"
  91. assert keyset.id == keyset_id.hex, "Keyset ID should match"
  92. print(f"✓ Retrieved keyset: {keyset.id}")
  93. # Query keysets for mint
  94. keysets = await db.get_mint_keysets(mint_url)
  95. assert keysets is not None and len(keysets) > 0, "Should have keysets for mint"
  96. print(f"✓ Retrieved {len(keysets)} keyset(s) for mint")
  97. print("✓ Test passed: Keyset management works")
  98. finally:
  99. if os.path.exists(db_path):
  100. os.unlink(db_path)
  101. async def test_wallet_keyset_counter():
  102. """Test keyset counter operations"""
  103. print("\n=== Test: Wallet Keyset Counter ===")
  104. with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
  105. db_path = tmp.name
  106. try:
  107. backend = cdk_ffi.WalletDbBackend.SQLITE(path=db_path)
  108. db = cdk_ffi.create_wallet_db(backend)
  109. mint_url = cdk_ffi.MintUrl(url="https://testmint.example.com")
  110. keyset_id = cdk_ffi.Id(hex="004146bdf4a9afab")
  111. # Setup
  112. await db.add_mint(mint_url, None)
  113. keyset_info = cdk_ffi.KeySetInfo(
  114. id=keyset_id.hex,
  115. unit=cdk_ffi.CurrencyUnit.SAT(),
  116. active=True,
  117. input_fee_ppk=0
  118. )
  119. await db.add_mint_keysets(mint_url, [keyset_info])
  120. print("✓ Setup complete")
  121. # Increment counter
  122. counter1 = await db.increment_keyset_counter(keyset_id, 1)
  123. counter2 = await db.increment_keyset_counter(keyset_id, 5)
  124. counter3 = await db.increment_keyset_counter(keyset_id, 0)
  125. print(f"✓ Counter after +1: {counter1}")
  126. assert counter1 == 1, f"Expected counter 1, got {counter1}"
  127. print(f"✓ Counter after +5: {counter2}")
  128. assert counter2 == 6, f"Expected counter 6, got {counter2}"
  129. print(f"✓ Current counter: {counter3}")
  130. assert counter3 == 6, f"Expected counter 6, got {counter3}"
  131. print("✓ Test passed: Keyset counter works")
  132. finally:
  133. if os.path.exists(db_path):
  134. os.unlink(db_path)
  135. async def test_wallet_quotes():
  136. """Test mint and melt quote operations"""
  137. print("\n=== Test: Wallet Quote Operations ===")
  138. with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
  139. db_path = tmp.name
  140. try:
  141. backend = cdk_ffi.WalletDbBackend.SQLITE(path=db_path)
  142. db = cdk_ffi.create_wallet_db(backend)
  143. mint_url = cdk_ffi.MintUrl(url="https://testmint.example.com")
  144. # Add mint
  145. await db.add_mint(mint_url, None)
  146. print("✓ Added mint")
  147. # Query quotes
  148. mint_quotes = await db.get_mint_quotes()
  149. assert isinstance(mint_quotes, list), "get_mint_quotes should return a list"
  150. print(f"✓ Retrieved {len(mint_quotes)} mint quote(s)")
  151. melt_quotes = await db.get_melt_quotes()
  152. assert isinstance(melt_quotes, list), "get_melt_quotes should return a list"
  153. print(f"✓ Retrieved {len(melt_quotes)} melt quote(s)")
  154. print("✓ Test passed: Quote operations work")
  155. finally:
  156. if os.path.exists(db_path):
  157. os.unlink(db_path)
  158. async def test_wallet_proofs_by_ys():
  159. """Test retrieving proofs by Y values"""
  160. print("\n=== Test: Wallet Get Proofs by Y Values ===")
  161. with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
  162. db_path = tmp.name
  163. try:
  164. backend = cdk_ffi.WalletDbBackend.SQLITE(path=db_path)
  165. db = cdk_ffi.create_wallet_db(backend)
  166. # Test with empty list
  167. proofs = await db.get_proofs_by_ys([])
  168. assert len(proofs) == 0, f"Expected 0 proofs, got {len(proofs)}"
  169. print("✓ get_proofs_by_ys returns empty for empty input")
  170. print("✓ Test passed: get_proofs_by_ys works")
  171. finally:
  172. if os.path.exists(db_path):
  173. os.unlink(db_path)
  174. async def main():
  175. """Run all tests"""
  176. print("Starting CDK FFI Wallet Database Tests")
  177. print("=" * 50)
  178. tests = [
  179. ("Wallet Creation", test_wallet_creation),
  180. ("Wallet Mint Management", test_wallet_mint_management),
  181. ("Wallet Keyset Management", test_wallet_keyset_management),
  182. ("Wallet Keyset Counter", test_wallet_keyset_counter),
  183. ("Wallet Quote Operations", test_wallet_quotes),
  184. ("Wallet Get Proofs by Y Values", test_wallet_proofs_by_ys),
  185. ]
  186. passed = 0
  187. failed = 0
  188. for test_name, test_func in tests:
  189. try:
  190. await test_func()
  191. passed += 1
  192. except Exception as e:
  193. failed += 1
  194. print(f"\n✗ Test failed: {test_name}")
  195. print(f"Error: {e}")
  196. import traceback
  197. traceback.print_exc()
  198. print("\n" + "=" * 50)
  199. print(f"Test Results: {passed} passed, {failed} failed")
  200. print("=" * 50)
  201. return 0 if failed == 0 else 1
  202. if __name__ == "__main__":
  203. exit_code = asyncio.run(main())
  204. sys.exit(exit_code)