Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: fix Python bindings to use async #2682

Merged
merged 18 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ant-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ prometheus-client = { version = "0.22", optional = true }
# watch out updating this, protoc compiler needs to be installed on all build systems
# arm builds + musl are very problematic
prost = { version = "0.9" }
pyo3 = { version = "0.20", features = ["extension-module"], optional = true }
pyo3 = { version = "0.23.4", features = ["extension-module"], optional = true }
rand = { version = "~0.8.5", features = ["small_rng"] }
rmp-serde = "1.1.1"
rayon = "1.8.0"
Expand Down
3 changes: 2 additions & 1 deletion ant-node/src/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ impl AntNode {
/// - Windows: C:\Users\<username>\AppData\Roaming\autonomi\node\<peer-id>
#[allow(clippy::redundant_closure)]
#[staticmethod]
#[pyo3(signature = (peer_id=None))]
fn get_default_root_dir(peer_id: Option<String>) -> PyResult<String> {
let peer_id = if let Some(id_str) = peer_id {
let id = id_str
Expand Down Expand Up @@ -467,7 +468,7 @@ impl AntNode {
/// Python module initialization
#[pymodule]
#[pyo3(name = "_antnode")]
fn init_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
fn init_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<AntNode>()?;
Ok(())
}
6 changes: 4 additions & 2 deletions autonomi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ name = "put_and_dir_upload"
[features]
default = []
external-signer = ["ant-evm/external-signer"]
extension-module = ["pyo3/extension-module"]
extension-module = ["pyo3/extension-module", "pyo3-async-runtimes"]
loud = []

[dependencies]
Expand All @@ -36,10 +36,12 @@ blstrs = "0.7.1"
bls = { package = "blsttc", version = "8.0.1" }
bytes = { version = "1.0.1", features = ["serde"] }
const-hex = "1.12.0"
eyre = "0.6.5"
futures = "0.3.30"
hex = "~0.4.3"
libp2p = "0.55.0"
pyo3 = { version = "0.20", optional = true, features = ["extension-module", "abi3-py38"] }
pyo3 = { version = "0.23.4", optional = true, features = ["extension-module", "abi3-py38"] }
pyo3-async-runtimes = { version = "0.23", optional = true, features = ["tokio-runtime"] }
rand = "0.8.5"
rayon = "1.8.0"
rmp-serde = "1.1.1"
Expand Down
32 changes: 1 addition & 31 deletions autonomi/python/autonomi_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,31 +1 @@
from .autonomi_client import (
Client,
Wallet,
PaymentOption,
VaultSecretKey,
UserData,
DataMapChunk,
encrypt,
ChunkAddress,
PointerTarget,
Pointer,
PointerAddress,
SecretKey,
PublicKey,
)

__all__ = [
"Client",
"Wallet",
"PaymentOption",
"VaultSecretKey",
"UserData",
"DataMapChunk",
"encrypt",
"ChunkAddress",
"PointerTarget",
"Pointer",
"PointerAddress",
"SecretKey",
"PublicKey",
]
from .autonomi_client import *
18 changes: 7 additions & 11 deletions autonomi/python/examples/autonomi_example.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from autonomi_client import Client, Wallet, PaymentOption
import asyncio

def main():
async def main():
# Initialize a wallet with a private key
# This should be a valid Ethereum private key (64 hex chars without '0x' prefix)
private_key = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
Expand All @@ -9,23 +10,18 @@ def main():
print(f"Wallet balance: {wallet.balance()}")

# Connect to the network
# These should be valid multiaddresses of network nodes
peers = [
"/ip4/127.0.0.1/tcp/12000",
"/ip4/127.0.0.1/tcp/12001"
]
client = Client.connect(peers)
client = await Client.init()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is much nicer


# Create payment option using the wallet
payment = PaymentOption.wallet(wallet)

# Upload some data
data = b"Hello, Safe Network!"
addr = client.data_put_public(data, payment)
addr = await client.data_put_public(data, payment)
print(f"Data uploaded to address: {addr}")

# Download the data back
downloaded = client.data_get_public(addr)
downloaded = await client.data_get_public(addr)
print(f"Downloaded data: {downloaded.decode()}")

# You can also upload files
Expand All @@ -34,5 +30,5 @@ def main():
file_addr = client.data_put_public(file_data, payment)
print(f"File uploaded to address: {file_addr}")

if __name__ == "__main__":
main()

asyncio.run(main())
56 changes: 29 additions & 27 deletions autonomi/python/examples/autonomi_pointers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,54 @@
Pointers allow for creating references to data that can be updated.
"""

from autonomi_client import Client, Wallet, PaymentOption, PublicKey, SecretKey, PointerTarget, ChunkAddress
from autonomi_client import Client, Network, Wallet, PaymentOption, SecretKey, PointerTarget, ChunkAddress, Pointer
import asyncio

def main():
async def main():
# Initialize a wallet with a private key
# This should be a valid Ethereum private key (64 hex chars without '0x' prefix)
private_key = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
wallet = Wallet(private_key)
# This should be a valid Ethereum private key (64 hex chars)
private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
network = Network(True)
wallet = Wallet.new_from_private_key(network, private_key)
print(f"Wallet address: {wallet.address()}")
print(f"Wallet balance: {wallet.balance()}")
print(f"Wallet balance: {await wallet.balance()}")

# Connect to the network
peers = [
"/ip4/127.0.0.1/tcp/12000",
"/ip4/127.0.0.1/tcp/12001"
]
client = Client.connect(peers)
client = await Client.init_local()

# First, let's upload some data that we want to point to
target_data = b"Hello, I'm the target data!"
target_addr = client.data_put_public(target_data, PaymentOption.wallet(wallet))
target_addr = await client.data_put_public(target_data, PaymentOption.wallet(wallet))
print(f"Target data uploaded to: {target_addr}")

# Create a pointer target from the address
chunk_addr = ChunkAddress.from_hex(target_addr)
target = PointerTarget.from_chunk_address(chunk_addr)
target = PointerTarget.from_chunk_address(ChunkAddress(target_addr))

# Create owner key pair
owner_key = SecretKey.new()
owner_pub = PublicKey.from_secret_key(owner_key)
key = SecretKey()

# Estimate the cost of the pointer
cost = await client.pointer_cost(key.public_key())
print(f"pointer cost: {cost}")

# Create the pointer
pointer = Pointer(key, 0, target)
payment_option = PaymentOption.wallet(wallet)

# Create and store the pointer
counter = 0 # Start with counter 0
client.pointer_put(owner_pub, counter, target, owner_key, wallet)
print(f"Pointer stored successfully")
pointer_addr = await client.pointer_put(pointer, payment_option)
print("Pointer stored successfully")

# Calculate the pointer address
pointer_addr = client.pointer_address(owner_pub, counter)
print(f"Pointer address: {pointer_addr}")
# Wait for the pointer to be stored by the network
await asyncio.sleep(1)

# Later, we can retrieve the pointer
pointer = client.pointer_get(pointer_addr)
print(f"Retrieved pointer target: {pointer.target().hex()}")
pointer = await client.pointer_get(pointer_addr)
print(f"Retrieved pointer target: {pointer}")

# We can then use the target address to get the original data
retrieved_data = client.data_get_public(pointer.target().hex())
retrieved_data = await client.data_get_public(pointer.target.hex)
print(f"Retrieved target data: {retrieved_data.decode()}")

if __name__ == "__main__":
main()

asyncio.run(main())
2 changes: 1 addition & 1 deletion autonomi/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl Client {

/// Initialize the client with the given configuration.
///
/// This will block until `CLOSE_GROUP_SIZE` have been added to the routing table.
/// This will block until [`CLOSE_GROUP_SIZE`] have been added to the routing table.
///
/// See [`ClientConfig`].
///
Expand Down
Loading
Loading