SingularityNET Platform SDK goals to provide a convenient programming interface for the application developers who want to use variety of AI models in their applications or even provide this capability to their users.
SDK protocol describes the structure, entities and functionality for the SingularityNET Platform SDK regardless of the implementation language.
Specific implementation of the SingularityNET Platform SDK may differ in its internal structure and entities but must maintain compatibility of all SDK interfaces with corresponding essential platform components.
Note: This section includes mandatory requirements for implementation.
This is a general scenario for an SDK user.
- creating a
Config's instance with the required values - creating a
SNETEngine's instance with the config passed to it - adding new account (wallet) (
Account) to the engine by callingSNETEngine's method (not necessary, but most likely will be needed) - creating new
ServiceClient's instance by callingSNETEngine's method (not necessary, but most likely will be needed).
Now the SDK functionality is available through instances of the entities SNETEngine
and ServiceClient.
- ServiceClient → call
- ServiceClient → PaymentChannel → functions of the MPE contract for the channel
(e.g.
add funds,extend expiraton) - ServiceClient → ServiceMetadata → functions for editing service metadata, as well as for publishing metadata to metadata provider, and downloading metadata from it
- SNETEngine → Channels → functions of the MPE contract for the set of channels
(e.g.
open channel,load channels) - SNETEngine → MPEContract → functions of the MPE contract for the account
(e.g.
claim,deposit) (in fact, MPEContract contains all the functionality of MPE, but access to other functions is more convenient in other ways (through other entities)) - SNETEngine → RegistryContract → functions of the Registry contract for services and organizations
- SNETEngine → MetadataProvider → OrgMetadata → functions for editing organization metadata, as well as for publishing metadata to metadata provider, and downloading metadata from it
Note: The presented structure is just one possible implementation. It doesn't have to be followed in its entirety, but it's worth using as an example.
All entities can be divided into 4 layers:
Config Layercontains entities with many fields, that are needed to configure SDK.- At
Interface Layerthere are entities through which users have access toFunctional Layer. Functional Layercontains in its entities all the functionality of the SDK that users may need.Tools Layercontains entities with various auxiliary functionality required for the operation of the functional level.
Note: The presented structure and entities is just one possible implementation. It doesn't have to be followed in its entirety, but it's worth using as an example.
Account is an abstract entity. It's the base entity to EthAccount and others that are planned to be
implemented to work with other blockchains on the SNET platform.
EthAccount implements Account. It is needed to identify user wallet in the Ethereum blockchain.
It contains all the fields, that need to be known for it to work correctly
(e.g. private key, mnemonic phrase, wallet address etc.).
Its instance is created using a name, account type (key, mnemonic or ledger)
and corresponding secret, the remaining fields are initialized automatically by Web3 by default.
Contains almost no logic, only account data.
- name
- address
- account type
- private key (optional)
- mnemonic phrase (optional)
- index (optional)
- nonce
- address determination by key/mnemonic/ledger by using Web3
- updating the nonce value and comparison it with the value received via Web3
Config is the main configuration entity containing all the data needed to work
in the SNET platform. It contains entry point, network name, blockchain type, smart contract
addresses (optional) and some other options. These values are specified when creating
an instance, which is then passed to SNETEngine.
- blockchain entry point
- blockchain type
- network name
- accounts (list/map)
- MPE, Registry, AGIX contracts addresses (optional)
- forced update protobuf files (bool) (optional)
- concurrency (bool) (optional)
- adding an account
- getting an account
SNETEngine is the most important entity from the user side. Config's instance
is installed in it, and new accounts and service clients are created by using it.
SNETEngine creates and contains instances of almost all entities from
Functional Layer (MPEContract, RegistryContract, MetadatProvider etc.),
so they are accessed through it, and therefore most of the SDK functions are accessible
from SNETEngine.
Config's instance- an instance of a Web3 library entity that will be passed to all dependent entities
MPEContract's instanceRegistryContract's instanceAGIXContract's instance- an instance of the metadata provider implementation
GRPCLibGenerator's instanceChannels's instance
- creating new
Account - creating and initializing new
Service - providing the user with access to
MPEContract's instance or to its functionality - providing the user with access to
RegistryContract's instance or to its functionality - providing the user with access to
AGIXContract's instance or to its functionality - providing the user with access to metadata provider or to its functionality
Service is an entity that allows an account to call a service and also call contracts and
metadata provider functionality related on service. It contains the most important abstract method
call for calling a service with given parameters. It's the base entity to ServiceClientByGRPC and
others that are planned to be implemented to access daemons using other methods, such as REST API.
- organization id
- service id
- payment group
- service metadata
- payment strategy
Account's instance (it's got from the owner's entitySNETEngine)Channels's instance (it's got from the owner's entitySNETEngine)MPEContract's instance (it's got from the owner's entitySNETEngine)RegistryContract's instance (it's got from the owner's entitySNETEngine)- an instance of the metadata provider implementation (it's got from the owner's entity
SNETEngine) - an instance of a Web3 library entity (it's got from the owner's entity
SNETEngine)
- call a service with given parameters (abstract)
- providing the user with access to
MPEContract's instance functionality related on channels - providing the user with access to
RegistryContract's instance functionality related on services - providing the user with access to metadata provider functionality related on service metadata
- getting service information
ServiceClientByGRPC extends ServiceClient. It allows you to call service functions by
communicating with the daemon via gRPC
- grpc channel
- data needed for grpc call
- protobuf modules
- implementation of a service call with given parameters via gRPC
Contract is an abstract entity. It contains abstract methods to call read and
write functions of smart contracts. It's the base entity to EthContract and others that are planned
to be implemented to work with other blockchains on the SNET platform.
EthContract implements Contract. It allows you to call read functions and perform
transactions for calling write functions of smart contracts in Ethereum. EthContract is the base
entity for MPEContract, RegistryContract and AGIXContract.
- an instance of a Web3 library entity (it's got from the owner's entity
SNETEngine) - smart contract object from Web3 library
- contract address
- getting Web3 library contract object by name and optionally address (using
snet.contractslibrary) - getting contract info from Web3 library contract object
- calling contract read functions by name and parameters
- calling contract write functions by name and parameters and execution of the entire transaction pipeline:
- building transaction
- signing transaction (using
TransactionHandler) - sending transaction (using
TransactionHandler) - processing transaction result
- getting and increasing gas price to efficiently execute a transaction on the blockchain using the following algorithm (in Python)
def _get_gas_price(self):
gas_price = self.w3.eth.gas_price
if gas_price <= 15000000000:
gas_price += gas_price * 1 / 3
elif 15000000000 < gas_price <= 50000000000:
gas_price += gas_price * 1 / 5
elif 50000000000 < gas_price <= 150000000000:
gas_price += 7000000000
elif gas_price > 150000000000:
gas_price += gas_price * 1 / 10
return int(gas_price)MPEContract extends EthContract. It's an entity that provides all the functionality from
MultyPartyEscrow Contract.
AGIXContract's instance (it's got from the owner's entitySNETEngine)
- calling read functions:
- balance
- channels
- calling write functions:
- deposit
- openChannel
- channelExtendAndAddFunds
- etc.
- Using
AGIXContractin functions where it is needed
RegistryContract extends EthContract. It's an entity that provides all the functionality from
Registry Contract.
- calling read functions:
- getOrganizationById
- getServiceRegistrationById
- etc.
- calling write functions:
- createOrganization
- updateServiceRegistration
- etc.
MetadataProvider is an abstract entity. It allows you to keep (save and get) organization and
service metadata (and by the way also .proto files). It's the base entity to IPFSMetadataProvider
and others that are planned to be implemented to work with other external file storages on
the SNET platform.
- getting organization metadata from external storage (abstract)
- getting service metadata from external storage (abstract)
- getting
.protofiles from external storage (abstract) - publishing organization metadata in external storage (abstract)
- publishing service metadata in external storage (abstract)
- publishing
.protoin from external storage (abstract)
IPFSMetadataProvider implements MetadataProvider. It allows you to work with metadata and
.proto files using Interplanetary Filesystem (IPFS).
RegistryContract's instance (it's got from the owner's entitySNETEngine)- an instance of a IPFS HTTP client entity from the corresponding library
- directory for storage protobuf files
- implementation of parent methods for IPFS
- converting hash to URL (bytes) and back
PaymentChannel is an entity that stores information about an open channel and allows the functions
provided by MPE to be performed on it.
- channel id
- an instance of a Web3 library entity (it's got from the owner's entity
Channels) - account
MPEContract's instance (it's got from the owner's entityChannels)- channel state
- MPE functions applied to account and channel data, such as:
- addFunds
- extendExpiration
- etc.
- channel state synchronization with MPE
Channels is an entity that stores set of PaymentChannels and allows services to interact with
them effectively.
- channels (list/map)
- an instance of a Web3 library entity (it's got from the owner's entity
SNETEngine) MPEContract's instance (it's got from the owner's entitySNETEngine)- MPE deployment block
- storing channels information (
PaymentChannels) - search for channels in blockchain
- MPE functions applied to channels, such as:
- openChannel
- etc.
GRPCLibGenerator is an entity needed to generate stub files in a specific language.
IPFSMetadataProvider's instance (it's got from the owner's entitySNETEngine)RegistryContract's instance (it's got from the owner's entitySNETEngine)
- generation of
stubfiles based on specified organization and service ids, including:- getting service metadata from Registry
- getting
.protofile from IPFS - compiling
.protofile tostubfile and saving it in a given directory
AGIXContract extends EthContract. It's an entity that provides the functionality from
SingularityNET AGIX Token Contract.
-
- calling read functions:
- allowance
- balanceOf
- etc.
-
- calling write functions:
- approve
- transfer
- etc.
ServiceMetadata is an entity for manipulating service metadata. It is possible that there may
be other entities inside for complex metadata fields. Below is an example of service metadata.
{
"version": 1,
"display_name": "Example service",
"encoding": "proto",
"service_type": "grpc",
"model_ipfs_hash": "QmeyrQkEyba8dd4rc3jrLd5pEwsxHutfH2RvsSaeSMqTtQ",
"mpe_address": "0x7E0aF8988DF45B824b2E0e0A87c6196897744970",
"groups": [
{
"free_calls": 0,
"free_call_signer_address": "0x7DF35C98f41F3Af0df1dc4c7F7D4C19a71Dd059F",
"daemon_addresses": [
"0x0709e9b78756b740ab0c64427f43f8305fd6d1a7"
],
"pricing": [
{
"default": true,
"price_model": "fixed_price",
"price_in_cogs": 1
}
],
"endpoints": [
"http://node1.naint.tech:62400"
],
"group_id": "/mb90Qs8VktxGQmU0uRu0bSlGgqeDlYrKrs+WbsOvOQ=",
"group_name": "default_group"
}
],
"service_description": {
"url": "https://ropsten-v2-publisher.singularitynet.io/org",
"short_description": "Example service",
"description": "Example service"
},
"media": [
{
"order": 1,
"url": "https://ropsten-marketplace-service-assets.s3.us-east-1.amazonaws.com/26072b8b6a0e448180f8c0e702ab6d2f/services/d05c62bf9aa84843a195457d98417f4e/assets/20240327124952_asset.jpeg",
"file_type": "image",
"asset_type": "hero_image",
"alt_text": ""
}
],
"contributors": [
{
"name": "test",
"email_id": ""
}
],
"tags": [
"exampleservice"
]
}- map (or just fields) with service data
- updating fields value
- adding new data to fields that are lists (media, groups, etc.)
- removing data from fields that are lists (media, groups, etc.)
- converting from
jsonand back
ServiceMetadata is an entity for manipulating organization metadata. It is possible that there may
be other entities inside for complex metadata fields. Below is an example of organization metadata.
{
"org_name": "Snet_test",
"org_id": "26072b8b6a0e448180f8c0e702ab6d2f",
"org_type": "individual",
"description": {
"description": "Snet_test",
"short_description": "Snet_test",
"url": "https://ropsten-v2-publisher.singularitynet.io"
},
"assets": {
"hero_image": "QmfTjcwBYwWCp5hdC5E3DRyHBFafaCVHDs1cCammDYkQPE/20240327124724_asset.jpeg"
},
"contacts": [
{
"email": "",
"phone": "+18005551234",
"contact_type": "general"
},
{
"email": "test@gmail.com",
"phone": "+18005551234",
"contact_type": "support"
}
],
"groups": [
{
"group_name": "default_group",
"group_id": "/mb90Qs8VktxGQmU0uRu0bSlGgqeDlYrKrs+WbsOvOQ=",
"payment": {
"payment_address": "0x0709e9B78756B740ab0C64427f43f8305fD6D1A7",
"payment_expiration_threshold": 40320,
"payment_channel_storage_type": "etcd",
"payment_channel_storage_client": {
"connection_timeout": "5s",
"request_timeout": "3s",
"endpoints": [
"https://127.0.0.1:2379"
]
}
}
}
]
}- map (or just fields) with organization data
- updating fields value
- adding new data to fields that are lists (groups, contacts, etc.)
- removing data from fields that are lists (groups, contacts, etc.)
- converting from
jsonand back
TransactionHandler is an abstract entity. It allows you to conduct transactions. TransactionHandler
is the base entity to LedgerTransactionHandler and KeyOrMnemonicTransactionHandler.
- signing transaction
- sending transaction
- getting wallet address
- signing message
LedgerTransactionHandler implements TransactionHandler. It allows you to conduct transactions
using ledger.
- address
- index
- dongle path
- connecting to ledger
KeyOrMnemonicTransactionHandler implements TransactionHandler. It allows you to conduct transactions
using key or mnemonic with index.
- private key
- address
- implementation parent's functionality using Web3
PaymentStrategy is an abstract entity. It's needed for execution of various types of payments. PaymentStrategy
is the base entity to DefaultPaymentStrategy, FreeCallPaymentStrategy, FreeCallPaymentStrategy
and PaidCallPaymentStrategy.
- getting call price (abstract)
- getting payment metadata (abstract)
DefaultPaymentStrategy implements PaymentStrategy. This payment strategy is used by default when
the user does not specify which strategy to use. And in fact, this is not a separate strategy, this entity,
depending on various conditions, chooses strategy from FreeCallPaymentStrategy, FreeCallPaymentStrategy
and PaidCallPaymentStrategy.
ConcurrencyManager's instance- channel
- choosing payment strategy
FreeCallPaymentStrategy implements PaymentStrategy. This payment strategy can be used when the user
has free service call tokens.
- checking for free call tokens
- implementation of parent's functionality for free-call type of call
PrepaidPaymentStrategy implements PaymentStrategy. This strategy can be used when the user has deposited
funds into the channel in advance and wants to pay for several calls at once.
ConcurrencyManager's instance (it's got from the owner's entity, usually fromDefaultPaymentStrategy)- call allowance
- block offset (240 by default)
- providing concurrency
- implementation of parent's functionality for prepaid type of call
- selecting channel with checking for its presence, amount and expiration
FreeCallPaymentStrategy implements PaymentStrategy. This payment strategy can be used when the user
wants to call the service once.
- call allowance
- block offset (240 by default)
- implementation of parent's functionality
- selecting channel with checking for its presence, amount and expiration
ConcurrencyManager is an entity that organizes and controls concurrency by turning to the daemon.
- amount of concurrent calls
- token
- planned and used amount
- working with channel
- getting token from daemon
- control of planned and used funds
Utils is an entity that contains a set of functions used in many other entities.
- validation of URL
- validation of endpoint
- getting address from private key and mnemonic
- getting data from abi
- etc.
Note: This section includes mandatory requirements for implementation.
Payment for service calls on the Singularity NET platform is made using the Singularity NET Token (AGIX) through a payment channel. To realize a service call on the platform, there are smart contracts. Each of them is responsible for a specific functionality.
The main purpose of MPE is to manage payment channels. For a call to be successful, a suitable payment channel must be open, it must have sufficient funds and it must not be overdue. MPE is needed to manage this and monitor the channels.
Here are the functions of this contract that the SDK must be able to call
balances- returns MPE balancechannels- returns the channel's stateopenChannel- opens a new channel with a given amount of funds and expirationchannelAddFunds- adds funds to the channelchannelExtend- extends the expiration of the channelchannelExtendAndAddFunds- extends the expiration of the channel and adds fundsdeposit- deposits funds into the MPEdepositAndOpenChannel- deposits funds into the MPE and opens a new channel with the same amount of funds and a given expirationwithdraw- withdraws funds from the MPE back to the walletchannelClaim- claims funds from the channel (for the service providers)multiChannelClaim- claims funds from multiple channels (for the service providers)channelClaimTimeout- claims funds from the channel if the channel has expired (for the service consumers)
You can see the implementation of MultiPartyEscrow in Ethereum here.
Registry is designed to manage data about organizations and services, as well as their metadata. With its help you can register an organization and a service, as well as get URI to their metadata in storage providers (and from the service metadata you can get a URI to the service API).
Here are the functions of this contract that the SDK must be able to call
getOrganizationById- returns organization datagetServiceRegistrationById- returns service URIlistOrganizations- returns list of organization IDslistServicesForOrganization- returns list of service IDs for an organizationcreateOrganization- creates an organizationdeleteOrganization- deletes an organizationcreateServiceRegistration- creates a servicedeleteServiceRegistration- deletes a serviceupdateServiceRegistration- updates service metadata URIaddOrganizationMembers- adds members to the organizationremoveOrganizationMembers- removes members from the organizationchangeOrganizationMetadataURI- changes organization metadata URIchangeOrganizationOwner- changes organization owner
You can see the implementation of Registry in Ethereum here.
The AGIX Token is an ERC-20 token that powers the SingularityNet platform. In the SDK, this contract is needed to check the balance and deposit funds into the MPE
Here are the functions of this contract that the SDK must be able to call
balanceOf- returns balance of the walletallowance- returns the allowance for spendingapprove- approves a spender (particularly MPE) to take a certain amount of your funds
You can see the implementation of SingularityNET AGIX Token in Ethereum here
The storage provider is designed to store metadata of services and organizations, as well as services (daemons) APIs.
Organization and service metadata URI are stored in Registry. Service API source (URI) is stored in service metadata
in the field service_api_source.
URI is a string consisting of a prefix with the name of the storage and the identifier of the file in that storage
<STORAGE_NAME>://<FILE_IDENTIFIER>. The organization and service metadata URIs stored in the registry are
additionally encoded in ASCII format and padded with null bytes.
URI example: ipfs://<IPFS_HASH>
URI example: filecoin://<FILECOIN_CID>
Interaction with the daemon is currently carried out only using gRPC. To call the service, you need to get the service API (.proto files) from the storage provider, compile them and call any of the described methods via gRPC. In addition, the daemon has methods that are the same for everyone. Therefore, the SDK stores .proto files for the following services, which are the same for all daemons:
state_service- needed to determine the current state of the channelcontrol_service- needed to change the configuration of the daemontoken_service- needed for concurrency implementationtraining- needed to work with AI models

