Skip to main content

snet-sdk-python

SingularityNET SDK for Python

Package

The package is published in PyPI at the following link:

Package Description
snet.sdk Integrate SingularityNET services seamlessly into Python applications

Core concepts

The SingularityNET SDK allows you to make calls to SingularityNET services programmatically from your application. To communicate between clients and services, SingularityNET uses gRPC. To handle payment of services, SingularityNET uses Ethereum state channels. The SingularityNET SDK abstracts and manages state channels with service providers on behalf of the user and handles authentication with the SingularityNET services.

Getting Started

These instructions are for the development and use of the SingularityNET SDK for Python.

Usage

To call a service on a SingularityNET platform, the user must be able to deposit funds (AGIX tokens) to the Multi-Party Escrow Smart Contract. To deposit these tokens or do any other transaction on the Ethereum blockchain.

Once you have installed snet-sdk in your current environment, you can import it into your Python script and create an instance of the base sdk class:

from snet import sdk

config = sdk.config.Config(private_key="YOUR_PRIVATE_KEY",
                               eth_rpc_endpoint=f"https://sepolia.infura.io/v3/YOUR_INFURA_KEY",
                               concurrency=False,
                               force_update=False)

snet_sdk = sdk.SnetSDK(config)

The config parameter is an instance of the Config class. See config.py for a reference.

Config parameters description
  • private_key: Your wallet's private key that will be used to pay for calls. Is required in config;
  • eth_rpc_endpoint: RPC endpoint that is used to access the Ethereum network. Is required in config;
  • wallet_index: The index of the wallet that will be used to pay for calls;
  • ipfs_endpoint: IPFS endpoint that is used to access IPFS;
  • concurrency: If set to True, will enable concurrency for the SDK;
  • force_update: If set to False, will reuse the existing gRPC stubs (if any) instead of downloading proto and regenerating them every time.
  • mpe_contract_address: The address of the Multi-Party Escrow smart contract;
  • token_contract_address: The address of the SingularityNET token smart contract;
  • registry_contract_address: The address of the Registry smart contract;
  • signer_private_key: The private key of the signer. Used to sign the service call. Equals to private_key by default.

List organizations and their services

