// File: node_modules\@openzeppelin\contracts\introspection\IERC165.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin\contracts\introspection\ERC165.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
// File: contracts\IRegistry.sol
pragma solidity ^0.6.0;
/**
* @title Open registry for management of AI services run on SingularityNET
* @author SingularityNET
*
*/
interface IRegistry {
// ___ _ _ _ __ __ _
// / _ \ _ __ __ _ __ _ _ __ (_)______ _| |_(_) ___ _ __ | \/ | __ _ _ __ ___ | |_
// | | | | '__/ _` |/ _` | '_ \| |_ / _` | __| |/ _ \| '_ \ | |\/| |/ _` | '_ ` _ \| __|
// | |_| | | | (_| | (_| | | | | |/ / (_| | |_| | (_) | | | | | | | | (_| | | | | | | |_
// \___/|_| \__, |\__,_|_| |_|_/___\__,_|\__|_|\___/|_| |_| |_| |_|\__, |_| |_| |_|\__|
// |___/ |___/
event OrganizationCreated (bytes32 indexed orgId);
event OrganizationModified(bytes32 indexed orgId);
event OrganizationDeleted (bytes32 indexed orgId);
/**
* @dev Adds a new organization that hosts SingularityNET services to the registry.
* Reverts if the given organization Id has already been registered.
*
* @param orgId Id of organization to create, must be unique registry-wide.
* @param orgMetadataURI MetadataURI of organization to create, must be unique registry-wide.
* @param members Array of member addresses to seed the organization with.
*/
function createOrganization(bytes32 orgId, bytes calldata orgMetadataURI, address[] calldata members) external;
/**
* @dev Updates the owner of the organization.
* Only the organization owner can invoke this method.
* Reverts if the given organization Id is unregistered.
*
* @param orgId Id of organization to update.
* @param newOwner Address of new owner.
*/
function changeOrganizationOwner(bytes32 orgId, address newOwner) external;
/**
* @dev Updates the name of the organization.
* Only the organization owner can invoke this method.
* Reverts if the given organization Id is unregistered.
*
* @param orgId Id of organization to update.
* @param orgMetadataURI Name of the organization.
*/
function changeOrganizationMetadataURI(bytes32 orgId, bytes calldata orgMetadataURI) external;
/**
* @dev Updates an organization to add members.
* Only an organization member can invoke this method.
* Reverts if the given organization Id is unregistered.
*
* @param orgId Id of organization to update.
* @param newMembers Array of member addresses to add to an organization.
*/
function addOrganizationMembers(bytes32 orgId, address[] calldata newMembers) external;
/**
* @dev Updates an organization to remove members.
* Only an organization member can invoke this method.
* Reverts if the given organization Id is unregistered.
*
* @param orgId Id of organization to update.
* @param existingMembers Array of member addresses to remove from an organization.
*/
function removeOrganizationMembers(bytes32 orgId, address[] calldata existingMembers) external;
/**
* @dev Removes an organization from the registry.
* Only the organization owner can invoke this method.
* Reverts if the given organization Id is unregistered
*
* @param orgId Id of organization to remove.
*/
function deleteOrganization(bytes32 orgId) external;
// ____ _ __ __ _
// / ___| ___ _ ____ ___) ___ ___ | \/ | __ _ _ __ ___ | |_
// \___ \ / _ \ '__\ \ / / |/ __/ _ \ | |\/| |/ _` | '_ ` _ \| __|
// ___) | __/ | \ V /| | (__ __/ | | | | (_| | | | | | | |_
// |____/ \___|_| \_/ |_|\___\___| |_| |_|\__, |_| |_| |_|\__|
// |___/
event ServiceCreated (bytes32 indexed orgId, bytes32 indexed serviceId, bytes metadataURI);
event ServiceMetadataModified(bytes32 indexed orgId, bytes32 indexed serviceId, bytes metadataURI);
event ServiceTagsModified (bytes32 indexed orgId, bytes32 indexed serviceId);
event ServiceDeleted (bytes32 indexed orgId, bytes32 indexed serviceId);
/**
* @dev Adds a new service to the registry.
* Only a member of the given organization can invoke this method.
* Reverts if the given organization does not exist or if the given service id has already been registered.
*
* @param orgId Id of SingularityNET organization that owns this service.
* @param serviceId Id of the service to create, must be unique organization-wide.
* @param metadataURI Service metadata. metadataURI should contain information for data consistency
* validation (for example hash). We support: IPFS URI.
*/
function createServiceRegistration(bytes32 orgId, bytes32 serviceId, bytes calldata metadataURI) external;
/**
* @dev Updates a service registration record.
* Only a member of the given organization can invoke this method.
* Reverts if the given organization or service does not exist.
*
* @param orgId Id of SingularityNET organization that owns this service.
* @param serviceId Id of the service to update.
* @param metadataURI Service metadata URI
*/
function updateServiceRegistration(bytes32 orgId, bytes32 serviceId, bytes calldata metadataURI) external;
/**
* @dev Removes a service from the registry.
* Only the owner of the given organization can invoke this method.
* Reverts if the given organization or service does not exist.
*
* @param orgId Id of SingularityNET organization that owns this service.
* @param serviceId Id of the service to remove.
*/
function deleteServiceRegistration(bytes32 orgId, bytes32 serviceId) external;
// ____ _ _
// / ___| ___| |_| |_ ___ _ __ ___
// | | _ / _ \ __| __/ _ \ '__/ __|
// | |_| | __/ |_| |_ __/ | \__ \
// \____|\___|\__|\__\___|_| |___/
//
/**
* @dev Returns an array of Ids of all registered organizations.
*
* @return orgIds Array of Ids of all registered organizations.
*/
function listOrganizations() external view returns (bytes32[] memory orgIds);
/**
* @dev Retrieves the detailed registration information of a single organization.
*
* @param orgId Id of the organization to look up.
* @return found true if an organization with this id exists, false otherwise. If false, all other
* returned fields should be ignored.
* @return id Id of organization, should be the same as the orgId parameter.
* @return orgMetadataURI Organization Metadata URI
* @return owner Address of the owner of the organization.
* @return members Array of addresses of the members of this organization.
* @return serviceIds Array of ids of services owned by the organization.
*/
function getOrganizationById(bytes32 orgId) external view
returns (bool found, bytes32 id, bytes memory orgMetadataURI, address owner, address[] memory members, bytes32[] memory serviceIds);
/**
* @dev Returns an array of ids of all services owned by a given organization.
*
* @param orgId Id of the organization whose services to list.
*
* @return found true if an organization with this id exists, false otherwise. If false, all other
* returned fields should be ignored.
* @return serviceIds Array of ids of all services owned by this organization.
*/
function listServicesForOrganization(bytes32 orgId) external view returns (bool found, bytes32[] memory serviceIds);
/**
* @dev Retrieves the detailed registration information of a single service.
*
* @param orgId Id of the organization that owns the service to look up.
* @param serviceId Id of the service to look up.
*
* @return found true if an organization and service with these ids exists, false otherwise. If false, all other
* returned fields should be ignored.
* @return id Id of the service, should be the same as the serviceId parameter.
* @return metadataURI Service metadata URI
*/
function getServiceRegistrationById(bytes32 orgId, bytes32 serviceId) external view
returns (bool found, bytes32 id, bytes memory metadataURI);
}
// File: contracts\Registry.sol
pragma solidity ^0.6.0;
contract Registry is IRegistry, ERC165 {
struct OrganizationRegistration {
bytes32 organizationId;
bytes orgMetadataURI;
address owner;
// member indexing note:
// case (members[someAddress]) of
// 0 -> not a member of this org
// n -> member of this org, and memberKeys[n-1] == someAddress
address[] memberKeys;
mapping(address => uint) members;
bytes32[] serviceKeys;
mapping(bytes32 => ServiceRegistration) servicesById;
uint globalOrgIndex;
}
struct ServiceRegistration {
bytes32 serviceId;
bytes metadataURI; //Service metadata. metadataURI should contain information for data consistency
//validation (for example hash). We support: IPFS URI.
uint orgServiceIndex;
}
bytes32[] orgKeys;
mapping(bytes32 => OrganizationRegistration) orgsById;
constructor ()
public
{
//ERC165: https://eips.ethereum.org/EIPS/eip-165
_registerInterface(0x3f2242ea);
}
/**
* @dev Guard function that forces a revert if the tx sender is unauthorized.
* Always authorizes org owner. Can also authorize org members.
*
* @param membersAllowed if true, revert when sender is non-owner and non-member, else revert when sender is non-owner
*/
function requireAuthorization(bytes32 orgId, bool membersAllowed) internal view {
require(msg.sender == orgsById[orgId].owner || (membersAllowed && orgsById[orgId].members[msg.sender] > 0)
, "unauthorized invocation");
}
/**
* @dev Guard function that forces a revert if the referenced org does not meet an existence criteria.
*
* @param exists if true, revert when org does not exist, else revert when org exists
*/
function requireOrgExistenceConstraint(bytes32 orgId, bool exists) internal view {
if (exists) {
require(orgsById[orgId].organizationId != bytes32(0x0), "org does not exist");
} else {
require(orgsById[orgId].organizationId == bytes32(0x0), "org already exists");
}
}
/**
* @dev Guard function that forces a revert if the referenced service does not meet an existence criteria.
*
* @param exists if true, revert when service does not exist, else revert when service exists
*/
function requireServiceExistenceConstraint(bytes32 orgId, bytes32 serviceId, bool exists) internal view {
if (exists) {
require(orgsById[orgId].servicesById[serviceId].serviceId != bytes32(0x0), "service does not exist");
} else {
require(orgsById[orgId].servicesById[serviceId].serviceId == bytes32(0x0), "service already exists");
}
}
// ___ _ _ _ __ __ _
// / _ \ _ __ __ _ __ _ _ __ (_)______ _| |_(_) ___ _ __ | \/ | __ _ _ __ ___ | |_
// | | | | '__/ _` |/ _` | '_ \| |_ / _` | __| |/ _ \| '_ \ | |\/| |/ _` | '_ ` _ \| __|
// | |_| | | | (_| | (_| | | | | |/ / (_| | |_| | (_) | | | | | | | | (_| | | | | | | |_
// \___/|_| \__, |\__,_|_| |_|_/___\__,_|\__|_|\___/|_| |_| |_| |_|\__, |_| |_| |_|\__|
// |___/ |___/
function createOrganization(bytes32 orgId, bytes calldata orgMetadataURI, address[] calldata members) external override {
requireOrgExistenceConstraint(orgId, false);
OrganizationRegistration memory organization;
orgsById[orgId] = organization;
orgsById[orgId].organizationId = orgId;
orgsById[orgId].orgMetadataURI = orgMetadataURI;
orgsById[orgId].owner = msg.sender;
orgsById[orgId].globalOrgIndex = orgKeys.length;
orgKeys.push(orgId);
addOrganizationMembersInternal(orgId, members);
emit OrganizationCreated(orgId);
}
function changeOrganizationOwner(bytes32 orgId, address newOwner) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, false);
orgsById[orgId].owner = newOwner;
emit OrganizationModified(orgId);
}
function changeOrganizationMetadataURI(bytes32 orgId, bytes calldata orgMetadataURI) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, false);
orgsById[orgId].orgMetadataURI = orgMetadataURI;
emit OrganizationModified(orgId);
}
function addOrganizationMembers(bytes32 orgId, address[] calldata newMembers) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, true);
addOrganizationMembersInternal(orgId, newMembers);
emit OrganizationModified(orgId);
}
function addOrganizationMembersInternal(bytes32 orgId, address[] memory newMembers) internal {
for (uint i = 0; i < newMembers.length; i++) {
if (orgsById[orgId].members[newMembers[i]] == 0) {
orgsById[orgId].memberKeys.push(newMembers[i]);
orgsById[orgId].members[newMembers[i]] = orgsById[orgId].memberKeys.length;
}
}
}
function removeOrganizationMembers(bytes32 orgId, address[] calldata existingMembers) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, true);
for (uint i = 0; i < existingMembers.length; i++) {
removeOrganizationMemberInternal(orgId, existingMembers[i]);
}
emit OrganizationModified(orgId);
}
function removeOrganizationMemberInternal(bytes32 orgId, address existingMember) internal {
// see "member indexing note"
if (orgsById[orgId].members[existingMember] != 0) {
uint storedIndexToRemove = orgsById[orgId].members[existingMember];
address memberToMove = orgsById[orgId].memberKeys[orgsById[orgId].memberKeys.length - 1];
// no-op if we are deleting the last entry
if (orgsById[orgId].memberKeys[storedIndexToRemove - 1] != memberToMove) {
// swap lut entries
orgsById[orgId].memberKeys[storedIndexToRemove - 1] = memberToMove;
orgsById[orgId].members[memberToMove] = storedIndexToRemove;
}
// shorten keys array
orgsById[orgId].memberKeys.pop();
// delete the mapping entry
delete orgsById[orgId].members[existingMember];
}
}
function deleteOrganization(bytes32 orgId) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, false);
for (uint serviceIndex = orgsById[orgId].serviceKeys.length; serviceIndex > 0; serviceIndex--) {
deleteServiceRegistrationInternal(orgId, orgsById[orgId].serviceKeys[serviceIndex-1]);
}
for (uint memberIndex = orgsById[orgId].memberKeys.length; memberIndex > 0; memberIndex--) {
removeOrganizationMemberInternal(orgId, orgsById[orgId].memberKeys[memberIndex-1]);
}
// swap lut entries
uint indexToUpdate = orgsById[orgId].globalOrgIndex;
bytes32 orgToUpdate = orgKeys[orgKeys.length-1];
if (orgKeys[indexToUpdate] != orgToUpdate) {
orgKeys[indexToUpdate] = orgToUpdate;
orgsById[orgToUpdate].globalOrgIndex = indexToUpdate;
}
// shorten keys array
orgKeys.pop();
// delete contents of organization registration
delete orgsById[orgId];
emit OrganizationDeleted(orgId);
}
// ____ _ __ __ _
// / ___| ___ _ ____ ___) ___ ___ | \/ | __ _ _ __ ___ | |_
// \___ \ / _ \ '__\ \ / / |/ __/ _ \ | |\/| |/ _` | '_ ` _ \| __|
// ___) | __/ | \ V /| | (__ __/ | | | | (_| | | | | | | |_
// |____/ \___|_| \_/ |_|\___\___| |_| |_|\__, |_| |_| |_|\__|
// |___/
function createServiceRegistration(bytes32 orgId, bytes32 serviceId, bytes calldata metadataURI) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, true);
requireServiceExistenceConstraint(orgId, serviceId, false);
ServiceRegistration memory service;
service.serviceId = serviceId;
service.metadataURI = metadataURI;
service.orgServiceIndex = orgsById[orgId].serviceKeys.length;
orgsById[orgId].servicesById[serviceId] = service;
orgsById[orgId].serviceKeys.push(serviceId);
emit ServiceCreated(orgId, serviceId, metadataURI);
}
function updateServiceRegistration(bytes32 orgId, bytes32 serviceId, bytes calldata metadataURI) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, true);
requireServiceExistenceConstraint(orgId, serviceId, true);
orgsById[orgId].servicesById[serviceId].metadataURI = metadataURI;
emit ServiceMetadataModified(orgId, serviceId, metadataURI);
}
function deleteServiceRegistration(bytes32 orgId, bytes32 serviceId) external override {
requireOrgExistenceConstraint(orgId, true);
requireAuthorization(orgId, true);
requireServiceExistenceConstraint(orgId, serviceId, true);
deleteServiceRegistrationInternal(orgId, serviceId);
emit ServiceDeleted(orgId, serviceId);
}
function deleteServiceRegistrationInternal(bytes32 orgId, bytes32 serviceId) internal {
// swap lut entries
uint indexToUpdate = orgsById[orgId].servicesById[serviceId].orgServiceIndex;
bytes32 serviceToUpdate = orgsById[orgId].serviceKeys[orgsById[orgId].serviceKeys.length-1];
if (orgsById[orgId].serviceKeys[indexToUpdate] != serviceToUpdate) {
orgsById[orgId].serviceKeys[indexToUpdate] = serviceToUpdate;
orgsById[orgId].servicesById[serviceToUpdate].orgServiceIndex = indexToUpdate;
}
orgsById[orgId].serviceKeys.pop();
// delete contents of service registration
delete orgsById[orgId].servicesById[serviceId];
}
// ____ _ _
// / ___| ___| |_| |_ ___ _ __ ___
// | | _ / _ \ __| __/ _ \ '__/ __|
// | |_| | __/ |_| |_ __/ | \__ \
// \____|\___|\__|\__\___|_| |___/
//
function listOrganizations() external override view returns (bytes32[] memory orgIds) {
return orgKeys;
}
function getOrganizationById(bytes32 orgId) external override view
returns(bool found, bytes32 id, bytes memory orgMetadataURI, address owner, address[] memory members, bytes32[] memory serviceIds) {
// check to see if this organization exists
if(orgsById[orgId].organizationId == bytes32(0x0)) {
found = false;
}
else {
found = true;
id = orgsById[orgId].organizationId;
orgMetadataURI = orgsById[orgId].orgMetadataURI;
owner = orgsById[orgId].owner;
members = orgsById[orgId].memberKeys;
serviceIds = orgsById[orgId].serviceKeys;
}
}
function listServicesForOrganization(bytes32 orgId) external override view returns (bool found, bytes32[] memory serviceIds) {
// check to see if this organization exists
if(orgsById[orgId].organizationId == bytes32(0x0)) {
found = false;
}
else {
found = true;
serviceIds = orgsById[orgId].serviceKeys;
}
}
function getServiceRegistrationById(bytes32 orgId, bytes32 serviceId) external override view
returns (bool found, bytes32 id, bytes memory metadataURI) {
// check to see if this organization exists
if(orgsById[orgId].organizationId == bytes32(0x0)) {
found = false;
}
else if(orgsById[orgId].servicesById[serviceId].serviceId == bytes32(0x0)) {
// check to see if this repo exists
found = false;
}
else {
found = true;
id = orgsById[orgId].servicesById[serviceId].serviceId;
metadataURI = orgsById[orgId].servicesById[serviceId].metadataURI;
}
}
// ERC165: https://eips.ethereum.org/EIPS/eip-165
//function supportsInterface(bytes4 interfaceID) external view returns (bool) {
// return
// interfaceID == this.supportsInterface.selector || // ERC165
// interfaceID == 0x3f2242ea; // IRegistry
//}
}
{
"compilationTarget": {
"Registry.sol": "Registry"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"}],"name":"OrganizationCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"}],"name":"OrganizationDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"}],"name":"OrganizationModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"metadataURI","type":"bytes"}],"name":"ServiceCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"serviceId","type":"bytes32"}],"name":"ServiceDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"metadataURI","type":"bytes"}],"name":"ServiceMetadataModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orgId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"serviceId","type":"bytes32"}],"name":"ServiceTagsModified","type":"event"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"address[]","name":"newMembers","type":"address[]"}],"name":"addOrganizationMembers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"bytes","name":"orgMetadataURI","type":"bytes"}],"name":"changeOrganizationMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOrganizationOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"bytes","name":"orgMetadataURI","type":"bytes"},{"internalType":"address[]","name":"members","type":"address[]"}],"name":"createOrganization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"internalType":"bytes","name":"metadataURI","type":"bytes"}],"name":"createServiceRegistration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"}],"name":"deleteOrganization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"bytes32","name":"serviceId","type":"bytes32"}],"name":"deleteServiceRegistration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"}],"name":"getOrganizationById","outputs":[{"internalType":"bool","name":"found","type":"bool"},{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"orgMetadataURI","type":"bytes"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address[]","name":"members","type":"address[]"},{"internalType":"bytes32[]","name":"serviceIds","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"bytes32","name":"serviceId","type":"bytes32"}],"name":"getServiceRegistrationById","outputs":[{"internalType":"bool","name":"found","type":"bool"},{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"metadataURI","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listOrganizations","outputs":[{"internalType":"bytes32[]","name":"orgIds","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"}],"name":"listServicesForOrganization","outputs":[{"internalType":"bool","name":"found","type":"bool"},{"internalType":"bytes32[]","name":"serviceIds","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"address[]","name":"existingMembers","type":"address[]"}],"name":"removeOrganizationMembers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orgId","type":"bytes32"},{"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"internalType":"bytes","name":"metadataURI","type":"bytes"}],"name":"updateServiceRegistration","outputs":[],"stateMutability":"nonpayable","type":"function"}]