Introducing pysui

pysui is the Python Sui RPC API Client SDK.

The role of Sui Binaries

pysui roughly relies on Sui Binaries for one core reason

  • If publishing or publishing upgrades, these functions rely on the
    presence of the binaries during the publish call as it invokes: sui move build
  • When not running with user configuration, creating a Client relies on the presence of the client.yaml the Sui binaries created.
    For example, if SuiConfig is created with pysui.sui.sui_config.SuiConfig.default_config() it looks for:
    .sui/sui_config/client.yaml

The Clients

All pysui SDK usage commonly starts with the creation of one or more SuiClients. Their job is handling the interactions between itself and the SUI blockchain via the SUI RPC API.

pysui SDK includes synchronous and asynchronous clients for interacting with SUI RPC API and an asynchronous client for subscriptions.

The first two client types have the same methods (parity) so it is a matter of choice, or necessity, on which to use. It is pretty much standard that the client is allocated at the very begining of your application. Here are examples of doing just that as well as allocating a subscription client:

 1 # The underlying configuration class
 2 from pysui import SuiConfig
 3
 4 # For synchronous RPC API interactions
 5 from pysui import SyncClient
 6
 7 # For asynchronous RPC API interactions
 8 from pysui import AsyncClient
 9
10 # For asynchronous subscriptions interactions
11 from pysui import Subscribe
12
13 # Synchronous client
14 client = SyncClient(SuiConfig.default_config())
15
16 # Asynchronous client
17 client = AsyncClient(SuiConfig.default_config())
18
19 # Asynchronous subscriber
20 client = Subscribe(SuiConfig.default_config())

The raw workhorse for submitting transactions is pysui.sui.sui_clients.sync_client.SuiClient.execute() which takes a Builder object. Builders describe the RPC call, any parameters and how to format sucessful results.

While some of the SuiClient convenience methods (e.g. pysui.sui.sui_clients.sync_client.SuiClient.get_object()) take care of creating a Builder for the caller, and then executing, all Builders are available to setup outside of the SuiClient.

Running With suibase

We have aligned with The sui-base utility which provides superior localnet configurability and repeatability. It is the framework for our pysui unit/integration testing and we’ve made usage easier to leverage in developing with pysui.

In the code block above, you will notice the use of SuiConfig.default_config() which is driven by the standard client.yaml.

Whereas with suibase it loads a persistant, and configurable, Sui configuration along with 5 addresses of each keytype and providing a copius amount of Sui coin per address.

First ensure proper setup of sui-base:

 1 # From ~/
 2 git clone git@github.com:sui-base/suibase.git
 3
 4 # Install sui-base scripts
 5 cd suibase
 6 ./install
 7
 8 # Generate and start a local node
 9 # This will clone the Sui source and buid the sui binary and sui-faucet
10 localnet start
11
12 # Ensure that active symlink is set to localnet
13 localnet set-active

Having compleded that, the change you will notices is loading the right configuration into your SuiClient so all operations interact with the sui-base localnet node. All operations are the same whether you are interacting with devnet, testnet, mainnet or the sui-base localnode. So once you set the client correctly all code should behave as normal:

 1 # The underlying configuration class
 2 from pysui import SuiConfig
 3
 4 # For synchronous RPC API interactions
 5 from pysui import SyncClient
 6
 7 # For asynchronous RPC API interactions
 8 from pysui import AsyncClient
 9
10 # For asynchronous subscriptions interactions
11 from pysui import Subscribe
12
13 # Synchronous client
14 client = SyncClient(SuiConfig.sui_base_config()) # Assumes sui-base localnet is running
15
16 # Asynchronous client
17 client = AsyncClient(SuiConfig.sui_base_config()) # Assumes sui-base localnet is running
18
19 # Asynchronous subscriber
20 client = Subscribe(SuiConfig.sui_base_config()) # Assumes sui-base localnet is running

Remember to shutdown suibase when done:

1 # When you are done you should stop the localnode
2 localnet stop

Running With user configuration

A new option for loading a configuration was added in pysui 0.25.0: pysui.sui.sui_config.SuiConfig.user_config()

With this option, you set the rpc_url, keystrings and optional web socket url. For example:

 1 # The underlying configuration class
 2 from pysui import SuiConfig, SyncClient
 3
 4 # Option-1: Setup configuration with one or more known keystrings and optional web services.
 5 cfg = SuiConfig.user_config(
 6     # Required
 7     rpc_url="https://fullnode.devnet.sui.io:443",
 8
 9     # Optional. First entry becomes the 'active-address'
10     # List elemente must be a valid Sui base64 keystring (i.e. 'key_type_flag | private_key_seed' )
11     # List can contain a dict for importing Wallet keys for example:
12     # prv_keys=['AO.....',{'wallet_key': '0x.....', 'key_scheme': SignatureScheme.ED25519}]
13     #   where
14     #   wallet_key value is 66 char hex string
15     #   key_scheme can be ED25519, SECP256K1 or SECP256R1
16     prv_keys=["AOM6UAQrFe7r9nNDGRlWwj1o7m1cGK6mDZ3efRJJmvcG"],
17
18     # Optional, only needed for subscribing
19     ws_url="wss://fullnode.devnet.sui.io:443",
20 )
21
22 # Option-2: Alternate setup configuration without keystrings or web sercices
23 cfg = SuiConfig.user_config(rpc_url="https://fullnode.devnet.sui.io:443")
24
25 # One address (and keypair), at least, should be created
26 # First becomes the 'active-address'
27 _mnen, _address = cfg.create_new_keypair_and_address(SignatureScheme.ED25519)
28
29 # Synchronous client
30 client = SyncClient(cfg)

Caveats

With user configuraiton, as it does not assume the installation of Sui binaries, the following are considerations:

  1. You can not publish or upgrade Sui move contracts, attempting to do so will thow a ValueError exception

  2. Any new address/keypair creations will not be persisted as user_config is emphemeral