You can use the sdk client instance`s methods get_organization_list() to list all organizations and get_services_list("org_id") to list all services of a given organization.

orgs_list = snet_sdk.get_organization_list()
print(*orgs_list, sep="\n")
# ...
# GoogleOrg3
# 26072b8b6a0e448180f8c0e702ab6d2f
# 43416d873fcb454589900189474b2eaa
# ...
org_id = "26072b8b6a0e448180f8c0e702ab6d2f"
services_list = snet_sdk.get_services_list(org_id=org_id)
print(*services_list, sep="\n")
# Exampleservice

Calling the service

Now, the instance of the sdk can be used to create the service client instances, using create_service_client() method.
Continuing from the previous code here is an example using Exampleservice from the 26072b8b6a0e448180f8c0e702ab6d2f organization:

service_client = snet_sdk.create_service_client(org_id="26072b8b6a0e448180f8c0e702ab6d2f", 
                                                service_id="Exampleservice",
                                                group_name="default_group")

After executing this code, you should have client libraries created for this service. They are located at the following path: ~/.snet/org_id/service_id/python/

Note: Currently you can only save files to ~/.snet/.

The instance of service_client that has been generated can be utilized to invoke the methods that the service offers. You can list these using the get_services_and_messages_info_as_pretty_string() method:

print(service_client.get_services_and_messages_info_as_pretty_string())
# Service: Calculator
#   Method: add, Input: Numbers, Output: Result
#   Method: sub, Input: Numbers, Output: Result
#   Method: mul, Input: Numbers, Output: Result
#   Method: div, Input: Numbers, Output: Result
# Message: Numbers
#   Field: float a
#   Field: float b
# Message: Result
#   Field: float value

To invoke the service's methods, you can use the call_rpc() method. This method requires the names of the method and data object, along with the data itself, to be passed into it. To continue with our example, here’s a call to the mul method of the Exampleservice from the 26072b8b6a0e448180f8c0e702ab6d2f organization:

result = service_client.call_rpc("mul", "Numbers", a=20, b=3)
print(f"Calculating 20 * 3: {result}") 
#  Calculating 20 * 3: 60.0

For more information about gRPC and how to use it with Python, please see:

Note: In this example, the user doesn't deposit funds to MPE, doesn't open a channel, and doesn't perform other actions related to payment. In this case, the choice of payment strategy, as well as, if necessary, opening a channel and depositing funds into MPE occurs automatically. For more information on payment, please visit the Payment section.

Payment

Free call

If you want to use the free calls you will need to pass these arguments to the create_service_client() method:

free_call_auth_token_bin = "f2548d27ffd319b9c05918eeac15ebab934e5cfcd68e1ec3db2b92765",
free_call_token_expiry_block = 172800

You can receive these for a given service from the Dapp

Creating a service client with free calls included would look like this:

service_client = snet_sdk.create_service_client(org_id="26072b8b6a0e448180f8c0e702ab6d2f", 
                                                service_id="Exampleservice",
                                                group_name="default_group",
                                                free_call_auth_token_bin="f2548d27ffd319b9c05918eeac15ebab934e5cfcd68e1ec3db2b92765",
                                                free_call_token_expiry_block=172800)

Paid call

Open channel with the specified amount of funds and expiration

open_channel()[1] opens a payment channel with the specified amount of AGIX tokens in cogs and expiration time. Expiration is payment channel's TTL in blocks. When opening a channel, funds are taken from MPE. So they must be pre-deposited on it. For this, you can use the deposit_to_escrow_account()[1] method.

snet_sdk.account.deposit_to_escrow_account(123456)
service_client.open_channel(amount=123456, expiration=33333)

You can also use the deposit_and_open_channel()[1] method instead. It does the same as the previous one, but first deposits the specified amount of AGIX tokens in cogs into an MPE.

service_client.deposit_and_open_channel(amount=123456, expiration=33333)

Extend expiration and add funds

open_channel() as well as deposit_and_open_channel() returns the payment channel. You can use it to add funds to it and extend its expiration using the following methods: add_funds()[1], extend_expiration[1] and extend_and_add_funds()[1].

payment_channel = service_client.open_channel(amount=123456, expiration=33333)

payment_channel.add_funds(amount=123456)
payment_channel.extend_expiration(expiration=33333)

payment_channel.extend_and_add_funds(amount=123456, expiration=33333)

Other useful features

Get the current block number

Service client also provides several useful functions. If you need to find out the number of the current block in the blockchain, there is a get_current_block_number() method for this:

block_number = service_client.get_current_block_number()
print(f"Current block is {block_number}")
# Current block is 6574322

Get the service call price

To find out the price of calling a service function, you need to use the get_price() method:

price = service_client.get_price()
print(f"The price in cogs for calling the service {service_client.service_id} is {price}")
# The price in cogs for calling the service Exampleservice is 1

Get the metadata of the service

The metadata of services is stored in IPFS. To view it, you need to call the get_service_metadata() method, passing the organization id and the service id to it.

service_metadata = snet_sdk.get_service_metadata(org_id="26072b8b6a0e448180f8c0e702ab6d2f", service_id="Exampleservice")
print(*service_metadata.m.items(), sep="\n", end="\n\n")
print(*service_metadata.get_tags(), sep=",", end="\n\n")
print(*service_metadata.get_all_endpoints_for_group(group_name="default_group"), sep=",", end="\n\n")

# ('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'])
# 
# exampleservice
# 
# http://node1.naint.tech:62400

Get raw services and messages info

In the section Calling the service we already talked about the function get_services_and_messages_info_as_pretty_string(), with which you can get information about the methods and messages of a service. But if you need to process lists of services and messages, it is better to use the get_services_and_messages_info() method.

services, messages = service_client.get_services_and_messages_info()
print(services)
print(messages)

# {'Calculator': [('add', 'Numbers', 'Result'), ('sub', 'Numbers', 'Result'), ('mul', 'Numbers', 'Result'), ('div', 'Numbers', 'Result')]}
# {'Numbers': [('float', 'a'), ('float', 'b')], 'Result': [('float', 'value')]}

1 This method uses a call to a paid smart contract function.

Development

Installing

Prerequisites


  • Clone the git repository
$ git clone git@github.com:singnet/snet-sdk-python.git
$ cd snet-sdk-python
  • Install the required dependencies
$ pip install -r requirements.txt
  • Install the package in development/editable mode
$ pip install -e .

License

This project is licensed under the MIT License - see the LICENSE file for details.

Metadata

Release files for snet-sdk 3.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for snet-sdk 3.5.0
File Size Uploaded
snet.sdk-3.5.0.tar.gz 186.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for snet-sdk 3.5.0
File Interpreter ABI Platform
snet.sdk-3.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 383.2 kB

Release files / snet.sdk-3.5.0.tar.gz

Download URL snet.sdk-3.5.0.tar.gz
Size 186.7 kB
Tags Source
SHA-256 checksum
How to use checksums
9a7a2280a87684c049d74a8a80fc41f828d0c4572dc7e7199c18e8c401bac93a
BLAKE2b-256 checksum
How to use checksums
ec85897c36cf8d2057bfc29d9a88c0f0d2645f44d9ae96a11777ba5028350fc0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.7

Release files / snet.sdk-3.5.0-py3-none-any.whl

Download URL snet.sdk-3.5.0-py3-none-any.whl
Size 196.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5d1f28d5bc4194aaa067d9966bd1982612f43e0bd53a37edf08f0bfa4aa5f43
BLAKE2b-256 checksum
How to use checksums
215650a9bf75b7459ee18a4c9383b6bff549f71f0c086d077b04889459e2f5ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.7

Release history Release notifications | RSS feed

6.0.0

2 release files

5.1.0

2 release files

5.0.0

2 release files

4.0.0

2 release files

3.7.2

2 release files

3.7.1

2 release files

3.7.0

2 release files

3.6.1

2 release files

3.6.0

2 release files

3.5.1

2 release files

This release

3.5.0 This release

2 release files

3.4.1

2 release files

3.4.0

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.1

2 release files

3.1.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.0.9

2 release files

2.0.8

2 release files

2.0.6

2 release files

2.0.5

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

1.0.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page