Tesseract is the way any wallet can provide its users with the advantage of being able to use the dApps.
Implementing Tesseract Protocol in a wallet is surprisingly simple. It all boils down to creating a persisting Tesseract
instance and registering services and transports that the wallet is planning to support.
let tesseract = tesseract_service::Tesseract::new()
.transport(plt::service::ServiceLocalTransport::new(&link))
.service(TestPolkadotService {});
In real world wallet, the tesseract
variable should be stored somewhere for a longer lifespan.
Now let's break it down: what are transports and what are services.
Transports represent the ways a dApp can connect to the wallet. Network, IPC, etc. The only thing that the wallet developer needs to take care about is to instantiate all the desired transports and register them within the Tesseract instance during Tesseract initialization.
//From the Playground example
let link = Arc::new(LocalLink::new());
let _ = tesseract_service::Tesseract::new()
.transport(plt::service::ServiceLocalTransport::new(&link));
This code creates a working Tesseract instance, capable of serving requests through a LocalTransport
.
In simple words, service represents a blockchain network. Like Polkadot. Or Bitcoin. Or Ethereum.
Every blockchain network is unique, has its own signature types, addresses, etc. and thus has to be implemenented with its own service. The service is the way, how the wallet responds to the request of a dApp: provides addresses, signs transactions, etc.
In many ways implementing a Tesseract service is very similar to implementing a web service.
struct TestPolkadotService {}
#[async_trait]
impl polkadot::service::PolkadotService for TestPolkadotService {
async fn sign_transaction(self: Arc<Self>, req: String) -> Result<String> {
if req == "make_error" {
Err(Error::described(
ErrorKind::Weird,
"intentional error for test",
))
} else {
Ok(req + "_signed!")
}
}
}
The code above is an example from Tesseract Playground test app and implements the test service protocol. The sign_transaction
method is executed every time the wallet is requested to sign a transaction by a dApp. It's a good place to present the user with a UI.
Also, due to some Rust limitations a bit of boilerplate code is required:
impl tesseract_service::Service for TestPolkadotService {
type Protocol = polkadot::Polkadot;
fn protocol(&self) -> &polkadot::Polkadot {
&polkadot::Polkadot::Network
}
fn to_executor(self) -> Box<dyn tesseract_service::Executor + Send + Sync> {
Box::new(crate::polkadot::service::PolkadotExecutor::from_service(
self,
))
}
}
This section will get populated once we have the Rust implementation finished and the crates published. For now, please, consider checking out the Playground:
- Install your Rust environment: https://www.rust-lang.org/tools/install
- Clone this repo:
git clone https://github.com/tesseract-one/Tesseract.rs.git
- Go to the playground
cd Tesseract.rs/tesseract-playground/
- Run the playground
cargo run
Tesseract.rs can be used, distributed and modified under the Apache 2.0 license.