use async_trait::async_trait;
use ledger_sdk_device_base::App;
use ledger_sdk_transport::Exchange;
pub mod commands;
pub mod errors;
pub mod instructions;
pub mod types;
pub mod utils;
pub use commands::*;
pub use errors::*;
pub use types::*;
#[derive(Debug, Clone)]
pub struct EthApp;
impl App for EthApp {
const CLA: u8 = 0xE0;
}
#[derive(Debug)]
pub struct EthereumApp<E: Exchange> {
transport: E,
}
impl<E: Exchange> EthereumApp<E> {
pub fn new(transport: E) -> Self {
Self { transport }
}
pub fn transport(&self) -> &E {
&self.transport
}
}
#[async_trait]
impl<E> GetAddress<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn get_address(
transport: &E,
params: GetAddressParams,
) -> EthAppResult<PublicKeyInfo, E::Error> {
EthApp::get_address(transport, params).await
}
}
#[async_trait]
impl<E> GetConfiguration<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn get_configuration(transport: &E) -> EthAppResult<AppConfiguration, E::Error> {
EthApp::get_configuration(transport).await
}
}
#[async_trait]
impl<E> SignPersonalMessage<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn sign_personal_message(
transport: &E,
params: SignMessageParams,
) -> EthAppResult<Signature, E::Error> {
EthApp::sign_personal_message(transport, params).await
}
}
#[async_trait]
impl<E> SignTransaction<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn sign_transaction(
transport: &E,
params: SignTransactionParams,
) -> EthAppResult<Signature, E::Error> {
EthApp::sign_transaction(transport, params).await
}
async fn sign_transaction_with_mode(
transport: &E,
params: SignTransactionParams,
mode: commands::sign_transaction::TransactionMode,
) -> EthAppResult<Option<Signature>, E::Error> {
EthApp::sign_transaction_with_mode(transport, params, mode).await
}
}
#[async_trait]
impl<E> SignEip712V0<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn sign_eip712_v0(
transport: &E,
params: SignEip712Params,
) -> EthAppResult<Signature, E::Error> {
EthApp::sign_eip712_v0(transport, params).await
}
}
#[async_trait]
impl<E> SignEip712Full<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn sign_eip712_full(transport: &E, path: &BipPath) -> EthAppResult<Signature, E::Error> {
EthApp::sign_eip712_full(transport, path).await
}
}
#[async_trait]
impl<E> Eip712StructDef<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn send_struct_definition(
transport: &E,
struct_def: &Eip712StructDefinition,
) -> EthAppResult<(), E::Error> {
EthApp::send_struct_definition(transport, struct_def).await
}
}
#[async_trait]
impl<E> Eip712StructImpl<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn send_struct_implementation(
transport: &E,
struct_impl: &Eip712StructImplementation,
) -> EthAppResult<(), E::Error> {
EthApp::send_struct_implementation(transport, struct_impl).await
}
async fn set_array_size(transport: &E, size: u8) -> EthAppResult<(), E::Error> {
EthApp::set_array_size(transport, size).await
}
}
#[async_trait]
impl<E> Eip712Filtering<E> for EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
async fn send_filter_config(
transport: &E,
filter_params: &Eip712FilterParams,
) -> EthAppResult<(), E::Error> {
EthApp::send_filter_config(transport, filter_params).await
}
async fn activate_filtering(transport: &E) -> EthAppResult<(), E::Error> {
EthApp::activate_filtering(transport).await
}
}
impl<E> EthereumApp<E>
where
E: Exchange + Send + Sync,
E::Error: std::error::Error,
{
pub async fn get_address(
&self,
params: GetAddressParams,
) -> EthAppResult<PublicKeyInfo, E::Error> {
EthApp::get_address(&self.transport, params).await
}
pub async fn get_configuration(&self) -> EthAppResult<AppConfiguration, E::Error> {
EthApp::get_configuration(&self.transport).await
}
pub async fn sign_personal_message(
&self,
params: SignMessageParams,
) -> EthAppResult<Signature, E::Error> {
EthApp::sign_personal_message(&self.transport, params).await
}
pub async fn sign_transaction(
&self,
params: SignTransactionParams,
) -> EthAppResult<Signature, E::Error> {
EthApp::sign_transaction(&self.transport, params).await
}
pub async fn sign_transaction_with_mode(
&self,
params: SignTransactionParams,
mode: commands::sign_transaction::TransactionMode,
) -> EthAppResult<Option<Signature>, E::Error> {
EthApp::sign_transaction_with_mode(&self.transport, params, mode).await
}
pub async fn sign_eip712_v0(
&self,
params: SignEip712Params,
) -> EthAppResult<Signature, E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_v0() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 v0 requires app version >= 1.5.0, found {}",
config.version
)));
}
EthApp::sign_eip712_v0(&self.transport, params).await
}
pub async fn sign_eip712_full(&self, path: &BipPath) -> EthAppResult<Signature, E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 full implementation requires app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::sign_eip712_full(&self.transport, path).await
}
pub async fn send_struct_definition(
&self,
struct_def: &Eip712StructDefinition,
) -> EthAppResult<(), E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 struct definitions require app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::send_struct_definition(&self.transport, struct_def).await
}
pub async fn send_struct_implementation(
&self,
struct_impl: &Eip712StructImplementation,
) -> EthAppResult<(), E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 struct implementations require app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::send_struct_implementation(&self.transport, struct_impl).await
}
pub async fn set_array_size(&self, size: u8) -> EthAppResult<(), E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 array operations require app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::set_array_size(&self.transport, size).await
}
pub async fn send_filter_config(
&self,
filter_params: &Eip712FilterParams,
) -> EthAppResult<(), E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 filtering requires app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::send_filter_config(&self.transport, filter_params).await
}
pub async fn activate_filtering(&self) -> EthAppResult<(), E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 filtering requires app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::activate_filtering(&self.transport).await
}
pub async fn sign_eip712_typed_data(
&self,
path: &BipPath,
typed_data: &Eip712TypedData,
) -> EthAppResult<crate::types::Signature, E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 typed data signing requires app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::sign_eip712_typed_data(&self.transport, path, typed_data).await
}
pub async fn sign_eip712_from_json(
&self,
path: &BipPath,
json_str: &str,
) -> EthAppResult<crate::types::Signature, E::Error> {
let config = self.get_configuration().await?;
if !config.version.supports_eip712_full() {
return Err(EthAppError::UnsupportedVersion(format!(
"EIP-712 JSON signing requires app version >= 1.9.19, found {}",
config.version
)));
}
EthApp::sign_eip712_from_json(&self.transport, path, json_str).await
}
}