meshtrade 1.22.0__tar.gz → 1.23.1__tar.gz

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.

Potentially problematic release.


This version of meshtrade might be problematic. Click here for more details.

Files changed (218) hide show
  1. {meshtrade-1.22.0 → meshtrade-1.23.1}/PKG-INFO +1 -1
  2. {meshtrade-1.22.0 → meshtrade-1.23.1}/pyproject.toml +1 -1
  3. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/__init__.py +12 -0
  4. meshtrade-1.23.1/python/src/meshtrade/compliance/client/v1/client_roles.py +123 -0
  5. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/service_meshpy.py +1 -0
  6. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/__init__.py +6 -0
  7. meshtrade-1.23.1/python/src/meshtrade/iam/api_user/v1/api_user_state_machine.py +104 -0
  8. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/service_meshpy.py +1 -0
  9. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/service_meshpy.py +1 -0
  10. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/role/v1/__init__.py +16 -2
  11. meshtrade-1.23.1/python/src/meshtrade/iam/role/v1/role.py +174 -0
  12. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/service_meshpy.py +1 -0
  13. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/__init__.py +4 -0
  14. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/service_meshpy.py +2 -1
  15. meshtrade-1.23.1/python/src/meshtrade/ledger/transaction/v1/transaction_state_machine.py +75 -0
  16. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/__init__.py +4 -0
  17. meshtrade-1.23.1/python/src/meshtrade/reporting/account_report/v1/income_entry.py +35 -0
  18. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/service_meshpy.py +1 -0
  19. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/service_meshpy.py +1 -0
  20. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/service_meshpy.py +1 -0
  21. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/__init__.py +81 -11
  22. meshtrade-1.23.1/python/src/meshtrade/type/v1/amount.py +502 -0
  23. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/decimal_built_in_conversions.py +8 -3
  24. meshtrade-1.23.1/python/src/meshtrade/type/v1/decimal_operations.py +354 -0
  25. meshtrade-1.23.1/python/src/meshtrade/type/v1/ledger.py +100 -0
  26. meshtrade-1.23.1/python/src/meshtrade/type/v1/token.py +144 -0
  27. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/service_meshpy.py +1 -0
  28. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade.egg-info/PKG-INFO +1 -1
  29. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade.egg-info/SOURCES.txt +6 -0
  30. meshtrade-1.22.0/python/src/meshtrade/iam/role/v1/role.py +0 -23
  31. meshtrade-1.22.0/python/src/meshtrade/type/v1/amount.py +0 -78
  32. meshtrade-1.22.0/python/src/meshtrade/type/v1/ledger.py +0 -25
  33. {meshtrade-1.22.0 → meshtrade-1.23.1}/README.md +0 -0
  34. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/buf/validate/validate_pb2.py +0 -0
  35. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/buf/validate/validate_pb2.pyi +0 -0
  36. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/__init__.py +0 -0
  37. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/common/__init__.py +0 -0
  38. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/common/config.py +0 -0
  39. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/common/grpc_client.py +0 -0
  40. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/common/service_options.py +0 -0
  41. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/__init__.py +0 -0
  42. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/__init__.py +0 -0
  43. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/client_pb2.py +0 -0
  44. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/client_pb2.pyi +0 -0
  45. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/client_pb2_grpc.py +0 -0
  46. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_pb2.py +0 -0
  47. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_pb2.pyi +0 -0
  48. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_pb2_grpc.py +0 -0
  49. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_representative_pb2.py +0 -0
  50. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_representative_pb2.pyi +0 -0
  51. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_representative_pb2_grpc.py +0 -0
  52. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_representative_role_pb2.py +0 -0
  53. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_representative_role_pb2.pyi +0 -0
  54. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/company_representative_role_pb2_grpc.py +0 -0
  55. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/fund_pb2.py +0 -0
  56. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/fund_pb2.pyi +0 -0
  57. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/fund_pb2_grpc.py +0 -0
  58. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/identification_document_type_pb2.py +0 -0
  59. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/identification_document_type_pb2.pyi +0 -0
  60. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/identification_document_type_pb2_grpc.py +0 -0
  61. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/industry_classification_pb2.py +0 -0
  62. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/industry_classification_pb2.pyi +0 -0
  63. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/industry_classification_pb2_grpc.py +0 -0
  64. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/natural_person_connection_type_pb2.py +0 -0
  65. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/natural_person_connection_type_pb2.pyi +0 -0
  66. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/natural_person_connection_type_pb2_grpc.py +0 -0
  67. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/natural_person_pb2.py +0 -0
  68. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/natural_person_pb2.pyi +0 -0
  69. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/natural_person_pb2_grpc.py +0 -0
  70. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/pep_status_pb2.py +0 -0
  71. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/pep_status_pb2.pyi +0 -0
  72. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/pep_status_pb2_grpc.py +0 -0
  73. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/service_pb2.py +0 -0
  74. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/service_pb2.pyi +0 -0
  75. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/service_pb2_grpc.py +0 -0
  76. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/source_of_income_and_wealth_pb2.py +0 -0
  77. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/source_of_income_and_wealth_pb2.pyi +0 -0
  78. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/source_of_income_and_wealth_pb2_grpc.py +0 -0
  79. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/tax_residency_pb2.py +0 -0
  80. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/tax_residency_pb2.pyi +0 -0
  81. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/tax_residency_pb2_grpc.py +0 -0
  82. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/trust_pb2.py +0 -0
  83. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/trust_pb2.pyi +0 -0
  84. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/trust_pb2_grpc.py +0 -0
  85. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/verification_status_pb2.py +0 -0
  86. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/verification_status_pb2.pyi +0 -0
  87. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/compliance/client/v1/verification_status_pb2_grpc.py +0 -0
  88. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/__init__.py +0 -0
  89. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_credentials.py +0 -0
  90. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_credentials_pb2.py +0 -0
  91. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_credentials_pb2.pyi +0 -0
  92. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_credentials_pb2_grpc.py +0 -0
  93. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_user_pb2.py +0 -0
  94. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_user_pb2.pyi +0 -0
  95. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/api_user_pb2_grpc.py +0 -0
  96. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/service.py +0 -0
  97. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/service_pb2.py +0 -0
  98. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/service_pb2.pyi +0 -0
  99. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/api_user/v1/service_pb2_grpc.py +0 -0
  100. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/__init__.py +0 -0
  101. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/__init__.py +0 -0
  102. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/group_pb2.py +0 -0
  103. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/group_pb2.pyi +0 -0
  104. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/group_pb2_grpc.py +0 -0
  105. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/service_pb2.py +0 -0
  106. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/service_pb2.pyi +0 -0
  107. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/group/v1/service_pb2_grpc.py +0 -0
  108. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/role/v1/role_pb2.py +0 -0
  109. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/role/v1/role_pb2.pyi +0 -0
  110. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/role/v1/role_pb2_grpc.py +0 -0
  111. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/__init__.py +0 -0
  112. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/service_pb2.py +0 -0
  113. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/service_pb2.pyi +0 -0
  114. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/service_pb2_grpc.py +0 -0
  115. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/user_pb2.py +0 -0
  116. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/user_pb2.pyi +0 -0
  117. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/iam/user/v1/user_pb2_grpc.py +0 -0
  118. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/__init__.py +0 -0
  119. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/__init__.py +0 -0
  120. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/service_pb2.py +0 -0
  121. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/service_pb2.pyi +0 -0
  122. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/service_pb2_grpc.py +0 -0
  123. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/transaction_action_pb2.py +0 -0
  124. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/transaction_action_pb2.pyi +0 -0
  125. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/transaction_action_pb2_grpc.py +0 -0
  126. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/transaction_state_pb2.py +0 -0
  127. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/transaction_state_pb2.pyi +0 -0
  128. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/ledger/transaction/v1/transaction_state_pb2_grpc.py +0 -0
  129. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/option/v1/__init__.py +0 -0
  130. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/option/v1/method_type_pb2.py +0 -0
  131. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/option/v1/method_type_pb2.pyi +0 -0
  132. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/option/v1/method_type_pb2_grpc.py +0 -0
  133. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/account_report_pb2.py +0 -0
  134. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/account_report_pb2.pyi +0 -0
  135. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/account_report_pb2_grpc.py +0 -0
  136. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/disclaimer_pb2.py +0 -0
  137. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/disclaimer_pb2.pyi +0 -0
  138. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/disclaimer_pb2_grpc.py +0 -0
  139. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/fee_entry_pb2.py +0 -0
  140. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/fee_entry_pb2.pyi +0 -0
  141. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/fee_entry_pb2_grpc.py +0 -0
  142. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/income_entry_pb2.py +0 -0
  143. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/income_entry_pb2.pyi +0 -0
  144. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/income_entry_pb2_grpc.py +0 -0
  145. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/service_pb2.py +0 -0
  146. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/service_pb2.pyi +0 -0
  147. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/service_pb2_grpc.py +0 -0
  148. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/trading_statement_entry_pb2.py +0 -0
  149. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/trading_statement_entry_pb2.pyi +0 -0
  150. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/reporting/account_report/v1/trading_statement_entry_pb2_grpc.py +0 -0
  151. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/__init__.py +0 -0
  152. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/instrument_pb2.py +0 -0
  153. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/instrument_pb2.pyi +0 -0
  154. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/instrument_pb2_grpc.py +0 -0
  155. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/instrument_type_pb2.py +0 -0
  156. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/instrument_type_pb2.pyi +0 -0
  157. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/instrument_type_pb2_grpc.py +0 -0
  158. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/unit_pb2.py +0 -0
  159. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/unit_pb2.pyi +0 -0
  160. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/studio/instrument/v1/unit_pb2_grpc.py +0 -0
  161. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/__init__.py +0 -0
  162. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/__init__.py +0 -0
  163. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/__init__.py +0 -0
  164. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/limit_order_pb2.py +0 -0
  165. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/limit_order_pb2.pyi +0 -0
  166. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/limit_order_pb2_grpc.py +0 -0
  167. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/service_pb2.py +0 -0
  168. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/service_pb2.pyi +0 -0
  169. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/limit_order/v1/service_pb2_grpc.py +0 -0
  170. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/__init__.py +0 -0
  171. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/market_order_pb2.py +0 -0
  172. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/market_order_pb2.pyi +0 -0
  173. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/market_order_pb2_grpc.py +0 -0
  174. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/service_pb2.py +0 -0
  175. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/service_pb2.pyi +0 -0
  176. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/trading/market_order/v1/service_pb2_grpc.py +0 -0
  177. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/__init__.py +0 -0
  178. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/address_pb2.py +0 -0
  179. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/address_pb2.pyi +0 -0
  180. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/address_pb2_grpc.py +0 -0
  181. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/amount_pb2.py +0 -0
  182. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/amount_pb2.pyi +0 -0
  183. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/amount_pb2_grpc.py +0 -0
  184. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/contact_details_pb2.py +0 -0
  185. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/contact_details_pb2.pyi +0 -0
  186. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/contact_details_pb2_grpc.py +0 -0
  187. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/date.py +0 -0
  188. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/date_pb2.py +0 -0
  189. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/date_pb2.pyi +0 -0
  190. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/date_pb2_grpc.py +0 -0
  191. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/decimal_pb2.py +0 -0
  192. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/decimal_pb2.pyi +0 -0
  193. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/decimal_pb2_grpc.py +0 -0
  194. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/ledger_pb2.py +0 -0
  195. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/ledger_pb2.pyi +0 -0
  196. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/ledger_pb2_grpc.py +0 -0
  197. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/sorting_pb2.py +0 -0
  198. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/sorting_pb2.pyi +0 -0
  199. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/sorting_pb2_grpc.py +0 -0
  200. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/time_of_day.py +0 -0
  201. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/time_of_day_pb2.py +0 -0
  202. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/time_of_day_pb2.pyi +0 -0
  203. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/time_of_day_pb2_grpc.py +0 -0
  204. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/token_pb2.py +0 -0
  205. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/token_pb2.pyi +0 -0
  206. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/type/v1/token_pb2_grpc.py +0 -0
  207. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/__init__.py +0 -0
  208. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/__init__.py +0 -0
  209. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/account_pb2.py +0 -0
  210. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/account_pb2.pyi +0 -0
  211. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/account_pb2_grpc.py +0 -0
  212. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/service_pb2.py +0 -0
  213. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/service_pb2.pyi +0 -0
  214. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade/wallet/account/v1/service_pb2_grpc.py +0 -0
  215. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade.egg-info/dependency_links.txt +0 -0
  216. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade.egg-info/requires.txt +0 -0
  217. {meshtrade-1.22.0 → meshtrade-1.23.1}/python/src/meshtrade.egg-info/top_level.txt +0 -0
  218. {meshtrade-1.22.0 → meshtrade-1.23.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshtrade
3
- Version: 1.22.0
3
+ Version: 1.23.1
4
4
  Summary: Integration SDK for Mesh API Services
5
5
  Author-email: Bernard Bussy <bernard@meshtrade.co>
6
6
  License: LicenseRef-My-Custom-License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshtrade"
7
- version = "1.22.0"
7
+ version = "1.23.1"
8
8
  authors = [
9
9
  { name = "Bernard Bussy", email = "bernard@meshtrade.co" },
10
10
  ]
@@ -55,6 +55,13 @@ from .service_meshpy import (
55
55
  #
56
56
  # ===================================================================
57
57
 
58
+ from .client_roles import (
59
+ get_client_default_role_index,
60
+ get_client_default_roles,
61
+ must_get_client_default_role_index,
62
+ must_get_client_default_roles,
63
+ )
64
+
58
65
  # ===================================================================
59
66
  # MODULE EXPORTS
60
67
  # ===================================================================
@@ -84,4 +91,9 @@ __all__ = [
84
91
  "TaxResidency",
85
92
  "Trust",
86
93
  "VerificationStatus",
94
+ # Manual exports
95
+ "get_client_default_role_index",
96
+ "get_client_default_roles",
97
+ "must_get_client_default_role_index",
98
+ "must_get_client_default_roles",
87
99
  ]
@@ -0,0 +1,123 @@
1
+ """Client roles utility functions."""
2
+
3
+ from meshtrade.compliance.client.v1.client_pb2 import Client
4
+ from meshtrade.iam.role.v1 import role_pb2
5
+ from meshtrade.iam.role.v1.role_pb2 import Role
6
+
7
+ # Cache for client default roles extracted from protobuf
8
+ _client_default_roles: list[Role] | None = None
9
+ _client_default_roles_error: str | None = None
10
+
11
+
12
+ def _initialize_client_default_roles() -> None:
13
+ """Initialize client default roles from protobuf extensions.
14
+
15
+ This function is called once to extract roles from the Client message's
16
+ message_roles extension. Results are cached for subsequent calls.
17
+ """
18
+ global _client_default_roles, _client_default_roles_error
19
+
20
+ if _client_default_roles is not None or _client_default_roles_error is not None:
21
+ return
22
+
23
+ try:
24
+ # Get the Client message descriptor
25
+ client_descriptor = Client.DESCRIPTOR
26
+
27
+ # Get message options
28
+ options = client_descriptor.GetOptions()
29
+
30
+ # Get the message_roles extension descriptor
31
+ message_roles_ext = role_pb2.message_roles
32
+
33
+ # Check if extension is present
34
+ # Type ignore: protobuf extension API has overly strict type stubs
35
+ if not options.HasExtension(message_roles_ext): # type: ignore[arg-type]
36
+ _client_default_roles_error = f"proto message {client_descriptor.full_name} does not define extension {message_roles_ext.full_name}"
37
+ return
38
+
39
+ # Get the RoleList from the extension
40
+ # Type ignore: protobuf extension API has overly strict type stubs
41
+ role_list = options.Extensions[message_roles_ext] # type: ignore[arg-type]
42
+
43
+ # Extract roles and make a copy
44
+ _client_default_roles = list(role_list.roles)
45
+
46
+ except Exception as e:
47
+ _client_default_roles_error = f"failed to extract roles from Client message: {e}"
48
+
49
+
50
+ def get_client_default_roles() -> list[Role]:
51
+ """Get default roles for a client.
52
+
53
+ Returns the roles declared on the meshtrade.compliance.client.v1.Client
54
+ message via the meshtrade.iam.role.v1.message_roles option. The returned
55
+ list is a copy so callers can safely mutate it without affecting subsequent reads.
56
+
57
+ Returns:
58
+ List of default Role values for clients
59
+ Empty list if retrieval fails
60
+ """
61
+ try:
62
+ return must_get_client_default_roles()
63
+ except ValueError:
64
+ return []
65
+
66
+
67
+ def must_get_client_default_roles() -> list[Role]:
68
+ """Get default roles for a client, raising error on failure.
69
+
70
+ Returns the roles declared on the meshtrade.compliance.client.v1.Client
71
+ message via the meshtrade.iam.role.v1.message_roles option. The returned
72
+ list is a copy so callers can safely mutate it without affecting subsequent reads.
73
+
74
+ Returns:
75
+ List of default Role values for clients
76
+
77
+ Raises:
78
+ ValueError: If default roles cannot be determined
79
+ """
80
+ _initialize_client_default_roles()
81
+
82
+ if _client_default_roles_error is not None:
83
+ raise ValueError(_client_default_roles_error)
84
+
85
+ if _client_default_roles is None:
86
+ raise ValueError("client default roles not initialized")
87
+
88
+ # Return a copy to prevent mutation
89
+ return list(_client_default_roles)
90
+
91
+
92
+ def get_client_default_role_index() -> dict[Role, bool]:
93
+ """Get default roles as a lookup index.
94
+
95
+ Builds a set-like map keyed by roles declared on the
96
+ meshtrade.compliance.client.v1.Client message. The map's values are always
97
+ True; the structure is intended for efficient membership checks.
98
+
99
+ Returns:
100
+ Dictionary mapping Role to True for default roles
101
+ Empty dict if retrieval fails
102
+ """
103
+ try:
104
+ return must_get_client_default_role_index()
105
+ except ValueError:
106
+ return {}
107
+
108
+
109
+ def must_get_client_default_role_index() -> dict[Role, bool]:
110
+ """Get default roles as lookup index, raising error on failure.
111
+
112
+ Builds a set-like map keyed by roles declared on the
113
+ meshtrade.compliance.client.v1.Client message. The map's values are always
114
+ True; the structure is intended for efficient membership checks.
115
+
116
+ Returns:
117
+ Dictionary mapping Role to True for default roles
118
+
119
+ Raises:
120
+ ValueError: If default roles cannot be determined
121
+ """
122
+ roles = must_get_client_default_roles()
123
+ return dict.fromkeys(roles, True)
@@ -9,6 +9,7 @@ the service interface with resource management capabilities, providing authentic
9
9
  timeouts, and proper connection handling.
10
10
  """
11
11
 
12
+ from collections.abc import Iterator
12
13
  from datetime import timedelta
13
14
  from typing import Optional
14
15
 
@@ -62,7 +62,10 @@ from meshtrade.common import (
62
62
  from .api_credentials import (
63
63
  MESH_API_CREDENTIALS_ENV_VAR,
64
64
  api_credentials_from_environment,
65
+ default_credentials_path,
66
+ find_credentials,
65
67
  load_api_credentials_from_file,
68
+ load_default_credentials,
66
69
  )
67
70
 
68
71
  # ===================================================================
@@ -97,5 +100,8 @@ __all__ = [
97
100
  "MESH_API_CREDENTIALS_ENV_VAR",
98
101
  "api_credentials_from_environment",
99
102
  "create_auth_metadata",
103
+ "default_credentials_path",
104
+ "find_credentials",
100
105
  "load_api_credentials_from_file",
106
+ "load_default_credentials",
101
107
  ]
@@ -0,0 +1,104 @@
1
+ """API User state machine validation and transition logic.
2
+
3
+ This module provides validation and state machine functions for API User states
4
+ and actions, implementing the API User lifecycle management logic.
5
+ """
6
+
7
+ from meshtrade.iam.api_user.v1.api_user_pb2 import APIUserAction, APIUserState
8
+
9
+
10
+ def api_user_state_is_valid(state: APIUserState | None) -> bool:
11
+ """Check if the APIUserState is a valid enum value.
12
+
13
+ Args:
14
+ state: The APIUserState to validate (can be None)
15
+
16
+ Returns:
17
+ True if the state is a valid enum value, False otherwise
18
+
19
+ None Safety:
20
+ Returns False if state is None
21
+
22
+ Example:
23
+ >>> api_user_state_is_valid(APIUserState.API_USER_STATE_ACTIVE)
24
+ True
25
+ >>> api_user_state_is_valid(999) # Invalid enum value
26
+ False
27
+ >>> api_user_state_is_valid(None)
28
+ False
29
+ """
30
+ if state is None:
31
+ return False
32
+ return state in APIUserState.values()
33
+
34
+
35
+ def api_user_state_is_valid_and_defined(state: APIUserState) -> bool:
36
+ """Check if the APIUserState is valid and not unspecified.
37
+
38
+ Args:
39
+ state: The APIUserState to validate
40
+
41
+ Returns:
42
+ True if the state is valid and not UNSPECIFIED, False otherwise
43
+
44
+ Example:
45
+ >>> api_user_state_is_valid_and_defined(APIUserState.API_USER_STATE_ACTIVE)
46
+ True
47
+ >>> api_user_state_is_valid_and_defined(APIUserState.API_USER_STATE_UNSPECIFIED)
48
+ False
49
+ """
50
+ return api_user_state_is_valid(state) and state != APIUserState.API_USER_STATE_UNSPECIFIED
51
+
52
+
53
+ def api_user_state_can_perform_action_at_state(state: APIUserState | None, action: APIUserAction | None) -> bool:
54
+ """Check if the given action can be performed at the current state.
55
+
56
+ This implements the state machine logic for API User lifecycle management.
57
+
58
+ State Transitions:
59
+ - INACTIVE -> ACTIVATE -> ACTIVE
60
+ - ACTIVE -> DEACTIVATE -> INACTIVE
61
+ - UPDATE action allowed in any state
62
+
63
+ Args:
64
+ state: The current APIUserState (can be None)
65
+ action: The APIUserAction to perform (can be None)
66
+
67
+ Returns:
68
+ True if the action can be performed at the given state, False otherwise
69
+
70
+ None Safety:
71
+ Returns False if either state or action is None
72
+
73
+ Example:
74
+ >>> can_perform_action_at_state(
75
+ ... APIUserState.API_USER_STATE_INACTIVE,
76
+ ... APIUserAction.API_USER_ACTION_ACTIVATE
77
+ ... )
78
+ True
79
+ >>> can_perform_action_at_state(
80
+ ... APIUserState.API_USER_STATE_INACTIVE,
81
+ ... APIUserAction.API_USER_ACTION_DEACTIVATE
82
+ ... )
83
+ False
84
+ """
85
+ if state is None or action is None:
86
+ return False
87
+
88
+ # Define actions that are allowed regardless of state (update operations)
89
+ general_update_actions = {
90
+ APIUserAction.API_USER_ACTION_UPDATE: True,
91
+ }
92
+
93
+ if state == APIUserState.API_USER_STATE_INACTIVE:
94
+ if action == APIUserAction.API_USER_ACTION_ACTIVATE:
95
+ return True
96
+ return general_update_actions.get(action, False)
97
+
98
+ elif state == APIUserState.API_USER_STATE_ACTIVE:
99
+ if action == APIUserAction.API_USER_ACTION_DEACTIVATE:
100
+ return True
101
+ return general_update_actions.get(action, False)
102
+
103
+ else:
104
+ return False
@@ -9,6 +9,7 @@ the service interface with resource management capabilities, providing authentic
9
9
  timeouts, and proper connection handling.
10
10
  """
11
11
 
12
+ from collections.abc import Iterator
12
13
  from datetime import timedelta
13
14
  from typing import Optional
14
15
 
@@ -9,6 +9,7 @@ the service interface with resource management capabilities, providing authentic
9
9
  timeouts, and proper connection handling.
10
10
  """
11
11
 
12
+ from collections.abc import Iterator
12
13
  from datetime import timedelta
13
14
  from typing import Optional
14
15
 
@@ -29,7 +29,15 @@ from .role_pb2 import Role, RoleList
29
29
  #
30
30
  # ===================================================================
31
31
 
32
- from .role import full_resource_name_from_group_name
32
+ from .role import (
33
+ must_parse_role_parts,
34
+ parse_role_parts,
35
+ role_from_full_resource_name,
36
+ role_full_resource_name_from_group,
37
+ role_full_resource_name_from_group_id,
38
+ role_is_valid,
39
+ role_is_valid_and_specified,
40
+ )
33
41
 
34
42
  # ===================================================================
35
43
  # MODULE EXPORTS
@@ -40,5 +48,11 @@ __all__ = [
40
48
  "Role",
41
49
  "RoleList",
42
50
  # Manual exports
43
- "full_resource_name_from_group_name",
51
+ "must_parse_role_parts",
52
+ "parse_role_parts",
53
+ "role_from_full_resource_name",
54
+ "role_full_resource_name_from_group",
55
+ "role_full_resource_name_from_group_id",
56
+ "role_is_valid",
57
+ "role_is_valid_and_specified",
44
58
  ]
@@ -0,0 +1,174 @@
1
+ """Role utility functions for Mesh API.
2
+
3
+ This module provides helper functions for working with Role enums and their resource names.
4
+ All functions use the 3-part integer format: groups/{groupID}/{roleNumber}
5
+ for cross-language compatibility.
6
+ """
7
+
8
+ from meshtrade.iam.role.v1.role_pb2 import Role
9
+
10
+
11
+ def role_is_valid(role: Role) -> bool:
12
+ """Check if role value is valid (within enum range).
13
+
14
+ Args:
15
+ role: Role enum value (integer)
16
+
17
+ Returns:
18
+ True if role is a valid enum value
19
+
20
+ Example:
21
+ >>> role_is_valid(Role.ROLE_IAM_ADMIN)
22
+ True
23
+ >>> role_is_valid(99999999)
24
+ False
25
+ """
26
+ return role in Role.values()
27
+
28
+
29
+ def role_is_valid_and_specified(role: Role) -> bool:
30
+ """Check if role is valid and not UNSPECIFIED.
31
+
32
+ Args:
33
+ role: Role enum value (integer)
34
+
35
+ Returns:
36
+ True if role is valid and not ROLE_UNSPECIFIED
37
+
38
+ Example:
39
+ >>> role_is_valid_and_specified(Role.ROLE_IAM_ADMIN)
40
+ True
41
+ >>> role_is_valid_and_specified(Role.ROLE_UNSPECIFIED)
42
+ False
43
+ """
44
+ return role_is_valid(role) and role != Role.ROLE_UNSPECIFIED
45
+
46
+
47
+ def role_full_resource_name_from_group_id(role: Role, group_id: str) -> str:
48
+ """Generate full resource name from role and group ID.
49
+
50
+ Format: groups/{group_id}/{role_int}
51
+
52
+ Args:
53
+ role: Role enum value (integer)
54
+ group_id: Group ID (UUID)
55
+
56
+ Returns:
57
+ Full resource name string using integer format
58
+
59
+ Example:
60
+ >>> role_full_resource_name_from_group_id(Role.ROLE_IAM_ADMIN, "01DD32GZ7R0000000000000001")
61
+ 'groups/01DD32GZ7R0000000000000001/3000000'
62
+ """
63
+ return f"groups/{group_id}/{int(role)}"
64
+
65
+
66
+ def role_full_resource_name_from_group(role: Role, group: str) -> str:
67
+ """Generate full resource name from role and group resource name.
68
+
69
+ Args:
70
+ role: Role enum value (integer)
71
+ group: Group resource name (e.g., "groups/{id}")
72
+
73
+ Returns:
74
+ Full resource name string using integer format
75
+
76
+ Raises:
77
+ ValueError: If group format is invalid
78
+
79
+ Example:
80
+ >>> role_full_resource_name_from_group(Role.ROLE_IAM_ADMIN, "groups/01DD32GZ7R0000000000000001")
81
+ 'groups/01DD32GZ7R0000000000000001/3000000'
82
+ """
83
+ if not group.startswith("groups/"):
84
+ raise ValueError(f"invalid group format, expected groups/{{groupID}}, got: {group}")
85
+
86
+ group_id = group[len("groups/") :]
87
+ if not group_id:
88
+ raise ValueError(f"group ID cannot be empty in group resource name: {group}")
89
+
90
+ return role_full_resource_name_from_group_id(role, group_id)
91
+
92
+
93
+ def role_from_full_resource_name(full_resource_name: str) -> Role:
94
+ """Extract Role from full resource name.
95
+
96
+ Args:
97
+ full_resource_name: Full resource name (e.g., "groups/{id}/{role_int}")
98
+
99
+ Returns:
100
+ Role enum value (integer), or ROLE_UNSPECIFIED if parsing fails
101
+
102
+ Example:
103
+ >>> role_from_full_resource_name("groups/01DD32GZ7R0000000000000001/3000000")
104
+ 3000000
105
+ >>> role_from_full_resource_name("invalid/format")
106
+ 0
107
+ """
108
+ from typing import cast
109
+
110
+ try:
111
+ _, role_int = parse_role_parts(full_resource_name)
112
+ # Python protobuf enums are integers, safe to cast
113
+ return cast(Role, role_int)
114
+ except ValueError:
115
+ return Role.ROLE_UNSPECIFIED
116
+
117
+
118
+ def parse_role_parts(role_full_resource_name: str) -> tuple[str, int]:
119
+ """Parse full resource name into group ID and Role.
120
+
121
+ Expected format: groups/{group_id}/{role_int}
122
+
123
+ Args:
124
+ role_full_resource_name: Full resource name
125
+
126
+ Returns:
127
+ Tuple of (group_id, role_int)
128
+
129
+ Raises:
130
+ ValueError: If format is invalid or role number cannot be parsed
131
+
132
+ Example:
133
+ >>> parse_role_parts("groups/01DD32GZ7R0000000000000001/3000000")
134
+ ('01DD32GZ7R0000000000000001', 3000000)
135
+ """
136
+ parts = role_full_resource_name.split("/")
137
+ if len(parts) != 3 or parts[0] != "groups":
138
+ raise ValueError(f"invalid role format, expected groups/{{groupID}}/{{role}}, got {role_full_resource_name}")
139
+
140
+ group_id = parts[1]
141
+ if not group_id:
142
+ raise ValueError("group ID cannot be empty")
143
+
144
+ try:
145
+ role_int = int(parts[2])
146
+ except ValueError as e:
147
+ raise ValueError(f"error parsing role enum value '{parts[2]}'") from e
148
+
149
+ if role_int < 0:
150
+ raise ValueError(f"invalid role number in full resource name: {role_full_resource_name}")
151
+
152
+ return group_id, role_int
153
+
154
+
155
+ def must_parse_role_parts(role_full_resource_name: str) -> tuple[str, int]:
156
+ """Parse role parts, raising error on failure.
157
+
158
+ This is an alias for parse_role_parts.
159
+ Both functions raise ValueError on parsing errors.
160
+
161
+ Args:
162
+ role_full_resource_name: Full resource name
163
+
164
+ Returns:
165
+ Tuple of (group_id, role_int)
166
+
167
+ Raises:
168
+ ValueError: If format is invalid
169
+
170
+ Example:
171
+ >>> must_parse_role_parts("groups/01DD32GZ7R0000000000000001/3000000")
172
+ ('01DD32GZ7R0000000000000001', 3000000)
173
+ """
174
+ return parse_role_parts(role_full_resource_name)
@@ -9,6 +9,7 @@ the service interface with resource management capabilities, providing authentic
9
9
  timeouts, and proper connection handling.
10
10
  """
11
11
 
12
+ from collections.abc import Iterator
12
13
  from datetime import timedelta
13
14
  from typing import Optional
14
15
 
@@ -43,6 +43,8 @@ from .service_meshpy import (
43
43
  #
44
44
  # ===================================================================
45
45
 
46
+ from .transaction_state_machine import transaction_state_can_perform_action_at_state
47
+
46
48
  # ===================================================================
47
49
  # MODULE EXPORTS
48
50
  # ===================================================================
@@ -58,4 +60,6 @@ __all__ = [
58
60
  "TransactionServiceGRPCClient",
59
61
  "TransactionServiceGRPCClientInterface",
60
62
  "TransactionState",
63
+ # Manual exports
64
+ "transaction_state_can_perform_action_at_state",
61
65
  ]
@@ -9,6 +9,7 @@ the service interface with resource management capabilities, providing authentic
9
9
  timeouts, and proper connection handling.
10
10
  """
11
11
 
12
+ from collections.abc import Iterator
12
13
  from datetime import timedelta
13
14
  from typing import Optional
14
15
 
@@ -147,7 +148,7 @@ class TransactionService(BaseGRPCClient):
147
148
  """
148
149
  return self._execute_method("GetTransactionState", request, timeout)
149
150
 
150
- def monitor_transaction_state(self, request: MonitorTransactionStateRequest, timeout: Optional[timedelta] = None):
151
+ def monitor_transaction_state(self, request: MonitorTransactionStateRequest, timeout: Optional[timedelta] = None) -> Iterator[MonitorTransactionStateResponse]:
151
152
  """MonitorTransactionState server-side streaming method with authentication and validation.
152
153
 
153
154
  Args:
@@ -0,0 +1,75 @@
1
+ """Transaction state machine validation and transition logic.
2
+
3
+ This module provides state machine functions for transaction states and actions,
4
+ implementing the transaction lifecycle management logic.
5
+ """
6
+
7
+ from meshtrade.ledger.transaction.v1.transaction_action_pb2 import TransactionAction
8
+ from meshtrade.ledger.transaction.v1.transaction_state_pb2 import TransactionState
9
+
10
+
11
+ def transaction_state_can_perform_action_at_state(state: TransactionState | None, action: TransactionAction | None) -> bool:
12
+ """Check if the given action can be performed at the current transaction state.
13
+
14
+ This implements the state machine logic for transaction lifecycle management.
15
+
16
+ State Transitions:
17
+ - DRAFT -> BUILD/COMMIT -> SIGNING_IN_PROGRESS
18
+ - SIGNING_IN_PROGRESS -> SIGN/MARK_PENDING -> PENDING
19
+ - PENDING -> SUBMIT -> SUBMISSION_IN_PROGRESS
20
+ - SUBMISSION_IN_PROGRESS -> SUBMIT (retry) -> INDETERMINATE or SUCCESS/FAILED
21
+ - INDETERMINATE -> SUBMIT (retry) -> SUCCESS/FAILED
22
+ - FAILED/SUCCESSFUL -> No further actions allowed (terminal states)
23
+
24
+ Args:
25
+ state: The current TransactionState (can be None)
26
+ action: The TransactionAction to perform (can be None)
27
+
28
+ Returns:
29
+ True if the action can be performed at the given state, False otherwise
30
+
31
+ None Safety:
32
+ Returns False if either state or action is None
33
+
34
+ Example:
35
+ >>> transaction_state_can_perform_action_at_state(
36
+ ... TransactionState.TRANSACTION_STATE_DRAFT,
37
+ ... TransactionAction.TRANSACTION_ACTION_BUILD
38
+ ... )
39
+ True
40
+ >>> transaction_state_can_perform_action_at_state(
41
+ ... TransactionState.TRANSACTION_STATE_SUCCESSFUL,
42
+ ... TransactionAction.TRANSACTION_ACTION_SUBMIT
43
+ ... )
44
+ False
45
+ """
46
+ if state is None or action is None:
47
+ return False
48
+
49
+ if state == TransactionState.TRANSACTION_STATE_DRAFT:
50
+ return action in {
51
+ TransactionAction.TRANSACTION_ACTION_BUILD,
52
+ TransactionAction.TRANSACTION_ACTION_COMMIT,
53
+ }
54
+
55
+ elif state == TransactionState.TRANSACTION_STATE_SIGNING_IN_PROGRESS:
56
+ return action in {
57
+ TransactionAction.TRANSACTION_ACTION_SIGN,
58
+ TransactionAction.TRANSACTION_ACTION_MARK_PENDING,
59
+ }
60
+
61
+ elif state in {
62
+ TransactionState.TRANSACTION_STATE_PENDING,
63
+ TransactionState.TRANSACTION_STATE_SUBMISSION_IN_PROGRESS,
64
+ TransactionState.TRANSACTION_STATE_INDETERMINATE,
65
+ }:
66
+ return action == TransactionAction.TRANSACTION_ACTION_SUBMIT
67
+
68
+ elif state in {
69
+ TransactionState.TRANSACTION_STATE_FAILED,
70
+ TransactionState.TRANSACTION_STATE_SUCCESSFUL,
71
+ }:
72
+ return False
73
+
74
+ else:
75
+ return False
@@ -41,6 +41,8 @@ from .service_meshpy import (
41
41
  #
42
42
  # ===================================================================
43
43
 
44
+ from .income_entry import income_narrative_pretty_string
45
+
44
46
  # ===================================================================
45
47
  # MODULE EXPORTS
46
48
  # ===================================================================
@@ -59,4 +61,6 @@ __all__ = [
59
61
  "IncomeEntry",
60
62
  "IncomeNarrative",
61
63
  "TradingStatementEntry",
64
+ # Manual exports
65
+ "income_narrative_pretty_string",
62
66
  ]