def add_agent_factory_options(parser): parser.set_defaults(cmd=AgentFactoryCommand) add_contract_identity_arguments(parser, [("", "agent_factory_at")]) subparsers = parser.add_subparsers(title="agent-factory commands", metavar="COMMAND") subparsers.required = True create_agent_p = subparsers.add_parser("create-agent", help="Create an agent") create_agent_p.set_defaults(fn="create_agent") create_agent_p.add_argument( "contract_named_input_price", type=type_converter("uint256"), metavar="PRICE", help="initial price for interacting with the service") create_agent_p.add_argument( "contract_named_input_endpoint", type=type_converter("string"), metavar="ENDPOINT", help="initial endpoint to call the service's API") create_agent_p.add_argument("contract_named_input_metadataURI", type=type_converter("string"), metavar="METADATA_URI", nargs="?", default="", help="uri where service metadata is stored") add_transaction_arguments(create_agent_p)
def _get_params_for_tags_update(self): tags = self._get_converted_tags() params = [ type_converter("bytes32")(self.args.org_id), type_converter("bytes32")(self.args.service_id), tags ] return params
def add_contract_function_options(parser, contract_name): add_contract_identity_arguments(parser) contract_def = get_contract_def(contract_name) parser.set_defaults(contract_def=contract_def) fns = [] for fn in filter(lambda e: e["type"] == "function", contract_def["abi"]): fns.append({ "name": fn["name"], "named_inputs": [(i["name"], i["type"]) for i in fn["inputs"] if i["name"] != ""], "positional_inputs": [i["type"] for i in fn["inputs"] if i["name"] == ""] }) if len(fns) > 0: subparsers = parser.add_subparsers(title="{} functions".format(contract_name), metavar="FUNCTION") subparsers.required = True for fn in fns: fn_p = subparsers.add_parser(fn["name"], help="{} function".format(fn["name"])) fn_p.set_defaults(fn="call") fn_p.set_defaults(contract_function=fn["name"]) for i in fn["positional_inputs"]: fn_p.add_argument(i, action=AppendPositionalAction, type=type_converter(i), metavar=i.upper()) for i in fn["named_inputs"]: fn_p.add_argument("contract_named_input_{}".format(i[0]), type=type_converter(i[1]), metavar="{}_{}".format(i[0].lstrip("_"), i[1].upper())) fn_p.add_argument("--transact", action="store_const", const="transact", dest="fn", help="invoke contract function as transaction") add_transaction_arguments(fn_p)
def delete_service_registration(self): params = [ type_converter("bytes32")(self.args.org_id), type_converter("bytes32")(self.args.service_id) ] self.transact_contract_command("Registry", "deleteServiceRegistration", params)
def publish_metadata_in_ipfs_and_update_registration(self): # first we check that we do not change payment_address or group_id in existed payment groups old_metadata = self._get_service_metadata_from_registry() new_metadata = load_mpe_service_metadata(self.args.metadata_file) for old_group in old_metadata["groups"]: if (new_metadata.is_group_name_exists(old_group["group_name"])): new_group = new_metadata.get_group(old_group["group_name"]) if (new_group["group_id"] != old_group["group_id"] or new_group["payment_address"] != old_group["payment_address"]): raise Exception( "\n\nYou are trying to change group_id or payment_address in group '%s'.\n" % old_group["group_name"] + "It would make all open channels invalid.\n" + "You shoudn't use 'metadata-init' for existed service, because it reinitialize group_id\n" + "Please use 'metadata-set-model' for change your protobuf file\n" + "Please use 'metadata-remove-all-endpoints/metadata-add-endpoints to update endpoints'\n\n" ) metadata_uri = hash_to_bytesuri( self._publish_metadata_in_ipfs(self.args.metadata_file)) params = [ type_converter("bytes32")(self.args.org_id), type_converter("bytes32")(self.args.service_id), metadata_uri ] self.transact_contract_command("Registry", "updateServiceRegistration", params)
def add_agent_factory_options(parser): parser.set_defaults(cmd=AgentFactoryCommand) with open( Path(__file__).absolute().parent.joinpath( "resources", "contracts", "AgentFactory.json")) as f: contract_json = json.load(f) parser.set_defaults(contract_json=contract_json) add_contract_identity_arguments(parser, [("", "agent_factory_at")]) subparsers = parser.add_subparsers(title="agent-factory commands", metavar="COMMAND") subparsers.required = True create_record_p = subparsers.add_parser("create-agent", help="Create an agent") create_record_p.set_defaults(fn="create_agent") create_record_p.set_defaults(contract_function="createAgent") create_record_p.add_argument("contract_named_input_price", type=type_converter("uint256"), metavar="PRICE", help="desired initial job price for agent") create_record_p.add_argument("contract_named_input_endpoint", type=type_converter("string"), metavar="ENDPOINT", help="initial endpoint for agebt's daemon") add_transaction_arguments(create_record_p)
def publish_metadata_in_ipfs_and_update_registration(self): metadata_uri = hash_to_bytesuri( self._publish_metadata_in_ipfs(self.args.metadata_file)) params = [ type_converter("bytes32")(self.args.org_id), type_converter("bytes32")(self.args.service_id), metadata_uri ] self.transact_contract_command("Registry", "updateServiceRegistration", params)
def _get_params_for_tags_update(self): registry_address = get_registry_address_from_args_or_networks( self.w3, self.args.registry) tags = self._get_converted_tags() params = [ type_converter("bytes32")(self.args.organization), type_converter("bytes32")(self.args.service), tags ] return registry_address, params
def publish_metadata_in_ipfs_and_update_registration(self): registry_address, metadata_uri = self._publish_metadata_and_get_registry_address( ) params = [ type_converter("bytes32")(self.args.organization), type_converter("bytes32")(self.args.service), metadata_uri ] self.transact_contract_command("Registry", registry_address, "updateServiceRegistration", params)
def delete_service_registration(self): registry_address = get_registry_address_from_args_or_networks( self.w3, self.args.registry) params = [ type_converter("bytes32")(self.args.organization), type_converter("bytes32")(self.args.service) ] self.transact_contract_command("Registry", registry_address, "deleteServiceRegistration", params)
def publish_service_with_metadata(self): metadata_uri = hash_to_bytesuri( self._publish_metadata_in_ipfs(self.args.metadata_file)) tags = self._get_converted_tags() params = [ type_converter("bytes32")(self.args.org_id), type_converter("bytes32")(self.args.service_id), metadata_uri, tags ] self.transact_contract_command("Registry", "createServiceRegistration", params)
def publish_service_with_metadata(self): registry_address, metadata_uri = self._publish_metadata_and_get_registry_address( ) tags = self._get_converted_tags() params = [ type_converter("bytes32")(self.args.organization), type_converter("bytes32")(self.args.service), metadata_uri, tags ] self.transact_contract_command("Registry", registry_address, "createServiceRegistration", params)
def _add_service_update_arguments(parser): parser.set_defaults(fn="update") parser.add_argument("--new-price", help="new price to call the service", type=type_converter("uint256")) parser.add_argument("--new-endpoint", help="new endpoint to call the service's API") parser.add_argument("--new-tags", nargs="+", type=type_converter("bytes32"), metavar=("TAGS", "TAG1, TAG2,"), help="new list of tags you want associated with the service registration") parser.add_argument("--new-description", help="new description for the service") parser.add_argument("--config", help="specify a custom service.json file path") add_transaction_arguments(parser) add_contract_identity_arguments(parser, [("registry", "registry_at")])
def _get_service_registration(self): params = [ type_converter("bytes32")(self.args.org_id), type_converter("bytes32")(self.args.service_id) ] rez = self.call_contract_command("Registry", "getServiceRegistrationById", params) if (rez[0] == False): raise Exception( "Cannot find Service with id=%s in Organization with id=%s" % (self.args.service_id, self.args.org_id)) return {"metadataURI": rez[2], "tags": rez[3]}
def _get_service_registration(self): params = [ type_converter("bytes32")(self.args.organization), type_converter("bytes32")(self.args.service) ] rez = self.call_contract_command("Registry", "getServiceRegistrationByName", params) if (rez[0] == False): raise Exception("Cannot find Service %s in Organization %s" % (self.args.service, self.args.organization)) return rez
def _get_service_metadata_hash_from_registry(self, registry_address, organization, service): params = [ type_converter("bytes32")(organization), type_converter("bytes32")(service) ] rez = self.call_contract_command("Registry", self.args.registry_address, "getMetadataIPFSHash", params) if (rez[0] == False): raise Exception("Cannot find Service %s in Organization %s" % (self.args.service, self.args.organization)) return base58.b58encode(rez[1]).decode("ascii")
def _publish_metadata_in_ipfs_and_registry(self, registry_address, organization, service, metadata_file): metadata_hash_base58 = self._publish_metadata_in_ipfs( self.args.metadata_file) metadata_hash = base58.b58decode(metadata_hash_base58) params = [ type_converter("bytes32")(organization), type_converter("bytes32")(service), metadata_hash ] self.transact_contract_command( "Registry", registry_address, "setMetadataIPFSHashInServiceRegistration", params)
def change_owner(self): # Check if Organization exists (found, _, owner, _, _, _) = self._getorganizationbyname() if not found: raise Exception("\n{} doesn't exist!\n".format(self.args.name)) new_owner = self.args.owner if not web3.eth.is_checksum_address(new_owner): raise Exception( "New owner account %s is not a valid Ethereum checksum address" % new_owner) if new_owner.lower() == owner.lower(): raise Exception("\n{} is the owner of {}!\n".format( new_owner, self.args.name)) self._printerr( "Creating transaction to change organization {}'s owner...\n". format(self.args.name)) try: self.transact_contract_command( "Registry", "changeOrganizationOwner", [type_converter("bytes32")(self.args.name), self.args.owner]) except Exception as e: self._printerr( "\nTransaction error!\nHINT: Check if you are the owner of {}\n" .format(self.args.name)) raise
def _get_service_metadata_from_registry(self): params = [ type_converter("bytes32")(self.args.organization), type_converter("bytes32")(self.args.service) ] rez = self.call_contract_command("Registry", "getServiceRegistrationByName", params) if (rez[0] == False): raise Exception("Cannot find Service %s in Organization %s" % (self.args.service, self.args.organization)) metadata_hash = bytesuri_to_hash(rez[2]) metadata_json = get_from_ipfs_and_checkhash(self._get_ipfs_client(), metadata_hash) metadata = mpe_service_metadata_from_json(metadata_json) return metadata
def _publish_service_with_metadata(self, registry_address, organization, service, service_path, tags, metadata_file): # publish service with empty agent tags = [type_converter("bytes32")(tag) for tag in tags] params = [ type_converter("bytes32")(organization), type_converter("bytes32")(service), type_converter("bytes32")(service_path), "0x0000000000000000000000000000000000000000", tags ] self.transact_contract_command("Registry", registry_address, "createServiceRegistration", params) self._publish_metadata_in_ipfs_and_registry(registry_address, organization, service, metadata_file)
def rem_members(self): org_id = self.args.org_id # Check if Organization exists and member is part of it (found, _, _, _, members, _, _) = self._getorganizationbyid(org_id) self.error_organization_not_found(org_id, found) members = [member.lower() for member in members] rem_members = [] for rem_member in self.get_members_from_args(): if rem_member.lower() not in members: self._printout("{} is not a member of organization {}".format(rem_member, org_id)) else: rem_members.append(rem_member) if not rem_members: self._printout("No member was removed from {}!\n".format(org_id)) return params = [type_converter("bytes32")(org_id), rem_members] self._printout("Creating transaction to remove {} members from organization with id={}...\n".format(len(rem_members), org_id)) try: self.transact_contract_command("Registry", "removeOrganizationMembers", params) except Exception as e: self._printerr("\nTransaction error!\nHINT: Check if you are the owner of {}\n".format(org_id)) raise
def add_members(self): org_id = self.args.org_id # Check if Organization exists and member is not part of it (found, _, _, _, members, _, _) = self._getorganizationbyid(org_id) self.error_organization_not_found(org_id, found) members = [member.lower() for member in members] add_members = [] for add_member in self.get_members_from_args(): if add_member.lower() in members: self._printout("{} is already a member of organization {}".format(add_member, org_id)) else: add_members.append(add_member) if not add_members: self._printout("No member was added to {}!\n".format(org_id)) return params = [type_converter("bytes32")(org_id), add_members] self._printout("Creating transaction to add {} members into organization {}...\n".format(len(add_members), org_id)) try: self.transact_contract_command("Registry", "addOrganizationMembers", params) except Exception as e: self._printerr("\nTransaction error!\nHINT: Check if you are the owner of {}\n".format(org_id)) raise
def delete(self): try: # Check if Organization exists (found, _, _, _, _, _) = self._getorganizationbyname() if not found: self._printerr("\n{} doesn't exist!\n".format(self.args.name)) return registry_contract_def = get_contract_def("Registry") registry_address = self._getstring("registry_at") cmd = ContractCommand(config=self.config, args=self.get_contract_argser( contract_address=registry_address, contract_function="deleteOrganization", contract_def=registry_contract_def)( type_converter("bytes32")( self.args.name)), out_f=self.err_f, err_f=self.err_f, w3=self.w3, ident=self.ident) self._printerr( "Creating transaction to delete organization {}...\n".format( self.args.name)) try: cmd.transact() except Exception as e: self._printerr( "\nTransaction error!\nHINT: Check if {} exists and you are its owner.\n" .format(self.args.name)) self._error(e) except Exception as e: self._printerr("\nTransaction error!\nHINT: Check ORG_NAME.\n") self._error(e)
def create(self): try: # Check if Organization already exists (found, _, _, _, _, _) = self._getorganizationbyname() if found: self._printerr("\n{} already exists!\n".format(self.args.name)) return members = [] if self.args.members: members_split = self.args.members.split(',') for idx, m in enumerate(members_split): members.append( str(m).replace("[", "").replace("]", "").lower()) registry_contract_def = get_contract_def("Registry") registry_address = self._getstring("registry_at") cmd = ContractCommand( config=self.config, args=self.get_contract_argser( contract_address=registry_address, contract_function="createOrganization", contract_def=registry_contract_def)( type_converter("bytes32")(self.args.name), [ type_converter("address")(member) for member in members ]), out_f=self.err_f, err_f=self.err_f, w3=self.w3, ident=self.ident) self._printerr( "Creating transaction to create organization {}...\n".format( self.args.name)) try: cmd.transact() except Exception as e: self._printerr( "\nTransaction error!\nHINT: Check if {} already exists.\n" .format(self.args.name)) self._error(e) except Exception as e: self._printerr( "\nTransaction error!\nHINT: Check if address is a 40-length hexadecimal.\n" ) self._error(e)
def change_owner(self): try: # Check if Organization exists (found, _, owner, _, _, _) = self._getorganizationbyname() if not found: self._printerr("\n{} doesn't exist!\n".format(self.args.name)) return new_owner = self.args.owner.lower() new_owner = new_owner if new_owner.startswith( "0x") else "0x" + new_owner if new_owner == owner: self._printerr("\n{} is the owner of!\n".format( self.args.owner, self.args.name)) return registry_contract_def = get_contract_def("Registry") registry_address = self._getstring("registry_at") cmd = ContractCommand( config=self.config, args=self.get_contract_argser( contract_address=registry_address, contract_function="changeOrganizationOwner", contract_def=registry_contract_def)( type_converter("bytes32")(self.args.name), type_converter("address")(self.args.owner)), out_f=self.err_f, err_f=self.err_f, w3=self.w3, ident=self.ident) self._printerr( "Creating transaction to change organization {}'s owner...\n". format(self.args.name)) try: cmd.transact() except Exception as e: self._printerr( "\nTransaction error!\nHINT: Check if {} already exists.\n" .format(self.args.name)) self._error(e) except Exception as e: self._printerr( "\nTransaction error!\nHINT: Check if address is a 40-length hexadecimal.\n" ) self._error(e)
def delete(self): org_id = self.args.org_id # Check if Organization exists (found,_,org_name,_,_,_,_) = self._getorganizationbyid(org_id) self.error_organization_not_found(org_id, found) self._printout("Creating transaction to delete organization with name={} id={}".format(org_name, org_id)) try: self.transact_contract_command("Registry", "deleteOrganization", [type_converter("bytes32")(org_id)]) except Exception as e: self._printerr("\nTransaction error!\nHINT: Check if you are the owner of organization with id={}\n".format(org_id)) raise
def add_contract_function_options(parser, contract_name): add_contract_identity_arguments(parser) contract_def = get_contract_def(contract_name) parser.set_defaults(contract_def=contract_def) parser.set_defaults(contract_name=contract_name) fns = [] for fn in filter(lambda e: e["type"] == "function", contract_def["abi"]): fns.append({ "name": fn["name"], "named_inputs": [(i["name"], i["type"]) for i in fn["inputs"] if i["name"] != ""], "positional_inputs": [i["type"] for i in fn["inputs"] if i["name"] == ""] }) if len(fns) > 0: subparsers = parser.add_subparsers(title="{} functions".format(contract_name), metavar="FUNCTION") subparsers.required = True for fn in fns: fn_p = subparsers.add_parser(fn["name"], help="{} function".format(fn["name"])) fn_p.set_defaults(fn="call") fn_p.set_defaults(contract_function=fn["name"]) for i in fn["positional_inputs"]: fn_p.add_argument(i, action=AppendPositionalAction, type=type_converter(i), metavar=i.upper()) for i in fn["named_inputs"]: fn_p.add_argument("contract_named_input_{}".format(i[0]), type=type_converter(i[1]), metavar="{}_{}".format(i[0].lstrip("_"), i[1].upper())) fn_p.add_argument("--transact", action="store_const", const="transact", dest="fn", help="Invoke contract function as transaction") add_transaction_arguments(fn_p)
def create(self): # Check if Organization already exists (found, _, _, _, _, _) = self._getorganizationbyname() if found: raise Exception("\n{} already exists!\n".format(self.args.name)) members = self.get_members_from_args() params = [type_converter("bytes32")(self.args.name), members] self._printerr( "Creating transaction to create organization {}...\n".format( self.args.name)) self.transact_contract_command("Registry", "createOrganization", params)
def add_contract_identity_arguments(parser, names_and_destinations=(("", "at"),)): identity_g = parser.add_argument_group(title="contract identity arguments") for (name, destination) in names_and_destinations: if name != "": arg_name = "{}-".format(name) metavar_name = "{}_".format(name.replace("-", "_")) else: arg_name = name metavar_name = name h = "{} contract address".format(name) if destination != "at": h += " (defaults to session.current_{})".format(destination) identity_g.add_argument("--{}at".format(arg_name), dest=destination, type=type_converter("address"), metavar="{}ADDRESS".format(metavar_name.upper()), help=h)
def change_name(self): org_id = self.args.org_id new_org_name = self.args.name # Check if Organization exists (found, _, org_name, _, _, _, _) = self._getorganizationbyid(org_id) self.error_organization_not_found(org_id, found) if new_org_name == org_name: raise Exception("\n{} is already the name of the Organization with id={}!\n".format(new_org_name, org_id)) self._printout("Creating transaction to change organization {}'s name...\n".format(org_id)) try: self.transact_contract_command("Registry", "changeOrganizationName", [type_converter("bytes32")(org_id), new_org_name]) except Exception as e: self._printerr("\nTransaction error!\nHINT: Check if you are the owner of {}\n".format(org_id)) raise
def create(self): org_id = self.args.org_id # create unique uuid if org_id haven't been specified manualy if (not org_id): alphabet = string.ascii_letters + string.digits org_id = ''.join(secrets.choice(alphabet) for i in range(32)) # Check if Organization already exists found = self._getorganizationbyid(org_id)[0] if found: raise Exception("\nOrganization with id={} already exists!\n".format(org_id)) members = self.get_members_from_args() params = [type_converter("bytes32")(org_id), self.args.org_name, members] self._printout("Creating transaction to create organization name={} id={}\n".format(self.args.org_name, org_id)) self.transact_contract_command("Registry", "createOrganization", params) self._printout("id:\n%s"%org_id)
def change_owner(self): org_id = self.args.org_id # Check if Organization exists (found, _, _, owner, _, _, _) = self._getorganizationbyid(org_id) self.error_organization_not_found(org_id, found) new_owner = self.args.owner if not is_checksum_address(new_owner): raise Exception("New owner account %s is not a valid Ethereum checksum address"%new_owner) if new_owner.lower() == owner.lower(): raise Exception("\n{} is the owner of Organization with id={}!\n".format(new_owner, org_id)) self._printout("Creating transaction to change organization {}'s owner...\n".format(org_id)) try: self.transact_contract_command("Registry", "changeOrganizationOwner", [type_converter("bytes32")(org_id), self.args.owner]) except Exception as e: self._printerr("\nTransaction error!\nHINT: Check if you are the owner of {}\n".format(org_id)) raise
def list_services(self): org_id = self.args.org_id (found, org_service_list) = self.call_contract_command("Registry", "listServicesForOrganization", [type_converter("bytes32")(org_id)]) self.error_organization_not_found(org_id, found) if org_service_list: self._printout("\nList of {}'s Services:".format(org_id)) for idx, org_service in enumerate(org_service_list): self._printout("- {}".format(bytes32_to_str(org_service))) else: self._printout("Organization with id={} exists but has no registered services.".format(org_id))
def _getorganizationbyid(self, org_id): org_id_bytes32 = type_converter("bytes32")(org_id) if (len(org_id_bytes32) > 32): raise Exception("Your org_id is too long, it should be 32 bytes or less. len(org_id_bytes32)=%i"%(len(org_id_bytes32))) return self.call_contract_command("Registry", "getOrganizationById", [org_id_bytes32])