You can imagine our API and libraries as a stack or an “onion” with several layers: the underlying library, SAFE Core, doesn’t have any notion of apps, Authenticator, or a browser. It’s just an abstract way to talk to the network, putting and getting structures like Immutable Data or Mutable Data. On top of that library we have a higher-level interfaces: SAFE App, the API to build apps, and SAFE Authenticator, the API for the “app centre”, for dealing with the users’ accounts, etc. And on the higher level we have the FFI interface: the functions that we expose to the world from Rust, and these functions can be used from any language, including Python.
So the problem on your side is that you’re looking at the lower-level Rust API; you’d want to use this API if you want to write your own libraries and layers like safe_authenticator or safe_app on top of safe_core. Instead, if you want to just write apps in Python, you’ll want to use the safe_appFFI layer, which is currently documented here: https://docs.rs/safe_app/0.4.0/safe_app/ffi/index.html
Unfortunately though, we don’t provide any official Python bindings yet, so for now you’ll have to write your own or use an automatic generator. I’d suggest trying to look into the CFFI library in Python: this library allows you to import function and type definitions from C headers, which we automatically generate and provide in safe_client_libs (just look inside the auto-gen/c-include directory after you manually build the libs).
Please let me know if this explanation doesn’t make much sense to you or if you have further questions
Thanks very much for this explanation, it helps a lot.
To add some context to my initial question (ie not looking for a response):
My main motivation is to be able to use safe via a scripting / non-gui interface with login and permissions etc all managed automatically. This goes against the canonical ‘safe app’ way of doing things (ie everything approved by the user via the browser / authenticator and developers using apps as the gateway to the network - from the getting started doc “When the user approves the request…” is the part I want to automate).
I can understand the desire to wrap everything around the app concept, but I find the way this a pretty unempowering interface. For now it’s fine, I’ll just write my code in rust so I can still do things at the very lowest level, but I think maybe in the future cleanly exposing the lowest level network interfaces will be useful (despite the security implications for end-users).
I prefer to be able to set permissions and authentication in $HOME/.safe_config file and let my safe apps run in the background with no gui or input needed.
But all the same I’m having a blast working with alpha2 so thanks for all the work so far
I too would like to be able to run scripts against an account. IoT stuff has so many methods, procedures etc that having something that I can script will make an easy path to integration in some cases.
Nothing prevents you from doing that now, actually. You can create your own minimal headless Authenticator on top of the safe_authenticator lib: the SAFE Browser and its Authenticator plugin aren’t magical, they’re too just apps that use the SAFE Client Libs underneath. And the Authenticator API is exposed and documented too, so you might want to experiment with it and build a terminal/non-GUI Authenticator that approves every request that it gets
So what I want to say is that it’s more a question of security/user interface rather than the technical ability. But yes, for now we don’t provide a native headless mode in the SAFE Browser, as @joshuefanswered here.
I know they’re outdated, but I’m just trying to find some examples on how to work directly with safe_client_libs via native rust in order to make some simple/basic command line programs. It seemed like safe_core/examples/self_authentication.rs is was going to be a good start but it gives me build errors.
I’m looking forward to the ~30 page guide from @polpolrene that was slated to be released soon…
Examples are there mainly for this purpose: to help you understand the native Rust API better, and they should work without requiring any changes. However, if you want to run them on the real network (i.e. not mock-routing), you’ll have to provide your credentials through environment variables.
Could you please provide more details about the build errors you’ve encountered?
The build errors look to be from api changes related to error messages being moved to private implementations and also from changes w.r.t. tokio connections. Example:
error[E0432]: unresolved import tokio_core::channel
51 | use tokio_core::channel;
| ^^^^^^^^^^^^^^^^^^^ no channel in the root
Ah sure, that’s why I am asking for details, wanting to help
You’re right, some of the examples haven’t yet been ported from the previous version of the SAFE Client Libs API (the pre-authenticator one). Others can be a bit complicated but you can check e.g. client_stress_test and gen_invites for working examples.
You should also bear in mind that the Rust Client Libs API is built upon the foundation of futures (which quickly became idiomatic in Rust). So you might want to read more on the futures API and examples too.
Most of the operations go through the Client interface which is defined and implemented in safe_core. That way you can talk to the network directly; but it can be rather overwhelming if you want to go to the territory of SAFE Authenticator and apps. That’s why we have a multitude of helper functions in safe_app and safe_authenticator.
If you just want to create an app, you’ll need to go through the App interface, providing your credentials. It will connect to the network, create the event loop, etc., and then you can use the App.send method to obtain a Client instance and perform network operations. You can also find multiple usage examples in safe_app tests.
It’s unfortunate that currently Rust examples are scattered around numerous places. This is caused by the API itself being very unstable at the time. Now that it’s been stabilised, we intend to improve the documentation in the foreseeable future.
If you have any other questions or if my description wasn’t clear enough, please don’t hesitate to ask!
I’m looking forward to the java bindings for the same reason. I moth balled my java fuse project as the rest API was being removed. I haven’t had much spare time to pursue this anyway, but I don’t think the java client libs are at a point where I could easily use them yet.
I am looking forward to working on this again though, especially when I may be out of contract in the summer.
i have been trying to get some more insight about python and safe and the C API
First of all: nope - i’m far away from our goal to utilize the C API from python and i would appreciate others helping and finding ways to make this happen
… but i thought if i share my experiences here maybe others do have hints or get motivated to help out =D …
As I understand the API all exposed functions are functions “without return values” - i call the functions and hand over a couple of data structures and those functions modify my structures (please correct me if i’m completely on the wrong train here)
like this i don’t need to care about return values/data types there … i just read the current status in those data structures and if i need to do something i ask the library nicely to do that for me and will see the result in the structures.
here we go… what i got running: i just added a very simple function to the library and a struct containing numeric data types:
…now the tiny problem i have is that as soon as i try to connect to something string-like everything stops working …
there seem to be differences between c-strings and rust strings, and i would assume that a C-API expects char-arrays … so the “standard-c-strings” that are being created as char containing a byte-structure … if i’m not mistaken …
…i know this really is not much … but it’s more knowledge about how this is supposed to work before this weekend xD so maybe it helps someone else …