diff --git a/common/defs/support.json b/common/defs/support.json
index 348122827c..f6f0aa5752 100644
--- a/common/defs/support.json
+++ b/common/defs/support.json
@@ -706,5 +706,123 @@
"nem:PAC:HRT": "not for T3W1 (#2793)",
"nem:XEM": "not for T3W1 (#2793)"
}
+ },
+ "T2W1": {
+ "supported": {
+ "bitcoin:ACM": "2.6.1",
+ "bitcoin:AXE": "2.6.1",
+ "bitcoin:BCH": "2.6.1",
+ "bitcoin:BTC": "2.6.1",
+ "bitcoin:BTCP": "2.6.1",
+ "bitcoin:BTX": "2.6.1",
+ "bitcoin:CPU": "2.6.1",
+ "bitcoin:CRW": "2.6.1",
+ "bitcoin:DOGE": "2.6.1",
+ "bitcoin:ELEMENTS": "2.6.1",
+ "bitcoin:FIRO": "2.6.1",
+ "bitcoin:FJC": "2.6.1",
+ "bitcoin:FLO": "2.6.1",
+ "bitcoin:FTC": "2.6.1",
+ "bitcoin:GRS": "2.6.1",
+ "bitcoin:KMD": "2.6.1",
+ "bitcoin:KOTO": "2.6.1",
+ "bitcoin:LTC": "2.6.1",
+ "bitcoin:MONA": "2.6.1",
+ "bitcoin:PPC": "2.6.1",
+ "bitcoin:QTUM": "2.6.1",
+ "bitcoin:REGTEST": "2.6.1",
+ "bitcoin:RITO": "2.6.1",
+ "bitcoin:RVN": "2.6.1",
+ "bitcoin:SMART": "2.6.1",
+ "bitcoin:SYS": "2.6.1",
+ "bitcoin:TAZ": "2.6.1",
+ "bitcoin:TBCH": "2.6.1",
+ "bitcoin:TEST": "2.6.1",
+ "bitcoin:UNO": "2.6.1",
+ "bitcoin:VIA": "2.6.1",
+ "bitcoin:VIPS": "2.6.1",
+ "bitcoin:XEC": "2.8.6",
+ "bitcoin:XPM": "2.6.1",
+ "bitcoin:XRC": "2.6.1",
+ "bitcoin:XSN": "2.6.1",
+ "bitcoin:XVG": "2.6.1",
+ "bitcoin:ZCR": "2.6.1",
+ "bitcoin:ZEC": "2.6.1",
+ "bitcoin:tFIRO": "2.6.1",
+ "bitcoin:tGRS": "2.6.1",
+ "bitcoin:tLTC": "2.6.1",
+ "bitcoin:tPPC": "2.6.1",
+ "bitcoin:tQTUM": "2.6.1",
+ "bitcoin:tRVN": "2.6.1",
+ "bitcoin:tSMART": "2.6.1",
+ "erc20:bnb:ATOM": "2.6.1",
+ "erc20:eth:AAVE": "2.6.1",
+ "erc20:eth:APE": "2.6.1",
+ "erc20:eth:AXS": "2.6.1",
+ "erc20:eth:BUSD": "2.6.1",
+ "erc20:eth:CHZ": "2.6.1",
+ "erc20:eth:CRO": "2.6.1",
+ "erc20:eth:DAI": "2.6.1",
+ "erc20:eth:FRAX": "2.6.1",
+ "erc20:eth:LEO": "2.6.1",
+ "erc20:eth:LINK": "2.6.1",
+ "erc20:eth:MANA": "2.6.1",
+ "erc20:eth:MATIC": "2.6.1",
+ "erc20:eth:OKB": "2.6.1",
+ "erc20:eth:QNT": "2.6.1",
+ "erc20:eth:SAND": "2.6.1",
+ "erc20:eth:SHIB": "2.6.1",
+ "erc20:eth:STETH": "2.6.1",
+ "erc20:eth:UNI": "2.6.1",
+ "erc20:eth:USDC": "2.6.1",
+ "erc20:eth:USDT": "2.6.1",
+ "erc20:eth:WBTC": "2.6.1",
+ "erc20:eth:XCN": "2.6.1",
+ "erc20:matic:WAVAX": "2.6.1",
+ "eth:ARB:42161": "2.6.1",
+ "eth:BASE:8453": "2.6.1",
+ "eth:BSC:56": "2.6.1",
+ "eth:ETC:61": "2.6.1",
+ "eth:ETH:1": "2.6.1",
+ "eth:OP:10": "2.6.1",
+ "eth:POL:137": "2.6.1",
+ "eth:tHOL:17000": "2.6.1",
+ "eth:tSEP:11155111": "2.6.1",
+ "misc:ADA": "2.6.1",
+ "misc:BNB": "2.6.1",
+ "misc:DSOL": "2.6.4",
+ "misc:MAID": "2.6.1",
+ "misc:OMNI": "2.6.1",
+ "misc:SOL": "2.6.4",
+ "misc:USDT": "2.6.1",
+ "misc:XLM": "2.6.1",
+ "misc:XMR": "2.6.1",
+ "misc:XRP": "2.6.1",
+ "misc:XTZ": "2.6.1",
+ "misc:tADA": "2.6.1",
+ "misc:tXRP": "2.6.1"
+ },
+ "unsupported": {
+ "bitcoin:BTG": "not for T3W1 (#2793)",
+ "bitcoin:DASH": "not for T3W1 (#2793)",
+ "bitcoin:DCR": "not for T3W1 (#2793)",
+ "bitcoin:DGB": "not for T3W1 (#2793)",
+ "bitcoin:NMC": "not for T3W1 (#2793)",
+ "bitcoin:PART": "incompatible fork",
+ "bitcoin:TBTG": "not for T3W1 (#2793)",
+ "bitcoin:TDCR": "not for T3W1 (#2793)",
+ "bitcoin:TRC": "address_type collides with Bitcoin",
+ "bitcoin:VTC": "not for T3W1 (#2793)",
+ "bitcoin:tDASH": "not for T3W1 (#2793)",
+ "bitcoin:tPART": "incompatible fork",
+ "misc:EOS": "not for T3W1 (#2793)",
+ "misc:LSK": "Incompatible mainnet hard-fork",
+ "nem:BREEZE": "not for T3W1 (#2793)",
+ "nem:DIM": "not for T3W1 (#2793)",
+ "nem:DIMTOK": "not for T3W1 (#2793)",
+ "nem:PAC:CHS": "not for T3W1 (#2793)",
+ "nem:PAC:HRT": "not for T3W1 (#2793)",
+ "nem:XEM": "not for T3W1 (#2793)"
+ }
}
}
diff --git a/core/embed/io/nrf/stm32f4/nrf.c b/core/embed/io/nrf/stm32f4/nrf.c
new file mode 100644
index 0000000000..b642fcd956
--- /dev/null
+++ b/core/embed/io/nrf/stm32f4/nrf.c
@@ -0,0 +1,763 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef KERNEL_MODE
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "../crc8.h"
+#include "../nrf_internal.h"
+
+#define MAX_SPI_DATA_SIZE (244)
+
+typedef struct {
+ uint8_t service_id;
+ uint8_t data[MAX_SPI_DATA_SIZE];
+ uint8_t crc;
+} spi_packet_t;
+
+typedef struct {
+ uint8_t service_id;
+ uint8_t msg_len;
+ uint8_t data[NRF_MAX_TX_DATA_SIZE + 1];
+ // uint8_t crc; part of data, as it has variable position
+} uart_packet_t;
+
+#define UART_OVERHEAD_SIZE (sizeof(uart_packet_t) - NRF_MAX_TX_DATA_SIZE)
+#define UART_HEADER_SIZE (UART_OVERHEAD_SIZE - 1)
+
+#define TX_QUEUE_SIZE (8)
+
+#define START_BYTE (0xA0)
+
+typedef struct {
+ uart_packet_t packet;
+ nrf_tx_callback_t callback;
+ void *context;
+} nrf_tx_request_t;
+
+typedef struct {
+ UART_HandleTypeDef urt;
+ DMA_HandleTypeDef urt_tx_dma;
+
+ uint8_t tx_buffers[TX_QUEUE_SIZE][sizeof(nrf_tx_request_t)];
+ tsqueue_entry_t tx_queue_entries[TX_QUEUE_SIZE];
+ tsqueue_t tx_queue;
+ nrf_tx_request_t tx_request;
+ int32_t tx_request_id;
+
+ uart_packet_t rx_buffer;
+ uint8_t rx_len;
+ uint8_t rx_byte;
+ uint16_t rx_idx;
+
+ SPI_HandleTypeDef spi;
+ DMA_HandleTypeDef spi_dma;
+ spi_packet_t long_rx_buffer;
+
+ bool comm_running;
+ bool initialized;
+
+ nrf_rx_callback_t service_listeners[NRF_SERVICE_CNT];
+
+} nrf_driver_t;
+
+__attribute__((section(".buf"))) static nrf_driver_t g_nrf_driver = {0};
+
+static void nrf_start(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return;
+ }
+
+ HAL_SPI_Receive_DMA(&drv->spi, (uint8_t *)&drv->long_rx_buffer,
+ sizeof(spi_packet_t));
+
+ tsqueue_reset(&drv->tx_queue);
+ HAL_UART_Receive_IT(&drv->urt, &drv->rx_byte, 1);
+
+ drv->comm_running = true;
+
+ nrf_signal_running();
+}
+
+static void nrf_abort_urt_comm(nrf_driver_t *drv) {
+ HAL_UART_AbortReceive(&drv->urt);
+ HAL_UART_AbortTransmit(&drv->urt);
+
+ if (drv->tx_request.callback != NULL) {
+ drv->tx_request.callback(NRF_STATUS_ERROR, drv->tx_request.context);
+ }
+
+ drv->rx_idx = 0;
+ drv->rx_len = 0;
+ drv->tx_request_id = -1;
+
+ while (tsqueue_dequeue(&drv->tx_queue, (uint8_t *)&drv->tx_request,
+ sizeof(nrf_tx_request_t), NULL, NULL)) {
+ if (drv->tx_request.callback != NULL) {
+ drv->tx_request.callback(NRF_STATUS_ERROR, drv->tx_request.context);
+ }
+ }
+
+ memset(&drv->tx_request, 0, sizeof(nrf_tx_request_t));
+
+ tsqueue_reset(&drv->tx_queue);
+}
+
+static void nrf_stop(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return;
+ }
+
+ nrf_signal_off();
+ irq_key_t key = irq_lock();
+ drv->comm_running = false;
+ HAL_SPI_DMAStop(&drv->spi);
+ nrf_abort_urt_comm(drv);
+ irq_unlock(key);
+}
+
+void nrf_init(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+
+ if (drv->initialized) {
+ return;
+ }
+
+ __HAL_RCC_USART1_CLK_ENABLE();
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ __HAL_RCC_SPI2_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+
+ memset(drv, 0, sizeof(*drv));
+ tsqueue_init(&drv->tx_queue, drv->tx_queue_entries,
+ (uint8_t *)drv->tx_buffers, sizeof(nrf_tx_request_t),
+ TX_QUEUE_SIZE);
+
+ GPIO_InitTypeDef GPIO_InitStructure = {0};
+
+ // synchronization signals
+ NRF_OUT_RESET_CLK_ENA();
+ HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_SET);
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Pull = GPIO_PULLDOWN;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Pin = NRF_OUT_RESET_PIN;
+ HAL_GPIO_Init(NRF_OUT_RESET_PORT, &GPIO_InitStructure);
+
+ NRF_IN_GPIO0_CLK_ENA();
+ GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStructure.Pull = GPIO_PULLDOWN;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Pin = NRF_IN_GPIO0_PIN;
+ HAL_GPIO_Init(NRF_IN_GPIO0_PORT, &GPIO_InitStructure);
+
+ NRF_IN_FW_RUNNING_CLK_ENA();
+ GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStructure.Pull = GPIO_PULLDOWN;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Pin = NRF_IN_FW_RUNNING_PIN;
+ HAL_GPIO_Init(NRF_IN_FW_RUNNING_PORT, &GPIO_InitStructure);
+
+ NRF_OUT_STAY_IN_BLD_CLK_ENA();
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Pin = NRF_OUT_STAY_IN_BLD_PIN;
+ HAL_GPIO_Init(NRF_OUT_STAY_IN_BLD_PORT, &GPIO_InitStructure);
+
+ NRF_OUT_FW_RUNNING_CLK_ENA();
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Pin = NRF_OUT_FW_RUNNING_PIN;
+ HAL_GPIO_Init(NRF_OUT_FW_RUNNING_PORT, &GPIO_InitStructure);
+
+ // UART PINS
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Alternate = GPIO_AF7_USART1;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+
+ GPIO_InitStructure.Pin = GPIO_PIN_9;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
+ GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_11;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
+ GPIO_InitStructure.Pin = GPIO_PIN_12;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ drv->urt.Init.Mode = UART_MODE_TX_RX;
+ drv->urt.Init.BaudRate = 1000000;
+ drv->urt.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
+ drv->urt.Init.OverSampling = UART_OVERSAMPLING_16;
+ drv->urt.Init.Parity = UART_PARITY_NONE;
+ drv->urt.Init.StopBits = UART_STOPBITS_1;
+ drv->urt.Init.WordLength = UART_WORDLENGTH_8B;
+ drv->urt.Instance = USART1;
+ drv->urt.hdmatx = &drv->urt_tx_dma;
+
+ drv->urt_tx_dma.Instance = DMA2_Stream7;
+ drv->urt_tx_dma.State = HAL_DMA_STATE_RESET;
+ drv->urt_tx_dma.Init.Channel = DMA_CHANNEL_4;
+ drv->urt_tx_dma.Init.Direction = DMA_MEMORY_TO_PERIPH;
+ drv->urt_tx_dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ drv->urt_tx_dma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
+ drv->urt_tx_dma.Init.MemBurst = DMA_MBURST_SINGLE;
+ drv->urt_tx_dma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ drv->urt_tx_dma.Init.MemInc = DMA_MINC_ENABLE;
+ drv->urt_tx_dma.Init.Mode = DMA_NORMAL;
+ drv->urt_tx_dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
+ drv->urt_tx_dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ drv->urt_tx_dma.Init.PeriphInc = DMA_PINC_DISABLE;
+ drv->urt_tx_dma.Init.Priority = DMA_PRIORITY_HIGH;
+
+ drv->urt_tx_dma.Parent = &drv->urt;
+ HAL_DMA_Init(&drv->urt_tx_dma);
+
+ HAL_UART_Init(&drv->urt);
+
+ NVIC_SetPriority(DMA2_Stream7_IRQn, IRQ_PRI_NORMAL);
+ NVIC_EnableIRQ(DMA2_Stream7_IRQn);
+ NVIC_SetPriority(USART1_IRQn, IRQ_PRI_NORMAL);
+ NVIC_EnableIRQ(USART1_IRQn);
+
+ // SPI pins
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_MEDIUM;
+ GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
+ GPIO_InitStructure.Pin = GPIO_PIN_3;
+ HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
+ GPIO_InitStructure.Pin = GPIO_PIN_9;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+ drv->spi_dma.Instance = DMA1_Stream3;
+ drv->spi_dma.State = HAL_DMA_STATE_RESET;
+ drv->spi_dma.Init.Channel = DMA_CHANNEL_0;
+ drv->spi_dma.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ drv->spi_dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ drv->spi_dma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
+ drv->spi_dma.Init.MemBurst = DMA_MBURST_SINGLE;
+ drv->spi_dma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ drv->spi_dma.Init.MemInc = DMA_MINC_ENABLE;
+ drv->spi_dma.Init.Mode = DMA_NORMAL;
+ drv->spi_dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
+ drv->spi_dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ drv->spi_dma.Init.PeriphInc = DMA_PINC_DISABLE;
+ drv->spi_dma.Init.Priority = DMA_PRIORITY_HIGH;
+
+ HAL_DMA_Init(&drv->spi_dma);
+
+ drv->spi.Instance = SPI2;
+ drv->spi.Init.Mode = SPI_MODE_SLAVE;
+ drv->spi.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
+ drv->spi.Init.DataSize = SPI_DATASIZE_8BIT;
+ drv->spi.Init.CLKPolarity = SPI_POLARITY_LOW;
+ drv->spi.Init.CLKPhase = SPI_PHASE_1EDGE;
+ drv->spi.Init.NSS = SPI_NSS_HARD_INPUT;
+ drv->spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+ drv->spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ drv->spi.Init.TIMode = SPI_TIMODE_DISABLE;
+ drv->spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ drv->spi.Init.CRCPolynomial = 0;
+ drv->spi.hdmarx = &drv->spi_dma;
+
+ drv->spi_dma.Parent = &drv->spi;
+
+ HAL_SPI_Init(&drv->spi);
+
+ NVIC_SetPriority(DMA1_Stream3_IRQn, IRQ_PRI_NORMAL);
+ NVIC_EnableIRQ(DMA1_Stream3_IRQn);
+ NVIC_SetPriority(SPI2_IRQn, IRQ_PRI_NORMAL);
+ NVIC_EnableIRQ(SPI2_IRQn);
+
+ drv->tx_request_id = -1;
+ drv->initialized = true;
+
+ nrf_start();
+}
+
+void nrf_deinit(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+
+ nrf_stop();
+
+ NVIC_DisableIRQ(DMA1_Stream3_IRQn);
+ NVIC_DisableIRQ(DMA2_Stream7_IRQn);
+ NVIC_DisableIRQ(SPI2_IRQn);
+
+ __HAL_RCC_SPI2_FORCE_RESET();
+ __HAL_RCC_SPI2_RELEASE_RESET();
+
+ __HAL_RCC_USART1_FORCE_RESET();
+ __HAL_RCC_USART1_RELEASE_RESET();
+
+ drv->initialized = false;
+}
+
+bool nrf_register_listener(nrf_service_id_t service,
+ nrf_rx_callback_t callback) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return false;
+ }
+
+ if (service >= NRF_SERVICE_CNT) {
+ return false;
+ }
+
+ if (drv->service_listeners[service] != NULL) {
+ return false;
+ }
+
+ irq_key_t key = irq_lock();
+ drv->service_listeners[service] = callback;
+ irq_unlock(key);
+
+ return true;
+}
+
+void nrf_unregister_listener(nrf_service_id_t service) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return;
+ }
+
+ if (service >= NRF_SERVICE_CNT) {
+ return;
+ }
+
+ irq_key_t key = irq_lock();
+ drv->service_listeners[service] = NULL;
+ irq_unlock(key);
+}
+
+static void nrf_process_msg(nrf_driver_t *drv, const uint8_t *data,
+ uint32_t len, nrf_service_id_t service) {
+ if (drv->service_listeners[service] != NULL) {
+ drv->service_listeners[service](data, len);
+ }
+}
+
+/// DFU communication
+/// ----------------------------------------------------------
+
+void nrf_dfu_comm_send(const uint8_t *data, uint32_t len) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return;
+ }
+
+ HAL_UART_Transmit(&drv->urt, (uint8_t *)data, len, 30);
+}
+
+uint32_t nrf_dfu_comm_receive(uint8_t *data, uint32_t len) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return 0;
+ }
+
+ if (__HAL_UART_GET_FLAG(&drv->urt, UART_FLAG_RXNE)) {
+ HAL_StatusTypeDef result = HAL_UART_Receive(&drv->urt, data, len, 30);
+
+ if (result == HAL_OK) {
+ return len;
+ }
+
+ if (drv->urt.RxXferCount == len) {
+ return 0;
+ }
+
+ return len - drv->urt.RxXferCount - 1;
+ }
+
+ return 0;
+}
+
+/// UART communication
+/// ---------------------------------------------------------
+
+int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data,
+ uint32_t len, nrf_tx_callback_t callback, void *context) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return -1;
+ }
+
+ if (len > NRF_MAX_TX_DATA_SIZE) {
+ return -1;
+ }
+
+ if (service > NRF_SERVICE_CNT) {
+ return -1;
+ }
+
+ if (!nrf_is_running()) {
+ return -1;
+ }
+
+ int32_t id = 0;
+
+ nrf_tx_request_t tx_request = {0};
+
+ tx_request.callback = callback;
+ tx_request.context = context;
+ tx_request.packet.service_id = 0xA0 | (uint8_t)service;
+ tx_request.packet.msg_len = len + UART_OVERHEAD_SIZE;
+ memcpy(&tx_request.packet.data, data, len);
+ tx_request.packet.data[len] =
+ crc8((uint8_t *)&tx_request.packet, len + UART_OVERHEAD_SIZE - 1, 0x07,
+ 0x00, false);
+
+ if (!tsqueue_enqueue(&drv->tx_queue, (uint8_t *)&tx_request,
+ sizeof(nrf_tx_request_t), &id)) {
+ return -1;
+ }
+
+ irq_key_t key = irq_lock();
+ if (drv->tx_request_id <= 0) {
+ int32_t tx_id = 0;
+ if (tsqueue_dequeue(&drv->tx_queue, (uint8_t *)&drv->tx_request,
+ sizeof(nrf_tx_request_t), NULL, &tx_id)) {
+ HAL_UART_Transmit_DMA(&drv->urt, (uint8_t *)&drv->tx_request.packet,
+ drv->tx_request.packet.msg_len);
+ drv->tx_request_id = tx_id;
+ }
+ }
+ irq_unlock(key);
+
+ return id;
+}
+
+bool nrf_abort_msg(int32_t id) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return false;
+ }
+
+ bool aborted = tsqueue_abort(&drv->tx_queue, id, NULL, 0, NULL);
+
+ if (aborted) {
+ return true;
+ }
+
+ irq_key_t key = irq_lock();
+ if (drv->tx_request_id == id) {
+ drv->tx_request_id = -1;
+ irq_unlock(key);
+ return true;
+ }
+
+ irq_unlock(key);
+ return false;
+}
+
+static bool nrf_is_valid_startbyte(uint8_t val) {
+ if ((val & 0xF0) != 0xA0) {
+ return false;
+ }
+
+ if ((val & 0x0F) >= NRF_SERVICE_CNT) {
+ return false;
+ }
+
+ return true;
+}
+
+void HAL_UART_RxCpltCallback(UART_HandleTypeDef *urt) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized && urt == &drv->urt) {
+ if (drv->rx_idx == 0) {
+ // received first byte: START BYTE
+ if (nrf_is_valid_startbyte(drv->rx_byte)) {
+ drv->rx_buffer.service_id = drv->rx_byte;
+ drv->rx_idx++;
+ } else {
+ // bad message, flush the line
+ drv->rx_idx = 0;
+ }
+ } else if (drv->rx_idx == 1) {
+ // received second byte: LEN
+
+ drv->rx_buffer.msg_len = drv->rx_byte;
+ drv->rx_len = drv->rx_byte;
+
+ if (drv->rx_len > sizeof(uart_packet_t)) {
+ drv->rx_len = 0;
+ drv->rx_idx = 0;
+ } else {
+ drv->rx_idx++;
+ }
+ } else if (drv->rx_idx >= UART_HEADER_SIZE &&
+ drv->rx_idx < (drv->rx_len - 1)) {
+ // receive the rest of the message
+
+ drv->rx_buffer.data[drv->rx_idx - UART_HEADER_SIZE] = drv->rx_byte;
+ drv->rx_idx++;
+
+ if (drv->rx_idx >= NRF_MAX_TX_DATA_SIZE) {
+ // message is too long, flush the line
+ drv->rx_idx = 0;
+ drv->rx_len = 0;
+ }
+
+ } else if (drv->rx_idx == (drv->rx_len - 1)) {
+ // received last byte: CRC
+
+ uint8_t crc =
+ crc8((uint8_t *)&drv->rx_buffer, drv->rx_len - 1, 0x07, 0x00, false);
+
+ if (drv->rx_byte == crc) {
+ uart_packet_t *packet = &drv->rx_buffer;
+ nrf_process_msg(drv, drv->rx_buffer.data,
+ drv->rx_len - UART_OVERHEAD_SIZE,
+ packet->service_id & 0x0F);
+ }
+
+ drv->rx_idx = 0;
+ drv->rx_len = 0;
+
+ } else {
+ // bad message, flush the line
+ drv->rx_idx = 0;
+ drv->rx_len = 0;
+ }
+ }
+
+ // receive the rest of the message, or new message in any case.
+ HAL_UART_Receive_IT(&drv->urt, &drv->rx_byte, 1);
+}
+
+void HAL_UART_ErrorCallback(UART_HandleTypeDef *urt) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized && urt == &drv->urt) {
+ nrf_abort_urt_comm(drv);
+
+ HAL_UART_Receive_IT(&drv->urt, &drv->rx_byte, 1);
+ }
+}
+
+void HAL_UART_TxCpltCallback(UART_HandleTypeDef *urt) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized && urt == &drv->urt) {
+ if (drv->tx_request.callback != NULL) {
+ drv->tx_request.callback(NRF_STATUS_OK, drv->tx_request.context);
+ }
+ drv->tx_request_id = -1;
+ memset(&drv->tx_request, 0, sizeof(nrf_tx_request_t));
+
+ bool msg =
+ tsqueue_dequeue(&drv->tx_queue, (uint8_t *)&drv->tx_request,
+ sizeof(nrf_tx_request_t), NULL, &drv->tx_request_id);
+ if (msg) {
+ HAL_UART_Transmit_DMA(&drv->urt, (uint8_t *)&drv->tx_request.packet,
+ drv->tx_request.packet.msg_len);
+ }
+ }
+}
+
+void USART1_IRQHandler(void) {
+ IRQ_LOG_ENTER();
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT);
+
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized) {
+ HAL_UART_IRQHandler(&drv->urt);
+ }
+
+ mpu_restore(mpu_mode);
+
+ IRQ_LOG_EXIT();
+}
+
+void DMA2_Stream7_IRQHandler(void) {
+ IRQ_LOG_ENTER();
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT);
+
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized) {
+ HAL_DMA_IRQHandler(&drv->urt_tx_dma);
+ }
+
+ mpu_restore(mpu_mode);
+
+ IRQ_LOG_EXIT();
+}
+
+/// SPI communication
+/// ----------------------------------------------------------
+
+void DMA1_Stream3_IRQHandler(void) {
+ IRQ_LOG_ENTER();
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT);
+
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized) {
+ HAL_DMA_IRQHandler(&drv->spi_dma);
+ }
+
+ mpu_restore(mpu_mode);
+
+ IRQ_LOG_EXIT();
+}
+
+void SPI2_IRQHandler(void) {
+ IRQ_LOG_ENTER();
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DEFAULT);
+
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (drv->initialized) {
+ HAL_SPI_IRQHandler(&drv->spi);
+ }
+
+ mpu_restore(mpu_mode);
+
+ IRQ_LOG_EXIT();
+}
+
+void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
+ nrf_driver_t *drv = &g_nrf_driver;
+
+ if (!drv->initialized) {
+ return;
+ }
+
+ if (hspi != &drv->spi) {
+ return;
+ }
+
+ spi_packet_t *packet = &drv->long_rx_buffer;
+
+ uint8_t crc = crc8((uint8_t *)&drv->long_rx_buffer, sizeof(spi_packet_t) - 1,
+ 0x07, 0x00, false);
+
+ if ((packet->service_id & 0xF0) != START_BYTE || packet->crc != crc) {
+ HAL_SPI_Abort(&drv->spi);
+ HAL_SPI_Receive_DMA(&drv->spi, (uint8_t *)&drv->long_rx_buffer,
+ sizeof(spi_packet_t));
+ return;
+ }
+
+ nrf_process_msg(drv, drv->long_rx_buffer.data, sizeof(packet->data),
+ packet->service_id & 0x0F);
+
+ HAL_SPI_Receive_DMA(&drv->spi, (uint8_t *)&drv->long_rx_buffer,
+ sizeof(spi_packet_t));
+}
+
+/// GPIO communication
+/// ---------------------------------------------------------
+
+bool nrf_reboot_to_bootloader(void) {
+ HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_RESET);
+
+ HAL_GPIO_WritePin(NRF_OUT_STAY_IN_BLD_PORT, NRF_OUT_STAY_IN_BLD_PIN,
+ GPIO_PIN_SET);
+
+ systick_delay_ms(50);
+
+ HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_SET);
+
+ systick_delay_ms(1000);
+
+ return true;
+}
+
+bool nrf_reboot(void) {
+ HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_SET);
+ HAL_GPIO_WritePin(NRF_OUT_STAY_IN_BLD_PORT, NRF_OUT_STAY_IN_BLD_PIN,
+ GPIO_PIN_RESET);
+ systick_delay_ms(50);
+ HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_RESET);
+ return true;
+}
+
+void nrf_signal_running(void) {
+ HAL_GPIO_WritePin(NRF_OUT_FW_RUNNING_PORT, NRF_OUT_FW_RUNNING_PIN,
+ GPIO_PIN_SET);
+}
+
+void nrf_signal_off(void) {
+ HAL_GPIO_WritePin(NRF_OUT_FW_RUNNING_PORT, NRF_OUT_FW_RUNNING_PIN,
+ GPIO_PIN_RESET);
+}
+
+bool nrf_firmware_running(void) {
+ return HAL_GPIO_ReadPin(NRF_IN_FW_RUNNING_PORT, NRF_IN_FW_RUNNING_PIN) != 0;
+}
+
+bool nrf_is_running(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return false;
+ }
+
+ if (!nrf_firmware_running()) {
+ return false;
+ }
+
+ return drv->comm_running;
+}
+
+void nrf_set_dfu_mode(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+
+ if (!drv->initialized) {
+ return;
+ }
+
+ // TODO
+ // if (nrf_reboot_to_bootloader()) {
+ // drv->mode_current = BLE_MODE_DFU;
+ // } else {
+ // drv->status_valid = false;
+ // }
+}
+
+bool nrf_is_dfu_mode(void) {
+ nrf_driver_t *drv = &g_nrf_driver;
+
+ if (!drv->initialized) {
+ return false;
+ }
+
+ return true;
+ // TODO
+}
+
+#endif
diff --git a/core/embed/models/T2W1/boards/t2w1.h b/core/embed/models/T2W1/boards/t2w1.h
new file mode 100644
index 0000000000..d178d61a42
--- /dev/null
+++ b/core/embed/models/T2W1/boards/t2w1.h
@@ -0,0 +1,91 @@
+#ifndef _TREZOR_T2W1_H
+#define _TREZOR_T2W1_H
+
+#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565
+
+#define DISPLAY_I8080_16BIT_DW 1
+#define DISPLAY_PANEL_LHS200KB_IF21 1
+
+#define TPS61043_FREQ 50000
+#define TPS61043_TIM TIM1
+#define TPS61043_TIM_CLK_EN __HAL_RCC_TIM1_CLK_ENABLE
+#define TPS61043_TIM_CLK_DIS __HAL_RCC_TIM1_CLK_DISABLE
+#define TPS61043_TIM_FORCE_RESET __HAL_RCC_TIM1_FORCE_RESET
+#define TPS61043_TIM_RELEASE_RESET __HAL_RCC_TIM1_RELEASE_RESET
+#define TPS61043_TIM_AF GPIO_AF1_TIM1
+#define TPS61043_TIM_OCMODE TIM_OCMODE_PWM2
+#define TPS61043_TIM_CHANNEL TIM_CHANNEL_1
+#define TPS61043_TIM_CCR CCR1
+#define TPS61043_PIN GPIO_PIN_7
+#define TPS61043_PORT GPIOA
+#define TPS61043_PORT_CLK_EN __HAL_RCC_GPIOA_CLK_ENABLE
+
+#define I2C_COUNT 1
+#define I2C_INSTANCE_0 I2C2
+#define I2C_INSTANCE_0_CLK_EN __HAL_RCC_I2C2_CLK_ENABLE
+#define I2C_INSTANCE_0_CLK_DIS __HAL_RCC_I2C2_CLK_DISABLE
+#define I2C_INSTANCE_0_PIN_AF GPIO_AF4_I2C2
+#define I2C_INSTANCE_0_SDA_PORT GPIOB
+#define I2C_INSTANCE_0_SDA_PIN GPIO_PIN_11
+#define I2C_INSTANCE_0_SDA_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define I2C_INSTANCE_0_SCL_PORT GPIOB
+#define I2C_INSTANCE_0_SCL_PIN GPIO_PIN_10
+#define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR
+#define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR_I2C2RST
+#define I2C_INSTANCE_0_EV_IRQHandler I2C2_EV_IRQHandler
+#define I2C_INSTANCE_0_ER_IRQHandler I2C2_ER_IRQHandler
+#define I2C_INSTANCE_0_EV_IRQn I2C2_EV_IRQn
+#define I2C_INSTANCE_0_ER_IRQn I2C2_ER_IRQn
+#define I2C_INSTANCE_0_GUARD_TIME 0
+
+#define TOUCH_SENSITIVITY 0x06
+#define TOUCH_I2C_INSTANCE 0
+#define TOUCH_RST_PORT GPIOC
+#define TOUCH_RST_PIN GPIO_PIN_5
+#define TOUCH_INT_PORT GPIOC
+#define TOUCH_INT_PIN GPIO_PIN_4
+#define TOUCH_ON_PORT GPIOB
+#define TOUCH_ON_PIN GPIO_PIN_8
+#define TOUCH_PANEL_LHS200KB_IF21 1
+
+#define SD_DETECT_PORT GPIOB
+#define SD_DETECT_PIN GPIO_PIN_0
+#define SD_ENABLE_PORT GPIOE
+#define SD_ENABLE_PIN GPIO_PIN_1
+
+#define SBU_1_PIN GPIO_PIN_2
+#define SBU_1_PORT GPIOA
+#define SBU_1_CLK_ENA __HAL_RCC_GPIOA_CLK_ENABLE
+#define SBU_2_PIN GPIO_PIN_3
+#define SBU_2_PORT GPIOA
+#define SBU_2_CLK_ENA __HAL_RCC_GPIOA_CLK_ENABLE
+
+#define GPIO_1_PORT GPIOC
+#define GPIO_1_PIN GPIO_PIN_1
+#define GPIO_2_PORT GPIOC
+#define GPIO_2_PIN GPIO_PIN_6
+#define GPIO_3_PORT GPIOC
+#define GPIO_3_PIN GPIO_PIN_7
+
+#define BTN_POWER_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
+#define BTN_POWER_PORT GPIOE
+#define BTN_POWER_PIN GPIO_PIN_0
+
+#define NRF_IN_GPIO0_PIN GPIO_PIN_1
+#define NRF_IN_GPIO0_PORT GPIOC
+#define NRF_IN_GPIO0_CLK_ENA __HAL_RCC_GPIOC_CLK_ENABLE
+#define NRF_IN_FW_RUNNING_PIN GPIO_PIN_6
+#define NRF_IN_FW_RUNNING_PORT GPIOC
+#define NRF_IN_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOC_CLK_ENABLE
+#define NRF_OUT_RESET_PIN GPIO_PIN_1
+#define NRF_OUT_RESET_PORT GPIOA
+#define NRF_OUT_RESET_CLK_ENA __HAL_RCC_GPIOA_CLK_ENABLE
+#define NRF_OUT_STAY_IN_BLD_PIN GPIO_PIN_12
+#define NRF_OUT_STAY_IN_BLD_PORT GPIOB
+#define NRF_OUT_STAY_IN_BLD_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
+#define NRF_OUT_FW_RUNNING_PIN GPIO_PIN_7
+#define NRF_OUT_FW_RUNNING_PORT GPIOC
+#define NRF_OUT_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOC_CLK_ENABLE
+
+#endif //_TREZOR_T3W1_H
diff --git a/core/embed/models/T2W1/bootloaders/bootloader_T2W1.bin b/core/embed/models/T2W1/bootloaders/bootloader_T2W1.bin
new file mode 100644
index 0000000000..4302d3451c
Binary files /dev/null and b/core/embed/models/T2W1/bootloaders/bootloader_T2W1.bin differ
diff --git a/core/embed/models/T2W1/config.mk b/core/embed/models/T2W1/config.mk
new file mode 100644
index 0000000000..a93e37f112
--- /dev/null
+++ b/core/embed/models/T2W1/config.mk
@@ -0,0 +1,3 @@
+MCU = STM32F4
+OPENOCD_TARGET = target/stm32f4x.cfg
+LAYOUT_FEATURE = layout_bolt
diff --git a/core/embed/models/T2W1/memory.ld b/core/embed/models/T2W1/memory.ld
new file mode 100644
index 0000000000..1614fb601e
--- /dev/null
+++ b/core/embed/models/T2W1/memory.ld
@@ -0,0 +1,68 @@
+/* Auto-generated file, do not edit.*/
+
+NORCOW_SECTOR_SIZE = 0x10000;
+FLASH_START = 0x8000000;
+BOARDLOADER_START = 0x8000000;
+BOARDLOADER_MAXSIZE = 0xc000;
+BOARDLOADER_SECTOR_START = 0x0;
+BOARDLOADER_SECTOR_END = 0x2;
+BOARDCAPS_START = 0x800bf00;
+BOARDCAPS_MAXSIZE = 0x100;
+UNUSED_1_START = 0x800c000;
+UNUSED_1_MAXSIZE = 0x4000;
+UNUSED_1_SECTOR_START = 0x3;
+UNUSED_1_SECTOR_END = 0x3;
+STORAGE_1_START = 0x8010000;
+STORAGE_1_MAXSIZE = 0x10000;
+STORAGE_1_SECTOR_START = 0x4;
+STORAGE_1_SECTOR_END = 0x4;
+BOOTLOADER_START = 0x8020000;
+BOOTLOADER_MAXSIZE = 0x20000;
+BOOTLOADER_SECTOR_START = 0x5;
+BOOTLOADER_SECTOR_END = 0x5;
+FIRMWARE_START = 0x8040000;
+FIRMWARE_MAXSIZE = 0x1a0000;
+FIRMWARE_P1_START = 0x8040000;
+FIRMWARE_P1_MAXSIZE = 0xc0000;
+FIRMWARE_P1_SECTOR_START = 0x6;
+FIRMWARE_P1_SECTOR_END = 0xb;
+KERNEL_START = 0x8040000;
+KERNEL_MAXSIZE = 0x80000;
+ASSETS_START = 0x8100000;
+ASSETS_MAXSIZE = 0xc000;
+ASSETS_SECTOR_START = 0xc;
+ASSETS_SECTOR_END = 0xe;
+UNUSED_2_START = 0x810c000;
+UNUSED_2_MAXSIZE = 0x4000;
+UNUSED_2_SECTOR_START = 0xf;
+UNUSED_2_SECTOR_END = 0xf;
+STORAGE_2_START = 0x8110000;
+STORAGE_2_MAXSIZE = 0x10000;
+STORAGE_2_SECTOR_START = 0x10;
+STORAGE_2_SECTOR_END = 0x10;
+FIRMWARE_P2_START = 0x8120000;
+FIRMWARE_P2_MAXSIZE = 0xe0000;
+FIRMWARE_P2_SECTOR_START = 0x11;
+FIRMWARE_P2_SECTOR_END = 0x17;
+S_MAIN_STACK_START = 0x10000000;
+S_MAIN_STACK_SIZE = 0x4000;
+S_FB1_RAM_START = 0x10004000;
+S_FB1_RAM_SIZE = 0x0;
+S_MAIN_RAM_START = 0x10004000;
+S_MAIN_RAM_SIZE = 0xbf00;
+K_MAIN_STACK_START = 0x10000000;
+K_MAIN_STACK_SIZE = 0x2000;
+K_AUX2_RAM_START = 0x10002000;
+K_AUX2_RAM_SIZE = 0xa000;
+K_FB1_RAM_START = 0x1000c000;
+K_FB1_RAM_SIZE = 0x0;
+K_MAIN_RAM_START = 0x1000c000;
+K_MAIN_RAM_SIZE = 0x3f00;
+BOOTARGS_START = 0x1000ff00;
+BOOTARGS_SIZE = 0x100;
+DMABUF_RAM_START = 0x20000000;
+DMABUF_RAM_SIZE = 0x800;
+AUX1_RAM_START = 0x20000800;
+AUX1_RAM_SIZE = 0x2f800;
+CODE_ALIGNMENT = 0x200;
+COREAPP_ALIGNMENT = 0x200;
diff --git a/core/embed/models/T2W1/model_T2W1.h b/core/embed/models/T2W1/model_T2W1.h
new file mode 100644
index 0000000000..d8f2f295f0
--- /dev/null
+++ b/core/embed/models/T2W1/model_T2W1.h
@@ -0,0 +1,128 @@
+#ifndef MODELS_MODEL_T2T1_H_
+#define MODELS_MODEL_T2T1_H_
+
+// #include "bootloaders/bootloader_hashes.h"
+
+#define MODEL_NAME "T2W1"
+#define MODEL_FULL_NAME "Trezor Model T2W1"
+#define MODEL_INTERNAL_NAME "T2W1"
+#define MODEL_INTERNAL_NAME_TOKEN T2W1
+#define MODEL_INTERNAL_NAME_QSTR MP_QSTR_T2W1
+#define MODEL_USB_MANUFACTURER "SatoshiLabs"
+#define MODEL_USB_PRODUCT "TREZOR"
+#define MODEL_HOMESCREEN_MAXSIZE 16384
+
+/*** PRODUCTION KEYS ***/
+#define MODEL_BOARDLOADER_KEYS \
+ (const uint8_t *)"\x0e\xb9\x85\x6b\xe9\xba\x7e\x97\x2c\x7f\x34\xea\xc1\xed\x9b\x6f\xd0\xef\xd1\x72\xec\x00\xfa\xf0\xc5\x89\x75\x9d\xa4\xdd\xfb\xa0", \
+ (const uint8_t *)"\xac\x8a\xb4\x0b\x32\xc9\x86\x55\x79\x8f\xd5\xda\x5e\x19\x2b\xe2\x7a\x22\x30\x6e\xa0\x5c\x6d\x27\x7c\xdf\xf4\xa3\xf4\x12\x5c\xd8", \
+ (const uint8_t *)"\xce\x0f\xcd\x12\x54\x3e\xf5\x93\x6c\xf2\x80\x49\x82\x13\x67\x07\x86\x3d\x17\x29\x5f\xac\xed\x72\xaf\x17\x1d\x6e\x65\x13\xff\x06",
+
+#define MODEL_BOOTLOADER_KEYS \
+ (const uint8_t *)"\xc2\xc8\x7a\x49\xc5\xa3\x46\x09\x77\xfb\xb2\xec\x9d\xfe\x60\xf0\x6b\xd6\x94\xdb\x82\x44\xbd\x49\x81\xfe\x3b\x7a\x26\x30\x7f\x3f", \
+ (const uint8_t *)"\x80\xd0\x36\xb0\x87\x39\xb8\x46\xf4\xcb\x77\x59\x30\x78\xde\xb2\x5d\xc9\x48\x7a\xed\xcf\x52\xe3\x0b\x4f\xb7\xcd\x70\x24\x17\x8a", \
+ (const uint8_t *)"\xb8\x30\x7a\x71\xf5\x52\xc6\x0a\x4c\xbb\x31\x7f\xf4\x8b\x82\xcd\xbf\x6b\x6b\xb5\xf0\x4c\x92\x0f\xec\x7b\xad\xf0\x17\x88\x37\x51",
+
+#define IMAGE_CHUNK_SIZE (128 * 1024)
+#define IMAGE_HASH_BLAKE2S
+
+#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RETAIN_CONTENT
+
+// SHARED WITH MAKEFILE
+// common
+
+#define NORCOW_SECTOR_SIZE (1 * 64 * 1024) // 64 kB
+#define FLASH_START 0x08000000
+
+// FLASH layout
+#define BOARDLOADER_START 0x08000000
+#define BOARDLOADER_MAXSIZE (3 * 16 * 1024) // 48 kB
+#define BOARDLOADER_SECTOR_START 0
+#define BOARDLOADER_SECTOR_END 2
+
+#define BOARDCAPS_START 0x0800BF00
+#define BOARDCAPS_MAXSIZE 0x100
+
+#define UNUSED_1_START 0x0800C000
+#define UNUSED_1_MAXSIZE (1 * 16 * 1024) // 16 kB
+#define UNUSED_1_SECTOR_START 3
+#define UNUSED_1_SECTOR_END 3
+
+#define STORAGE_1_START 0x08010000
+#define STORAGE_1_MAXSIZE (1 * 64 * 1024) // 64 kB
+#define STORAGE_1_SECTOR_START 4
+#define STORAGE_1_SECTOR_END 4
+
+#define BOOTLOADER_START 0x08020000
+#define BOOTLOADER_MAXSIZE (1 * 128 * 1024) // 128 kB
+#define BOOTLOADER_SECTOR_START 5
+#define BOOTLOADER_SECTOR_END 5
+
+#define FIRMWARE_START 0x08040000
+#define FIRMWARE_MAXSIZE (13 * 128 * 1024) // 1664 kB
+#define FIRMWARE_P1_START 0x08040000
+#define FIRMWARE_P1_MAXSIZE (6 * 128 * 1024)
+#define FIRMWARE_P1_SECTOR_START 6
+#define FIRMWARE_P1_SECTOR_END 11
+// part of firmware P1
+#define KERNEL_START 0x08040000
+#define KERNEL_MAXSIZE (4 * 128 * 1024)
+
+#define ASSETS_START 0x08100000
+#define ASSETS_MAXSIZE (3 * 16 * 1024) // 48 kB
+#define ASSETS_SECTOR_START 12
+#define ASSETS_SECTOR_END 14
+
+#define UNUSED_2_START 0x0810C000
+#define UNUSED_2_MAXSIZE (1 * 16 * 1024) // 16 kB
+#define UNUSED_2_SECTOR_START 15
+#define UNUSED_2_SECTOR_END 15
+
+#define STORAGE_2_START 0x08110000
+#define STORAGE_2_MAXSIZE (1 * 64 * 1024) // 64 kB
+#define STORAGE_2_SECTOR_START 16
+#define STORAGE_2_SECTOR_END 16
+
+#define FIRMWARE_P2_START 0x08120000
+#define FIRMWARE_P2_MAXSIZE (7 * 128 * 1024)
+#define FIRMWARE_P2_SECTOR_START 17
+#define FIRMWARE_P2_SECTOR_END 23
+
+// Ram layout - shared boardloader, bootloader, prodtest
+#define S_MAIN_STACK_START 0x10000000
+#define S_MAIN_STACK_SIZE (16 * 1024)
+
+#define S_FB1_RAM_START 0x10004000
+#define S_FB1_RAM_SIZE (0)
+
+#define S_MAIN_RAM_START 0x10004000
+#define S_MAIN_RAM_SIZE (48 * 1024 - 0x100)
+
+// RAM layout - kernel
+#define K_MAIN_STACK_START 0x10000000
+#define K_MAIN_STACK_SIZE (8 * 1024)
+
+#define K_AUX2_RAM_START 0x10002000
+#define K_AUX2_RAM_SIZE (40 * 1024)
+
+#define K_FB1_RAM_START 0x1000C000
+#define K_FB1_RAM_SIZE (0)
+
+#define K_MAIN_RAM_START 0x1000C000
+#define K_MAIN_RAM_SIZE (16 * 1024 - 0x100)
+
+// RAM layout - common
+#define BOOTARGS_START 0x1000FF00
+#define BOOTARGS_SIZE 0x100
+
+#define DMABUF_RAM_START 0x20000000
+#define DMABUF_RAM_SIZE (2 * 1024)
+
+#define AUX1_RAM_START (0x20000800)
+#define AUX1_RAM_SIZE (190 * 1024)
+
+// misc
+#define CODE_ALIGNMENT 0x200
+#define COREAPP_ALIGNMENT 0x200
+
+#endif
diff --git a/core/embed/models/T2W1/vendorheader/vendor_dev_DO_NOT_SIGN.json b/core/embed/models/T2W1/vendorheader/vendor_dev_DO_NOT_SIGN.json
new file mode 100644
index 0000000000..c791aab382
--- /dev/null
+++ b/core/embed/models/T2W1/vendorheader/vendor_dev_DO_NOT_SIGN.json
@@ -0,0 +1,22 @@
+{
+ "header_len": 4608,
+ "text": "DEV ONLY, DO NOT USE!",
+ "hw_model": "T2W1",
+ "expiry": 0,
+ "version": [0, 0],
+ "sig_m": 2,
+ "trust": {
+ "_reserved": 0,
+ "_dont_provide_secret": false,
+ "allow_run_with_secret": false,
+ "show_vendor_string": false,
+ "require_user_click": false,
+ "red_background": false,
+ "delay": 0
+ },
+ "pubkeys": [
+ "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351",
+ "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869",
+ "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef"
+ ]
+}
diff --git a/core/embed/models/T2W1/vendorheader/vendor_dev_DO_NOT_SIGN.toif b/core/embed/models/T2W1/vendorheader/vendor_dev_DO_NOT_SIGN.toif
new file mode 120000
index 0000000000..3dc5d9734f
--- /dev/null
+++ b/core/embed/models/T2W1/vendorheader/vendor_dev_DO_NOT_SIGN.toif
@@ -0,0 +1 @@
+./vendor_satoshilabs.toif
\ No newline at end of file
diff --git a/core/embed/models/T2W1/vendorheader/vendor_prodtest.json b/core/embed/models/T2W1/vendorheader/vendor_prodtest.json
new file mode 100644
index 0000000000..fe8a356749
--- /dev/null
+++ b/core/embed/models/T2W1/vendorheader/vendor_prodtest.json
@@ -0,0 +1,21 @@
+{
+ "header_len": 4608,
+ "text": "UNSAFE, FACTORY TEST ONLY",
+ "hw_model": "T2W1",
+ "expiry": 0,
+ "version": [0, 0],
+ "sig_m": 2,
+ "trust": {
+ "_reserved": 0,
+ "_dont_provide_secret": false,
+ "allow_run_with_secret": false,
+ "show_vendor_string": false,
+ "require_user_click": false,
+ "red_background": false,
+ "delay": 0
+ },
+ "pubkeys": [
+ "c17d221529b70da08aa42ccb1b2cef773736a7d48434209f6eb16b1b474716d2",
+ "6622ee8403464acfc2fe1e20311937b115e60771f3ee6e70f22bf2921977e534"
+ ]
+}
diff --git a/core/embed/models/T2W1/vendorheader/vendor_prodtest.toif b/core/embed/models/T2W1/vendorheader/vendor_prodtest.toif
new file mode 120000
index 0000000000..22ac5e8400
--- /dev/null
+++ b/core/embed/models/T2W1/vendorheader/vendor_prodtest.toif
@@ -0,0 +1 @@
+vendor_unsafe.toif
\ No newline at end of file
diff --git a/core/embed/models/T2W1/vendorheader/vendor_satoshilabs.json b/core/embed/models/T2W1/vendorheader/vendor_satoshilabs.json
new file mode 100644
index 0000000000..32d01bbebc
--- /dev/null
+++ b/core/embed/models/T2W1/vendorheader/vendor_satoshilabs.json
@@ -0,0 +1,22 @@
+{
+ "header_len": 4608,
+ "text": "SatoshiLabs",
+ "hw_model": "T2W1",
+ "expiry": 0,
+ "version": [0, 1],
+ "sig_m": 2,
+ "trust": {
+ "_reserved": 0,
+ "_dont_provide_secret": false,
+ "allow_run_with_secret": false,
+ "show_vendor_string": false,
+ "require_user_click": false,
+ "red_background": false,
+ "delay": 0
+ },
+ "pubkeys": [
+ "47fbdc84d8abef44fe6abde8f87b6ead821b7082ec63b9f7cc33dc53bf6c708d",
+ "9af22a52ab47a93091403612b3d6731a2dfef8a33383048ed7556a20e8b03c81",
+ "2218c25f8ba70c82eba8ed6a321df209c0a7643d014f33bf9317846f62923830"
+ ]
+}
diff --git a/core/embed/models/T2W1/vendorheader/vendor_satoshilabs.toif b/core/embed/models/T2W1/vendorheader/vendor_satoshilabs.toif
new file mode 100644
index 0000000000..231990e5a2
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendor_satoshilabs.toif differ
diff --git a/core/embed/models/T2W1/vendorheader/vendor_unsafe.json b/core/embed/models/T2W1/vendorheader/vendor_unsafe.json
new file mode 100644
index 0000000000..89d987f8a1
--- /dev/null
+++ b/core/embed/models/T2W1/vendorheader/vendor_unsafe.json
@@ -0,0 +1,22 @@
+{
+ "header_len": 4608,
+ "text": "UNSAFE, DO NOT USE!",
+ "hw_model": "T2W1",
+ "expiry": 0,
+ "version": [0, 1],
+ "sig_m": 2,
+ "trust": {
+ "_reserved": 0,
+ "_dont_provide_secret": false,
+ "allow_run_with_secret": false,
+ "show_vendor_string": true,
+ "require_user_click": true,
+ "red_background": true,
+ "delay": 1
+ },
+ "pubkeys": [
+ "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351",
+ "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869",
+ "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef"
+ ]
+}
diff --git a/core/embed/models/T2W1/vendorheader/vendor_unsafe.toif b/core/embed/models/T2W1/vendorheader/vendor_unsafe.toif
new file mode 100644
index 0000000000..8c25f0ddd9
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendor_unsafe.toif differ
diff --git a/core/embed/models/T2W1/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin b/core/embed/models/T2W1/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin
new file mode 100644
index 0000000000..1a04ecaab3
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin differ
diff --git a/core/embed/models/T2W1/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin b/core/embed/models/T2W1/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin
new file mode 100644
index 0000000000..a819463ca7
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin differ
diff --git a/core/embed/models/T2W1/vendorheader/vendorheader_prodtest_unsigned.bin b/core/embed/models/T2W1/vendorheader/vendorheader_prodtest_unsigned.bin
new file mode 100644
index 0000000000..c45817eef1
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendorheader_prodtest_unsigned.bin differ
diff --git a/core/embed/models/T2W1/vendorheader/vendorheader_satoshilabs_unsigned.bin b/core/embed/models/T2W1/vendorheader/vendorheader_satoshilabs_unsigned.bin
new file mode 100644
index 0000000000..2212dcb3d0
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendorheader_satoshilabs_unsigned.bin differ
diff --git a/core/embed/models/T2W1/vendorheader/vendorheader_unsafe_signed_dev.bin b/core/embed/models/T2W1/vendorheader/vendorheader_unsafe_signed_dev.bin
new file mode 100644
index 0000000000..aa79ad8f70
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendorheader_unsafe_signed_dev.bin differ
diff --git a/core/embed/models/T2W1/vendorheader/vendorheader_unsafe_unsigned.bin b/core/embed/models/T2W1/vendorheader/vendorheader_unsafe_unsigned.bin
new file mode 100644
index 0000000000..30dba7fbc6
Binary files /dev/null and b/core/embed/models/T2W1/vendorheader/vendorheader_unsafe_unsigned.bin differ
diff --git a/core/embed/models/T2W1/versions.h b/core/embed/models/T2W1/versions.h
new file mode 100644
index 0000000000..546ca6a16b
--- /dev/null
+++ b/core/embed/models/T2W1/versions.h
@@ -0,0 +1,3 @@
+
+#define BOOTLOADER_MONOTONIC_VERSION 2
+#define FIRMWARE_MONOTONIC_VERSION 2
diff --git a/core/site_scons/models/T2W1/__init__.py b/core/site_scons/models/T2W1/__init__.py
new file mode 100644
index 0000000000..c99f655eab
--- /dev/null
+++ b/core/site_scons/models/T2W1/__init__.py
@@ -0,0 +1,27 @@
+from __future__ import annotations
+
+from typing import Optional
+
+from .t2w1 import configure
+
+
+def configure_board(
+ revision: Optional[int | str],
+ features_wanted: list[str],
+ env: dict, # type: ignore
+ defines: list[str | tuple[str, str]],
+ sources: list[str],
+ paths: list[str],
+):
+ defines += (("MODEL_HEADER", '"T2W1/model_T2W1.h"'),)
+ defines += (("VERSIONS_HEADER", '"T2W1/versions.h"'),)
+
+ return configure(env, features_wanted, defines, sources, paths)
+
+
+def get_model_ui() -> str:
+ return "bolt"
+
+
+def get_model_ui_conf() -> list[str]:
+ return []
diff --git a/core/site_scons/models/T2W1/t2w1.py b/core/site_scons/models/T2W1/t2w1.py
new file mode 100644
index 0000000000..af86980c55
--- /dev/null
+++ b/core/site_scons/models/T2W1/t2w1.py
@@ -0,0 +1,129 @@
+from __future__ import annotations
+
+from .. import get_hw_model_as_number
+from ..stm32f4_common import stm32f4_common_files
+
+
+def configure(
+ env: dict,
+ features_wanted: list[str],
+ defines: list[str | tuple[str, str]],
+ sources: list[str],
+ paths: list[str],
+) -> list[str]:
+ features_available: list[str] = []
+ board = "T2W1/boards/t2w1.h"
+ hw_model = get_hw_model_as_number("T2W1")
+ hw_revision = 0
+
+ features_available.append("display_rgb565")
+ defines += [
+ "DISPLAY_RGB565",
+ ("USE_RGB_COLORS", "1"),
+ ("DISPLAY_RESX", "240"),
+ ("DISPLAY_RESY", "320"),
+ ]
+
+ mcu = "STM32F427xx"
+
+ stm32f4_common_files(env, defines, sources, paths)
+
+ env.get("ENV")[
+ "CPU_ASFLAGS"
+ ] = "-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16"
+ env.get("ENV")[
+ "CPU_CCFLAGS"
+ ] = "-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 "
+ env.get("ENV")["RUST_TARGET"] = "thumbv7em-none-eabihf"
+
+ defines += [
+ mcu,
+ ("TREZOR_BOARD", f'"{board}"'),
+ ("HW_MODEL", str(hw_model)),
+ ("HW_REVISION", str(hw_revision)),
+ ("HSE_VALUE", "8000000"),
+ ("USE_HSE", "1"),
+ ]
+
+ sources += ["embed/io/display/st-7789/display_nofb.c"]
+ sources += ["embed/io/display/st-7789/display_driver.c"]
+ sources += ["embed/io/display/st-7789/display_io.c"]
+ sources += ["embed/io/display/st-7789/display_panel.c"]
+ sources += ["embed/io/display/st-7789/panels/lhs200kb-if21.c"]
+ paths += ["embed/io/display/inc"]
+
+ features_available.append("backlight")
+ defines += [("USE_BACKLIGHT", "1")]
+ sources += ["embed/io/backlight/stm32/tps61043.c"]
+ paths += ["embed/io/backlight/inc"]
+
+ if "input" in features_wanted:
+ sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"]
+ sources += ["embed/io/touch/ft6x36/ft6x36.c"]
+ sources += ["embed/io/touch/ft6x36/panels/lhs200kb-if21.c"]
+ paths += ["embed/io/i2c_bus/inc"]
+ paths += ["embed/io/touch/inc"]
+ features_available.append("touch")
+ defines += [("USE_TOUCH", "1")]
+ defines += [("USE_BUTTON", "1")]
+ sources += ["embed/io/button/stm32/button.c"]
+ paths += ["embed/io/button/inc"]
+ features_available.append("button")
+ defines += [("USE_I2C", "1")]
+
+ if "sd_card" in features_wanted:
+ sources += ["embed/io/sdcard/stm32f4/sdcard.c"]
+ sources += ["embed/upymod/modtrezorio/ff.c"]
+ sources += ["embed/upymod/modtrezorio/ffunicode.c"]
+ sources += [
+ "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c"
+ ]
+ paths += ["embed/io/sdcard/inc"]
+ features_available.append("sd_card")
+ defines += [("USE_SD_CARD", "1")]
+
+ if "sbu" in features_wanted:
+ sources += ["embed/io/sbu/stm32/sbu.c"]
+ paths += ["embed/io/sbu/inc"]
+ features_available.append("sbu")
+ defines += [("USE_SBU", "1")]
+
+ if "ble" in features_wanted:
+ sources += ["embed/io/ble/stm32/ble.c"]
+ paths += ["embed/io/ble/inc"]
+ features_available.append("ble")
+ defines += [("USE_BLE", "1")]
+ sources += ["embed/io/nrf/stm32f4/nrf.c"]
+ sources += ["embed/io/nrf/crc8.c"]
+ paths += ["embed/io/nrf/inc"]
+ sources += [
+ "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c",
+ ]
+
+ if "usb" in features_wanted:
+ sources += [
+ "embed/io/usb/stm32/usb_class_hid.c",
+ "embed/io/usb/stm32/usb_class_vcp.c",
+ "embed/io/usb/stm32/usb_class_webusb.c",
+ "embed/io/usb/stm32/usb.c",
+ "embed/io/usb/stm32/usbd_conf.c",
+ "embed/io/usb/stm32/usbd_core.c",
+ "embed/io/usb/stm32/usbd_ctlreq.c",
+ "embed/io/usb/stm32/usbd_ioreq.c",
+ "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
+ ]
+ features_available.append("usb")
+ paths += ["embed/io/usb/inc"]
+ defines += [("USE_USB", "1")]
+
+ if "dma2d" in features_wanted:
+ defines += ["USE_DMA2D"]
+ sources += ["embed/gfx/bitblt/stm32/dma2d_bitblt.c"]
+ sources += [
+ "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c"
+ ]
+ features_available.append("dma2d")
+
+ defines += [("USE_PVD", "1")]
+
+ return features_available
diff --git a/core/src/apps/common/coininfo.py b/core/src/apps/common/coininfo.py
index 602f2ada3f..f8ec8d9acc 100644
--- a/core/src/apps/common/coininfo.py
+++ b/core/src/apps/common/coininfo.py
@@ -7040,4 +7040,1341 @@ def by_name(name: str) -> CoinInfo:
None, # confidential_assets
)
raise ValueError # Unknown coin name
+ if utils.INTERNAL_MODEL == "T2W1":
+ if name == "Bitcoin":
+ return CoinInfo(
+ name, # coin_name
+ "BTC", # coin_shortcut
+ 8, # decimals
+ 0, # address_type
+ 5, # address_type_p2sh
+ 2000000, # maxfee_kb
+ "Bitcoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0295b43f, # xpub_magic_multisig_segwit_p2sh
+ 0x02aa7ed3, # xpub_magic_multisig_segwit_native
+ "bc", # bech32_prefix
+ None, # cashaddr_prefix
+ 0, # slip44
+ True, # segwit
+ True, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Regtest":
+ return CoinInfo(
+ name, # coin_name
+ "REGTEST", # coin_shortcut
+ 8, # decimals
+ 111, # address_type
+ 196, # address_type_p2sh
+ 10000000, # maxfee_kb
+ "Bitcoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x024289ef, # xpub_magic_multisig_segwit_p2sh
+ 0x02575483, # xpub_magic_multisig_segwit_native
+ "bcrt", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ True, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "TEST", # coin_shortcut
+ 8, # decimals
+ 111, # address_type
+ 196, # address_type_p2sh
+ 10000000, # maxfee_kb
+ "Bitcoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x024289ef, # xpub_magic_multisig_segwit_p2sh
+ 0x02575483, # xpub_magic_multisig_segwit_native
+ "tb", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ True, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if not utils.BITCOIN_ONLY:
+ if name == "Actinium":
+ return CoinInfo(
+ name, # coin_name
+ "ACM", # coin_shortcut
+ 8, # decimals
+ 53, # address_type
+ 55, # address_type_p2sh
+ 320000000000, # maxfee_kb
+ "Actinium Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "acm", # bech32_prefix
+ None, # cashaddr_prefix
+ 228, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Axe":
+ return CoinInfo(
+ name, # coin_name
+ "AXE", # coin_shortcut
+ 8, # decimals
+ 55, # address_type
+ 16, # address_type_p2sh
+ 21000000000, # maxfee_kb
+ "DarkCoin Signed Message:\n", # signed_message_header
+ 0x02fe52cc, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 4242, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Bcash":
+ return CoinInfo(
+ name, # coin_name
+ "BCH", # coin_shortcut
+ 8, # decimals
+ 0, # address_type
+ 5, # address_type_p2sh
+ 14000000, # maxfee_kb
+ "Bitcoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ "bitcoincash", # cashaddr_prefix
+ 145, # slip44
+ False, # segwit
+ False, # taproot
+ 0, # fork_id
+ True, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Bcash Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "TBCH", # coin_shortcut
+ 8, # decimals
+ 111, # address_type
+ 196, # address_type_p2sh
+ 10000000, # maxfee_kb
+ "Bitcoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ "bchtest", # cashaddr_prefix
+ 1, # slip44
+ False, # segwit
+ False, # taproot
+ 0, # fork_id
+ True, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Bprivate":
+ return CoinInfo(
+ name, # coin_name
+ "BTCP", # coin_shortcut
+ 8, # decimals
+ 4901, # address_type
+ 5039, # address_type_p2sh
+ 32000000000, # maxfee_kb
+ "BitcoinPrivate Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 183, # slip44
+ False, # segwit
+ False, # taproot
+ 42, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Bitcore":
+ return CoinInfo(
+ name, # coin_name
+ "BTX", # coin_shortcut
+ 8, # decimals
+ 3, # address_type
+ 125, # address_type_p2sh
+ 14000000000, # maxfee_kb
+ "BitCore Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "btx", # bech32_prefix
+ None, # cashaddr_prefix
+ 160, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "CPUchain":
+ return CoinInfo(
+ name, # coin_name
+ "CPU", # coin_shortcut
+ 8, # decimals
+ 28, # address_type
+ 30, # address_type_p2sh
+ 8700000000000, # maxfee_kb
+ "CPUchain Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "cpu", # bech32_prefix
+ None, # cashaddr_prefix
+ 363, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Crown":
+ return CoinInfo(
+ name, # coin_name
+ "CRW", # coin_shortcut
+ 8, # decimals
+ 95495, # address_type
+ 95473, # address_type_p2sh
+ 52000000000, # maxfee_kb
+ "Crown Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 72, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Dogecoin":
+ return CoinInfo(
+ name, # coin_name
+ "DOGE", # coin_shortcut
+ 8, # decimals
+ 30, # address_type
+ 22, # address_type_p2sh
+ 1200000000000, # maxfee_kb
+ "Dogecoin Signed Message:\n", # signed_message_header
+ 0x02facafd, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 3, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Elements":
+ return CoinInfo(
+ name, # coin_name
+ "ELEMENTS", # coin_shortcut
+ 8, # decimals
+ 235, # address_type
+ 75, # address_type_p2sh
+ 10000000, # maxfee_kb
+ "Bitcoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x043587cf, # xpub_magic_multisig_segwit_p2sh
+ 0x043587cf, # xpub_magic_multisig_segwit_native
+ "ert", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ {'address_prefix': 4, 'blech32_prefix': 'el'}, # confidential_assets
+ )
+ if name == "Feathercoin":
+ return CoinInfo(
+ name, # coin_name
+ "FTC", # coin_shortcut
+ 8, # decimals
+ 14, # address_type
+ 5, # address_type_p2sh
+ 390000000000, # maxfee_kb
+ "Feathercoin Signed Message:\n", # signed_message_header
+ 0x0488bc26, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488bc26, # xpub_magic_multisig_segwit_p2sh
+ 0x0488bc26, # xpub_magic_multisig_segwit_native
+ "fc", # bech32_prefix
+ None, # cashaddr_prefix
+ 8, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Firo":
+ return CoinInfo(
+ name, # coin_name
+ "FIRO", # coin_shortcut
+ 8, # decimals
+ 82, # address_type
+ 7, # address_type_p2sh
+ 640000000, # maxfee_kb
+ "Zcoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 136, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Firo Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tFIRO", # coin_shortcut
+ 8, # decimals
+ 65, # address_type
+ 178, # address_type_p2sh
+ 1000000, # maxfee_kb
+ "Zcoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Florincoin":
+ return CoinInfo(
+ name, # coin_name
+ "FLO", # coin_shortcut
+ 8, # decimals
+ 35, # address_type
+ 94, # address_type_p2sh
+ 78000000000, # maxfee_kb
+ "Florincoin Signed Message:\n", # signed_message_header
+ 0x00174921, # xpub_magic
+ 0x01b26ef6, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x00174921, # xpub_magic_multisig_segwit_p2sh
+ 0x00174921, # xpub_magic_multisig_segwit_native
+ "flo", # bech32_prefix
+ None, # cashaddr_prefix
+ 216, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Fujicoin":
+ return CoinInfo(
+ name, # coin_name
+ "FJC", # coin_shortcut
+ 8, # decimals
+ 36, # address_type
+ 16, # address_type_p2sh
+ 35000000000000, # maxfee_kb
+ "FujiCoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0295b43f, # xpub_magic_multisig_segwit_p2sh
+ 0x02aa7ed3, # xpub_magic_multisig_segwit_native
+ "fc", # bech32_prefix
+ None, # cashaddr_prefix
+ 75, # slip44
+ True, # segwit
+ True, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Groestlcoin":
+ return CoinInfo(
+ name, # coin_name
+ "GRS", # coin_shortcut
+ 8, # decimals
+ 36, # address_type
+ 5, # address_type_p2sh
+ 16000000000, # maxfee_kb
+ "GroestlCoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "grs", # bech32_prefix
+ None, # cashaddr_prefix
+ 17, # slip44
+ True, # segwit
+ True, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1-groestl', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Groestlcoin Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tGRS", # coin_shortcut
+ 8, # decimals
+ 111, # address_type
+ 196, # address_type_p2sh
+ 100000, # maxfee_kb
+ "GroestlCoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x043587cf, # xpub_magic_multisig_segwit_p2sh
+ 0x043587cf, # xpub_magic_multisig_segwit_native
+ "tgrs", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ True, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1-groestl', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Komodo":
+ return CoinInfo(
+ name, # coin_name
+ "KMD", # coin_shortcut
+ 8, # decimals
+ 60, # address_type
+ 85, # address_type_p2sh
+ 4800000000, # maxfee_kb
+ "Komodo Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 141, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ True, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ True, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Koto":
+ return CoinInfo(
+ name, # coin_name
+ "KOTO", # coin_shortcut
+ 8, # decimals
+ 6198, # address_type
+ 6203, # address_type_p2sh
+ 1000000, # maxfee_kb
+ "Koto Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 510, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ True, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Litecoin":
+ return CoinInfo(
+ name, # coin_name
+ "LTC", # coin_shortcut
+ 8, # decimals
+ 48, # address_type
+ 50, # address_type_p2sh
+ 67000000, # maxfee_kb
+ "Litecoin Signed Message:\n", # signed_message_header
+ 0x019da462, # xpub_magic
+ 0x01b26ef6, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x019da462, # xpub_magic_multisig_segwit_p2sh
+ 0x019da462, # xpub_magic_multisig_segwit_native
+ "ltc", # bech32_prefix
+ None, # cashaddr_prefix
+ 2, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Litecoin Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tLTC", # coin_shortcut
+ 8, # decimals
+ 111, # address_type
+ 58, # address_type_p2sh
+ 40000000, # maxfee_kb
+ "Litecoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x043587cf, # xpub_magic_multisig_segwit_p2sh
+ 0x043587cf, # xpub_magic_multisig_segwit_native
+ "tltc", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Monacoin":
+ return CoinInfo(
+ name, # coin_name
+ "MONA", # coin_shortcut
+ 8, # decimals
+ 50, # address_type
+ 55, # address_type_p2sh
+ 2100000000, # maxfee_kb
+ "Monacoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "mona", # bech32_prefix
+ None, # cashaddr_prefix
+ 22, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Peercoin":
+ return CoinInfo(
+ name, # coin_name
+ "PPC", # coin_shortcut
+ 6, # decimals
+ 55, # address_type
+ 117, # address_type_p2sh
+ 13000000000, # maxfee_kb
+ "Peercoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "pc", # bech32_prefix
+ None, # cashaddr_prefix
+ 6, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ True, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Peercoin Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tPPC", # coin_shortcut
+ 6, # decimals
+ 111, # address_type
+ 196, # address_type_p2sh
+ 2000000, # maxfee_kb
+ "Peercoin Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x043587cf, # xpub_magic_multisig_segwit_p2sh
+ 0x043587cf, # xpub_magic_multisig_segwit_native
+ "tpc", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ True, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Primecoin":
+ return CoinInfo(
+ name, # coin_name
+ "XPM", # coin_shortcut
+ 8, # decimals
+ 23, # address_type
+ 83, # address_type_p2sh
+ 89000000000, # maxfee_kb
+ "Primecoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 24, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Qtum":
+ return CoinInfo(
+ name, # coin_name
+ "QTUM", # coin_shortcut
+ 8, # decimals
+ 58, # address_type
+ 50, # address_type_p2sh
+ 1000000000, # maxfee_kb
+ "Qtum Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "qc", # bech32_prefix
+ None, # cashaddr_prefix
+ 2301, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Qtum Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tQTUM", # coin_shortcut
+ 8, # decimals
+ 120, # address_type
+ 110, # address_type_p2sh
+ 40000000, # maxfee_kb
+ "Qtum Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ 0x044a5262, # xpub_magic_segwit_p2sh
+ 0x045f1cf6, # xpub_magic_segwit_native
+ 0x043587cf, # xpub_magic_multisig_segwit_p2sh
+ 0x043587cf, # xpub_magic_multisig_segwit_native
+ "tq", # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Ravencoin":
+ return CoinInfo(
+ name, # coin_name
+ "RVN", # coin_shortcut
+ 8, # decimals
+ 60, # address_type
+ 122, # address_type_p2sh
+ 170000000000, # maxfee_kb
+ "Raven Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 175, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Ravencoin Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tRVN", # coin_shortcut
+ 8, # decimals
+ 111, # address_type
+ 196, # address_type_p2sh
+ 170000000000, # maxfee_kb
+ "Raven Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Ritocoin":
+ return CoinInfo(
+ name, # coin_name
+ "RITO", # coin_shortcut
+ 8, # decimals
+ 25, # address_type
+ 105, # address_type_p2sh
+ 39000000000000, # maxfee_kb
+ "Rito Signed Message:\n", # signed_message_header
+ 0x0534e7ca, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 19169, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "SmartCash":
+ return CoinInfo(
+ name, # coin_name
+ "SMART", # coin_shortcut
+ 8, # decimals
+ 63, # address_type
+ 18, # address_type_p2sh
+ 780000000000, # maxfee_kb
+ "SmartCash Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 224, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1-smart', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "SmartCash Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "tSMART", # coin_shortcut
+ 8, # decimals
+ 65, # address_type
+ 21, # address_type_p2sh
+ 1000000, # maxfee_kb
+ "SmartCash Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1-smart', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Stakenet":
+ return CoinInfo(
+ name, # coin_name
+ "XSN", # coin_shortcut
+ 8, # decimals
+ 76, # address_type
+ 16, # address_type_p2sh
+ 11000000000, # maxfee_kb
+ "DarkCoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "xc", # bech32_prefix
+ None, # cashaddr_prefix
+ 199, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Syscoin":
+ return CoinInfo(
+ name, # coin_name
+ "SYS", # coin_shortcut
+ 8, # decimals
+ 63, # address_type
+ 5, # address_type_p2sh
+ 42000000000, # maxfee_kb
+ "Syscoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "sys", # bech32_prefix
+ None, # cashaddr_prefix
+ 57, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Unobtanium":
+ return CoinInfo(
+ name, # coin_name
+ "UNO", # coin_shortcut
+ 8, # decimals
+ 130, # address_type
+ 30, # address_type_p2sh
+ 53000000, # maxfee_kb
+ "Unobtanium Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 92, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "VIPSTARCOIN":
+ return CoinInfo(
+ name, # coin_name
+ "VIPS", # coin_shortcut
+ 8, # decimals
+ 70, # address_type
+ 50, # address_type_p2sh
+ 140000000000000, # maxfee_kb
+ "VIPSTARCOIN Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "vips", # bech32_prefix
+ None, # cashaddr_prefix
+ 1919, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Verge":
+ return CoinInfo(
+ name, # coin_name
+ "XVG", # coin_shortcut
+ 6, # decimals
+ 30, # address_type
+ 33, # address_type_p2sh
+ 550000000000, # maxfee_kb
+ "Name: Dogecoin Dark\n", # signed_message_header
+ 0x022d2533, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 77, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ True, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Viacoin":
+ return CoinInfo(
+ name, # coin_name
+ "VIA", # coin_shortcut
+ 8, # decimals
+ 71, # address_type
+ 33, # address_type_p2sh
+ 14000000000, # maxfee_kb
+ "Viacoin Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ 0x049d7cb2, # xpub_magic_segwit_p2sh
+ 0x04b24746, # xpub_magic_segwit_native
+ 0x0488b21e, # xpub_magic_multisig_segwit_p2sh
+ 0x0488b21e, # xpub_magic_multisig_segwit_native
+ "via", # bech32_prefix
+ None, # cashaddr_prefix
+ 14, # slip44
+ True, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "ZCore":
+ return CoinInfo(
+ name, # coin_name
+ "ZCR", # coin_shortcut
+ 8, # decimals
+ 142, # address_type
+ 145, # address_type_p2sh
+ 170000000000, # maxfee_kb
+ "DarkNet Signed Message:\n", # signed_message_header
+ 0x04b24746, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 428, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Zcash":
+ return CoinInfo(
+ name, # coin_name
+ "ZEC", # coin_shortcut
+ 8, # decimals
+ 7352, # address_type
+ 7357, # address_type_p2sh
+ 51000000, # maxfee_kb
+ "Zcash Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 133, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ True, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Zcash Testnet":
+ return CoinInfo(
+ name, # coin_name
+ "TAZ", # coin_shortcut
+ 8, # decimals
+ 7461, # address_type
+ 7354, # address_type_p2sh
+ 10000000, # maxfee_kb
+ "Zcash Signed Message:\n", # signed_message_header
+ 0x043587cf, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 1, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ True, # extra_data
+ False, # timestamp
+ True, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Ecash":
+ return CoinInfo(
+ name, # coin_name
+ "XEC", # coin_shortcut
+ 2, # decimals
+ 0, # address_type
+ 5, # address_type_p2sh
+ 14000000, # maxfee_kb
+ "eCash Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ "ecash", # cashaddr_prefix
+ 899, # slip44
+ False, # segwit
+ False, # taproot
+ 0, # fork_id
+ True, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ if name == "Brhodium":
+ return CoinInfo(
+ name, # coin_name
+ "XRC", # coin_shortcut
+ 8, # decimals
+ 61, # address_type
+ 123, # address_type_p2sh
+ 1000000000, # maxfee_kb
+ "BitCoin Rhodium Signed Message:\n", # signed_message_header
+ 0x0488b21e, # xpub_magic
+ None, # xpub_magic_segwit_p2sh
+ None, # xpub_magic_segwit_native
+ None, # xpub_magic_multisig_segwit_p2sh
+ None, # xpub_magic_multisig_segwit_native
+ None, # bech32_prefix
+ None, # cashaddr_prefix
+ 10291, # slip44
+ False, # segwit
+ False, # taproot
+ None, # fork_id
+ False, # force_bip143
+ False, # decred
+ False, # negative_fee
+ 'secp256k1', # curve_name
+ False, # extra_data
+ False, # timestamp
+ False, # overwintered
+ None, # confidential_assets
+ )
+ raise ValueError # Unknown coin name
raise ValueError # Unknown model
diff --git a/core/src/apps/ethereum/networks.py b/core/src/apps/ethereum/networks.py
index 9c00d1a86f..57d6824e57 100644
--- a/core/src/apps/ethereum/networks.py
+++ b/core/src/apps/ethereum/networks.py
@@ -334,3 +334,58 @@ def _networks_iterator() -> Iterator[NetworkInfoTuple]:
"tSEP", # symbol
"Sepolia", # name
)
+ if utils.INTERNAL_MODEL == "T2W1":
+ yield (
+ 1, # chain_id
+ 60, # slip44
+ "ETH", # symbol
+ "Ethereum", # name
+ )
+ yield (
+ 10, # chain_id
+ 614, # slip44
+ "ETH", # symbol
+ "Optimism", # name
+ )
+ yield (
+ 56, # chain_id
+ 714, # slip44
+ "BNB", # symbol
+ "BNB Smart Chain", # name
+ )
+ yield (
+ 61, # chain_id
+ 61, # slip44
+ "ETC", # symbol
+ "Ethereum Classic", # name
+ )
+ yield (
+ 137, # chain_id
+ 966, # slip44
+ "POL", # symbol
+ "Polygon", # name
+ )
+ yield (
+ 8453, # chain_id
+ 8453, # slip44
+ "ETH", # symbol
+ "Base", # name
+ )
+ yield (
+ 17000, # chain_id
+ 1, # slip44
+ "tHOL", # symbol
+ "Holesky", # name
+ )
+ yield (
+ 42161, # chain_id
+ 9001, # slip44
+ "ETH", # symbol
+ "Arbitrum One", # name
+ )
+ yield (
+ 11155111, # chain_id
+ 1, # slip44
+ "tSEP", # symbol
+ "Sepolia", # name
+ )
diff --git a/core/src/apps/ethereum/tokens.py b/core/src/apps/ethereum/tokens.py
index c83e548899..3174074219 100644
--- a/core/src/apps/ethereum/tokens.py
+++ b/core/src/apps/ethereum/tokens.py
@@ -782,3 +782,151 @@ def _token_iterator(chain_id: int) -> Iterator[tuple[bytes, str, int, str]]:
18,
"Wrapped AVAX",
)
+ if utils.INTERNAL_MODEL == "T2W1":
+ if chain_id == 1: # eth
+ yield ( # address, symbol, decimals, name
+ b"\x7f\xc6\x65\x00\xc8\x4a\x76\xad\x7e\x9c\x93\x43\x7b\xfc\x5a\xc3\x3e\x2d\xda\xe9",
+ "AAVE",
+ 18,
+ "Aave",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x4d\x22\x44\x52\x80\x1a\xce\xd8\xb2\xf0\xae\xbe\x15\x53\x79\xbb\x5d\x59\x43\x81",
+ "APE",
+ 18,
+ "ApeCoin",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\xbb\x0e\x17\xef\x65\xf8\x2a\xb0\x18\xd8\xed\xd7\x76\xe8\xdd\x94\x03\x27\xb2\x8b",
+ "AXS",
+ 18,
+ "Axie Infinity",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x4f\xab\xb1\x45\xd6\x46\x52\xa9\x48\xd7\x25\x33\x02\x3f\x6e\x7a\x62\x3c\x7c\x53",
+ "BUSD",
+ 18,
+ "Binance USD",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x35\x06\x42\x4f\x91\xfd\x33\x08\x44\x66\xf4\x02\xd5\xd9\x7f\x05\xf8\xe3\xb4\xaf",
+ "CHZ",
+ 18,
+ "Chiliz",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\xa0\xb7\x3e\x1f\xf0\xb8\x09\x14\xab\x6f\xe0\x44\x4e\x65\x84\x8c\x4c\x34\x45\x0b",
+ "CRO",
+ 8,
+ "Cronos",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x6b\x17\x54\x74\xe8\x90\x94\xc4\x4d\xa9\x8b\x95\x4e\xed\xea\xc4\x95\x27\x1d\x0f",
+ "DAI",
+ 18,
+ "Dai",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x85\x3d\x95\x5a\xce\xf8\x22\xdb\x05\x8e\xb8\x50\x59\x11\xed\x77\xf1\x75\xb9\x9e",
+ "FRAX",
+ 18,
+ "Frax",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x2a\xf5\xd2\xad\x76\x74\x11\x91\xd1\x5d\xfe\x7b\xf6\xac\x92\xd4\xbd\x91\x2c\xa3",
+ "LEO",
+ 18,
+ "LEO Token",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x51\x49\x10\x77\x1a\xf9\xca\x65\x6a\xf8\x40\xdf\xf8\x3e\x82\x64\xec\xf9\x86\xca",
+ "LINK",
+ 18,
+ "Chainlink",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x0f\x5d\x2f\xb2\x9f\xb7\xd3\xcf\xee\x44\x4a\x20\x02\x98\xf4\x68\x90\x8c\xc9\x42",
+ "MANA",
+ 18,
+ "Decentraland",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x7d\x1a\xfa\x7b\x71\x8f\xb8\x93\xdb\x30\xa3\xab\xc0\xcf\xc6\x08\xaa\xcf\xeb\xb0",
+ "MATIC",
+ 18,
+ "Polygon",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x75\x23\x1f\x58\xb4\x32\x40\xc9\x71\x8d\xd5\x8b\x49\x67\xc5\x11\x43\x42\xa8\x6c",
+ "OKB",
+ 18,
+ "OKB",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x4a\x22\x0e\x60\x96\xb2\x5e\xad\xb8\x83\x58\xcb\x44\x06\x8a\x32\x48\x25\x46\x75",
+ "QNT",
+ 18,
+ "Quant",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x38\x45\xba\xda\xde\x8e\x6d\xff\x04\x98\x20\x68\x0d\x1f\x14\xbd\x39\x03\xa5\xd0",
+ "SAND",
+ 18,
+ "The Sandbox",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x95\xad\x61\xb0\xa1\x50\xd7\x92\x19\xdc\xf6\x4e\x1e\x6c\xc0\x1f\x0b\x64\xc4\xce",
+ "SHIB",
+ 18,
+ "Shiba Inu",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\xae\x7a\xb9\x65\x20\xde\x3a\x18\xe5\xe1\x11\xb5\xea\xab\x09\x53\x12\xd7\xfe\x84",
+ "STETH",
+ 18,
+ "Lido Staked Ether",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x1f\x98\x40\xa8\x5d\x5a\xf5\xbf\x1d\x17\x62\xf9\x25\xbd\xad\xdc\x42\x01\xf9\x84",
+ "UNI",
+ 18,
+ "Uniswap",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\xa0\xb8\x69\x91\xc6\x21\x8b\x36\xc1\xd1\x9d\x4a\x2e\x9e\xb0\xce\x36\x06\xeb\x48",
+ "USDC",
+ 6,
+ "USD Coin",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\xda\xc1\x7f\x95\x8d\x2e\xe5\x23\xa2\x20\x62\x06\x99\x45\x97\xc1\x3d\x83\x1e\xc7",
+ "USDT",
+ 6,
+ "Tether",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\x22\x60\xfa\xc5\xe5\x54\x2a\x77\x3a\xa4\x4f\xbc\xfe\xdf\x7c\x19\x3b\xc2\xc5\x99",
+ "WBTC",
+ 8,
+ "Wrapped Bitcoin",
+ )
+ yield ( # address, symbol, decimals, name
+ b"\xa2\xcd\x3d\x43\xc7\x75\x97\x8a\x96\xbd\xbf\x12\xd7\x33\xd5\xa1\xed\x94\xfb\x18",
+ "XCN",
+ 18,
+ "Chain",
+ )
+ if chain_id == 56: # bnb
+ yield ( # address, symbol, decimals, name
+ b"\x0e\xb3\xa7\x05\xfc\x54\x72\x50\x37\xcc\x9e\x00\x8b\xde\xde\x69\x7f\x62\xf3\x35",
+ "ATOM",
+ 18,
+ "Cosmos Hub",
+ )
+ if chain_id == 137: # matic
+ yield ( # address, symbol, decimals, name
+ b"\x2c\x89\xbb\xc9\x2b\xd8\x6f\x80\x75\xd1\xde\xcc\x58\xc7\xf4\xe0\x10\x7f\x28\x6b",
+ "WAVAX",
+ 18,
+ "Wrapped AVAX",
+ )
diff --git a/python/src/trezorlib/firmware/models.py b/python/src/trezorlib/firmware/models.py
index a8fa08a988..080dd07203 100644
--- a/python/src/trezorlib/firmware/models.py
+++ b/python/src/trezorlib/firmware/models.py
@@ -33,6 +33,7 @@ class Model(Enum):
T1B1 = b"T1B1"
T2B1 = b"T2B1"
T2T1 = b"T2T1"
+ T2W1 = b"T2W1"
T3B1 = b"T3B1"
T3T1 = b"T3T1"
T3W1 = b"T3W1"
@@ -178,6 +179,31 @@ T2T1 = ModelKeys(
firmware_sigs_needed=-1,
)
+
+T2W1 = ModelKeys(
+ production=True,
+ boardloader_keys=[
+ bytes.fromhex(key)
+ for key in (
+ "0eb9856be9ba7e972c7f34eac1ed9b6fd0efd172ec00faf0c589759da4ddfba0",
+ "ac8ab40b32c98655798fd5da5e192be27a22306ea05c6d277cdff4a3f4125cd8",
+ "ce0fcd12543ef5936cf2804982136707863d17295faced72af171d6e6513ff06",
+ )
+ ],
+ boardloader_sigs_needed=2,
+ bootloader_keys=[
+ bytes.fromhex(key)
+ for key in (
+ "c2c87a49c5a3460977fbb2ec9dfe60f06bd694db8244bd4981fe3b7a26307f3f",
+ "80d036b08739b846f4cb77593078deb25dc9487aedcf52e30b4fb7cd7024178a",
+ "b8307a71f552c60a4cbb317ff48b82cdbf6b6bb5f04c920fec7badf017883751",
+ )
+ ],
+ bootloader_sigs_needed=2,
+ firmware_keys=(),
+ firmware_sigs_needed=-1,
+)
+
TREZOR_CORE_DEV = ModelKeys(
production=False,
boardloader_keys=[
@@ -310,6 +336,12 @@ T2T1_HASH_PARAMS = FirmwareHashParameters(
padding_byte=None,
)
+T2W1_HASH_PARAMS = FirmwareHashParameters(
+ hash_function=hashlib.blake2s,
+ chunk_size=1024 * 128,
+ padding_byte=None,
+)
+
T3T1_HASH_PARAMS = FirmwareHashParameters(
hash_function=hashlib.sha256,
chunk_size=1024 * 128,
@@ -337,6 +369,7 @@ D002_HASH_PARAMS = FirmwareHashParameters(
MODEL_MAP = {
Model.T1B1: LEGACY_V3,
Model.T2T1: T2T1,
+ Model.T2W1: T2W1,
Model.T2B1: T2B1,
Model.T3T1: T3T1,
Model.T3B1: T3B1,
@@ -348,6 +381,7 @@ MODEL_MAP = {
MODEL_MAP_DEV = {
Model.T1B1: LEGACY_V3_DEV,
Model.T2T1: TREZOR_CORE_DEV,
+ Model.T2W1: TREZOR_CORE_DEV,
Model.T2B1: TREZOR_CORE_DEV,
Model.T3T1: TREZOR_CORE_DEV,
Model.T3B1: TREZOR_CORE_DEV,
@@ -359,6 +393,7 @@ MODEL_MAP_DEV = {
MODEL_HASH_PARAMS_MAP = {
Model.T1B1: LEGACY_HASH_PARAMS,
Model.T2T1: T2T1_HASH_PARAMS,
+ Model.T2W1: T2W1_HASH_PARAMS,
Model.T2B1: T2T1_HASH_PARAMS,
Model.T3T1: T3T1_HASH_PARAMS,
Model.T3B1: T3B1_HASH_PARAMS,
diff --git a/python/src/trezorlib/models.py b/python/src/trezorlib/models.py
index e7a4d9ea75..a5f3236c75 100644
--- a/python/src/trezorlib/models.py
+++ b/python/src/trezorlib/models.py
@@ -63,6 +63,15 @@ T2T1 = TrezorModel(
default_mapping=mapping.DEFAULT_MAPPING,
)
+T2W1 = TrezorModel(
+ name="T2W1",
+ internal_name="T2W1",
+ minimum_version=(2, 1, 0),
+ vendors=VENDORS,
+ usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
+ default_mapping=mapping.DEFAULT_MAPPING,
+)
+
T2B1 = TrezorModel(
name="Safe 3",
internal_name="T2B1",
@@ -127,7 +136,7 @@ TREZOR_SAFE5 = T3T1
TREZOR_DISC1 = DISC1
TREZOR_DISC2 = DISC2
-TREZORS = frozenset({T1B1, T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
+TREZORS = frozenset({T1B1, T2T1, T2W1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
def by_name(name: str | None) -> TrezorModel | None: