diff --git a/common/protob/messages-solana.proto b/common/protob/messages-solana.proto new file mode 100644 index 000000000..d62f07e29 --- /dev/null +++ b/common/protob/messages-solana.proto @@ -0,0 +1,43 @@ +syntax = "proto2"; +package hw.trezor.messages.solana; + +import "messages-common.proto"; + +/** + * Request: Ask device for public key corresponding to address_n path + * @start + * @next SolanaPublicKey + * @next Failure + */ +message SolanaGetPublicKey { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bool show_display = 2; // optionally show on display before sending the result +} + +/** + * Response: Contains public key derived from device private seed + * @end + */ +message SolanaPublicKey { + required string xpub = 1; // Xpub key + required hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 public node +} + +/** + * Request: Ask device for Solana address + * @start + * @next SolanaAddress + * @next Failure + */ +message SolanaGetAddress { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bool show_display = 2; // optionally show on display before sending the result +} + +/** + * Response: Contains a Solana address derived from device private seed + * @end + */ +message SolanaAddress { + required string address = 1; // Solana address as Base58 encoded string +} diff --git a/common/protob/messages.proto b/common/protob/messages.proto index dd8119141..a3350143d 100644 --- a/common/protob/messages.proto +++ b/common/protob/messages.proto @@ -359,4 +359,10 @@ enum MessageType { MessageType_WebAuthnCredentials = 801 [(wire_out) = true]; MessageType_WebAuthnAddResidentCredential = 802 [(wire_in) = true]; MessageType_WebAuthnRemoveResidentCredential = 803 [(wire_in) = true]; + + // Solana + MessageType_SolanaGetPublicKey = 900 [(wire_in) = true]; + MessageType_SolanaPublicKey = 901 [(wire_out) = true]; + MessageType_SolanaGetAddress = 902 [(wire_in) = true]; + MessageType_SolanaAddress = 903 [(wire_out) = true]; } diff --git a/core/src/trezor/enums/MessageType.py b/core/src/trezor/enums/MessageType.py index 75b9228f0..203de339d 100644 --- a/core/src/trezor/enums/MessageType.py +++ b/core/src/trezor/enums/MessageType.py @@ -233,3 +233,7 @@ if not utils.BITCOIN_ONLY: WebAuthnCredentials = 801 WebAuthnAddResidentCredential = 802 WebAuthnRemoveResidentCredential = 803 + SolanaGetPublicKey = 900 + SolanaPublicKey = 901 + SolanaGetAddress = 902 + SolanaAddress = 903 diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py index e562b556f..5d3e37086 100644 --- a/core/src/trezor/enums/__init__.py +++ b/core/src/trezor/enums/__init__.py @@ -251,6 +251,10 @@ if TYPE_CHECKING: WebAuthnCredentials = 801 WebAuthnAddResidentCredential = 802 WebAuthnRemoveResidentCredential = 803 + SolanaGetPublicKey = 900 + SolanaPublicKey = 901 + SolanaGetAddress = 902 + SolanaAddress = 903 class FailureType(IntEnum): UnexpectedMessage = 1 diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index f111e2375..482ac2201 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -5102,6 +5102,68 @@ if TYPE_CHECKING: def is_type_of(cls, msg: Any) -> TypeGuard["RipplePayment"]: return isinstance(msg, cls) + class SolanaGetPublicKey(protobuf.MessageType): + address_n: "list[int]" + show_display: "bool | None" + + def __init__( + self, + *, + address_n: "list[int] | None" = None, + show_display: "bool | None" = None, + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["SolanaGetPublicKey"]: + return isinstance(msg, cls) + + class SolanaPublicKey(protobuf.MessageType): + xpub: "str" + node: "HDNodeType" + + def __init__( + self, + *, + xpub: "str", + node: "HDNodeType", + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["SolanaPublicKey"]: + return isinstance(msg, cls) + + class SolanaGetAddress(protobuf.MessageType): + address_n: "list[int]" + show_display: "bool | None" + + def __init__( + self, + *, + address_n: "list[int] | None" = None, + show_display: "bool | None" = None, + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["SolanaGetAddress"]: + return isinstance(msg, cls) + + class SolanaAddress(protobuf.MessageType): + address: "str" + + def __init__( + self, + *, + address: "str", + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["SolanaAddress"]: + return isinstance(msg, cls) + class StellarAsset(protobuf.MessageType): type: "StellarAssetType" code: "str | None" diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 2d6926b4c..19bbf2d51 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -259,6 +259,10 @@ class MessageType(IntEnum): WebAuthnCredentials = 801 WebAuthnAddResidentCredential = 802 WebAuthnRemoveResidentCredential = 803 + SolanaGetPublicKey = 900 + SolanaPublicKey = 901 + SolanaGetAddress = 902 + SolanaAddress = 903 class FailureType(IntEnum): @@ -6519,6 +6523,71 @@ class RipplePayment(protobuf.MessageType): self.destination_tag = destination_tag +class SolanaGetPublicKey(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 900 + FIELDS = { + 1: protobuf.Field("address_n", "uint32", repeated=True, required=False, default=None), + 2: protobuf.Field("show_display", "bool", repeated=False, required=False, default=None), + } + + def __init__( + self, + *, + address_n: Optional[Sequence["int"]] = None, + show_display: Optional["bool"] = None, + ) -> None: + self.address_n: Sequence["int"] = address_n if address_n is not None else [] + self.show_display = show_display + + +class SolanaPublicKey(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 901 + FIELDS = { + 1: protobuf.Field("xpub", "string", repeated=False, required=True), + 2: protobuf.Field("node", "HDNodeType", repeated=False, required=True), + } + + def __init__( + self, + *, + xpub: "str", + node: "HDNodeType", + ) -> None: + self.xpub = xpub + self.node = node + + +class SolanaGetAddress(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 902 + FIELDS = { + 1: protobuf.Field("address_n", "uint32", repeated=True, required=False, default=None), + 2: protobuf.Field("show_display", "bool", repeated=False, required=False, default=None), + } + + def __init__( + self, + *, + address_n: Optional[Sequence["int"]] = None, + show_display: Optional["bool"] = None, + ) -> None: + self.address_n: Sequence["int"] = address_n if address_n is not None else [] + self.show_display = show_display + + +class SolanaAddress(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 903 + FIELDS = { + 1: protobuf.Field("address", "string", repeated=False, required=True), + } + + def __init__( + self, + *, + address: "str", + ) -> None: + self.address = address + + class StellarAsset(protobuf.MessageType): MESSAGE_WIRE_TYPE = None FIELDS = {