From 33ab122c4bf1a6d159bf2e229ebcfcabf2fbb9a0 Mon Sep 17 00:00:00 2001 From: Valerio Versace Date: Thu, 9 May 2019 11:38:00 +0200 Subject: [PATCH] Monorepo first commit Reorganized sdk and cli to be two different packages in the same repository Moved sdk to cli repo Rewrote SDK to match JS SDK implementation --- .gitignore | 26 +-- MANIFEST.in => snet_cli/MANIFEST.in | 0 {docs => snet_cli/docs}/Makefile | 0 {docs => snet_cli/docs}/build-docs.sh | 0 {docs => snet_cli/docs}/source/conf.py | 0 .../docs}/source/generate_rst.py | 0 .../docs}/source/img/singularityNET.png | Bin .../docs}/source/index_template.tpl | 0 .../docs}/source/snet-cli-static/theme.css | 0 .../docs}/source/subcommand_template.tpl | 0 {scripts => snet_cli/scripts}/blockchain | 2 +- {scripts => snet_cli/scripts}/package-pip | 0 setup.py => snet_cli/setup.py | 0 snet_cli/{ => snet_cli}/__init__.py | 0 snet_cli/{ => snet_cli}/_vendor/__init__.py | 0 .../_vendor/ledgerblue/BlueHSMServer_pb2.py | 0 .../_vendor/ledgerblue/Dongle.py | 0 .../_vendor/ledgerblue/__init__.py | 0 .../_vendor/ledgerblue/checkGenuine.py | 0 .../{ => snet_cli}/_vendor/ledgerblue/comm.py | 0 .../_vendor/ledgerblue/commException.py | 0 .../_vendor/ledgerblue/commHTTP.py | 0 .../_vendor/ledgerblue/commU2F.py | 0 .../_vendor/ledgerblue/deleteApp.py | 0 .../_vendor/ledgerblue/deployed.py | 0 .../_vendor/ledgerblue/derivePassphrase.py | 0 .../_vendor/ledgerblue/ecWrapper.py | 0 .../_vendor/ledgerblue/endorsementSetup.py | 0 .../ledgerblue/endorsementSetupLedger.py | 0 .../_vendor/ledgerblue/genCAPair.py | 0 .../_vendor/ledgerblue/getMemInfo.py | 0 .../_vendor/ledgerblue/hashApp.py | 0 .../_vendor/ledgerblue/hexLoader.py | 0 .../_vendor/ledgerblue/hexParser.py | 0 .../_vendor/ledgerblue/hostOnboard.py | 0 .../_vendor/ledgerblue/ledgerWrapper.py | 0 .../_vendor/ledgerblue/listApps.py | 0 .../_vendor/ledgerblue/loadApp.py | 0 .../_vendor/ledgerblue/loadMCU.py | 0 .../_vendor/ledgerblue/mcuBootloader.py | 0 .../_vendor/ledgerblue/resetCustomCA.py | 0 .../_vendor/ledgerblue/runApp.py | 0 .../_vendor/ledgerblue/runScript.py | 0 .../_vendor/ledgerblue/setupCustomCA.py | 0 .../_vendor/ledgerblue/signApp.py | 0 .../_vendor/ledgerblue/updateFirmware.py | 0 .../_vendor/ledgerblue/verifyApp.py | 0 .../_vendor/ledgerblue/verifyEndorsement1.py | 0 .../_vendor/ledgerblue/verifyEndorsement2.py | 0 snet_cli/{ => snet_cli}/arguments.py | 0 snet_cli/{ => snet_cli}/commands.py | 0 snet_cli/{ => snet_cli}/config.py | 0 snet_cli/{ => snet_cli}/contract.py | 0 snet_cli/{ => snet_cli}/identity.py | 0 .../{ => snet_cli}/mpe_account_command.py | 0 .../{ => snet_cli}/mpe_channel_command.py | 0 snet_cli/{ => snet_cli}/mpe_client_command.py | 0 .../{ => snet_cli}/mpe_service_command.py | 0 .../{ => snet_cli}/mpe_service_metadata.py | 0 .../{ => snet_cli}/mpe_treasurer_command.py | 0 .../resources/contracts/placeholder.txt | 0 .../resources/proto/control_service.proto | 0 .../resources/proto/merckledag.proto | 0 .../resources/proto/state_service.proto | 0 .../resources/proto/unixfs.proto | 0 snet_cli/{ => snet_cli}/sdk_command.py | 0 snet_cli/{ => snet_cli}/utils.py | 0 snet_cli/{ => snet_cli}/utils_agi2cogs.py | 0 snet_cli/{ => snet_cli}/utils_config.py | 0 snet_cli/{ => snet_cli}/utils_ipfs.py | 0 snet_cli/{ => snet_cli}/utils_proto.py | 0 snet_cli/{ => snet_cli}/version.py | 0 {test => snet_cli/test}/README.md | 0 .../script10_claim_timeout_all.sh | 0 .../script11_update_metadata.sh | 0 .../script12_extend_add_for_service.sh | 0 .../script13_call_reinitialize.sh | 0 .../functional_tests/script1_twogroups.sh | 0 .../script2_deposit_transfer.sh | 0 .../script3_without_addresses.sh | 0 .../script4_only_with_networks.sh | 0 .../script5_identity1_rpc_mnemonic.sh | 0 .../functional_tests/script6_organization.sh | 0 .../functional_tests/script7_contracts.sh | 0 .../functional_tests/script8_networks.sh | 0 .../functional_tests/script9_treasurer.sh | 0 .../service_spec1/ExampleService.proto | 0 .../simple_daemon/test_simple_daemon.py | 0 .../unit_tests/test_mpe_service_metadata_1.py | 0 .../test}/utils/reset_environment.sh | 0 .../test}/utils/run_all_functional.sh | 0 snet_sdk/LICENSE | 21 +++ snet_sdk/MANIFEST.in | 3 + snet_sdk/README.md | 101 ++++++++++++ snet_sdk/blockchain/package.json | 6 + snet_sdk/scripts/blockchain | 55 +++++++ snet_sdk/scripts/package-pip | 3 + snet_sdk/setup.py | 23 +++ snet_sdk/snet_sdk/__init__.py | 71 ++++++++ snet_sdk/snet_sdk/account.py | 88 ++++++++++ snet_sdk/snet_sdk/contract.py | 27 ++++ .../snet_sdk/generic_client_interceptor.py | 55 +++++++ snet_sdk/snet_sdk/mpe_contract.py | 72 +++++++++ snet_sdk/snet_sdk/payment_channel.py | 54 +++++++ .../__init__.py | 0 .../default.py | 45 ++++++ .../resources/contracts/placeholder.txt | 0 snet_sdk/snet_sdk/service_client.py | 127 +++++++++++++++ snet_sdk/snet_sdk/state_service_pb2.py | 153 ++++++++++++++++++ snet_sdk/snet_sdk/state_service_pb2_grpc.py | 54 +++++++ snet_sdk/snet_sdk/utils.py | 41 +++++ 111 files changed, 1017 insertions(+), 10 deletions(-) rename MANIFEST.in => snet_cli/MANIFEST.in (100%) rename {docs => snet_cli/docs}/Makefile (100%) rename {docs => snet_cli/docs}/build-docs.sh (100%) rename {docs => snet_cli/docs}/source/conf.py (100%) rename {docs => snet_cli/docs}/source/generate_rst.py (100%) rename {docs => snet_cli/docs}/source/img/singularityNET.png (100%) rename {docs => snet_cli/docs}/source/index_template.tpl (100%) rename {docs => snet_cli/docs}/source/snet-cli-static/theme.css (100%) rename {docs => snet_cli/docs}/source/subcommand_template.tpl (100%) rename {scripts => snet_cli/scripts}/blockchain (98%) rename {scripts => snet_cli/scripts}/package-pip (100%) rename setup.py => snet_cli/setup.py (100%) rename snet_cli/{ => snet_cli}/__init__.py (100%) rename snet_cli/{ => snet_cli}/_vendor/__init__.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/BlueHSMServer_pb2.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/Dongle.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/__init__.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/checkGenuine.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/comm.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/commException.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/commHTTP.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/commU2F.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/deleteApp.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/deployed.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/derivePassphrase.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/ecWrapper.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/endorsementSetup.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/endorsementSetupLedger.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/genCAPair.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/getMemInfo.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/hashApp.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/hexLoader.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/hexParser.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/hostOnboard.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/ledgerWrapper.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/listApps.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/loadApp.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/loadMCU.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/mcuBootloader.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/resetCustomCA.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/runApp.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/runScript.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/setupCustomCA.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/signApp.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/updateFirmware.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/verifyApp.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/verifyEndorsement1.py (100%) rename snet_cli/{ => snet_cli}/_vendor/ledgerblue/verifyEndorsement2.py (100%) rename snet_cli/{ => snet_cli}/arguments.py (100%) rename snet_cli/{ => snet_cli}/commands.py (100%) rename snet_cli/{ => snet_cli}/config.py (100%) rename snet_cli/{ => snet_cli}/contract.py (100%) rename snet_cli/{ => snet_cli}/identity.py (100%) rename snet_cli/{ => snet_cli}/mpe_account_command.py (100%) rename snet_cli/{ => snet_cli}/mpe_channel_command.py (100%) rename snet_cli/{ => snet_cli}/mpe_client_command.py (100%) rename snet_cli/{ => snet_cli}/mpe_service_command.py (100%) rename snet_cli/{ => snet_cli}/mpe_service_metadata.py (100%) rename snet_cli/{ => snet_cli}/mpe_treasurer_command.py (100%) rename snet_cli/{ => snet_cli}/resources/contracts/placeholder.txt (100%) rename snet_cli/{ => snet_cli}/resources/proto/control_service.proto (100%) rename snet_cli/{ => snet_cli}/resources/proto/merckledag.proto (100%) rename snet_cli/{ => snet_cli}/resources/proto/state_service.proto (100%) rename snet_cli/{ => snet_cli}/resources/proto/unixfs.proto (100%) rename snet_cli/{ => snet_cli}/sdk_command.py (100%) rename snet_cli/{ => snet_cli}/utils.py (100%) rename snet_cli/{ => snet_cli}/utils_agi2cogs.py (100%) rename snet_cli/{ => snet_cli}/utils_config.py (100%) rename snet_cli/{ => snet_cli}/utils_ipfs.py (100%) rename snet_cli/{ => snet_cli}/utils_proto.py (100%) rename snet_cli/{ => snet_cli}/version.py (100%) rename {test => snet_cli/test}/README.md (100%) rename {test => snet_cli/test}/functional_tests/script10_claim_timeout_all.sh (100%) rename {test => snet_cli/test}/functional_tests/script11_update_metadata.sh (100%) rename {test => snet_cli/test}/functional_tests/script12_extend_add_for_service.sh (100%) rename {test => snet_cli/test}/functional_tests/script13_call_reinitialize.sh (100%) rename {test => snet_cli/test}/functional_tests/script1_twogroups.sh (100%) rename {test => snet_cli/test}/functional_tests/script2_deposit_transfer.sh (100%) rename {test => snet_cli/test}/functional_tests/script3_without_addresses.sh (100%) rename {test => snet_cli/test}/functional_tests/script4_only_with_networks.sh (100%) rename {test => snet_cli/test}/functional_tests/script5_identity1_rpc_mnemonic.sh (100%) rename {test => snet_cli/test}/functional_tests/script6_organization.sh (100%) rename {test => snet_cli/test}/functional_tests/script7_contracts.sh (100%) rename {test => snet_cli/test}/functional_tests/script8_networks.sh (100%) rename {test => snet_cli/test}/functional_tests/script9_treasurer.sh (100%) rename {test => snet_cli/test}/functional_tests/service_spec1/ExampleService.proto (100%) rename {test => snet_cli/test}/functional_tests/simple_daemon/test_simple_daemon.py (100%) rename {test => snet_cli/test}/unit_tests/test_mpe_service_metadata_1.py (100%) rename {test => snet_cli/test}/utils/reset_environment.sh (100%) rename {test => snet_cli/test}/utils/run_all_functional.sh (100%) create mode 100644 snet_sdk/LICENSE create mode 100644 snet_sdk/MANIFEST.in create mode 100644 snet_sdk/README.md create mode 100644 snet_sdk/blockchain/package.json create mode 100755 snet_sdk/scripts/blockchain create mode 100755 snet_sdk/scripts/package-pip create mode 100644 snet_sdk/setup.py create mode 100644 snet_sdk/snet_sdk/__init__.py create mode 100644 snet_sdk/snet_sdk/account.py create mode 100644 snet_sdk/snet_sdk/contract.py create mode 100644 snet_sdk/snet_sdk/generic_client_interceptor.py create mode 100644 snet_sdk/snet_sdk/mpe_contract.py create mode 100644 snet_sdk/snet_sdk/payment_channel.py create mode 100644 snet_sdk/snet_sdk/payment_channel_management_strategies/__init__.py create mode 100644 snet_sdk/snet_sdk/payment_channel_management_strategies/default.py create mode 100644 snet_sdk/snet_sdk/resources/contracts/placeholder.txt create mode 100644 snet_sdk/snet_sdk/service_client.py create mode 100644 snet_sdk/snet_sdk/state_service_pb2.py create mode 100644 snet_sdk/snet_sdk/state_service_pb2_grpc.py create mode 100644 snet_sdk/snet_sdk/utils.py diff --git a/.gitignore b/.gitignore index 0e0157d0..ba0a07e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,19 @@ -venv/ -.idea/ -snet_cli.egg-info/ blockchain/node_modules/ __pycache__/ -snet_cli/resources/contracts/abi -snet_cli/resources/contracts/networks -snet_cli/resources/proto/*.py -build/ -dist/ -client_libraries/ + +snet_cli/venv/ +.idea/ +snet_cli/snet_cli.egg-info/ +snet_cli/snet_cli/resources/contracts/abi +snet_cli/snet_cli/resources/contracts/networks +snet_cli/snet_cli/resources/proto/*.py +snet_cli/build/ +snet_cli/dist/ + +snet_sdk/venv/ +snet_sdk/snet_sdk.egg-info/ +__pycache__ +snet_sdk/snet_sdk/resources/contracts/abi +snet_sdk/snet_sdk/resources/contracts/networks +snet_sdk/build/ +snet_sdk/dist/ diff --git a/MANIFEST.in b/snet_cli/MANIFEST.in similarity index 100% rename from MANIFEST.in rename to snet_cli/MANIFEST.in diff --git a/docs/Makefile b/snet_cli/docs/Makefile similarity index 100% rename from docs/Makefile rename to snet_cli/docs/Makefile diff --git a/docs/build-docs.sh b/snet_cli/docs/build-docs.sh similarity index 100% rename from docs/build-docs.sh rename to snet_cli/docs/build-docs.sh diff --git a/docs/source/conf.py b/snet_cli/docs/source/conf.py similarity index 100% rename from docs/source/conf.py rename to snet_cli/docs/source/conf.py diff --git a/docs/source/generate_rst.py b/snet_cli/docs/source/generate_rst.py similarity index 100% rename from docs/source/generate_rst.py rename to snet_cli/docs/source/generate_rst.py diff --git a/docs/source/img/singularityNET.png b/snet_cli/docs/source/img/singularityNET.png similarity index 100% rename from docs/source/img/singularityNET.png rename to snet_cli/docs/source/img/singularityNET.png diff --git a/docs/source/index_template.tpl b/snet_cli/docs/source/index_template.tpl similarity index 100% rename from docs/source/index_template.tpl rename to snet_cli/docs/source/index_template.tpl diff --git a/docs/source/snet-cli-static/theme.css b/snet_cli/docs/source/snet-cli-static/theme.css similarity index 100% rename from docs/source/snet-cli-static/theme.css rename to snet_cli/docs/source/snet-cli-static/theme.css diff --git a/docs/source/subcommand_template.tpl b/snet_cli/docs/source/subcommand_template.tpl similarity index 100% rename from docs/source/subcommand_template.tpl rename to snet_cli/docs/source/subcommand_template.tpl diff --git a/scripts/blockchain b/snet_cli/scripts/blockchain similarity index 98% rename from scripts/blockchain rename to snet_cli/scripts/blockchain index e943b8cf..4edb62ef 100755 --- a/scripts/blockchain +++ b/snet_cli/scripts/blockchain @@ -10,7 +10,7 @@ import sys def main(): assert len(sys.argv) > 1, "please select a target from 'install', 'uninstall'" target = sys.argv[1] - blockchain_dir = pathlib.Path(__file__).absolute().parent.parent.joinpath("blockchain") + blockchain_dir = pathlib.Path(__file__).absolute().parent.parent.parent.joinpath("blockchain") node_modules_dir = blockchain_dir.joinpath("node_modules") platform_json_src_dir = node_modules_dir.joinpath("singularitynet-platform-contracts") token_json_src_dir = node_modules_dir.joinpath("singularitynet-token-contracts") diff --git a/scripts/package-pip b/snet_cli/scripts/package-pip similarity index 100% rename from scripts/package-pip rename to snet_cli/scripts/package-pip diff --git a/setup.py b/snet_cli/setup.py similarity index 100% rename from setup.py rename to snet_cli/setup.py diff --git a/snet_cli/__init__.py b/snet_cli/snet_cli/__init__.py similarity index 100% rename from snet_cli/__init__.py rename to snet_cli/snet_cli/__init__.py diff --git a/snet_cli/_vendor/__init__.py b/snet_cli/snet_cli/_vendor/__init__.py similarity index 100% rename from snet_cli/_vendor/__init__.py rename to snet_cli/snet_cli/_vendor/__init__.py diff --git a/snet_cli/_vendor/ledgerblue/BlueHSMServer_pb2.py b/snet_cli/snet_cli/_vendor/ledgerblue/BlueHSMServer_pb2.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/BlueHSMServer_pb2.py rename to snet_cli/snet_cli/_vendor/ledgerblue/BlueHSMServer_pb2.py diff --git a/snet_cli/_vendor/ledgerblue/Dongle.py b/snet_cli/snet_cli/_vendor/ledgerblue/Dongle.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/Dongle.py rename to snet_cli/snet_cli/_vendor/ledgerblue/Dongle.py diff --git a/snet_cli/_vendor/ledgerblue/__init__.py b/snet_cli/snet_cli/_vendor/ledgerblue/__init__.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/__init__.py rename to snet_cli/snet_cli/_vendor/ledgerblue/__init__.py diff --git a/snet_cli/_vendor/ledgerblue/checkGenuine.py b/snet_cli/snet_cli/_vendor/ledgerblue/checkGenuine.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/checkGenuine.py rename to snet_cli/snet_cli/_vendor/ledgerblue/checkGenuine.py diff --git a/snet_cli/_vendor/ledgerblue/comm.py b/snet_cli/snet_cli/_vendor/ledgerblue/comm.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/comm.py rename to snet_cli/snet_cli/_vendor/ledgerblue/comm.py diff --git a/snet_cli/_vendor/ledgerblue/commException.py b/snet_cli/snet_cli/_vendor/ledgerblue/commException.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/commException.py rename to snet_cli/snet_cli/_vendor/ledgerblue/commException.py diff --git a/snet_cli/_vendor/ledgerblue/commHTTP.py b/snet_cli/snet_cli/_vendor/ledgerblue/commHTTP.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/commHTTP.py rename to snet_cli/snet_cli/_vendor/ledgerblue/commHTTP.py diff --git a/snet_cli/_vendor/ledgerblue/commU2F.py b/snet_cli/snet_cli/_vendor/ledgerblue/commU2F.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/commU2F.py rename to snet_cli/snet_cli/_vendor/ledgerblue/commU2F.py diff --git a/snet_cli/_vendor/ledgerblue/deleteApp.py b/snet_cli/snet_cli/_vendor/ledgerblue/deleteApp.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/deleteApp.py rename to snet_cli/snet_cli/_vendor/ledgerblue/deleteApp.py diff --git a/snet_cli/_vendor/ledgerblue/deployed.py b/snet_cli/snet_cli/_vendor/ledgerblue/deployed.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/deployed.py rename to snet_cli/snet_cli/_vendor/ledgerblue/deployed.py diff --git a/snet_cli/_vendor/ledgerblue/derivePassphrase.py b/snet_cli/snet_cli/_vendor/ledgerblue/derivePassphrase.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/derivePassphrase.py rename to snet_cli/snet_cli/_vendor/ledgerblue/derivePassphrase.py diff --git a/snet_cli/_vendor/ledgerblue/ecWrapper.py b/snet_cli/snet_cli/_vendor/ledgerblue/ecWrapper.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/ecWrapper.py rename to snet_cli/snet_cli/_vendor/ledgerblue/ecWrapper.py diff --git a/snet_cli/_vendor/ledgerblue/endorsementSetup.py b/snet_cli/snet_cli/_vendor/ledgerblue/endorsementSetup.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/endorsementSetup.py rename to snet_cli/snet_cli/_vendor/ledgerblue/endorsementSetup.py diff --git a/snet_cli/_vendor/ledgerblue/endorsementSetupLedger.py b/snet_cli/snet_cli/_vendor/ledgerblue/endorsementSetupLedger.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/endorsementSetupLedger.py rename to snet_cli/snet_cli/_vendor/ledgerblue/endorsementSetupLedger.py diff --git a/snet_cli/_vendor/ledgerblue/genCAPair.py b/snet_cli/snet_cli/_vendor/ledgerblue/genCAPair.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/genCAPair.py rename to snet_cli/snet_cli/_vendor/ledgerblue/genCAPair.py diff --git a/snet_cli/_vendor/ledgerblue/getMemInfo.py b/snet_cli/snet_cli/_vendor/ledgerblue/getMemInfo.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/getMemInfo.py rename to snet_cli/snet_cli/_vendor/ledgerblue/getMemInfo.py diff --git a/snet_cli/_vendor/ledgerblue/hashApp.py b/snet_cli/snet_cli/_vendor/ledgerblue/hashApp.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/hashApp.py rename to snet_cli/snet_cli/_vendor/ledgerblue/hashApp.py diff --git a/snet_cli/_vendor/ledgerblue/hexLoader.py b/snet_cli/snet_cli/_vendor/ledgerblue/hexLoader.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/hexLoader.py rename to snet_cli/snet_cli/_vendor/ledgerblue/hexLoader.py diff --git a/snet_cli/_vendor/ledgerblue/hexParser.py b/snet_cli/snet_cli/_vendor/ledgerblue/hexParser.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/hexParser.py rename to snet_cli/snet_cli/_vendor/ledgerblue/hexParser.py diff --git a/snet_cli/_vendor/ledgerblue/hostOnboard.py b/snet_cli/snet_cli/_vendor/ledgerblue/hostOnboard.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/hostOnboard.py rename to snet_cli/snet_cli/_vendor/ledgerblue/hostOnboard.py diff --git a/snet_cli/_vendor/ledgerblue/ledgerWrapper.py b/snet_cli/snet_cli/_vendor/ledgerblue/ledgerWrapper.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/ledgerWrapper.py rename to snet_cli/snet_cli/_vendor/ledgerblue/ledgerWrapper.py diff --git a/snet_cli/_vendor/ledgerblue/listApps.py b/snet_cli/snet_cli/_vendor/ledgerblue/listApps.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/listApps.py rename to snet_cli/snet_cli/_vendor/ledgerblue/listApps.py diff --git a/snet_cli/_vendor/ledgerblue/loadApp.py b/snet_cli/snet_cli/_vendor/ledgerblue/loadApp.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/loadApp.py rename to snet_cli/snet_cli/_vendor/ledgerblue/loadApp.py diff --git a/snet_cli/_vendor/ledgerblue/loadMCU.py b/snet_cli/snet_cli/_vendor/ledgerblue/loadMCU.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/loadMCU.py rename to snet_cli/snet_cli/_vendor/ledgerblue/loadMCU.py diff --git a/snet_cli/_vendor/ledgerblue/mcuBootloader.py b/snet_cli/snet_cli/_vendor/ledgerblue/mcuBootloader.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/mcuBootloader.py rename to snet_cli/snet_cli/_vendor/ledgerblue/mcuBootloader.py diff --git a/snet_cli/_vendor/ledgerblue/resetCustomCA.py b/snet_cli/snet_cli/_vendor/ledgerblue/resetCustomCA.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/resetCustomCA.py rename to snet_cli/snet_cli/_vendor/ledgerblue/resetCustomCA.py diff --git a/snet_cli/_vendor/ledgerblue/runApp.py b/snet_cli/snet_cli/_vendor/ledgerblue/runApp.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/runApp.py rename to snet_cli/snet_cli/_vendor/ledgerblue/runApp.py diff --git a/snet_cli/_vendor/ledgerblue/runScript.py b/snet_cli/snet_cli/_vendor/ledgerblue/runScript.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/runScript.py rename to snet_cli/snet_cli/_vendor/ledgerblue/runScript.py diff --git a/snet_cli/_vendor/ledgerblue/setupCustomCA.py b/snet_cli/snet_cli/_vendor/ledgerblue/setupCustomCA.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/setupCustomCA.py rename to snet_cli/snet_cli/_vendor/ledgerblue/setupCustomCA.py diff --git a/snet_cli/_vendor/ledgerblue/signApp.py b/snet_cli/snet_cli/_vendor/ledgerblue/signApp.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/signApp.py rename to snet_cli/snet_cli/_vendor/ledgerblue/signApp.py diff --git a/snet_cli/_vendor/ledgerblue/updateFirmware.py b/snet_cli/snet_cli/_vendor/ledgerblue/updateFirmware.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/updateFirmware.py rename to snet_cli/snet_cli/_vendor/ledgerblue/updateFirmware.py diff --git a/snet_cli/_vendor/ledgerblue/verifyApp.py b/snet_cli/snet_cli/_vendor/ledgerblue/verifyApp.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/verifyApp.py rename to snet_cli/snet_cli/_vendor/ledgerblue/verifyApp.py diff --git a/snet_cli/_vendor/ledgerblue/verifyEndorsement1.py b/snet_cli/snet_cli/_vendor/ledgerblue/verifyEndorsement1.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/verifyEndorsement1.py rename to snet_cli/snet_cli/_vendor/ledgerblue/verifyEndorsement1.py diff --git a/snet_cli/_vendor/ledgerblue/verifyEndorsement2.py b/snet_cli/snet_cli/_vendor/ledgerblue/verifyEndorsement2.py similarity index 100% rename from snet_cli/_vendor/ledgerblue/verifyEndorsement2.py rename to snet_cli/snet_cli/_vendor/ledgerblue/verifyEndorsement2.py diff --git a/snet_cli/arguments.py b/snet_cli/snet_cli/arguments.py similarity index 100% rename from snet_cli/arguments.py rename to snet_cli/snet_cli/arguments.py diff --git a/snet_cli/commands.py b/snet_cli/snet_cli/commands.py similarity index 100% rename from snet_cli/commands.py rename to snet_cli/snet_cli/commands.py diff --git a/snet_cli/config.py b/snet_cli/snet_cli/config.py similarity index 100% rename from snet_cli/config.py rename to snet_cli/snet_cli/config.py diff --git a/snet_cli/contract.py b/snet_cli/snet_cli/contract.py similarity index 100% rename from snet_cli/contract.py rename to snet_cli/snet_cli/contract.py diff --git a/snet_cli/identity.py b/snet_cli/snet_cli/identity.py similarity index 100% rename from snet_cli/identity.py rename to snet_cli/snet_cli/identity.py diff --git a/snet_cli/mpe_account_command.py b/snet_cli/snet_cli/mpe_account_command.py similarity index 100% rename from snet_cli/mpe_account_command.py rename to snet_cli/snet_cli/mpe_account_command.py diff --git a/snet_cli/mpe_channel_command.py b/snet_cli/snet_cli/mpe_channel_command.py similarity index 100% rename from snet_cli/mpe_channel_command.py rename to snet_cli/snet_cli/mpe_channel_command.py diff --git a/snet_cli/mpe_client_command.py b/snet_cli/snet_cli/mpe_client_command.py similarity index 100% rename from snet_cli/mpe_client_command.py rename to snet_cli/snet_cli/mpe_client_command.py diff --git a/snet_cli/mpe_service_command.py b/snet_cli/snet_cli/mpe_service_command.py similarity index 100% rename from snet_cli/mpe_service_command.py rename to snet_cli/snet_cli/mpe_service_command.py diff --git a/snet_cli/mpe_service_metadata.py b/snet_cli/snet_cli/mpe_service_metadata.py similarity index 100% rename from snet_cli/mpe_service_metadata.py rename to snet_cli/snet_cli/mpe_service_metadata.py diff --git a/snet_cli/mpe_treasurer_command.py b/snet_cli/snet_cli/mpe_treasurer_command.py similarity index 100% rename from snet_cli/mpe_treasurer_command.py rename to snet_cli/snet_cli/mpe_treasurer_command.py diff --git a/snet_cli/resources/contracts/placeholder.txt b/snet_cli/snet_cli/resources/contracts/placeholder.txt similarity index 100% rename from snet_cli/resources/contracts/placeholder.txt rename to snet_cli/snet_cli/resources/contracts/placeholder.txt diff --git a/snet_cli/resources/proto/control_service.proto b/snet_cli/snet_cli/resources/proto/control_service.proto similarity index 100% rename from snet_cli/resources/proto/control_service.proto rename to snet_cli/snet_cli/resources/proto/control_service.proto diff --git a/snet_cli/resources/proto/merckledag.proto b/snet_cli/snet_cli/resources/proto/merckledag.proto similarity index 100% rename from snet_cli/resources/proto/merckledag.proto rename to snet_cli/snet_cli/resources/proto/merckledag.proto diff --git a/snet_cli/resources/proto/state_service.proto b/snet_cli/snet_cli/resources/proto/state_service.proto similarity index 100% rename from snet_cli/resources/proto/state_service.proto rename to snet_cli/snet_cli/resources/proto/state_service.proto diff --git a/snet_cli/resources/proto/unixfs.proto b/snet_cli/snet_cli/resources/proto/unixfs.proto similarity index 100% rename from snet_cli/resources/proto/unixfs.proto rename to snet_cli/snet_cli/resources/proto/unixfs.proto diff --git a/snet_cli/sdk_command.py b/snet_cli/snet_cli/sdk_command.py similarity index 100% rename from snet_cli/sdk_command.py rename to snet_cli/snet_cli/sdk_command.py diff --git a/snet_cli/utils.py b/snet_cli/snet_cli/utils.py similarity index 100% rename from snet_cli/utils.py rename to snet_cli/snet_cli/utils.py diff --git a/snet_cli/utils_agi2cogs.py b/snet_cli/snet_cli/utils_agi2cogs.py similarity index 100% rename from snet_cli/utils_agi2cogs.py rename to snet_cli/snet_cli/utils_agi2cogs.py diff --git a/snet_cli/utils_config.py b/snet_cli/snet_cli/utils_config.py similarity index 100% rename from snet_cli/utils_config.py rename to snet_cli/snet_cli/utils_config.py diff --git a/snet_cli/utils_ipfs.py b/snet_cli/snet_cli/utils_ipfs.py similarity index 100% rename from snet_cli/utils_ipfs.py rename to snet_cli/snet_cli/utils_ipfs.py diff --git a/snet_cli/utils_proto.py b/snet_cli/snet_cli/utils_proto.py similarity index 100% rename from snet_cli/utils_proto.py rename to snet_cli/snet_cli/utils_proto.py diff --git a/snet_cli/version.py b/snet_cli/snet_cli/version.py similarity index 100% rename from snet_cli/version.py rename to snet_cli/snet_cli/version.py diff --git a/test/README.md b/snet_cli/test/README.md similarity index 100% rename from test/README.md rename to snet_cli/test/README.md diff --git a/test/functional_tests/script10_claim_timeout_all.sh b/snet_cli/test/functional_tests/script10_claim_timeout_all.sh similarity index 100% rename from test/functional_tests/script10_claim_timeout_all.sh rename to snet_cli/test/functional_tests/script10_claim_timeout_all.sh diff --git a/test/functional_tests/script11_update_metadata.sh b/snet_cli/test/functional_tests/script11_update_metadata.sh similarity index 100% rename from test/functional_tests/script11_update_metadata.sh rename to snet_cli/test/functional_tests/script11_update_metadata.sh diff --git a/test/functional_tests/script12_extend_add_for_service.sh b/snet_cli/test/functional_tests/script12_extend_add_for_service.sh similarity index 100% rename from test/functional_tests/script12_extend_add_for_service.sh rename to snet_cli/test/functional_tests/script12_extend_add_for_service.sh diff --git a/test/functional_tests/script13_call_reinitialize.sh b/snet_cli/test/functional_tests/script13_call_reinitialize.sh similarity index 100% rename from test/functional_tests/script13_call_reinitialize.sh rename to snet_cli/test/functional_tests/script13_call_reinitialize.sh diff --git a/test/functional_tests/script1_twogroups.sh b/snet_cli/test/functional_tests/script1_twogroups.sh similarity index 100% rename from test/functional_tests/script1_twogroups.sh rename to snet_cli/test/functional_tests/script1_twogroups.sh diff --git a/test/functional_tests/script2_deposit_transfer.sh b/snet_cli/test/functional_tests/script2_deposit_transfer.sh similarity index 100% rename from test/functional_tests/script2_deposit_transfer.sh rename to snet_cli/test/functional_tests/script2_deposit_transfer.sh diff --git a/test/functional_tests/script3_without_addresses.sh b/snet_cli/test/functional_tests/script3_without_addresses.sh similarity index 100% rename from test/functional_tests/script3_without_addresses.sh rename to snet_cli/test/functional_tests/script3_without_addresses.sh diff --git a/test/functional_tests/script4_only_with_networks.sh b/snet_cli/test/functional_tests/script4_only_with_networks.sh similarity index 100% rename from test/functional_tests/script4_only_with_networks.sh rename to snet_cli/test/functional_tests/script4_only_with_networks.sh diff --git a/test/functional_tests/script5_identity1_rpc_mnemonic.sh b/snet_cli/test/functional_tests/script5_identity1_rpc_mnemonic.sh similarity index 100% rename from test/functional_tests/script5_identity1_rpc_mnemonic.sh rename to snet_cli/test/functional_tests/script5_identity1_rpc_mnemonic.sh diff --git a/test/functional_tests/script6_organization.sh b/snet_cli/test/functional_tests/script6_organization.sh similarity index 100% rename from test/functional_tests/script6_organization.sh rename to snet_cli/test/functional_tests/script6_organization.sh diff --git a/test/functional_tests/script7_contracts.sh b/snet_cli/test/functional_tests/script7_contracts.sh similarity index 100% rename from test/functional_tests/script7_contracts.sh rename to snet_cli/test/functional_tests/script7_contracts.sh diff --git a/test/functional_tests/script8_networks.sh b/snet_cli/test/functional_tests/script8_networks.sh similarity index 100% rename from test/functional_tests/script8_networks.sh rename to snet_cli/test/functional_tests/script8_networks.sh diff --git a/test/functional_tests/script9_treasurer.sh b/snet_cli/test/functional_tests/script9_treasurer.sh similarity index 100% rename from test/functional_tests/script9_treasurer.sh rename to snet_cli/test/functional_tests/script9_treasurer.sh diff --git a/test/functional_tests/service_spec1/ExampleService.proto b/snet_cli/test/functional_tests/service_spec1/ExampleService.proto similarity index 100% rename from test/functional_tests/service_spec1/ExampleService.proto rename to snet_cli/test/functional_tests/service_spec1/ExampleService.proto diff --git a/test/functional_tests/simple_daemon/test_simple_daemon.py b/snet_cli/test/functional_tests/simple_daemon/test_simple_daemon.py similarity index 100% rename from test/functional_tests/simple_daemon/test_simple_daemon.py rename to snet_cli/test/functional_tests/simple_daemon/test_simple_daemon.py diff --git a/test/unit_tests/test_mpe_service_metadata_1.py b/snet_cli/test/unit_tests/test_mpe_service_metadata_1.py similarity index 100% rename from test/unit_tests/test_mpe_service_metadata_1.py rename to snet_cli/test/unit_tests/test_mpe_service_metadata_1.py diff --git a/test/utils/reset_environment.sh b/snet_cli/test/utils/reset_environment.sh similarity index 100% rename from test/utils/reset_environment.sh rename to snet_cli/test/utils/reset_environment.sh diff --git a/test/utils/run_all_functional.sh b/snet_cli/test/utils/run_all_functional.sh similarity index 100% rename from test/utils/run_all_functional.sh rename to snet_cli/test/utils/run_all_functional.sh diff --git a/snet_sdk/LICENSE b/snet_sdk/LICENSE new file mode 100644 index 00000000..c674cd51 --- /dev/null +++ b/snet_sdk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 SingularityNET + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/snet_sdk/MANIFEST.in b/snet_sdk/MANIFEST.in new file mode 100644 index 00000000..5f2a16ee --- /dev/null +++ b/snet_sdk/MANIFEST.in @@ -0,0 +1,3 @@ +include snet_sdk/resources/proto/* +include snet_sdk/resources/contracts/abi/* +include snet_sdk/resources/contracts/networks/* diff --git a/snet_sdk/README.md b/snet_sdk/README.md new file mode 100644 index 00000000..4d2cb275 --- /dev/null +++ b/snet_sdk/README.md @@ -0,0 +1,101 @@ +# snet-sdk-python + +SingularityNET SDK for Python + +## Getting Started + +These instructions are for the development and use of the SingularityNET SDK for Python. + +### Usage + +The SingularityNET SDK allows you to import compiled client libraries for your service or services or choice and make calls to those services programmatically from your application by setting up state channels with the providers of those services and making gRPC calls to the SingularityNET daemons for those services by selecting a channel with sufficient funding and supplying the appropriate metadata for authentication. + +Once you have installed the snet-sdk in your current environment and it's in your PYTHONPATH, you should import it and create an instance of the base sdk class: + +```python +from snet_sdk import Snet +import config +snet = Snet(private_key=config.private_key) +``` + +Now, the instance of the sdk can be used to instantiate clients for SingularityNET services. To interact with those services, the sdk needs to be supplied the compiled client libraries and a reference to their path on your file system. + +To generate the client libraries, you need the SingularityNET Command Line Interface, or CLI, which you can download from PyPi, see [https://github.com/singnet/snet-cli#installing-with-pip](https://github.com/singnet/snet-cli#installing-with-pip) + +Once you have the CLI installed, run the following command: +```bash +snet sdk generate-client-library python +``` + +Optionally, you can specify an output path; otherwise it's going to be `./client_libraries/python//` + +Now, by default the sdk is going to look for those client libraries in the `./grpc//` in the directory of the main process of the module it's being imported by. + +Once you have the generated client libraries in place, you can create an instance of a SingularityNET service client: +```python +client = snet.client("", "") +``` + +The client exposes the following properties and methods: +- All of the modules from the generated client library as `client.grpc. 1, "please select a target from 'install', 'uninstall'" + target = sys.argv[1] + blockchain_dir = pathlib.Path(__file__).absolute().parent.parent.parent.joinpath("blockchain") + node_modules_dir = blockchain_dir.joinpath("node_modules") + platform_json_src_dir = node_modules_dir.joinpath("singularitynet-platform-contracts") + token_json_src_dir = node_modules_dir.joinpath("singularitynet-token-contracts") + token_contract_name = "SingularityNetToken" + contract_json_dest_dir = pathlib.Path(__file__).absolute().parent.parent.joinpath("snet_sdk", "resources", "contracts") + abi_contract_names = ["Registry", "MultiPartyEscrow"] + networks_contract_names = ["Registry", "MultiPartyEscrow"] + + npm_location = shutil.which('npm') + if not npm_location: + raise Exception("This script requires 'npm' to be installed and in your PATH") + + if target == "install": + shutil.rmtree(contract_json_dest_dir) + + subprocess.call([npm_location, "install"], cwd=blockchain_dir) + + os.makedirs(contract_json_dest_dir.joinpath("abi"), exist_ok=True) + os.makedirs(contract_json_dest_dir.joinpath("networks"), exist_ok=True) + + for contract_name in abi_contract_names: + shutil.copy(platform_json_src_dir.joinpath("abi", "{}.json".format(contract_name)), + contract_json_dest_dir.joinpath("abi", "{}.json".format(contract_name))) + for contract_name in networks_contract_names: + shutil.copy(platform_json_src_dir.joinpath("networks", "{}.json".format(contract_name)), + contract_json_dest_dir.joinpath("networks", "{}.json".format(contract_name))) + + shutil.copy(token_json_src_dir.joinpath("abi", "{}.json".format(token_contract_name)), + contract_json_dest_dir.joinpath("abi", "{}.json".format(token_contract_name))) + shutil.copy(token_json_src_dir.joinpath("networks", "{}.json".format(token_contract_name)), + contract_json_dest_dir.joinpath("networks", "{}.json".format(token_contract_name))) + elif target == "uninstall": + try: + shutil.rmtree(node_modules_dir) + shutil.rmtree(contract_json_dest_dir.joinpath("abi")) + shutil.rmtree(contract_json_dest_dir.joinpath("networks")) + except FileNotFoundError: + pass + + +if __name__ == "__main__": + main() diff --git a/snet_sdk/scripts/package-pip b/snet_sdk/scripts/package-pip new file mode 100755 index 00000000..4dda00f6 --- /dev/null +++ b/snet_sdk/scripts/package-pip @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +python3.6 setup.py sdist bdist_wheel diff --git a/snet_sdk/setup.py b/snet_sdk/setup.py new file mode 100644 index 00000000..6e0530ff --- /dev/null +++ b/snet_sdk/setup.py @@ -0,0 +1,23 @@ +from setuptools import setup, find_packages +import re + +with open('snet_sdk/__init__.py', 'rt', encoding='utf8') as f: + version = re.search(r'__version__ = "(.*?)"', f.read()).group(1) + +setup( + name='snet_sdk', + version=version, + packages=find_packages(), + url='https://github.com/singnet/snet-sdk-python', + license='MIT', + author='SingularityNET Foundation', + author_email='info@singularitynet.io', + description='SingularityNET Python SDK', + install_requires=[ + 'grpcio-tools==1.17.1', + 'ecdsa==0.13', + 'web3==4.2.1', + 'ipfsapi==0.4.2.post1', + 'rfc3986==1.1.0' + ] +) diff --git a/snet_sdk/snet_sdk/__init__.py b/snet_sdk/snet_sdk/__init__.py new file mode 100644 index 00000000..f1b69224 --- /dev/null +++ b/snet_sdk/snet_sdk/__init__.py @@ -0,0 +1,71 @@ +import operator +from functools import reduce +import sys +import os +import importlib +import json +import base64 +from pathlib import PurePath, Path +from urllib.parse import urljoin + +import hashlib +import collections +import web3 +from web3.gas_strategies.rpc import rpc_gas_price_strategy +from eth_account.messages import defunct_hash_message +from rfc3986 import urlparse +import ipfsapi +from web3.utils.datastructures import AttributeDict, MutableAttributeDict + +import snet_sdk.generic_client_interceptor as generic_client_interceptor + +from snet_sdk.utils import get_contract_object +from snet_sdk.service_client import ServiceClient +from snet_sdk.account import Account +from snet_sdk.mpe_contract import MPEContract +from snet_sdk.payment_channel_management_strategies.default import PaymentChannelManagementStrategy + +__version__ = "0.0.1" + + +class SnetSDK: + """Base Snet SDK""" + def __init__( + self, + config + ): + self._config = config + + # Instantiate Ethereum client + eth_rpc_endpoint = self._config.get("eth_rpc_endpoint", "https://mainnet.infura.io") + provider = web3.HTTPProvider(eth_rpc_endpoint) + self.web3 = web3.Web3(provider) + self.web3.eth.setGasPriceStrategy(rpc_gas_price_strategy) + + self.mpe_contract = MPEContract(self.web3) + + # Instantiate IPFS client + ipfs_rpc_endpoint = self._config.get("ipfs_rpc_endpoint", "https://ipfs.singularitynet.io:80") + ipfs_rpc_endpoint = urlparse(ipfs_rpc_endpoint) + ipfs_scheme = ipfs_rpc_endpoint.scheme if ipfs_rpc_endpoint.scheme else "http" + ipfs_port = ipfs_rpc_endpoint.port if ipfs_rpc_endpoint.port else 5001 + self.ipfs_client = ipfsapi.connect(urljoin(ipfs_scheme, ipfs_rpc_endpoint.hostname), ipfs_port) + + self.registry_contract = get_contract_object(self.web3, "Registry.json") + self.account = Account(self.web3, config, self.mpe_contract) + + self.block_offset = self._config.get("block_offset", 604800) + + def create_service_client(self, org_id, service_id, service_stub, group_name="default_group", payment_channel_management_strategy=PaymentChannelManagementStrategy, options={}): + service_metadata = self.service_metadata(org_id, service_id) + try: + group = next(filter(lambda group: group["group_name"] == group_name, service_metadata.groups)) + except StopIteration: + raise ValueError("Group[name: {}] not found for orgId: {} and serviceId: {}".format(group_name, org_id, service_id)) + service_client = ServiceClient(self, service_metadata, group, service_stub, payment_channel_management_strategy(self), options) + return service_client + + def service_metadata(self, org_id, service_id): + (found, registration_id, metadata_uri, tags) = self.registry_contract.functions.getServiceRegistrationById(bytes(org_id, "utf-8"), bytes(service_id, "utf-8")).call() + metadata = AttributeDict(json.loads(self.ipfs_client.cat(metadata_uri.rstrip(b"\0").decode('ascii')[7:]))) + return metadata diff --git a/snet_sdk/snet_sdk/account.py b/snet_sdk/snet_sdk/account.py new file mode 100644 index 00000000..4164e8ca --- /dev/null +++ b/snet_sdk/snet_sdk/account.py @@ -0,0 +1,88 @@ +import json + +from snet_sdk.utils import normalize_private_key, get_address_from_private, get_contract_object + +DEFAULT_GAS = 210000 + + +class TransactionError(Exception): + """Raised when an Ethereum transaction receipt has a status of 0. Can provide a custom message. Optionally includes receipt""" + def __init__(self, message, receipt=None): + super().__init__(message) + self.message = message + self.receipt = receipt + def __str__(self): + return self.message + + +class Account: + def __init__(self, w3, config, mpe_contract): + self.config = config + self.web3 = w3 + self.mpe_contract = mpe_contract + self.token_contract = get_contract_object(self.web3, "SingularityNetToken.json") + private_key = config.get("private_key", None) + signer_private_key = config.get("signer_private_key", None) + if private_key is not None: + self.private_key = normalize_private_key(config["private_key"]) + if signer_private_key is not None: + self.signer_private_key = normalize_private_key(config["signer_private_key"]) + else: + self.signer_private_key = self.private_key + self.address = get_address_from_private(self.private_key) + self.signer_address = get_address_from_private(self.signer_private_key) + self.nonce = 0 + + + def _get_nonce(self): + nonce = self.web3.eth.getTransactionCount(self.address) + if self.nonce >= nonce: + nonce = self.nonce + 1 + self.nonce = nonce + return nonce + + + def _get_gas_price(self): + return self.web3.eth.generateGasPrice() + + + def _send_signed_transaction(self, contract_fn, *args): + transaction = contract_fn(*args).buildTransaction({ + "chainId": int(self.web3.version.network), + "gas": DEFAULT_GAS, + "gasPrice": self._get_gas_price(), + "nonce": self._get_nonce() + }) + signed_txn = self.web3.eth.account.signTransaction(transaction, private_key=self.private_key) + return self.web3.toHex(self.web3.eth.sendRawTransaction(signed_txn.rawTransaction)) + + + def send_transaction(self, contract_fn, *args): + txn_hash = self._send_signed_transaction(contract_fn, *args) + return self.web3.eth.waitForTransactionReceipt(txn_hash) + + + def _parse_receipt(self, receipt, event, encoder=json.JSONEncoder): + if receipt.status == 0: + raise TransactionError("Transaction failed", receipt) + else: + return json.dumps(dict(event().processReceipt(receipt)[0]["args"]), cls=encoder) + + + def escrow_balance(self): + return self.mpe_contract.balance(self.address) + + + def deposit_to_escrow_account(self, amount_in_cogs): + already_approved = self.allowance() + if amount_in_cogs > already_approved: + self.approve_transfer(amount_in_cogs) + return self.mpe_contract.deposit(self, amount_in_cogs) + + + def approve_transfer(self, amount_in_cogs): + return self.send_transaction(self.token_contract.functions.approve(self.mpe_contract.contract.address, amount_in_cogs)) + + + def allowance(self): + return self.token_contract.functions.allowance(self.address, self.mpe_contract.contract.address).call() diff --git a/snet_sdk/snet_sdk/contract.py b/snet_sdk/snet_sdk/contract.py new file mode 100644 index 00000000..c23eaddc --- /dev/null +++ b/snet_sdk/snet_sdk/contract.py @@ -0,0 +1,27 @@ +class Contract: + def __init__(self, w3, address, abi): + self.w3 = w3 + self.contract = self.w3.eth.contract(address=self.w3.toChecksumAddress(address), abi=abi) + self.abi = abi + + def call(self, function_name, *positional_inputs, **named_inputs): + return getattr(self.contract.functions, function_name)(*positional_inputs, **named_inputs).call() + + def build_transaction(self, function_name, from_address, gas_price, *positional_inputs, **named_inputs): + nonce = self.w3.eth.getTransactionCount(from_address) + chain_id = self.w3.version.network + return getattr(self.contract.functions, function_name)(*positional_inputs, **named_inputs).buildTransaction({ + "from": from_address, + "nonce": nonce, + "gasPrice": gas_price, + "chainId": int(chain_id) + }) + + def process_receipt(self, receipt): + events = [] + + contract_events = map(lambda e: e["name"], filter(lambda e: e["type"] == "event", self.abi)) + for contract_event in contract_events: + events.extend(getattr(self.contract.events, contract_event)().processReceipt(receipt)) + + return events diff --git a/snet_sdk/snet_sdk/generic_client_interceptor.py b/snet_sdk/snet_sdk/generic_client_interceptor.py new file mode 100644 index 00000000..d2bb7e56 --- /dev/null +++ b/snet_sdk/snet_sdk/generic_client_interceptor.py @@ -0,0 +1,55 @@ +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Base class for interceptors that operate on all RPC types.""" + +import grpc + + +class _GenericClientInterceptor( + grpc.UnaryUnaryClientInterceptor, grpc.UnaryStreamClientInterceptor, + grpc.StreamUnaryClientInterceptor, grpc.StreamStreamClientInterceptor): + + def __init__(self, interceptor_function): + self._fn = interceptor_function + + def intercept_unary_unary(self, continuation, client_call_details, request): + new_details, new_request_iterator, postprocess = self._fn( + client_call_details, iter((request,)), False, False) + response = continuation(new_details, next(new_request_iterator)) + return postprocess(response) if postprocess else response + + def intercept_unary_stream(self, continuation, client_call_details, + request): + new_details, new_request_iterator, postprocess = self._fn( + client_call_details, iter((request,)), False, True) + response_it = continuation(new_details, next(new_request_iterator)) + return postprocess(response_it) if postprocess else response_it + + def intercept_stream_unary(self, continuation, client_call_details, + request_iterator): + new_details, new_request_iterator, postprocess = self._fn( + client_call_details, request_iterator, True, False) + response = continuation(new_details, new_request_iterator) + return postprocess(response) if postprocess else response + + def intercept_stream_stream(self, continuation, client_call_details, + request_iterator): + new_details, new_request_iterator, postprocess = self._fn( + client_call_details, request_iterator, True, True) + response_it = continuation(new_details, new_request_iterator) + return postprocess(response_it) if postprocess else response_it + + +def create(intercept_call): + return _GenericClientInterceptor(intercept_call) diff --git a/snet_sdk/snet_sdk/mpe_contract.py b/snet_sdk/snet_sdk/mpe_contract.py new file mode 100644 index 00000000..3e879352 --- /dev/null +++ b/snet_sdk/snet_sdk/mpe_contract.py @@ -0,0 +1,72 @@ +import base64 + +import web3 +from snet_sdk.utils import get_contract_object, get_contract_deployment_block +from snet_sdk.payment_channel import PaymentChannel + +BLOCKS_PER_BATCH = 20000 +EVENT_ABI = {'anonymous': False, 'inputs': [{'indexed': False, 'name': 'channelId', 'type': 'uint256'}, {'indexed': False, 'name': 'nonce', 'type': 'uint256'}, {'indexed': True, 'name': 'sender', 'type': 'address'}, {'indexed': False, 'name': 'signer', 'type': 'address'}, {'indexed': True, 'name': 'recipient', 'type': 'address'}, {'indexed': True, 'name': 'groupId', 'type': 'bytes32'}, {'indexed': False, 'name': 'amount', 'type': 'uint256'}, {'indexed': False, 'name': 'expiration', 'type': 'uint256'}], 'name': 'ChannelOpen', 'type': 'event'} + + +class MPEContract: + def __init__(self, w3): + self.web3 = w3 + self.contract = get_contract_object(self.web3, "MultiPartyEscrow.json") + self.event_topics = [self.web3.sha3(text="ChannelOpen(uint256,uint256,address,address,address,bytes32,uint256,uint256)").hex()] + self.deployment_block = get_contract_deployment_block(self.web3, "MultiPartyEscrow.json") + + + def get_past_open_channels(self, account, service, starting_block_number=0, to_block_number=None): + if to_block_number is None: + to_block_number = self.web3.eth.getBlock("latest")["number"] + + if starting_block_number == 0: + starting_block_number = self.deployment_block + + logs = [] + from_block = starting_block_number + while from_block <= to_block_number: + to_block = min(from_block + BLOCKS_PER_BATCH, to_block_number) + logs = logs + self.web3.eth.getLogs({"fromBlock" : from_block, "toBlock": to_block, "address": self.contract.address, "topics": self.event_topics}) + from_block = to_block + 1 + + channels_opened = list(filter(lambda channel: channel.sender == account.address and channel.signer == account.signer_address and channel.recipient == service.group["payment_address"], [web3.utils.events.get_event_data(EVENT_ABI, l)["args"] for l in logs])) + return list(map(lambda channel: PaymentChannel(channel["channelId"], self.web3, account, service, self), channels_opened)) + + + def balance(self, address): + return self.contract.functions.balances(address).call() + + + def deposit(self, account, amount_in_cogs): + return account.send_transaction(self.contract.functions.deposit, amount_in_cogs) + + + def open_channel(self, account, service, amount, expiration): + return account.send_transaction(self.contract.functions.openChannel, account.signer_address, service.group["payment_address"], base64.b64decode(str(service.group["group_id"])), amount, expiration) + + + def deposit_and_open_channel(self, account, service, amount, expiration): + already_approved_amount = account.allowance() + if amount > already_approved_amount: + account.approve_transfer(amount) + return account.send_transaction(self.contract.functions.depositAndOpenChannel, account.signer_address, service.group["payment_address"], base64.b64decode(str(service.group["group_id"])), amount, expiration) + + + def channel_add_funds(self, account, channel_id, amount): + self._fund_escrow_account(account, amount) + return account.send_transaction(self.contract.functions.channelAddFunds, channel_id, amount) + + + def channel_extend(self, account, channel_id, expiration): + return account.send_transaction(self.contract.functions.channelExtend, channel_id, expiration) + + + def channel_extend_and_add_funds(self, account, channel_id, expiration, amount): + self._fund_escrow_account(account, amount) + return account.send_transaction(self.contract.functions.channelExtendAndAddFunds, channel_id, expiration, amount) + + def _fund_escrow_account(self, account, amount): + current_escrow_balance = self.balance(account.address) + if amount > current_escrow_balance: + account.deposit_to_escrow_account(amount - current_escrow_balance) diff --git a/snet_sdk/snet_sdk/payment_channel.py b/snet_sdk/snet_sdk/payment_channel.py new file mode 100644 index 00000000..87cdbd30 --- /dev/null +++ b/snet_sdk/snet_sdk/payment_channel.py @@ -0,0 +1,54 @@ +import web3 +from eth_account.messages import defunct_hash_message + +import snet_sdk.state_service_pb2 as state_service_pb2 + +class PaymentChannel: + def __init__(self, channel_id, w3, account, service, mpe_contract): + self.channel_id = channel_id + self.web3 = w3 + self.account = account + self.mpe_contract = mpe_contract + self.payment_channel_state_service_client = service.payment_channel_state_service_client + self.state = { + "nonce": 0, + "last_signed_amount": 0 + } + + + def add_funds(self, amount): + return self.mpe_contract.channel_add_funds(self.account, self.channel_id, amount) + + + def extend_expiration(self, expiration): + return self.mpe_contract.channel_extend(self.account, self.channel_id, expiration) + + + def extend_and_add_funds(self, expiration, amount): + return self.mpe_contract.channel_extend_and_add_funds(self.account, self.channel_id, expiration, amount) + + + def sync_state(self): + channel_blockchain_data = self.mpe_contract.contract.functions.channels(self.channel_id).call() + (current_nonce, last_signed_amount) = self._get_current_channel_state() + nonce = channel_blockchain_data[0] + total_amount = channel_blockchain_data[5] + expiration = channel_blockchain_data[6] + available_amount = total_amount - last_signed_amount + self.state = { + "current_nonce": current_nonce, + "last_signed_amount": last_signed_amount, + "nonce": nonce, + "total_amount": total_amount, + "expiration": expiration, + "available_amount": available_amount + } + + + def _get_current_channel_state(self): + stub = self.payment_channel_state_service_client + message = web3.Web3.soliditySha3(["uint256"], [self.channel_id]) + signature = self.web3.eth.account.signHash(defunct_hash_message(message), self.account.signer_private_key).signature + request = state_service_pb2.ChannelStateRequest(channel_id=web3.Web3.toBytes(self.channel_id), signature=bytes(signature)) + response = stub.GetChannelState(request) + return int.from_bytes(response.current_nonce, byteorder="big"), int.from_bytes(response.current_signed_amount, byteorder="big") diff --git a/snet_sdk/snet_sdk/payment_channel_management_strategies/__init__.py b/snet_sdk/snet_sdk/payment_channel_management_strategies/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/snet_sdk/snet_sdk/payment_channel_management_strategies/default.py b/snet_sdk/snet_sdk/payment_channel_management_strategies/default.py new file mode 100644 index 00000000..60147274 --- /dev/null +++ b/snet_sdk/snet_sdk/payment_channel_management_strategies/default.py @@ -0,0 +1,45 @@ +class PaymentChannelManagementStrategy: + def __init__(self, sdk_context): + self.sdk_context = sdk_context + + def select_channel(self, service_client): + account = self.sdk_context.account + service_client.load_open_channels() + service_client.update_channel_states() + payment_channels = service_client.payment_channels + service_call_price = service_client.metadata.pricing["price_in_cogs"] + mpe_balance = account.escrow_balance() + default_expiration = service_client.default_channel_expiration() + + if len(payment_channels) == 0: + if mpe_balance > service_call_price: + return service_client.open_channel(service_call_price, default_expiration + self.sdk_context.block_offset) + return service_client.deposit_and_open_channel(service_call_price, default_expiration + self.sdk_context.block_offset) + + funded_valid_channels = [channel for channel in payment_channels if self._has_sufficient_funds(channel, service_call_price) and self._is_valid(channel, default_expiration)] + if len(funded_valid_channels): + return funded_valid_channels[0] + + funded_channels = [channel for channel in payment_channels if self._has_sufficient_funds(channel, service_call_price)] + if len(funded_channels): + funded_channels[0].extend_expiration(default_expiration + self.sdk_context.block_offset) + return funded_channels[0] + + valid_channels = [channel for channel in payment_channels if self._is_valid(channel, default_expiration)] + if len(valid_channels): + valid_channels[0].add_funds(service_call_price) + return valid_channels[0] + + first_expired_and_unfunded_channel = payment_channels[0] + first_expired_and_unfunded_channel.extend_and_add_funds(default_expiration + self.sdk_context.block_offset, service_call_price) + return first_expired_and_unfunded_channel + + + @staticmethod + def _has_sufficient_funds(channel, amount): + return channel.state["available_amount"] >= amount + + + @staticmethod + def _is_valid(channel, expiry): + return channel.state["expiration"] >= expiry diff --git a/snet_sdk/snet_sdk/resources/contracts/placeholder.txt b/snet_sdk/snet_sdk/resources/contracts/placeholder.txt new file mode 100644 index 00000000..e69de29b diff --git a/snet_sdk/snet_sdk/service_client.py b/snet_sdk/snet_sdk/service_client.py new file mode 100644 index 00000000..8039e369 --- /dev/null +++ b/snet_sdk/snet_sdk/service_client.py @@ -0,0 +1,127 @@ +import collections +import grpc +import web3 +from rfc3986 import urlparse +from eth_account.messages import defunct_hash_message + +import snet_sdk.generic_client_interceptor as generic_client_interceptor + +import snet_sdk.state_service_pb2_grpc as state_service_pb2_grpc + + +class _ClientCallDetails( + collections.namedtuple( + '_ClientCallDetails', + ('method', 'timeout', 'metadata', 'credentials')), + grpc.ClientCallDetails): + pass + + +class ServiceClient: + def __init__(self, sdk, metadata, group, service_stub, payment_channel_management_strategy, options): + self.sdk = sdk + self.options = options + self.group = group + self.metadata = metadata + self.payment_channel_management_strategy = payment_channel_management_strategy + self.payment_channel_state_service_client = self._generate_payment_channel_state_service_client() + self.expiry_threshold = self.metadata.payment_expiration_threshold + self.stub = self._generate_grpc_stub(service_stub) + self.payment_channels = [] + self.last_read_block = 0 + + + def _generate_grpc_stub(self, service_stub): + grpc_channel = self._get_grpc_channel() + disable_blockchain_operations = self.options.get("disable_blockchain_operations", False) + if disable_blockchain_operations is False: + grpc_channel = grpc.intercept_channel(grpc_channel, generic_client_interceptor.create(self._intercept_call)) + stub_instance = service_stub(grpc_channel) + return stub_instance + + + def _get_grpc_channel(self): + endpoint = self.options.get("endpoint", None) + if endpoint is None: + endpoint = next(filter(lambda endpoint: endpoint["group_name"] == self.group["group_name"], self.metadata["endpoints"]))["endpoint"] + endpoint_object = urlparse(endpoint) + if endpoint_object.port is not None: + channel_endpoint = endpoint_object.hostname + ":" + str(endpoint_object.port) + else: + channel_endpoint = endpoint_object.hostname + + if endpoint_object.scheme == "http": + return grpc.insecure_channel(channel_endpoint) + elif endpoint_object.scheme == "https": + return grpc.secure_channel(channel_endpoint, grpc.ssl_channel_credentials()) + else: + raise ValueError('Unsupported scheme in service metadata ("{}")'.format(endpoint_object.scheme)) + + + def _get_service_call_metadata(self): + channel = self.payment_channel_management_strategy.select_channel(self) + amount = channel.state["last_signed_amount"] + int(self.metadata.pricing["price_in_cogs"]) + message = web3.Web3.soliditySha3( + ["address", "uint256", "uint256", "uint256"], + [self.sdk.mpe_contract.contract.address, channel.channel_id, channel.state["nonce"], amount] + ) + signature = bytes(self.sdk.web3.eth.account.signHash(defunct_hash_message(message), self.sdk.account.signer_private_key).signature) + metadata = [ + ("snet-payment-type", "escrow"), + ("snet-payment-channel-id", str(channel.channel_id)), + ("snet-payment-channel-nonce", str(channel.state["nonce"])), + ("snet-payment-channel-amount", str(amount)), + ("snet-payment-channel-signature-bin", signature) + ] + return metadata + + + def _intercept_call(self, client_call_details, request_iterator, request_streaming, + response_streaming): + metadata = [] + if client_call_details.metadata is not None: + metadata = list(client_call_details.metadata) + metadata.extend(self._get_service_call_metadata()) + client_call_details = _ClientCallDetails( + client_call_details.method, client_call_details.timeout, metadata, + client_call_details.credentials) + return client_call_details, request_iterator, None + + + def load_open_channels(self): + current_block_number = self.sdk.web3.eth.getBlock("latest").number + new_payment_channels = self.sdk.mpe_contract.get_past_open_channels(self.sdk.account, self, self.last_read_block) + self.payment_channels = self.payment_channels + new_payment_channels + self.last_read_block = current_block_number + return self.payment_channels + + + def update_channel_states(self): + for channel in self.payment_channels: + channel.sync_state() + return self.payment_channels + + + def default_channel_expiration(self): + current_block_number = self.sdk.web3.eth.getBlock("latest").number + return current_block_number + self.expiry_threshold + + + def _generate_payment_channel_state_service_client(self): + grpc_channel = self._get_grpc_channel() + return state_service_pb2_grpc.PaymentChannelStateServiceStub(grpc_channel) + + + def open_channel(self, amount, expiration): + receipt = self.sdk.mpe_contract.open_channel(self.sdk.account, self, amount, expiration) + return self._get_newly_opened_channel(receipt) + + + def deposit_and_open_channel(self, amount, expiration): + receipt = self.sdk.mpe_contract.deposit_and_open_channel(self.sdk.account, self, amount, expiration) + return self._get_newly_opened_channel(receipt) + + + def _get_newly_opened_channel(self, receipt): + open_channels = self.sdk.mpe_contract.get_past_open_channels(self.sdk.account, self, receipt["blockNumber"], receipt["blockNumber"]) + return open_channels[0] diff --git a/snet_sdk/snet_sdk/state_service_pb2.py b/snet_sdk/snet_sdk/state_service_pb2.py new file mode 100644 index 00000000..bac2e3fa --- /dev/null +++ b/snet_sdk/snet_sdk/state_service_pb2.py @@ -0,0 +1,153 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: state_service.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='state_service.proto', + package='escrow', + syntax='proto3', + serialized_pb=_b('\n\x13state_service.proto\x12\x06\x65scrow\"<\n\x13\x43hannelStateRequest\x12\x12\n\nchannel_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\"d\n\x11\x43hannelStateReply\x12\x15\n\rcurrent_nonce\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63urrent_signed_amount\x18\x02 \x01(\x0c\x12\x19\n\x11\x63urrent_signature\x18\x03 \x01(\x0c\x32i\n\x1aPaymentChannelStateService\x12K\n\x0fGetChannelState\x12\x1b.escrow.ChannelStateRequest\x1a\x19.escrow.ChannelStateReply\"\x00\x62\x06proto3') +) + + + + +_CHANNELSTATEREQUEST = _descriptor.Descriptor( + name='ChannelStateRequest', + full_name='escrow.ChannelStateRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='channel_id', full_name='escrow.ChannelStateRequest.channel_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='signature', full_name='escrow.ChannelStateRequest.signature', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=31, + serialized_end=91, +) + + +_CHANNELSTATEREPLY = _descriptor.Descriptor( + name='ChannelStateReply', + full_name='escrow.ChannelStateReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='current_nonce', full_name='escrow.ChannelStateReply.current_nonce', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='current_signed_amount', full_name='escrow.ChannelStateReply.current_signed_amount', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='current_signature', full_name='escrow.ChannelStateReply.current_signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=93, + serialized_end=193, +) + +DESCRIPTOR.message_types_by_name['ChannelStateRequest'] = _CHANNELSTATEREQUEST +DESCRIPTOR.message_types_by_name['ChannelStateReply'] = _CHANNELSTATEREPLY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ChannelStateRequest = _reflection.GeneratedProtocolMessageType('ChannelStateRequest', (_message.Message,), dict( + DESCRIPTOR = _CHANNELSTATEREQUEST, + __module__ = 'state_service_pb2' + # @@protoc_insertion_point(class_scope:escrow.ChannelStateRequest) + )) +_sym_db.RegisterMessage(ChannelStateRequest) + +ChannelStateReply = _reflection.GeneratedProtocolMessageType('ChannelStateReply', (_message.Message,), dict( + DESCRIPTOR = _CHANNELSTATEREPLY, + __module__ = 'state_service_pb2' + # @@protoc_insertion_point(class_scope:escrow.ChannelStateReply) + )) +_sym_db.RegisterMessage(ChannelStateReply) + + + +_PAYMENTCHANNELSTATESERVICE = _descriptor.ServiceDescriptor( + name='PaymentChannelStateService', + full_name='escrow.PaymentChannelStateService', + file=DESCRIPTOR, + index=0, + options=None, + serialized_start=195, + serialized_end=300, + methods=[ + _descriptor.MethodDescriptor( + name='GetChannelState', + full_name='escrow.PaymentChannelStateService.GetChannelState', + index=0, + containing_service=None, + input_type=_CHANNELSTATEREQUEST, + output_type=_CHANNELSTATEREPLY, + options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_PAYMENTCHANNELSTATESERVICE) + +DESCRIPTOR.services_by_name['PaymentChannelStateService'] = _PAYMENTCHANNELSTATESERVICE + +# @@protoc_insertion_point(module_scope) diff --git a/snet_sdk/snet_sdk/state_service_pb2_grpc.py b/snet_sdk/snet_sdk/state_service_pb2_grpc.py new file mode 100644 index 00000000..bb7e8122 --- /dev/null +++ b/snet_sdk/snet_sdk/state_service_pb2_grpc.py @@ -0,0 +1,54 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import snet_sdk.state_service_pb2 as state__service__pb2 + + +class PaymentChannelStateServiceStub(object): + """PaymentChannelStateService contains methods to get the MultiPartyEscrow + payment channel state. + channel_id, channel_nonce, value and amount fields below in fact are + Solidity uint256 values. Which are big-endian integers padded by zeros, see + https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#formal-specification-of-the-encoding + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GetChannelState = channel.unary_unary( + '/escrow.PaymentChannelStateService/GetChannelState', + request_serializer=state__service__pb2.ChannelStateRequest.SerializeToString, + response_deserializer=state__service__pb2.ChannelStateReply.FromString, + ) + + +class PaymentChannelStateServiceServicer(object): + """PaymentChannelStateService contains methods to get the MultiPartyEscrow + payment channel state. + channel_id, channel_nonce, value and amount fields below in fact are + Solidity uint256 values. Which are big-endian integers padded by zeros, see + https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#formal-specification-of-the-encoding + """ + + def GetChannelState(self, request, context): + """GetChannelState method returns a channel state by channel id. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_PaymentChannelStateServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'GetChannelState': grpc.unary_unary_rpc_method_handler( + servicer.GetChannelState, + request_deserializer=state__service__pb2.ChannelStateRequest.FromString, + response_serializer=state__service__pb2.ChannelStateReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'escrow.PaymentChannelStateService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) diff --git a/snet_sdk/snet_sdk/utils.py b/snet_sdk/snet_sdk/utils.py new file mode 100644 index 00000000..5654523d --- /dev/null +++ b/snet_sdk/snet_sdk/utils.py @@ -0,0 +1,41 @@ +import os +import json +from pathlib import PurePath + +import web3 +import ecdsa +import hashlib + + +cur_dir = PurePath(os.path.realpath(__file__)).parent + + +def get_contract_object(w3, contract_file): + with open(cur_dir.joinpath("resources", "contracts", "abi", contract_file)) as f: + abi = json.load(f) + with open(cur_dir.joinpath("resources", "contracts", "networks", contract_file)) as f: + networks = json.load(f) + address = w3.toChecksumAddress(networks[w3.version.network]["address"]) + return w3.eth.contract(abi=abi, address=address) + + +def get_contract_deployment_block(w3, contract_file): + with open(cur_dir.joinpath("resources", "contracts", "networks", contract_file)) as f: + networks = json.load(f) + txn_hash = networks[w3.version.network]["transactionHash"] + return w3.eth.getTransactionReceipt(txn_hash).blockNumber + + +def normalize_private_key(private_key): + if private_key.startswith("0x"): + private_key = bytes(bytearray.fromhex(private_key[2:])) + else: + private_key = bytes(bytearray.fromhex(private_key)) + return private_key + + +def get_address_from_private(private_key): + public_key = ecdsa.SigningKey.from_string(string=private_key, + curve=ecdsa.SECP256k1, + hashfunc=hashlib.sha256).get_verifying_key() + return web3.Web3.toChecksumAddress("0x" + web3.Web3.sha3(hexstr=public_key.to_string().hex())[12:].hex())