From 18cc9ae251d3c14e44e3dec288f71113735aee18 Mon Sep 17 00:00:00 2001 From: soralit Date: Fri, 3 Jan 2025 16:21:30 +0800 Subject: [PATCH 1/7] feat: add keystone connect functions --- rust/apps/wallets/src/keystone_connect.rs | 425 ++++++++++++++++++ rust/apps/wallets/src/lib.rs | 1 + .../multi_coins_wallet/keystone_connect.rs | 64 +++ .../src/wallet/multi_coins_wallet/mod.rs | 1 + rust/rust_c/src/zcash/mod.rs | 3 + src/ui/gui_wallet/multi/web3/gui_wallet.c | 42 ++ src/ui/gui_wallet/multi/web3/gui_wallet.h | 1 + .../multi/web3/gui_connect_wallet_widgets.c | 9 +- 8 files changed, 542 insertions(+), 4 deletions(-) create mode 100644 rust/apps/wallets/src/keystone_connect.rs create mode 100644 rust/rust_c/src/wallet/multi_coins_wallet/keystone_connect.rs diff --git a/rust/apps/wallets/src/keystone_connect.rs b/rust/apps/wallets/src/keystone_connect.rs new file mode 100644 index 000000000..fc9f842e5 --- /dev/null +++ b/rust/apps/wallets/src/keystone_connect.rs @@ -0,0 +1,425 @@ +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use core::str::FromStr; + +use { + bitcoin::bip32::{ChildNumber, DerivationPath}, + bitcoin::secp256k1::Secp256k1, + hex, + ur_registry::{ + crypto_hd_key::CryptoHDKey, + crypto_key_path::{CryptoKeyPath, PathComponent}, + error::{URError, URResult}, + extend::crypto_multi_accounts::CryptoMultiAccounts, + }, +}; + +use crate::{common::get_path_component, ExtendedPublicKey}; + +fn get_device_id(serial_number: &str) -> String { + use cryptoxide::hashing::sha256; + hex::encode(&sha256(&sha256(serial_number.as_bytes()))[0..20]) +} + +const BTC_LEGACY_PREFIX: &str = "44'/0'/0'"; +const BTC_SEGWIT_PREFIX: &str = "49'/0'/0'"; +const BTC_NATIVE_SEGWIT_PREFIX: &str = "84'/0'/0'"; +const BTC_TAPROOT_PREFIX: &str = "86'/0'/0'"; +const ETH_STANDARD_PREFIX: &str = "44'/60'/0'"; +const ETH_LEDGER_LIVE_PREFIX: &str = "44'/60'"; //overlap with ETH_STANDARD at 0 +const TRX_PREFIX: &str = "44'/195'/0'"; + +pub fn generate_crypto_multi_accounts( + master_fingerprint: [u8; 4], + serial_number: &str, + extended_public_keys: Vec, + device_type: &str, + device_version: &str, +) -> URResult { + let device_id = get_device_id(serial_number); + let mut keys = vec![]; + let k1_keys = [ + BTC_LEGACY_PREFIX.to_string(), + BTC_SEGWIT_PREFIX.to_string(), + BTC_NATIVE_SEGWIT_PREFIX.to_string(), + BTC_TAPROOT_PREFIX.to_string(), + TRX_PREFIX.to_string(), + ]; + for ele in extended_public_keys { + match ele.get_path() { + _path if k1_keys.contains(&_path.to_string().to_lowercase()) => { + keys.push(generate_k1_normal_key( + master_fingerprint, + ele.clone(), + None, + false, + )?); + } + _path if _path.to_string().to_lowercase().eq(ETH_STANDARD_PREFIX) => { + keys.push(generate_k1_normal_key( + master_fingerprint, + ele.clone(), + Some("account.standard".to_string()), + true, + )?); + keys.push(generate_eth_ledger_legacy_pubkey( + master_fingerprint, + ele.clone(), + Some("account.ledger_legacy".to_string()), + )?); + keys.push(generate_eth_ledger_live_key( + master_fingerprint, + ele, + Some("account.ledger_live".to_string()), + )?); + } + _path + if _path + .to_string() + .to_lowercase() + .starts_with(ETH_LEDGER_LIVE_PREFIX) => + { + keys.push(generate_eth_ledger_live_key( + master_fingerprint, + ele, + Some("account.ledger_live".to_string()), + )?); + } + _ => { + return Err(URError::UrEncodeError(format!( + "Unknown key path: {}", + ele.path + ))) + } + } + } + + Ok(CryptoMultiAccounts::new( + master_fingerprint, + keys, + Some(device_type.to_string()), + Some(device_id), + Some(device_version.to_string()), + )) +} + +fn generate_eth_ledger_legacy_pubkey( + mfp: [u8; 4], + key: ExtendedPublicKey, + note: Option, +) -> URResult { + let xpub = bitcoin::bip32::Xpub::decode(&key.get_key()) + .map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let path = key.get_path(); + let sub_path = + DerivationPath::from_str("m/0").map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let _target_key = xpub + .derive_pub(&Secp256k1::new(), &sub_path) + .map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let target_path = path.child(ChildNumber::Normal { index: 0 }); + let key_path = CryptoKeyPath::new( + target_path + .into_iter() + .map(|v| match v { + ChildNumber::Normal { index } => get_path_component(Some(*index), false), + ChildNumber::Hardened { index } => get_path_component(Some(*index), true), + }) + .collect::>>()?, + Some(mfp), + Some(xpub.depth as u32), + ); + + Ok(CryptoHDKey::new_extended_key( + Some(false), + _target_key.public_key.serialize().to_vec(), + None, + None, + Some(key_path), + None, + Some(_target_key.parent_fingerprint.to_bytes()), + Some("Keystone".to_string()), + note, + )) +} + +fn generate_k1_normal_key( + mfp: [u8; 4], + key: ExtendedPublicKey, + note: Option, + is_standard: bool, +) -> URResult { + let xpub = bitcoin::bip32::Xpub::decode(&key.get_key()) + .map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let path = key.get_path(); + let key_path = CryptoKeyPath::new( + path.into_iter() + .map(|v| match v { + ChildNumber::Normal { index } => get_path_component(Some(*index), false), + ChildNumber::Hardened { index } => get_path_component(Some(*index), true), + }) + .collect::>>()?, + Some(mfp), + Some(xpub.depth as u32), + ); + + let children = CryptoKeyPath::new( + match is_standard { + true => { + vec![ + get_path_component(Some(0), false)?, + get_path_component(None, false)?, + ] + } + false => vec![get_path_component(None, false)?], + }, + None, + Some(0), + ); + Ok(CryptoHDKey::new_extended_key( + Some(false), + xpub.public_key.serialize().to_vec(), + Some(xpub.chain_code.to_bytes().to_vec()), + None, + Some(key_path), + Some(children), + Some(xpub.parent_fingerprint.to_bytes()), + Some("Keystone".to_string()), + note, + )) +} + +fn generate_eth_ledger_live_key( + mfp: [u8; 4], + key: ExtendedPublicKey, + note: Option, +) -> URResult { + let xpub = bitcoin::bip32::Xpub::decode(&key.get_key()) + .map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let path = key.get_path(); + let sub_path = + DerivationPath::from_str("m/0/0").map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let _target_key = xpub + .derive_pub(&Secp256k1::new(), &sub_path) + .map_err(|_e| URError::UrEncodeError(_e.to_string()))?; + let target_path = path + .child(ChildNumber::Normal { index: 0 }) + .child(ChildNumber::Normal { index: 0 }); + let key_path = CryptoKeyPath::new( + target_path + .into_iter() + .map(|v| match v { + ChildNumber::Normal { index } => get_path_component(Some(*index), false), + ChildNumber::Hardened { index } => get_path_component(Some(*index), true), + }) + .collect::>>()?, + Some(mfp), + Some(xpub.depth as u32), + ); + Ok(CryptoHDKey::new_extended_key( + Some(false), + _target_key.public_key.serialize().to_vec(), + None, + None, + Some(key_path), + None, + Some(_target_key.parent_fingerprint.to_bytes()), + Some("Keystone".to_string()), + note, + )) +} + +#[cfg(test)] +mod tests { + extern crate std; + use crate::DEVICE_TYPE; + + use super::*; + use alloc::vec::Vec; + + use hex; + use hex::FromHex; + #[test] + fn test_generate_crypto_multi_accounts() { + let mfp = hex::encode([82, 116, 71, 3]); + let mfp = Vec::from_hex(mfp).unwrap(); + let mfp: [u8; 4] = mfp.try_into().unwrap(); + + let x_pub_1_path = "m/44'/60'/0'"; + let x_pub_1 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 0, 150, 103, 43, 221, 62, 231, 33, + 47, 231, 148, 112, 64, 231, 3, 205, 219, 170, 181, 180, 152, 129, 87, 135, 166, 1, 71, + 108, 117, 231, 231, 137, 157, 3, 76, 114, 154, 166, 56, 179, 38, 22, 64, 168, 240, 106, + 94, 171, 191, 228, 192, 77, 46, 10, 172, 67, 75, 52, 65, 71, 161, 165, 250, 53, 85, + 163, + ]; + let x_pub_2_path = "m/44'/60'/1'"; + let x_pub_2 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 1, 148, 143, 211, 16, 153, 241, 166, + 9, 231, 144, 251, 55, 121, 251, 223, 181, 222, 157, 63, 38, 163, 162, 65, 50, 248, 30, + 93, 185, 103, 109, 120, 129, 2, 55, 60, 190, 7, 95, 36, 155, 222, 189, 16, 51, 171, + 118, 251, 92, 168, 24, 193, 204, 69, 67, 178, 12, 79, 7, 216, 134, 139, 30, 103, 186, + 251, + ]; + + let x_pub_3_path = "m/44'/60'/2'"; + let x_pub_3 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 2, 16, 107, 233, 212, 0, 17, 88, + 106, 139, 83, 176, 242, 100, 190, 71, 214, 17, 166, 120, 29, 31, 68, 180, 142, 32, 235, + 36, 81, 84, 233, 42, 191, 3, 151, 84, 229, 42, 100, 158, 78, 217, 45, 36, 148, 174, 59, + 182, 164, 145, 107, 245, 4, 218, 72, 95, 171, 102, 158, 205, 1, 177, 203, 247, 38, 220, + ]; + let x_pub_4_path = "m/44'/60'/3'"; + let x_pub_4 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 3, 74, 223, 222, 76, 163, 132, 239, + 26, 157, 40, 237, 242, 53, 73, 61, 122, 193, 54, 44, 251, 71, 234, 29, 105, 138, 186, + 91, 239, 193, 10, 107, 68, 2, 159, 183, 206, 159, 91, 8, 120, 253, 25, 25, 122, 144, + 226, 118, 212, 104, 225, 155, 24, 210, 77, 167, 138, 132, 194, 194, 67, 128, 113, 141, + 1, 27, + ]; + + let x_pub_5_path = "m/44'/60'/4'"; + let x_pub_5 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 4, 138, 172, 17, 199, 232, 239, 212, + 251, 67, 191, 6, 103, 42, 86, 181, 161, 55, 146, 19, 187, 179, 189, 184, 247, 243, 149, + 25, 7, 176, 132, 47, 122, 2, 16, 111, 49, 181, 222, 200, 141, 94, 51, 86, 244, 64, 221, + 221, 193, 97, 67, 228, 185, 183, 66, 125, 195, 244, 6, 90, 12, 233, 210, 136, 60, 187, + ]; + + let x_pub_6_path = "m/44'/60'/5'"; + let x_pub_6 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 5, 62, 230, 228, 88, 237, 74, 149, + 156, 199, 102, 0, 127, 143, 56, 85, 221, 226, 212, 35, 82, 103, 109, 9, 24, 81, 48, + 216, 87, 112, 0, 49, 225, 3, 58, 34, 37, 52, 169, 50, 194, 74, 19, 194, 180, 6, 156, + 241, 54, 136, 69, 65, 171, 141, 95, 179, 189, 34, 150, 82, 2, 154, 186, 11, 116, 184, + ]; + + let x_pub_7_path = "m/44'/60'/6'"; + let x_pub_7 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 6, 158, 224, 95, 103, 228, 232, 148, + 203, 99, 195, 37, 140, 15, 199, 125, 197, 42, 209, 179, 116, 4, 24, 134, 222, 120, 76, + 123, 113, 130, 69, 68, 2, 2, 205, 139, 195, 67, 65, 220, 173, 157, 52, 93, 196, 12, + 242, 246, 89, 191, 217, 35, 106, 9, 37, 7, 143, 141, 162, 160, 73, 97, 69, 0, 140, 36, + ]; + + let x_pub_8_path = "m/44'/60'/7'"; + let x_pub_8 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 7, 108, 132, 52, 99, 212, 233, 149, + 22, 235, 206, 217, 140, 53, 85, 233, 66, 195, 191, 103, 228, 78, 24, 2, 63, 32, 170, + 61, 153, 173, 194, 5, 194, 2, 181, 234, 55, 152, 34, 162, 157, 219, 30, 82, 241, 134, + 12, 173, 159, 198, 171, 40, 44, 112, 78, 128, 106, 118, 51, 187, 150, 164, 210, 192, + 170, 96, + ]; + + let x_pub_9_path = "m/44'/60'/8'"; + let x_pub_9 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 8, 148, 81, 116, 27, 224, 203, 95, + 155, 195, 120, 112, 171, 17, 25, 0, 244, 176, 200, 94, 136, 65, 84, 191, 180, 100, 210, + 90, 91, 155, 119, 155, 111, 2, 147, 97, 104, 39, 151, 40, 160, 135, 226, 145, 37, 55, + 28, 147, 157, 160, 71, 20, 179, 46, 89, 242, 178, 211, 152, 240, 193, 81, 46, 185, 7, + 133, + ]; + + let x_pub_10_path = "m/44'/60'/9'"; + let x_pub_10 = vec![ + 4, 136, 178, 30, 3, 225, 141, 236, 200, 128, 0, 0, 9, 207, 200, 119, 68, 9, 204, 133, + 63, 160, 113, 213, 93, 158, 70, 181, 249, 98, 3, 206, 34, 73, 6, 41, 10, 108, 33, 118, + 198, 159, 13, 156, 227, 3, 197, 46, 28, 0, 66, 10, 72, 140, 130, 55, 161, 162, 81, 181, + 48, 125, 109, 186, 143, 69, 241, 243, 214, 178, 67, 70, 221, 8, 37, 216, 238, 137, + ]; + + let x_pub_11_path = "m/44'/0'/0'"; + let x_pub_11 = vec![ + 4, 136, 178, 30, 3, 116, 65, 243, 92, 128, 0, 0, 0, 81, 116, 56, 174, 194, 183, 142, + 129, 194, 117, 164, 27, 230, 61, 246, 8, 51, 88, 7, 12, 190, 253, 181, 157, 230, 155, + 210, 249, 156, 0, 62, 138, 3, 235, 213, 82, 2, 123, 115, 173, 177, 222, 26, 164, 148, + 202, 124, 237, 254, 120, 20, 52, 214, 241, 2, 165, 83, 85, 177, 24, 160, 197, 218, 120, + 188, + ]; + + let x_pub_12_path = "m/49'/0'/0'"; + let x_pub_12 = vec![ + 4, 136, 178, 30, 3, 89, 252, 178, 101, 128, 0, 0, 0, 172, 49, 222, 228, 221, 63, 70, + 50, 249, 132, 224, 164, 30, 135, 40, 237, 195, 236, 103, 246, 20, 200, 240, 49, 129, + 73, 12, 137, 69, 209, 157, 116, 2, 243, 185, 124, 243, 243, 56, 126, 44, 77, 140, 113, + 65, 162, 21, 41, 169, 14, 5, 133, 233, 240, 50, 112, 103, 152, 209, 143, 152, 138, 86, + 227, 241, + ]; + + let _x_pub_13_path = "m/84'/0'/0'"; + let _x_pub_13 = vec![ + 4, 136, 178, 30, 3, 129, 255, 52, 49, 128, 0, 0, 0, 57, 156, 154, 156, 107, 152, 113, + 18, 53, 162, 72, 79, 142, 68, 203, 181, 241, 230, 86, 48, 106, 225, 90, 11, 178, 154, + 13, 126, 210, 39, 240, 168, 2, 56, 80, 109, 189, 148, 232, 33, 102, 203, 104, 83, 111, + 250, 13, 14, 20, 95, 203, 135, 185, 117, 217, 219, 208, 71, 95, 219, 102, 79, 61, 174, + 166, + ]; + + let _x_pub_14_path = "m/86'/0'/0'"; + let _x_pub_14 = vec![ + 4, 136, 178, 30, 3, 160, 104, 43, 1, 128, 0, 0, 0, 175, 58, 35, 239, 123, 26, 84, 211, + 219, 219, 108, 62, 80, 35, 130, 229, 93, 229, 255, 87, 95, 19, 206, 172, 245, 43, 224, + 27, 227, 124, 11, 68, 2, 108, 57, 94, 23, 99, 245, 166, 240, 122, 222, 53, 87, 66, 156, + 75, 218, 180, 93, 84, 135, 89, 158, 210, 131, 231, 133, 52, 172, 24, 22, 64, 143, + ]; + + let account = generate_crypto_multi_accounts( + mfp, + "31206", + vec![ + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_1_path).unwrap(), x_pub_1), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_2_path).unwrap(), x_pub_2), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_3_path).unwrap(), x_pub_3), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_4_path).unwrap(), x_pub_4), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_5_path).unwrap(), x_pub_5), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_6_path).unwrap(), x_pub_6), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_7_path).unwrap(), x_pub_7), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_8_path).unwrap(), x_pub_8), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_9_path).unwrap(), x_pub_9), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_10_path).unwrap(), x_pub_10), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_11_path).unwrap(), x_pub_11), + ExtendedPublicKey::new(DerivationPath::from_str(x_pub_12_path).unwrap(), x_pub_12), + ], + DEVICE_TYPE, + "1.1.0", + ) + .unwrap(); + let cbor: Vec = account.try_into().unwrap(); + + assert_eq!(hex::encode(cbor).to_lowercase(), + "a5011a52744703028ed9012fa802f4035821034c729aa638b3261640a8f06a5eabbfe4c04d2e0aac434b344147a1a5fa3555a304582096672bdd3ee7212fe7947040e703cddbaab5b498815787a601476c75e7e7899d06d90130a30186182cf5183cf500f5021a52744703030307d90130a2018400f480f40300081ae18decc809684b657973746f6e650a706163636f756e742e7374616e64617264d9012fa802f4035821034c729aa638b3261640a8f06a5eabbfe4c04d2e0aac434b344147a1a5fa3555a304582096672bdd3ee7212fe7947040e703cddbaab5b498815787a601476c75e7e7899d06d90130a30186182cf5183cf500f5021a52744703030307d90130a2018280f40300081ae18decc809684b657973746f6e650a756163636f756e742e6c65646765725f6c6567616379d9012fa602f4035821039f4e693730f116e7ab01dac46b94ad4fcabc3ca7d91a6b121cc26782a8f2b8b206d90130a3018a182cf5183cf500f500f400f4021a527447030303081aaea3081709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102f6cb8d18cef477defff35eae0d4fbfdb7e929fcf124056642bb52005121f2b8206d90130a3018a182cf5183cf501f500f400f4021a527447030303081afbdad0f009684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821025bac93928fb3a1b42abd1ef04a9df7152c3e3ac9784b0adeb8c74f02d6e081a706d90130a3018a182cf5183cf502f500f400f4021a527447030303081a127d09a409684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821031c4731b1d0f2813f25732a07bc8634a1d43678fb5f3e339e31868e7a3e161b3106d90130a3018a182cf5183cf503f500f400f4021a527447030303081aaa7ae17b09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103ee66c1903304ae22499bb7236ed9afe9de557ae4aa8756660bd13468e016ebfe06d90130a3018a182cf5183cf504f500f400f4021a527447030303081a53cb808a09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103b36c22174290c6ce6edb10df4386f7a4dee680313a7daecab7ceb48edb41d0d406d90130a3018a182cf5183cf505f500f400f4021a527447030303081a37d6210c09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f40358210301e2533680aceb0eea3cd0c23ca1fcec7ef0c085c4ba89986b56d919c6e775c106d90130a3018a182cf5183cf506f500f400f4021a527447030303081a14ff4a1509684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102a54598a178b1153c19a3678851c4e35162c018a1b5f354ad9cbf169fc365e6e106d90130a3018a182cf5183cf507f500f400f4021a527447030303081af4cff0d209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103934334794763b31983061359e7c5de9aa400083fcdffbb7c3c8791bda35700fe06d90130a3018a182cf5183cf508f500f400f4021a527447030303081a4267812709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821026f95e551487e0c75ebfdbdcf6c68d4cf3596729f6b0700e4b789f161dd41557906d90130a3018a182cf5183cf509f500f400f4021a527447030303081aa109680309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa702f403582103ebd552027b73adb1de1aa494ca7cedfe781434d6f102a55355b118a0c5da78bc045820517438aec2b78e81c275a41be63df6083358070cbefdb59de69bd2f99c003e8a06d90130a30186182cf500f500f5021a52744703030307d90130a2018280f40300081a7441f35c09684b657973746f6e65d9012fa702f403582102f3b97cf3f3387e2c4d8c7141a21529a90e0585e9f032706798d18f988a56e3f1045820ac31dee4dd3f4632f984e0a41e8728edc3ec67f614c8f03181490c8945d19d7406d90130a301861831f500f500f5021a52744703030307d90130a2018280f40300081a59fcb26509684b657973746f6e65036e4b657973746f6e6520332050726f047828626635353461326136316463336362303366656362303031333335323563353561356138316433310565312e312e30") + } + + #[test] + fn test_generate_with_ton_keys() { + let mfp = [18, 80, 182, 188]; + let serial_number = "DVT230712345"; + let device_type = "Keystone 3 Pro"; + let device_version = "1.7.0"; + + let keys = vec![ + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/0'").unwrap(), hex::decode("0488b21e0363c5ea6780000000bf103cfabcab325a7463ab5c432a4042109279d6c3531c8c5ea712684cf31f3703c4ad25226a98764f7b753b6c763be112c940182e0b6698944c9def253cec4676").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/1'").unwrap(), hex::decode("0488b21e0363c5ea678000000198a39a788ccbb42873c3301841cf2f1b9cec097825b7723c3613411b5edfe36e02d89a27cf3e1e256e37f1c8eb5c80825c064b499443eae32469b6758686c6faaf").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/2'").unwrap(), hex::decode("0488b21e0363c5ea67800000029ccc3e21cc93df5a845c786733e19bac47e4b862642e53772b314a01161b3b8b022ec57c196ad963bc52fa7ce43050ec3d9316a537d97507744cf44831aa7b08fd").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/3'").unwrap(), hex::decode("0488b21e0363c5ea67800000039993b525a98e702cf95de593f8d2fe86a4cadb5a51aa0c1391887e20353ef42e03f2bd77ec2cf50e0746591beac19a949166b91619a628bd3893ff6f09605d2dea").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/4'").unwrap(), hex::decode("0488b21e0363c5ea6780000004824a734567f27f87812bcc0beda329ae998e1c5fcf559b32418d995d30c17d6a02a7ce81a54633ef9e853214d1cf915e2889730fa691ac8da9e58dbbc70dca52c9").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/5'").unwrap(), hex::decode("0488b21e0363c5ea6780000005799bffbf6bf0b74ffb899096528c523e9c12caa1f96183779ded0292224fbed602c074419d25973cf7fce728691f8c59face7a92d87288d7319ac0c1a35d9c11ef").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/6'").unwrap(), hex::decode("0488b21e0363c5ea67800000060bb4adaeee1876fd5e828d6ea83cc19833067e7a10eea23360f2fcc76b7009a602f18e29894166aa95184993c88174dd1f62b5c16dfbbc5bdc9a62e476c2af5216").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/7'").unwrap(), hex::decode("0488b21e0363c5ea6780000007a1781270805f0361c3bc96a11b333c7e996d3a4e0081e649884a2eeb9ab4af1603706361f5ced38b85aae5defcd63b62667eca3f7a7cca1cc1b41ef454675c820a").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/8'").unwrap(), hex::decode("0488b21e0363c5ea6780000008ebdb2a570770fbe2feb042b43fc80472209e67051eec4884f41f4ea0bf5488fe026f84908e600a4c4830228fe98e05ca8a648d819d82b957377a232742709fd6ce").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/60'/9'").unwrap(), hex::decode("0488b21e0363c5ea67800000092f8a054f02f61f09ea86a8e66fcadb95a52a27c7cfe17cecdf4a97c5df80a3c103fbd0987d1f47906476ac432d2a0c91563cf2d30bd31f4593d87cc0543afa55dd").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/0'/0'").unwrap(), hex::decode("0488b21e03b5d6f4508000000051872c7bb8270a7655ae15d738bb21379962ff11fb048b55630395afcfef44280246696468fa5c46647bdd186f568983e2a26773dc5b4c174790fee7ef9b9a7c99").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/49'/0'/0'").unwrap(), hex::decode("0488b21e03197077c880000000bad8f929afd65c4b3ff78db1a386062374f2d2e6552e9fdc59aa7dd9b5db6e2c03ab6a1908b437179b914dc3cf4b829d7387adf60fdee483e9c748d5ee79ba4be4").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/84'/0'/0'").unwrap(), hex::decode("0488b21e039f6b7e4b80000000de47dd17679605b84abf439bdf5477c6cb94ff5a541d3cb1734afebfa3d3fdb90262ba42544acc4223c74511b37bae54de22565f25f8034f5af8aa10a04c3621b9").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/86'/0'/0'").unwrap(), hex::decode("0488b21e030484004d80000000a75805b89c5079ba74e9002c3e587f7c97ea8018ab1d5245638a45de3c845e0b03e0db6ca7c71e72a40091141b9dc4596ab3a9192ac41eebe1f2b048c654423ecb").unwrap()), + ExtendedPublicKey::new(DerivationPath::from_str("m/44'/607'/0'").unwrap(), hex::decode("895881fe5bab8b88e450055ff6916bf2bf41bc315325cee7975f33069beb079c").unwrap()), + ]; + + let account = + generate_crypto_multi_accounts(mfp, serial_number, keys, device_type, device_version) + .unwrap(); + let cbor: Vec = account.try_into().unwrap(); + assert_eq!(hex::encode(cbor), "a5011a1250b6bc0291d9012fa802f403582103c4ad25226a98764f7b753b6c763be112c940182e0b6698944c9def253cec4676045820bf103cfabcab325a7463ab5c432a4042109279d6c3531c8c5ea712684cf31f3706d90130a30186182cf5183cf500f5021a1250b6bc030307d90130a2018400f480f40300081a63c5ea6709684b657973746f6e650a706163636f756e742e7374616e64617264d9012fa802f403582103c4ad25226a98764f7b753b6c763be112c940182e0b6698944c9def253cec4676045820bf103cfabcab325a7463ab5c432a4042109279d6c3531c8c5ea712684cf31f3706d90130a30186182cf5183cf500f5021a1250b6bc030307d90130a2018280f40300081a63c5ea6709684b657973746f6e650a756163636f756e742e6c65646765725f6c6567616379d9012fa602f403582103de2f443b5070e839d6a209ed1afaadfd43daf7bc610a1fefef201a3aca5350ee06d90130a3018a182cf5183cf500f500f400f4021a1250b6bc0303081a769cd41a09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103a96bae34b46e82eee9c5beae52e446693b5c2e365714b223adea7caae47e1b7f06d90130a3018a182cf5183cf501f500f400f4021a1250b6bc0303081a998dec6209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821029299ea371a1c6cdcc75b91d26322a2dbdfedb58285e33760a2af82cfee1a7a6e06d90130a3018a182cf5183cf502f500f400f4021a1250b6bc0303081ac49452d709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821030f1808f972aed2b8e01d92b09b9c0d55b994592fb5599557e0d4828705204a4106d90130a3018a182cf5183cf503f500f400f4021a1250b6bc0303081a0823c44c09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821021c885e79f19ba2658755952801366f00f5304db8597eb72a78a6886d8175037d06d90130a3018a182cf5183cf504f500f400f4021a1250b6bc0303081aef4e5bae09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821037653d3a64a3d1fce16d5693e044e9aea644082371f4d31f6eb83096b5b84d97b06d90130a3018a182cf5183cf505f500f400f4021a1250b6bc0303081a364c571b09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103ded46d3bc515112c1c99b5f5b5f6c4abc76cc40d98ba4c1808c97038fe976ff606d90130a3018a182cf5183cf506f500f400f4021a1250b6bc0303081a456759fc09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102447d94e1937819a79a0ef56cd7b7a29de7c80a45b34480ef0b593083e418557906d90130a3018a182cf5183cf507f500f400f4021a1250b6bc0303081a09f362d709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103d94fb59028252ab9353ee376e868cfd59e9d0bc24ef35fe1b06310cd0e4e908b06d90130a3018a182cf5183cf508f500f400f4021a1250b6bc0303081a4e09767009684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821034d53b1c2630e12b853b96d70fb671363d5d4ec9406f722b4deea1f2a9eb6e76406d90130a3018a182cf5183cf509f500f400f4021a1250b6bc0303081ac418564209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa702f40358210246696468fa5c46647bdd186f568983e2a26773dc5b4c174790fee7ef9b9a7c9904582051872c7bb8270a7655ae15d738bb21379962ff11fb048b55630395afcfef442806d90130a30186182cf500f500f5021a1250b6bc030307d90130a2018280f40300081ab5d6f45009684b657973746f6e65d9012fa702f403582103ab6a1908b437179b914dc3cf4b829d7387adf60fdee483e9c748d5ee79ba4be4045820bad8f929afd65c4b3ff78db1a386062374f2d2e6552e9fdc59aa7dd9b5db6e2c06d90130a301861831f500f500f5021a1250b6bc030307d90130a2018280f40300081a197077c809684b657973746f6e65d9012fa702f40358210262ba42544acc4223c74511b37bae54de22565f25f8034f5af8aa10a04c3621b9045820de47dd17679605b84abf439bdf5477c6cb94ff5a541d3cb1734afebfa3d3fdb906d90130a301861854f500f500f5021a1250b6bc030307d90130a2018280f40300081a9f6b7e4b09684b657973746f6e65d9012fa702f403582103e0db6ca7c71e72a40091141b9dc4596ab3a9192ac41eebe1f2b048c654423ecb045820a75805b89c5079ba74e9002c3e587f7c97ea8018ab1d5245638a45de3c845e0b06d90130a301861856f500f500f5021a1250b6bc030307d90130a2018280f40300081a0484004d09684b657973746f6e65d9012fa2035820895881fe5bab8b88e450055ff6916bf2bf41bc315325cee7975f33069beb079c06d90130a20186182cf519025ff500f5021a1250b6bc036e4b657973746f6e6520332050726f047828626339633466373135376165363937643433346163383536323332306564353335653737373638300565312e372e30"); + } +} diff --git a/rust/apps/wallets/src/lib.rs b/rust/apps/wallets/src/lib.rs index ff9fd1896..3bfb96c6b 100644 --- a/rust/apps/wallets/src/lib.rs +++ b/rust/apps/wallets/src/lib.rs @@ -32,6 +32,7 @@ mod utils; pub mod xbull; pub mod xrp_toolkit; pub mod zcash; +pub mod keystone_connect; //TODO: get these value from device pub const DEVICE_TYPE: &str = "Keystone 3 Pro"; diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/keystone_connect.rs b/rust/rust_c/src/wallet/multi_coins_wallet/keystone_connect.rs new file mode 100644 index 000000000..a9784a00e --- /dev/null +++ b/rust/rust_c/src/wallet/multi_coins_wallet/keystone_connect.rs @@ -0,0 +1,64 @@ +use crate::common::ffi::CSliceFFI; +use crate::common::structs::ExtendedPublicKey; +use crate::common::types::{Ptr, PtrBytes, PtrString}; +use crate::common::ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT}; +use crate::common::utils::{recover_c_array, recover_c_char}; +use crate::extract_array; +use alloc::{format, string::ToString}; +use ur_registry::{ + error::URError, extend::crypto_multi_accounts::CryptoMultiAccounts, traits::RegistryItem, +}; + +use super::utils::normalize_xpub; + +#[no_mangle] +pub extern "C" fn get_keystone_connect_wallet_ur( + master_fingerprint: PtrBytes, + master_fingerprint_length: u32, + serial_number: PtrString, + public_keys: Ptr>, + device_type: PtrString, + device_version: PtrString, +) -> Ptr { + if master_fingerprint_length != 4 { + return UREncodeResult::from(URError::UrEncodeError(format!( + "master fingerprint length must be 4, current is {}", + master_fingerprint_length + ))) + .c_ptr(); + } + let mfp = extract_array!(master_fingerprint, u8, master_fingerprint_length); + let mfp = match <[u8; 4]>::try_from(mfp) { + Ok(mfp) => mfp, + Err(e) => return UREncodeResult::from(URError::UrEncodeError(e.to_string())).c_ptr(), + }; + unsafe { + let keys = recover_c_array(public_keys); + let serial_number = recover_c_char(serial_number); + let device_version = recover_c_char(device_version); + let device_type = recover_c_char(device_type); + match normalize_xpub(keys) { + Ok(_keys) => { + match app_wallets::keystone_connect::generate_crypto_multi_accounts( + mfp, + &serial_number, + _keys, + &device_type, + &device_version, + ) { + Ok(data) => match data.try_into() { + Ok(_v) => UREncodeResult::encode( + _v, + CryptoMultiAccounts::get_registry_type().get_type(), + FRAGMENT_MAX_LENGTH_DEFAULT, + ) + .c_ptr(), + Err(_e) => UREncodeResult::from(_e).c_ptr(), + }, + Err(_e) => UREncodeResult::from(_e).c_ptr(), + } + } + Err(_e) => UREncodeResult::from(_e).c_ptr(), + } + } +} diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs index a91bacd0b..9fd574e06 100644 --- a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs +++ b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs @@ -13,6 +13,7 @@ pub mod tonkeeper; mod utils; pub mod xbull; pub mod xrp_toolkit; +pub mod keystone_connect; pub mod core_wallet; pub mod thor_wallet; diff --git a/rust/rust_c/src/zcash/mod.rs b/rust/rust_c/src/zcash/mod.rs index 5b46e1846..99afc8461 100644 --- a/rust/rust_c/src/zcash/mod.rs +++ b/rust/rust_c/src/zcash/mod.rs @@ -218,6 +218,9 @@ mod tests { #[test] fn test_aes256_cbc_decrypt() { + //8dd387c3b2656d9f24ace7c3daf6fc26a1c161098460f8dddd37545fc951f9cd7da6c75c71ae52f32ceb8827eca2169ef4a643d2ccb9f01389d281a85850e2ddd100630ab1ca51310c3e6ccdd3029d0c48db18cdc971dba8f0daff9ad281b56221ffefc7d32333ea310a1f74f99dea444f8a089002cf1f0cd6a4ddf608a7b5388dc09f9417612657b9bf335a466f951547f9707dd129b3c24c900a26010f51c543eba10e9aabef7062845dc6969206b25577a352cb4d984db67c54c7615fe60769726bffa59fd8bd0b66fe29ee3c358af13cf0796c2c062bc79b73271eb0366f0536e425f8e42307ead4c695804fd3281aca5577d9a621e3a8047b14128c280c45343b5bbb783a065d94764e90ad6820fe81a200637401c256b1fb8f58a9d412d303b89c647411662907cdc55ed93adb + //73e6ca87d5cd5622cdc747367905efe7 + //68487dc295052aa79c530e283ce698b8c6bb1b42ff0944252e1910dbecdc5425 let data = convert_c_char("639194f4bf964e15d8ea9c9bd9d96918".to_string()); let password = convert_c_char("password".to_string()); let mut seed = hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.c b/src/ui/gui_wallet/multi/web3/gui_wallet.c index 64e8eb4a6..b7a8c29fa 100644 --- a/src/ui/gui_wallet/multi/web3/gui_wallet.c +++ b/src/ui/gui_wallet/multi/web3/gui_wallet.c @@ -445,6 +445,48 @@ UREncodeResult *GuiGetKeystoneWalletData(void) return g_urEncode; } +UREncodeResult *GuiGetKeystoneConnectWalletData(void) +{ + uint8_t mfp[4] = {0}; + GetMasterFingerPrint(mfp); + PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey)); + // btc 4 + // + eth 10 + // + trx 1 + ExtendedPublicKey keys[15]; + public_keys->data = keys; + public_keys->size = 15; + for (int i = XPUB_TYPE_ETH_LEDGER_LIVE_0; i <= XPUB_TYPE_ETH_LEDGER_LIVE_9; i++) { + keys[i - XPUB_TYPE_ETH_LEDGER_LIVE_0].path = SRAM_MALLOC(BUFFER_SIZE_64); + snprintf_s(keys[i - XPUB_TYPE_ETH_LEDGER_LIVE_0].path, BUFFER_SIZE_64, "m/44'/60'/%d'", i - XPUB_TYPE_ETH_LEDGER_LIVE_0); + keys[i - XPUB_TYPE_ETH_LEDGER_LIVE_0].xpub = GetCurrentAccountPublicKey(i); + } + + keys[10].path = "m/44'/0'/0'"; + keys[10].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY); + + keys[11].path = "m/49'/0'/0'"; + keys[11].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC); + + keys[12].path = "m/84'/0'/0'"; + keys[12].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT); + + keys[13].path = "m/86'/0'/0'"; + keys[13].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_TAPROOT); + + keys[14].path = GetXPubPath(XPUB_TYPE_TRX); + keys[14].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX); + + char serialNumber[256]; + GetSerialNumber(serialNumber); + char firmwareVersion[12]; + GetSoftWareVersionNumber(firmwareVersion); + g_urEncode = get_keystone_connect_wallet_ur(mfp, sizeof(mfp), serialNumber, public_keys, "Keystone 3 Pro", firmwareVersion); + CHECK_CHAIN_PRINT(g_urEncode); + SRAM_FREE(public_keys); + return g_urEncode; +} + UREncodeResult *GuiGetBitgetWalletData(void) { uint8_t mfp[4] = {0}; diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.h b/src/ui/gui_wallet/multi/web3/gui_wallet.h index 257d69d10..04be18654 100644 --- a/src/ui/gui_wallet/multi/web3/gui_wallet.h +++ b/src/ui/gui_wallet/multi/web3/gui_wallet.h @@ -31,4 +31,5 @@ UREncodeResult *GuiGetImTokenData(void); UREncodeResult *GuiGetCoreWalletData(void); UREncodeResult *GuiGetKeystoneWalletData(void); UREncodeResult *GuiGetThorWalletBtcData(void); +UREncodeResult *GuiGetKeystoneConnectWalletData(void); #endif diff --git a/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c b/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c index 914d91917..00a613729 100644 --- a/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c +++ b/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c @@ -324,9 +324,10 @@ static void GuiInitWalletListArray() case WALLET_LIST_WANDER: enable = !isTempAccount; break; - case WALLET_LIST_KEYSTONE: - enable = isRussian; - break; + // open keystone for test + // case WALLET_LIST_KEYSTONE: + // enable = isRussian; + // break; default: break; } @@ -1352,7 +1353,7 @@ void GuiConnectWalletSetQrdata(WALLET_LIST_INDEX_ENUM index) break; case WALLET_LIST_KEYSTONE: // todo add keystone ur logic - func = GuiGetKeystoneWalletData; + func = GuiGetKeystoneConnectWalletData; AddKeystoneWalletCoins(); break; default: From 356328f1b8faeb681aeea17feb048c254f279dbf Mon Sep 17 00:00:00 2001 From: soralit Date: Tue, 14 Jan 2025 10:37:57 +0800 Subject: [PATCH 2/7] test: update ut --- rust/apps/bitcoin/src/addresses/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rust/apps/bitcoin/src/addresses/mod.rs b/rust/apps/bitcoin/src/addresses/mod.rs index 1fff6a02e..c94c34ac6 100644 --- a/rust/apps/bitcoin/src/addresses/mod.rs +++ b/rust/apps/bitcoin/src/addresses/mod.rs @@ -152,6 +152,17 @@ mod tests { #[test] fn test_btc_p2tr_no_script_address() { + let extended_pubkey = "xpub6Cq9mdT8xwFe9LYQnt9y1hJXTyo7KQJM8pRH6K95F1mbELzgm825m3hyAZ97vsUV8Xh7VRwu7bKuLZEmUV1ABqCRQqFzZHAsfaJXTYSY1cf"; + let address = + get_address("M/86'/0'/0'/0/0".to_string(), &extended_pubkey.to_string()).unwrap(); + assert_eq!( + address, + "bc1pf7al7fmsrfxftwp0durgv3zv9ezqzrqdhk34gjcuqasw6fnlxu7sw8xvjs" + ); + } + + #[test] + fn test_btc_p2tr_no_script_address_testnet() { let extended_pubkey = "tpubDDfvzhdVV4unsoKt5aE6dcsNsfeWbTgmLZPi8LQDYU2xixrYemMfWJ3BaVneH3u7DBQePdTwhpybaKRU95pi6PMUtLPBJLVQRpzEnjfjZzX"; let address = get_address("M/86'/1'/0'/0/0".to_string(), &extended_pubkey.to_string()).unwrap(); From f6326cfba4305ebe787ade29315dcd92fb75bddf Mon Sep 17 00:00:00 2001 From: ZhenQian Date: Tue, 4 Mar 2025 14:00:37 +0800 Subject: [PATCH 3/7] feat: add keystone nexus --- images/walletList/walletListKeystone.png | Bin 8543 -> 5695 bytes src/ui/gui_assets/images_hash.txt | 2 +- .../walletList/walletListKeystone.c | 96 +++---- src/ui/gui_components/gui_status_bar.c | 2 +- src/ui/gui_wallet/multi/web3/gui_wallet.c | 36 +-- .../multi/web3/gui_connect_wallet_widgets.c | 13 +- src/ui/lv_i18n/data.csv | 2 +- src/ui/lv_i18n/lv_i18n.c | 236 ++++++++---------- 8 files changed, 177 insertions(+), 210 deletions(-) diff --git a/images/walletList/walletListKeystone.png b/images/walletList/walletListKeystone.png index 87182f3861dd0931cf95013943bc0a9ddcfb1a08..fbd747e3209b62ff06ba49630571ccb881f9d260 100644 GIT binary patch literal 5695 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 literal 8543 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 g|DFagcMwQ{Y9SRDQt}2b{~-YH<<;csWX!|data = keys; - public_keys->size = 15; - for (int i = XPUB_TYPE_ETH_LEDGER_LIVE_0; i <= XPUB_TYPE_ETH_LEDGER_LIVE_9; i++) { - keys[i - XPUB_TYPE_ETH_LEDGER_LIVE_0].path = SRAM_MALLOC(BUFFER_SIZE_64); - snprintf_s(keys[i - XPUB_TYPE_ETH_LEDGER_LIVE_0].path, BUFFER_SIZE_64, "m/44'/60'/%d'", i - XPUB_TYPE_ETH_LEDGER_LIVE_0); - keys[i - XPUB_TYPE_ETH_LEDGER_LIVE_0].xpub = GetCurrentAccountPublicKey(i); - } + public_keys->size = 6; - keys[10].path = "m/44'/0'/0'"; - keys[10].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY); + // eth standard + keys[0].path = "m/44'/60'/0'"; + keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_ETH_BIP44_STANDARD); - keys[11].path = "m/49'/0'/0'"; - keys[11].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC); - keys[12].path = "m/84'/0'/0'"; - keys[12].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT); + keys[1].path = "m/44'/0'/0'"; + keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY); - keys[13].path = "m/86'/0'/0'"; - keys[13].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_TAPROOT); + keys[2].path = "m/49'/0'/0'"; + keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC); + + keys[3].path = "m/84'/0'/0'"; + keys[3].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT); + + keys[4].path = "m/86'/0'/0'"; + keys[4].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_TAPROOT); - keys[14].path = GetXPubPath(XPUB_TYPE_TRX); - keys[14].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX); + keys[5].path = GetXPubPath(XPUB_TYPE_TRX); + keys[5].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX); char serialNumber[256]; GetSerialNumber(serialNumber); diff --git a/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c b/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c index 00a613729..fb637fec2 100644 --- a/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c +++ b/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c @@ -132,8 +132,7 @@ static const lv_img_dsc_t *g_backpackWalletCoinArray[2] = { }; static const lv_img_dsc_t *g_keystoneWalletCoinArray[] = { - &coinBtc, &coinEth, &coinBnb, &coinBch, - &coinDash, &coinLtc, &coinTrx, &coinXrp, + &coinBtc, &coinEth,&coinTrx }; static const lv_img_dsc_t *g_blueWalletCoinArray[4] = { @@ -850,11 +849,11 @@ static void AddKeystoneWalletCoins(void) lv_img_set_pivot(img, 0, 0); lv_obj_align(img, LV_ALIGN_TOP_LEFT, 32 * i, 0); } - lv_obj_t *img = GuiCreateImg(g_coinCont, &imgMore); - lv_img_set_zoom(img, 150); - lv_img_set_pivot(img, 0, 0); - lv_obj_set_style_img_opa(img, LV_OPA_30, LV_PART_MAIN); - lv_obj_align(img, LV_ALIGN_TOP_LEFT, 132, 2); + // lv_obj_t *img = GuiCreateImg(g_coinCont, &imgMore); + // lv_img_set_zoom(img, 150); + // lv_img_set_pivot(img, 0, 0); + // lv_obj_set_style_img_opa(img, LV_OPA_30, LV_PART_MAIN); + // lv_obj_align(img, LV_ALIGN_TOP_LEFT, 132, 2); } static void AddBlueWalletCoins(void) diff --git a/src/ui/lv_i18n/data.csv b/src/ui/lv_i18n/data.csv index 9e002c193..471098d42 100644 --- a/src/ui/lv_i18n/data.csv +++ b/src/ui/lv_i18n/data.csv @@ -905,7 +905,7 @@ Wallet Profile,24,wallet_profile_mid_btn,Wallet Profile,Профиль коше ,20,ar_address_check_desc,"Different wallets may generate AR addresses differently, resulting in different addresses from the same phrase. This is normal. After connecting to the software wallet, please compare the address to ensure it matches the hardware wallet.","Разные кошельки могут генерировать AR-адреса по-разному, что приводит к различным адресам от одной и той же фразы. Это нормально. После подключения к программному кошельку, пожалуйста, сравните адрес, чтобы убедиться, что он совпадает с адресом аппаратного кошелька.","서로 다른 지갑은 AR 주소를 다르게 생성할 수 있으며, 결과적으로 동일한 구문에서도 다른 주소가 생성될 수 있습니다. 이는 정상적인 현상입니다. 소프트웨어 지갑에 연결한 후 주소가 하드웨어 지갑과 일치하는지 확인해주시기 바랍니다","不同的钱包可能以不同的方式生成AR地址, 从而导致相同的短语产生不同的地址。这是正常的。连接到软件钱包后, 请比较地址以确保与硬件钱包匹配。","Diferentes monederos pueden generar direcciones AR de manera diferente, resultando en direcciones diferentes a partir de la misma frase. Esto es normal. Después de conectarse al monedero de software, por favor compare la dirección para asegurarse de que coincide con el monedero de hardware.","Unterschiedliche Wallets können AR-Adressen unterschiedlich generieren, was zu unterschiedlichen Adressen aus demselben Satz führt. Dies ist normal. Nach dem Verbinden mit der Software-Wallet vergleichen Sie bitte die Adresse, um sicherzustellen, dass sie mit der Hardware Wallet übereinstimmt",異なるウォレットは、同じフレーズから異なるアドレスを生成する場合があります。これは正常な動作です。ソフトウェアウォレットに接続後、アドレスがハードウェアウォレットと一致するかどうか確認してください。 ,20,solana_parse_tx_notice,The accounts in Instructions will be affected by this transaction. Please review carefully.,"Счета, указанные в Инструкциях, будут затронуты этой операцией. Пожалуйста, внимательно проверьте.",지침서에 명시된 계좌들은 이 거래의 영향을 받게 됩니다. 주의 깊게 검토해 주시기 바랍니다.,说明中的账户将受到此交易的影响。请仔细检查。,"Las cuentas indicadas en las Instrucciones se verán afectadas por esta transacción. Por favor, revíselas detenidamente.",Laut Anweisung betroffene Konten werden von dieser Transaktion beeinflusst. Bitte sorgfältig prüfen.,指示書の口座がこの取引の影響を受けます。慎重に確認してください。 ,20,solana_alt_notice,The Address Lookup Table URL provides a reference to view detailed account information related to this transaction. Please note that the URL may expire or change over time,"Ссылка на таблицу адресов предоставляет информацию по счетам, связанным с этой операцией. Имейте в виду, что ссылка может измениться или устареть со временем.","주소록 테이블 URL은 이 거래와 관련된 계좌 정보를 제공합니다. 단, URL이 만료되거나 변경될 수 있음을 유의하시기 바랍니다.",地址查找表的网址提供了与此交易相关账户信息的参考。请注意该网址可能会过期。,La URL de la Tabla de Consulta de Direcciones proporciona una referencia para ver la información detallada de las cuentas relacionadas con esta transacción. Tenga en cuenta que la URL puede expirar o cambiar con el tiempo.,"Die URL der Adresstabelle bietet eine Referenz, um detaillierte Kontoinformationen zu dieser Transaktion einzusehen. Bitte beachten Sie, dass die URL ablaufen oder sich ändern kann.",アドレス参照表のURLでは、この取引に関連する詳細な口座情報を確認できます。URLは期限切れや変更の可能性があることにご留意ください。 -,20,connect_keystone_title,Keystone,Keystone,Keystone,Keystone,Keystone,Keystone,Keystone +,20,connect_keystone_title,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus ,20,connect_keystone_link,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone ,20,hardware_call_approve_notice,"Please note, if the path not saved on the device will require a password to be recalculated.","Обратите внимание, что если путь не сохранен на устройстве, потребуется пересчитать пароль.",주의사항: 경로가 기기에 저장되어 있지 않으면 비밀번호를 다시 계산해야 합니다.,"请注意,如果路径未保存在设备上,将需要重新计算密码。","Tenga en cuenta que, si la ruta no se guarda en el dispositivo, se requerirá recalcular la contraseña.","Bitte beachten Sie, dass wenn der Pfad nicht auf dem Gerät gespeichert ist, ein Passwort neu berechnet werden muss.",注意事項: デバイスにパスが保存されていない場合、パスワードを再計算する必要があります。 ,20,invaild_account_path,Invalid Account Path,Недействительный путь учетной записи,잘못된 계정 경로,无效的账户路径,Ruta de cuenta no válida,Ungültiger Kontopfad,無効なアカウントパス diff --git a/src/ui/lv_i18n/lv_i18n.c b/src/ui/lv_i18n/lv_i18n.c index 857f3ca16..90a62f5f4 100644 --- a/src/ui/lv_i18n/lv_i18n.c +++ b/src/ui/lv_i18n/lv_i18n.c @@ -9,35 +9,13 @@ #define UNUSED(x) (void)(x) -static inline uint32_t op_n(int32_t val) -{ - return (uint32_t)(val < 0 ? -val : val); -} -static inline uint32_t op_i(uint32_t val) -{ - return val; -} +static inline uint32_t op_n(int32_t val) { return (uint32_t)(val < 0 ? -val : val); } +static inline uint32_t op_i(uint32_t val) { return val; } // always zero, when decimal part not exists. -static inline uint32_t op_v(uint32_t val) -{ - UNUSED(val); - return 0; -} -static inline uint32_t op_w(uint32_t val) -{ - UNUSED(val); - return 0; -} -static inline uint32_t op_f(uint32_t val) -{ - UNUSED(val); - return 0; -} -static inline uint32_t op_t(uint32_t val) -{ - UNUSED(val); - return 0; -} +static inline uint32_t op_v(uint32_t val) { UNUSED(val); return 0;} +static inline uint32_t op_w(uint32_t val) { UNUSED(val); return 0; } +static inline uint32_t op_f(uint32_t val) { UNUSED(val); return 0; } +static inline uint32_t op_t(uint32_t val) { UNUSED(val); return 0; } const static lv_i18n_phrase_t en_singulars[] = { {"Address", "Address"}, @@ -207,7 +185,7 @@ const static lv_i18n_phrase_t en_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr (Extension)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -390,7 +368,7 @@ const static lv_i18n_phrase_t en_singulars[] = { {"firmware_update_no_upgradable_firmware_desc", "Your device firmware version is higher than or equal to the one on your microSD card."}, {"firmware_update_no_upgradable_firmware_title", "No Upgradable Firmware Detected"}, {"firmware_update_sd_checksum_desc", "#F5870A Show Checksum#"}, - {"firmware_update_sd_checksum_done", "Checksum:\r\n"}, + {"firmware_update_sd_checksum_done", "Checksum:\n"}, {"firmware_update_sd_checksum_fmt", "#F5870A Show Checksum(%d%%)#"}, {"firmware_update_sd_checksum_notice", "This is an optional feature to further enhance security. Compare the following checksum with the checksum of your download package on the official website, ensure that they are consistent."}, {"firmware_update_sd_copying_desc", "Do not remove the MicroSD Card while the update is underway."}, @@ -451,11 +429,11 @@ const static lv_i18n_phrase_t en_singulars[] = { {"import_wallet_phrase_desc", "Enter your seed phrase in the blanks provided below."}, {"import_wallet_phrase_title", "Import Your Seed"}, {"import_wallet_shamir_backup", "Shamir Backup"}, - {"import_wallet_shamir_backup_desc", "You'll need a couple of seed phrase\r\nshares to recover your wallet"}, + {"import_wallet_shamir_backup_desc", "You'll need a couple of seed phrase\nshares to recover your wallet"}, {"import_wallet_share_success_desc", "This share of your seed phrase matches your wallet."}, {"import_wallet_single_backup_desc", "Recover your wallet with the specific seed phrase. Please complete the setup process in one go to avoid any security risks."}, {"import_wallet_single_phrase", "Single Secret Phrase"}, - {"import_wallet_single_phrase_desc", "You'll need a 12/18/24 seed phrase\r\nto recover your wallet."}, + {"import_wallet_single_phrase_desc", "You'll need a 12/18/24 seed phrase\nto recover your wallet."}, {"import_wallet_ssb_cancel_desc", "Upon cancellation, you will be required to re-enter all the Shares again."}, {"import_wallet_ssb_cancel_title", "Cancel Import Wallet?"}, {"import_wallet_ssb_desc_fmt", "Enter your #F5870A %d#-word seed phrase for Share #F5870A %d# in the blanks provided below."}, @@ -592,7 +570,7 @@ const static lv_i18n_phrase_t en_singulars[] = { {"purpose_title", "New Wallet"}, {"receive_ada_enterprise_address", "Address (Not Delegated)"}, {"receive_ada_more_t_desc1", "On the Cardano blockchain, we provide 24 accounts, and each account can generate numerous addresses for your use. You can easily switch between the accounts you need."}, - {"receive_ada_more_t_desc2", "1. Payment & Stake Keys: In Cardano, every account has a Payment Key for regular ADA transactions (sending and receiving) and a Stake Key for staking and receiving rewards.\r\n2. Base Address: A Base Address is derived from both the Payment Key and Stake Key. It can be used for both regular transactions and staking. Also known as \"External Addresses (Delegated).\"\r\n3. Enterprise Address: This address only contains the Payment Key and is used solely for regular transactions, not for staking. It's designed for \"business\" scenarios that don't involve staking, like exchanges. Also known as \"External Addresses (Not Delegated).\"\r\n4. Stake & Reward Addresses: The Stake Key is used for staking, and the associated Stake Address is also called a Reward Address, used to receive staking rewards."}, + {"receive_ada_more_t_desc2", "1. Payment & Stake Keys: In Cardano, every account has a Payment Key for regular ADA transactions (sending and receiving) and a Stake Key for staking and receiving rewards.\n2. Base Address: A Base Address is derived from both the Payment Key and Stake Key. It can be used for both regular transactions and staking. Also known as \"External Addresses (Delegated).\"\n3. Enterprise Address: This address only contains the Payment Key and is used solely for regular transactions, not for staking. It's designed for \"business\" scenarios that don't involve staking, like exchanges. Also known as \"External Addresses (Not Delegated).\"\n4. Stake & Reward Addresses: The Stake Key is used for staking, and the associated Stake Address is also called a Reward Address, used to receive staking rewards."}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano Native"}, {"receive_ada_more_t_title1", "Multiple Cardano Accounts on Keystone"}, @@ -605,9 +583,9 @@ const static lv_i18n_phrase_t en_singulars[] = { {"receive_btc_extended_public_key", "Extended Public Key"}, {"receive_btc_more_address_settings", "Address Settings"}, {"receive_btc_more_export_xpub", "Export xPub"}, - {"receive_btc_more_t_desc1", "Bitcoin (BTC) uses three address formats for receiving funds:\r\n1. Native SegWit is the most efficient and secure Bitcoin address format. It provides cost savings and improved security compared to other traditional address formats, typically starting with \"bc1\"\r\n2. Legacy format is one of the earliest versions of Bitcoin, typically starting with \"1\"\r\n3. Nested SegWit is a solution designed to facilitate the transition to Native SegWit in a smooth manner, typically starting with \"3\""}, - {"receive_btc_more_t_desc2", "Yes, the three distinct Bitcoin address formats can be used for transferring funds among each other. However, it’s important to keep in mind the following aspects:\r\n1. Differing transaction fees: The choice of address format can influence transaction fees, with Native SegWit addresses generally having lower fees.\r\n2. Wallet and exchange compatibility: Make sure that the wallet or exchange you are using supports your chosen address format. Some wallets may only be compatible with specific address formats."}, - {"receive_btc_more_t_desc3", "1. Privacy: Reusing addresses increases transaction traceability, endangering privacy. New addresses help maintain transaction privacy.\r\n2. Transaction Efficiency: Multiple UTXOs linked to one address can raise costs for consolidation, impacting wallet efficiency.\r\n3. Security: Repeated address use heightens the risk of private key exposure, potentially leading to losses if compromised.\r\nIn short, not reusing addresses safeguards privacy, optimizes transactions, and reduces security risks within the UTXO model."}, + {"receive_btc_more_t_desc1", "Bitcoin (BTC) uses three address formats for receiving funds:\n1. Native SegWit is the most efficient and secure Bitcoin address format. It provides cost savings and improved security compared to other traditional address formats, typically starting with \"bc1\"\n2. Legacy format is one of the earliest versions of Bitcoin, typically starting with \"1\"\n3. Nested SegWit is a solution designed to facilitate the transition to Native SegWit in a smooth manner, typically starting with \"3\""}, + {"receive_btc_more_t_desc2", "Yes, the three distinct Bitcoin address formats can be used for transferring funds among each other. However, it’s important to keep in mind the following aspects:\n1. Differing transaction fees: The choice of address format can influence transaction fees, with Native SegWit addresses generally having lower fees.\n2. Wallet and exchange compatibility: Make sure that the wallet or exchange you are using supports your chosen address format. Some wallets may only be compatible with specific address formats."}, + {"receive_btc_more_t_desc3", "1. Privacy: Reusing addresses increases transaction traceability, endangering privacy. New addresses help maintain transaction privacy.\n2. Transaction Efficiency: Multiple UTXOs linked to one address can raise costs for consolidation, impacting wallet efficiency.\n3. Security: Repeated address use heightens the risk of private key exposure, potentially leading to losses if compromised.\nIn short, not reusing addresses safeguards privacy, optimizes transactions, and reduces security risks within the UTXO model."}, {"receive_btc_more_t_title1", "What are the three different address formats for BTC?"}, {"receive_btc_more_t_title2", "Can the three different address formats be used to transfer funds to each other?"}, {"receive_btc_more_t_title3", "Benefits of not reusing addresses"}, @@ -623,19 +601,19 @@ const static lv_i18n_phrase_t en_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "Ledger Legacy"}, {"receive_eth_more_derivation_path_ledger_live", "Ledger Live"}, {"receive_eth_more_derivation_path_title2", "Accounts eg:"}, - {"receive_eth_more_t_desc1", "1. Standard Path: This path is widely employed by numerous software wallets for address generation. Examples of such wallets encompass MetaMask, Rabby, BitKeep, and Core Wallet.\r\n2. Ledger Live: Choose this path if you intend to import a seed phrase from Ledger Live. Please note that Keystone supports synchronizing only the initial 10 addresses using this format.\r\n3. Ledger Legacy: Transition to this path if you manage your digital assets with Ledger Legacy"}, + {"receive_eth_more_t_desc1", "1. Standard Path: This path is widely employed by numerous software wallets for address generation. Examples of such wallets encompass MetaMask, Rabby, BitKeep, and Core Wallet.\n2. Ledger Live: Choose this path if you intend to import a seed phrase from Ledger Live. Please note that Keystone supports synchronizing only the initial 10 addresses using this format.\n3. Ledger Legacy: Transition to this path if you manage your digital assets with Ledger Legacy"}, {"receive_eth_more_t_title1", "Exploring Differences: Standard, Ledger Live, and Legacy Derivation Paths in Ethereum"}, {"receive_eth_receive_main_title", "Receive ETH"}, {"receive_generate_new_address", "Generate New Address"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "Account-based Path"}, - {"receive_sol_more_t_desc1", "1. Account-based Path: Widely adopted across numerous Solana wallets. An example of such a wallet is Solflare.\r\n2. Single Account Path: Choose this path if you intend to import a seed phrase from Sollet / MathWallet. Please note that Keystone supports synchronizing only the initial 10 addresses using this format.\r\n3. Sub-account Path: Transition to this path if you manage your digital assets with software wallets like Phantom / Exodus."}, + {"receive_sol_more_t_desc1", "1. Account-based Path: Widely adopted across numerous Solana wallets. An example of such a wallet is Solflare.\n2. Single Account Path: Choose this path if you intend to import a seed phrase from Sollet / MathWallet. Please note that Keystone supports synchronizing only the initial 10 addresses using this format.\n3. Sub-account Path: Transition to this path if you manage your digital assets with software wallets like Phantom / Exodus."}, {"receive_sol_more_t_single_path", "Single Account Path"}, {"receive_sol_more_t_sub_path", "Sub-account Path"}, {"receive_sol_more_t_title1", "Exploring Solana Path Options"}, {"receive_ton_hint", "Keystone default address format is V4R2. If they don’t match Tonkeeper, please check and switch in Tonkeeper. This address is exclusively for TON transactions only. Sending other types of digital assets to this address will result in their loss."}, {"receive_trx_hint", "This address is only for TRX, TRC-20 tokens and TRC-10 tokens, other digital assets sent to this address will be lost."}, - {"receive_xmr_more_t_desc1", "1.The Primary Account is your main Monero account, holding your primary balance and capable of directly receiving funds.\r\n2.A Subaddress is a secondary address linked to your Primary Account, designed for receiving payments privately. Each Subaddress keeps transactions separate, hiding your main account balance.\r\n3.Use the Primary Account for larger or long-term funds. Use Subaddresses when you want to receive payments without revealing your main balance or account details."}, + {"receive_xmr_more_t_desc1", "1.The Primary Account is your main Monero account, holding your primary balance and capable of directly receiving funds.\n2.A Subaddress is a secondary address linked to your Primary Account, designed for receiving payments privately. Each Subaddress keeps transactions separate, hiding your main account balance.\n3.Use the Primary Account for larger or long-term funds. Use Subaddresses when you want to receive payments without revealing your main balance or account details."}, {"receive_xmr_more_t_title1", "Know The Difference: Primary Account and Subaddress"}, {"repeat_passcode_desc", "Double confirm the PIN code you've entered."}, {"repeat_passcode_title", "Re-Enter PIN Code"}, @@ -933,12 +911,9 @@ const static lv_i18n_phrase_t en_singulars[] = { static uint8_t en_plural_fn(int32_t num) { - uint32_t n = op_n(num); - UNUSED(n); - uint32_t i = op_i(n); - UNUSED(i); - uint32_t v = op_v(n); - UNUSED(v); + uint32_t n = op_n(num); UNUSED(n); + uint32_t i = op_i(n); UNUSED(i); + uint32_t v = op_v(n); UNUSED(v); if ((i == 1 && v == 0)) return LV_I18N_PLURAL_TYPE_ONE; return LV_I18N_PLURAL_TYPE_OTHER; @@ -1119,7 +1094,7 @@ const static lv_i18n_phrase_t de_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr (Erweiterung)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -1302,7 +1277,7 @@ const static lv_i18n_phrase_t de_singulars[] = { {"firmware_update_no_upgradable_firmware_desc", "Ihre Geräte-Firmware-Version ist höher als oder gleich der auf Ihrer microSD-Karte."}, {"firmware_update_no_upgradable_firmware_title", "Keine aktualisierbare Firmware erkannt"}, {"firmware_update_sd_checksum_desc", "#F5870A Zeige Prüfsumme#"}, - {"firmware_update_sd_checksum_done", "Prüfsumme\r\n"}, + {"firmware_update_sd_checksum_done", "Prüfsumme\n"}, {"firmware_update_sd_checksum_fmt", "#F5870A Prüfsumme anzeigen(%d%%)#"}, {"firmware_update_sd_checksum_notice", "Dies ist eine optionale Funktion, um die Sicherheit weiter zu verbessern. Vergleichen Sie die folgende Prüfsumme mit der Prüfsumme Ihres Download-Pakets auf der offiziellen Website, stellen Sie sicher, dass sie übereinstimmen."}, {"firmware_update_sd_copying_desc", "Entfernen Sie die MicroSD-Karte nicht, während das Update im Gange ist."}, @@ -1504,7 +1479,7 @@ const static lv_i18n_phrase_t de_singulars[] = { {"purpose_title", "Neue Brieftasche"}, {"receive_ada_enterprise_address", "Adresse (Nicht übertragen)"}, {"receive_ada_more_t_desc1", "Auf der Cardano-Blockchain stellen wir 24 Konten zur Verfügung, und jedes Konto kann zahlreiche Adressen für Ihren Gebrauch generieren. Sie können problemlos zwischen den benötigten Konten wechseln."}, - {"receive_ada_more_t_desc2", "1. Zahlungs- und Stake-Schlüssel: Bei Cardano hat jedes Konto einen Zahlungsschlüssel für reguläre ADA-Transaktionen (Senden und Empfangen) und einen Stake-Schlüssel für das Staken und den Erhalt von Belohnungen.\r\n2. Basisadresse: Eine Basisadresse wird aus dem Zahlungsschlüssel und dem Stake-Schlüssel abgeleitet. Sie kann sowohl für reguläre Transaktionen als auch für das Staken verwendet werden. Auch bekannt als \"Externe Adressen (Delegiert)\".\r\n3. Unternehmensadresse: Diese Adresse enthält nur den Zahlungsschlüssel und wird ausschließlich für reguläre Transaktionen und nicht zum Staken verwendet. Sie ist für \"geschäftliche\" Szenarien gedacht, die kein Staken beinhalten, wie z.B. Börsen. Auch bekannt als \"Externe Adressen (Nicht delegiert)\".\r\n4. Stake- und Belohnungsadressen: Der Stake-Schlüssel wird zum Staken verwendet und die zugehörige Stake-Adresse wird auch als Belohnungsadresse bezeichnet und dient zum Empfangen von Staking-Belohnungen."}, + {"receive_ada_more_t_desc2", "1. Zahlungs- und Stake-Schlüssel: Bei Cardano hat jedes Konto einen Zahlungsschlüssel für reguläre ADA-Transaktionen (Senden und Empfangen) und einen Stake-Schlüssel für das Staken und den Erhalt von Belohnungen.\n2. Basisadresse: Eine Basisadresse wird aus dem Zahlungsschlüssel und dem Stake-Schlüssel abgeleitet. Sie kann sowohl für reguläre Transaktionen als auch für das Staken verwendet werden. Auch bekannt als \"Externe Adressen (Delegiert)\".\n3. Unternehmensadresse: Diese Adresse enthält nur den Zahlungsschlüssel und wird ausschließlich für reguläre Transaktionen und nicht zum Staken verwendet. Sie ist für \"geschäftliche\" Szenarien gedacht, die kein Staken beinhalten, wie z.B. Börsen. Auch bekannt als \"Externe Adressen (Nicht delegiert)\".\n4. Stake- und Belohnungsadressen: Der Stake-Schlüssel wird zum Staken verwendet und die zugehörige Stake-Adresse wird auch als Belohnungsadresse bezeichnet und dient zum Empfangen von Staking-Belohnungen."}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano Native"}, {"receive_ada_more_t_title1", "Mehrere Cardano-Konten auf Keystone."}, @@ -1517,9 +1492,9 @@ const static lv_i18n_phrase_t de_singulars[] = { {"receive_btc_extended_public_key", "Erweitertes öffentliches Schlüssel"}, {"receive_btc_more_address_settings", "Adress-Einstellungen"}, {"receive_btc_more_export_xpub", "Exportieren Sie xPub."}, - {"receive_btc_more_t_desc1", "Bitcoin (BTC) utiliza tres formatos de direcciones para recibir fondos:\r\n1. Native SegWit es el formato de dirección de Bitcoin más eficiente y seguro. Ofrece ahorros en costos y mejor seguridad en comparación con otros formatos de dirección tradicionales, generalmente comienza con bc1.\r\n2. El formato Legacy es una de las primeras versiones de Bitcoin, que generalmente comienza con 1.\r\n3. Nested SegWit es una solución diseñada para facilitar la transición a Native SegWit de manera suave, generalmente comienza con 3."}, - {"receive_btc_more_t_desc2", "Ja, die drei unterschiedlichen Bitcoin-Adressformate können zur Übertragung von Geldern untereinander verwendet werden. Es ist jedoch wichtig, folgende Aspekte im Hinterkopf zu behalten:\r\n1. Unterschiedliche Transaktionsgebühren: Die Wahl des Adressformats kann die Transaktionsgebühren beeinflussen, wobei Native SegWit-Adressen normalerweise niedrigere Gebühren haben.\r\n2. Kompatibilität von Wallet und Börse: Stellen Sie sicher, dass das von Ihnen verwendete Wallet oder die Börse Ihr gewähltes Adressformat unterstützt. Manche Wallets sind möglicherweise nur mit bestimmten Adressformaten kompatibel."}, - {"receive_btc_more_t_desc3", "1. Datenschutz: Durch das Wiederverwenden von Adressen erhöht sich die Rückverfolgbarkeit von Transaktionen und gefährdet die Privatsphäre. Neue Adressen helfen dabei, den Datenschutz bei Transaktionen aufrechtzuerhalten.\r\n2. Transaktionseffizienz: Mehrere UTXOs, die einer Adresse zugeordnet sind, können die Kosten für die Konsolidierung erhöhen und die Effizienz der Geldbörse beeinträchtigen.\r\n3. Sicherheit: Die wiederholte Verwendung von Adressen erhöht das Risiko einer Offenlegung des privaten Schlüssels und kann zu Verlusten führen, wenn er kompromittiert wird.\r\nKurz gesagt, das Nicht-Wiederverwenden von Adressen schützt die Privatsphäre, optimiert Transaktionen und reduziert Sicherheitsrisiken im UTXO-Modell."}, + {"receive_btc_more_t_desc1", "Bitcoin (BTC) utiliza tres formatos de direcciones para recibir fondos:\n1. Native SegWit es el formato de dirección de Bitcoin más eficiente y seguro. Ofrece ahorros en costos y mejor seguridad en comparación con otros formatos de dirección tradicionales, generalmente comienza con bc1.\n2. El formato Legacy es una de las primeras versiones de Bitcoin, que generalmente comienza con 1.\n3. Nested SegWit es una solución diseñada para facilitar la transición a Native SegWit de manera suave, generalmente comienza con 3."}, + {"receive_btc_more_t_desc2", "Ja, die drei unterschiedlichen Bitcoin-Adressformate können zur Übertragung von Geldern untereinander verwendet werden. Es ist jedoch wichtig, folgende Aspekte im Hinterkopf zu behalten:\n1. Unterschiedliche Transaktionsgebühren: Die Wahl des Adressformats kann die Transaktionsgebühren beeinflussen, wobei Native SegWit-Adressen normalerweise niedrigere Gebühren haben.\n2. Kompatibilität von Wallet und Börse: Stellen Sie sicher, dass das von Ihnen verwendete Wallet oder die Börse Ihr gewähltes Adressformat unterstützt. Manche Wallets sind möglicherweise nur mit bestimmten Adressformaten kompatibel."}, + {"receive_btc_more_t_desc3", "1. Datenschutz: Durch das Wiederverwenden von Adressen erhöht sich die Rückverfolgbarkeit von Transaktionen und gefährdet die Privatsphäre. Neue Adressen helfen dabei, den Datenschutz bei Transaktionen aufrechtzuerhalten.\n2. Transaktionseffizienz: Mehrere UTXOs, die einer Adresse zugeordnet sind, können die Kosten für die Konsolidierung erhöhen und die Effizienz der Geldbörse beeinträchtigen.\n3. Sicherheit: Die wiederholte Verwendung von Adressen erhöht das Risiko einer Offenlegung des privaten Schlüssels und kann zu Verlusten führen, wenn er kompromittiert wird.\nKurz gesagt, das Nicht-Wiederverwenden von Adressen schützt die Privatsphäre, optimiert Transaktionen und reduziert Sicherheitsrisiken im UTXO-Modell."}, {"receive_btc_more_t_title1", "Welche sind die drei verschiedenen Adressformate für BTC?"}, {"receive_btc_more_t_title2", "Können die drei verschiedenen Adressformate verwendet werden, um Gelder untereinander zu übertragen?"}, {"receive_btc_more_t_title3", "Vorteile der Nicht-Wiederverwendung von Adressen"}, @@ -1535,19 +1510,19 @@ const static lv_i18n_phrase_t de_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "Ledger Legacy"}, {"receive_eth_more_derivation_path_ledger_live", "Ledger Live"}, {"receive_eth_more_derivation_path_title2", "Konten z.B.:"}, - {"receive_eth_more_t_desc1", "1. Standardpfad: Dieser Pfad wird von zahlreichen Software-Wallets zur Adressgenerierung weit verbreitet eingesetzt. Beispiele für solche Wallets sind MetaMask, Rabby, BitKeep und Core Wallet.\r\n2. Ledger Live: Wählen Sie diesen Pfad, wenn Sie eine Seed-Phrase aus Ledger Live importieren möchten. Bitte beachten Sie, dass Keystone nur die ersten 10 Adressen mit diesem Format synchronisieren kann.\r\n3. Ledger Legacy: Wechseln Sie zu diesem Pfad, wenn Sie Ihre digitalen Vermögenswerte mit Ledger Legacy verwalten."}, + {"receive_eth_more_t_desc1", "1. Standardpfad: Dieser Pfad wird von zahlreichen Software-Wallets zur Adressgenerierung weit verbreitet eingesetzt. Beispiele für solche Wallets sind MetaMask, Rabby, BitKeep und Core Wallet.\n2. Ledger Live: Wählen Sie diesen Pfad, wenn Sie eine Seed-Phrase aus Ledger Live importieren möchten. Bitte beachten Sie, dass Keystone nur die ersten 10 Adressen mit diesem Format synchronisieren kann.\n3. Ledger Legacy: Wechseln Sie zu diesem Pfad, wenn Sie Ihre digitalen Vermögenswerte mit Ledger Legacy verwalten."}, {"receive_eth_more_t_title1", "Erkundung von Unterschieden: Standard, Ledger Live und Legacy Derivation Pfade in Ethereum"}, {"receive_eth_receive_main_title", "Erhalte ETH"}, {"receive_generate_new_address", "Neue Adresse generieren"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "Aktengestützter Pfad"}, - {"receive_sol_more_t_desc1", "1. Kontobasierter Pfad: Weit verbreitet in zahlreichen Solana-Wallets übernommen. Ein Beispiel für ein solches Wallet ist Solflare.\r\n2. Einzelkontopfad: Wählen Sie diesen Pfad, wenn Sie vorhaben, eine Seed-Phrase von Sollet / MathWallet zu importieren. Bitte beachten Sie, dass Keystone nur das erstmalige Synchronisieren von 10 Adressen mit diesem Format unterstützt.\r\n3. Unterkontopfad: Wechseln Sie zu diesem Pfad, wenn Sie Ihre digitalen Vermögenswerte mit Software-Wallets wie Phantom / Exodus verwalten."}, + {"receive_sol_more_t_desc1", "1. Kontobasierter Pfad: Weit verbreitet in zahlreichen Solana-Wallets übernommen. Ein Beispiel für ein solches Wallet ist Solflare.\n2. Einzelkontopfad: Wählen Sie diesen Pfad, wenn Sie vorhaben, eine Seed-Phrase von Sollet / MathWallet zu importieren. Bitte beachten Sie, dass Keystone nur das erstmalige Synchronisieren von 10 Adressen mit diesem Format unterstützt.\n3. Unterkontopfad: Wechseln Sie zu diesem Pfad, wenn Sie Ihre digitalen Vermögenswerte mit Software-Wallets wie Phantom / Exodus verwalten."}, {"receive_sol_more_t_single_path", "Einzelkonto Pfad"}, {"receive_sol_more_t_sub_path", "Unterkonto-Pfad"}, {"receive_sol_more_t_title1", "Exploring Solana-Pfadoptionen"}, {"receive_ton_hint", "Das Standardadressenformat von Keystone ist V4R2. Wenn sie nicht mit Tonkeeper übereinstimmen, überprüfen und wechseln Sie bitte in Tonkeeper. Diese Adresse ist ausschließlich für TON-Transaktionen. Das Senden anderer Arten von digitalen Assets an diese Adresse führt zu deren Verlust."}, {"receive_trx_hint", "Diese Adresse ist nur für TRX, TRC-20 Token und TRC-10 Token bestimmt. Andere digitale Vermögenswerte, die an diese Adresse gesendet werden, gehen verloren."}, - {"receive_xmr_more_t_desc1", "1. Das Hauptkonto ist Ihr Haupt-Monero-Konto, das Ihr primäres Guthaben hält und direkt Gelder empfangen kann.\r\n2. Eine Unteradresse ist eine sekundäre Adresse, die mit Ihrem Hauptkonto verknüpft ist und für den privaten Zahlungsempfang konzipiert wurde. Jede Unteradresse hält Transaktionen getrennt und verbirgt so den Saldo Ihres Hauptkontos.\r\n3. Verwenden Sie das Hauptkonto für größere oder langfristige Gelder. Verwenden Sie Unteradressen, wenn Sie Zahlungen erhalten möchten, ohne Ihren Hauptkontostand oder Kontodetails preiszugeben."}, + {"receive_xmr_more_t_desc1", "1. Das Hauptkonto ist Ihr Haupt-Monero-Konto, das Ihr primäres Guthaben hält und direkt Gelder empfangen kann.\n2. Eine Unteradresse ist eine sekundäre Adresse, die mit Ihrem Hauptkonto verknüpft ist und für den privaten Zahlungsempfang konzipiert wurde. Jede Unteradresse hält Transaktionen getrennt und verbirgt so den Saldo Ihres Hauptkontos.\n3. Verwenden Sie das Hauptkonto für größere oder langfristige Gelder. Verwenden Sie Unteradressen, wenn Sie Zahlungen erhalten möchten, ohne Ihren Hauptkontostand oder Kontodetails preiszugeben."}, {"receive_xmr_more_t_title1", "Kennen Sie den Unterschied: Hauptkonto und Unteradresse"}, {"repeat_passcode_desc", "Bitte bestätigen Sie die eingegebene PIN-Nummer erneut."}, {"repeat_passcode_title", "Geben Sie die PIN erneut ein"}, @@ -1845,12 +1820,9 @@ const static lv_i18n_phrase_t de_singulars[] = { static uint8_t de_plural_fn(int32_t num) { - uint32_t n = op_n(num); - UNUSED(n); - uint32_t i = op_i(n); - UNUSED(i); - uint32_t v = op_v(n); - UNUSED(v); + uint32_t n = op_n(num); UNUSED(n); + uint32_t i = op_i(n); UNUSED(i); + uint32_t v = op_v(n); UNUSED(v); if ((i == 1 && v == 0)) return LV_I18N_PLURAL_TYPE_ONE; return LV_I18N_PLURAL_TYPE_OTHER; @@ -2031,7 +2003,7 @@ const static lv_i18n_phrase_t es_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr (Extensión)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -2416,7 +2388,7 @@ const static lv_i18n_phrase_t es_singulars[] = { {"purpose_title", "Nueva billetera"}, {"receive_ada_enterprise_address", "Dirección (No Delegada)"}, {"receive_ada_more_t_desc1", "En la blockchain de Cardano, proporcionamos 24 cuentas y cada cuenta puedes generar numerosas direcciones para su uso. Puedes cambiar fácilmente entre las cuentas que necesites."}, - {"receive_ada_more_t_desc2", "1. Pagos y Claves de Participación: En Cardano, cada cuenta tiene una Clave de Pago para transacciones regulares de ADA (envío y recepción) y una Clave de Participación para participar y recibir recompensas.\r\n2. Dirección Base: Una Dirección Base se deriva tanto de la Clave de Pago como de la Clave de Participación. Se puede usar tanto para transacciones regulares como para participación. También conocida como Direcciones Externas (Delegadas).\r\n3. Dirección de Empresa: Esta dirección solo contiene la Clave de Pago y se utiliza únicamente para transacciones regulares, no para participación. Está diseñada para escenarios empresariales que no implican participación, como intercambios. También conocida como Direcciones Externas (No Delegadas).\r\n4. Direcciones de Participación y Recompensa: La Clave de Participación se utiliza para la participación, y la Dirección de Participación asociada también se llama Dirección de Recompensa, utilizada para recibir recompensas por la participación."}, + {"receive_ada_more_t_desc2", "1. Pagos y Claves de Participación: En Cardano, cada cuenta tiene una Clave de Pago para transacciones regulares de ADA (envío y recepción) y una Clave de Participación para participar y recibir recompensas.\n2. Dirección Base: Una Dirección Base se deriva tanto de la Clave de Pago como de la Clave de Participación. Se puede usar tanto para transacciones regulares como para participación. También conocida como Direcciones Externas (Delegadas).\n3. Dirección de Empresa: Esta dirección solo contiene la Clave de Pago y se utiliza únicamente para transacciones regulares, no para participación. Está diseñada para escenarios empresariales que no implican participación, como intercambios. También conocida como Direcciones Externas (No Delegadas).\n4. Direcciones de Participación y Recompensa: La Clave de Participación se utiliza para la participación, y la Dirección de Participación asociada también se llama Dirección de Recompensa, utilizada para recibir recompensas por la participación."}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano 네이티브"}, {"receive_ada_more_t_title1", "Múltiples cuentas de Cardano en Keystone"}, @@ -2429,9 +2401,9 @@ const static lv_i18n_phrase_t es_singulars[] = { {"receive_btc_extended_public_key", "Clave pública extendida"}, {"receive_btc_more_address_settings", "Ajustes de dirección"}, {"receive_btc_more_export_xpub", "Exportar xPub"}, - {"receive_btc_more_t_desc1", "Bitcoin (BTC) utiliza tres formatos de direcciones para recibir fondos:\r\n1. SegWit nativo es el formato de dirección de Bitcoin más eficiente y seguro. Proporciona ahorros de costos y una seguridad mejorada en comparación con otros formatos de dirección tradicionales, generalmente comenzando con bc1.\r\n2. Formato heredado es una de las primeras versiones de Bitcoin, generalmente comenzando con 1.\r\n3. SegWit anidado es una solución diseñada para facilitar la transición al SegWit nativo de manera fluida, generalmente comenzando con 3."}, - {"receive_btc_more_t_desc2", "Sí, los tres formatos de dirección Bitcoin se pueden utilizar para transferir fondos entre sí. Sin embargo, es importante tener en cuenta los siguientes aspectos:\r\n1. Diferentes comisiones de transacción: la elección del formato de dirección puede influir en las comisiones de transacción, siendo las direcciones de Native SegWit generalmente las que tienen comisiones más bajas.\r\n2. Compatibilidad de billetera e intercambio: asegúrate de que la billetera o el intercambio que estás utilizando admita el formato de dirección elegido. Algunas billeteras pueden ser compatibles únicamente con formatos de dirección específicos."}, - {"receive_btc_more_t_desc3", "1. Privacidad: Reutilizar direcciones aumenta la rastreabilidad de las transacciones, poniendo en peligro la privacidad. Las nuevas direcciones ayudan a mantener la privacidad de las transacciones.\r\n2. Eficiencia de transacciones: Varios UTXOs vinculados a una misma dirección pueden aumentar los costos de consolidación, afectando la eficiencia de la billetera.\r\n3. Seguridad: El uso repetido de direcciones aumenta el riesgo de exposición de la clave privada, lo que potencialmente puede llevar a pérdidas si se compromete.\r\nEn resumen, no reutilizar direcciones protege la privacidad, optimiza las transacciones y reduce los riesgos de seguridad dentro del modelo UTXO."}, + {"receive_btc_more_t_desc1", "Bitcoin (BTC) utiliza tres formatos de direcciones para recibir fondos:\n1. SegWit nativo es el formato de dirección de Bitcoin más eficiente y seguro. Proporciona ahorros de costos y una seguridad mejorada en comparación con otros formatos de dirección tradicionales, generalmente comenzando con bc1.\n2. Formato heredado es una de las primeras versiones de Bitcoin, generalmente comenzando con 1.\n3. SegWit anidado es una solución diseñada para facilitar la transición al SegWit nativo de manera fluida, generalmente comenzando con 3."}, + {"receive_btc_more_t_desc2", "Sí, los tres formatos de dirección Bitcoin se pueden utilizar para transferir fondos entre sí. Sin embargo, es importante tener en cuenta los siguientes aspectos:\n1. Diferentes comisiones de transacción: la elección del formato de dirección puede influir en las comisiones de transacción, siendo las direcciones de Native SegWit generalmente las que tienen comisiones más bajas.\n2. Compatibilidad de billetera e intercambio: asegúrate de que la billetera o el intercambio que estás utilizando admita el formato de dirección elegido. Algunas billeteras pueden ser compatibles únicamente con formatos de dirección específicos."}, + {"receive_btc_more_t_desc3", "1. Privacidad: Reutilizar direcciones aumenta la rastreabilidad de las transacciones, poniendo en peligro la privacidad. Las nuevas direcciones ayudan a mantener la privacidad de las transacciones.\n2. Eficiencia de transacciones: Varios UTXOs vinculados a una misma dirección pueden aumentar los costos de consolidación, afectando la eficiencia de la billetera.\n3. Seguridad: El uso repetido de direcciones aumenta el riesgo de exposición de la clave privada, lo que potencialmente puede llevar a pérdidas si se compromete.\nEn resumen, no reutilizar direcciones protege la privacidad, optimiza las transacciones y reduce los riesgos de seguridad dentro del modelo UTXO."}, {"receive_btc_more_t_title1", "¿Cuáles son los tres formatos de dirección diferentes para BTC?"}, {"receive_btc_more_t_title2", "¿Se pueden utilizar los tres formatos de dirección diferentes para transferir fondos entre ellos?"}, {"receive_btc_more_t_title3", "Beneficios de no reutilizar direcciones"}, @@ -2447,19 +2419,19 @@ const static lv_i18n_phrase_t es_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "Ledger Legacy"}, {"receive_eth_more_derivation_path_ledger_live", "Ledger Live"}, {"receive_eth_more_derivation_path_title2", "Cuentas de ejemplo:"}, - {"receive_eth_more_t_desc1", "1. Ruta estándar: Esta ruta es ampliamente utilizada por numerosas billeteras de software para la generación de direcciones. Ejemplos de estas billeteras son MetaMask, Rabby, BitKeep y Core Wallet.\r\n2. Ledger Live: Elija esta ruta si desea importar una frase de recuperación desde Ledger Live. Por favor tenga en cuenta que Keystone solo admite la sincronización de las primeras 10 direcciones utilizando este formato.\r\n3. Ledger Legacy: Transita a esta ruta si administras tus activos digitales con Ledger Legacy."}, + {"receive_eth_more_t_desc1", "1. Ruta estándar: Esta ruta es ampliamente utilizada por numerosas billeteras de software para la generación de direcciones. Ejemplos de estas billeteras son MetaMask, Rabby, BitKeep y Core Wallet.\n2. Ledger Live: Elija esta ruta si desea importar una frase de recuperación desde Ledger Live. Por favor tenga en cuenta que Keystone solo admite la sincronización de las primeras 10 direcciones utilizando este formato.\n3. Ledger Legacy: Transita a esta ruta si administras tus activos digitales con Ledger Legacy."}, {"receive_eth_more_t_title1", "Explorando diferencias: caminos de derivación estándar, Ledger Live y Legacy en Ethereum"}, {"receive_eth_receive_main_title", "Recibir ETH"}, {"receive_generate_new_address", "Generar nueva dirección"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "Ruta basada en cuentas"}, - {"receive_sol_more_t_desc1", "1. Ruta basada en cuentas: Ampliamente adoptada en numerosas billeteras de Solana. Un ejemplo de esta billetera es Solflare.\r\n2. Ruta de cuenta única: Elije esta ruta si deseas importar una frase de recuperación desde Sollet / MathWallet. Ten en cuenta que Keystone solo admite la sincronización de las 10 direcciones iniciales utilizando este formato.\r\n3. Ruta de subcuenta: Haz la transición a esta ruta si administras tus activos digitales con billeteras de software como Phantom / Exodus."}, + {"receive_sol_more_t_desc1", "1. Ruta basada en cuentas: Ampliamente adoptada en numerosas billeteras de Solana. Un ejemplo de esta billetera es Solflare.\n2. Ruta de cuenta única: Elije esta ruta si deseas importar una frase de recuperación desde Sollet / MathWallet. Ten en cuenta que Keystone solo admite la sincronización de las 10 direcciones iniciales utilizando este formato.\n3. Ruta de subcuenta: Haz la transición a esta ruta si administras tus activos digitales con billeteras de software como Phantom / Exodus."}, {"receive_sol_more_t_single_path", "Ruta de cuenta única"}, {"receive_sol_more_t_sub_path", "Ruta de Subcuenta"}, {"receive_sol_more_t_title1", "Explorando opciones de ruta en Solana"}, {"receive_ton_hint", "El formato de dirección predeterminado de Keystone es V4R2. Si no coinciden con Tonkeeper, por favor verifique y cambie en Tonkeeper. Esta dirección es exclusivamente para transacciones de TON. Enviar otros tipos de activos digitales a esta dirección resultará en su pérdida."}, {"receive_trx_hint", "Esta dirección es solo para TRX, tokens TRC-20 y tokens TRC-10, otros activos digitales enviados a esta dirección se perderán."}, - {"receive_xmr_more_t_desc1", "1.La Cuenta Principal es tu principal cuenta de Monero, que mantiene tu saldo primario y es capaz de recibir fondos directamente.\r\n2.Una Subdirección es una dirección secundaria vinculada a tu Cuenta Principal, diseñada para recibir pagos de manera privada. Cada Subdirección mantiene las transacciones separadas, ocultando el saldo de tu cuenta principal.\r\n3.Utiliza la Cuenta Principal para fondos más grandes o a largo plazo. Usa Subdirecciones cuando quieras recibir pagos sin revelar tu saldo principal o los detalles de la cuenta."}, + {"receive_xmr_more_t_desc1", "1.La Cuenta Principal es tu principal cuenta de Monero, que mantiene tu saldo primario y es capaz de recibir fondos directamente.\n2.Una Subdirección es una dirección secundaria vinculada a tu Cuenta Principal, diseñada para recibir pagos de manera privada. Cada Subdirección mantiene las transacciones separadas, ocultando el saldo de tu cuenta principal.\n3.Utiliza la Cuenta Principal para fondos más grandes o a largo plazo. Usa Subdirecciones cuando quieras recibir pagos sin revelar tu saldo principal o los detalles de la cuenta."}, {"receive_xmr_more_t_title1", "Conozca la diferencia: Cuenta principal y subdirección"}, {"repeat_passcode_desc", "Confirma dos veces el código PIN que has ingresado"}, {"repeat_passcode_title", "Vuelva a ingresar el código PIN"}, @@ -2685,7 +2657,7 @@ const static lv_i18n_phrase_t es_singulars[] = { {"usb_transport_sign_unkown_error_message", "No se puede reconocer la información de los datos."}, {"usb_transport_sign_unkown_error_title", "Error Desconocido"}, {"verification_code_desc", "Ingresa este código en el sitio web oficial de Keystone para verificar la seguridad de tu dispositivo"}, - {"verification_code_failed_desc", "Tu dispositivo puede haber sido comprometido, lo que representa un riesgo para tus datos sensibles y activos digitales. \r\nPara tu seguridad, recomendamos borrar todos los datos personales y contactar de inmediato al equipo de soporte de Keystone para obtener ayuda."}, + {"verification_code_failed_desc", "Tu dispositivo puede haber sido comprometido, lo que representa un riesgo para tus datos sensibles y activos digitales. \nPara tu seguridad, recomendamos borrar todos los datos personales y contactar de inmediato al equipo de soporte de Keystone para obtener ayuda."}, {"verification_code_failed_title", "¡Se ha detectado un intento de violación no autorizada!"}, {"verification_code_title", "Código de verificación"}, {"verification_success", "Verificado"}, @@ -2757,8 +2729,7 @@ const static lv_i18n_phrase_t es_singulars[] = { static uint8_t es_plural_fn(int32_t num) { - uint32_t n = op_n(num); - UNUSED(n); + uint32_t n = op_n(num); UNUSED(n); if ((n == 1)) return LV_I18N_PLURAL_TYPE_ONE; @@ -2940,7 +2911,7 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr(エクステンション)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -3123,7 +3094,7 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"firmware_update_no_upgradable_firmware_desc", "あなたのデバイスのファームウェアバージョンは、マイクロSDカードに保存されているものと同じかそれよりも高いです."}, {"firmware_update_no_upgradable_firmware_title", "アップグレード可能なファームウェアが検出されませんでした."}, {"firmware_update_sd_checksum_desc", "#F5870A チェックサムを表示#"}, - {"firmware_update_sd_checksum_done", "チェックサム:\r\n"}, + {"firmware_update_sd_checksum_done", "チェックサム:\n"}, {"firmware_update_sd_checksum_fmt", "#F5870A チェックサムを表示(%d%%) #"}, {"firmware_update_sd_checksum_notice", "これはセキュリティをさらに強化するためのオプション機能です.公式ウェブサイトでのダウンロードパッケージのチェックサムと以下のチェックサムを比較し、一致することを確認してください."}, {"firmware_update_sd_copying_desc", "アップデート中はMicroSDカードを取り外さないでください."}, @@ -3325,7 +3296,7 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"purpose_title", "新しい財布"}, {"receive_ada_enterprise_address", "住所(委任されていません)"}, {"receive_ada_more_t_desc1", "カルダノブロックチェーン上では、24つのアカウントを提供しており、各アカウントは使用するために多くのアドレスを生成することができます.必要なアカウント間を簡単に切り替えることができます."}, - {"receive_ada_more_t_desc2", "1. 支払いとステークのキー:Cardanoでは、各アカウントには通常のADAトランザクション(送受信)のための支払いキーと、ステーキングおよび報酬を受け取るためのステークキーがあります.\r\n\r\n2. ベースアドレス:ベースアドレスは支払いキーとステークキーの両方から派生したものです.通常のトランザクションとステーキングの両方に使用することができます.また、「外部アドレス(委任)」とも呼ばれています.\r\n\r\n3. 企業アドレス:このアドレスには支払いキーのみが含まれており、ステーキングには使用されません.ステーキングを含まない「ビジネス」シナリオ(取引所など)のために設計されています.また、「外部アドレス(委任されていない)」とも呼ばれています.\r\n\r\n4. ステークおよび報酬のアドレス:ステークキーはステーキングに使用され、関連するステークアドレスは報酬アドレスとも呼ばれ、ステーキング報酬を受け取るために使用されます."}, + {"receive_ada_more_t_desc2", "1. 支払いとステークのキー:Cardanoでは、各アカウントには通常のADAトランザクション(送受信)のための支払いキーと、ステーキングおよび報酬を受け取るためのステークキーがあります.\n\n2. ベースアドレス:ベースアドレスは支払いキーとステークキーの両方から派生したものです.通常のトランザクションとステーキングの両方に使用することができます.また、「外部アドレス(委任)」とも呼ばれています.\n\n3. 企業アドレス:このアドレスには支払いキーのみが含まれており、ステーキングには使用されません.ステーキングを含まない「ビジネス」シナリオ(取引所など)のために設計されています.また、「外部アドレス(委任されていない)」とも呼ばれています.\n\n4. ステークおよび報酬のアドレス:ステークキーはステーキングに使用され、関連するステークアドレスは報酬アドレスとも呼ばれ、ステーキング報酬を受け取るために使用されます."}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano ネイティブ"}, {"receive_ada_more_t_title1", "キーストーン上の複数のカルダノアカウント"}, @@ -3338,9 +3309,9 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"receive_btc_extended_public_key", "拡張公開鍵"}, {"receive_btc_more_address_settings", "アドレス設定"}, {"receive_btc_more_export_xpub", "エクスポート xPub"}, - {"receive_btc_more_t_desc1", "ビットコイン(BTC)は資金受領用に以下の3つのアドレス形式を使用しています:\r\n1. Native SegWitは、最も効率的で安全なビットコインアドレス形式です。従来のアドレス形式に比べてコスト削減とセキュリティの向上を提供し、通常は「bc1」で始まります。\r\n2. Legacy形式はビットコインの最も初期のバージョンの一つで、通常は「1」で始まります。\r\n3. Nested SegWitは、スムーズにNative SegWitへの移行を促進するために設計されたソリューションで、通常は「3」で始まります"}, - {"receive_btc_more_t_desc2", "はい、3つの異なるBitcoinアドレスフォーマットは互いに資金を送金するために使用することができます.ただし、以下の点に注意することが重要です:\r\n1. 異なるトランザクション手数料:アドレスフォーマットの選択はトランザクション手数料に影響を与える可能性があります.ネイティブSegWitアドレスは通常、より低い手数料で使用できます.\r\n2. ウォレットと取引所の互換性:使用しているウォレットや取引所が選択したアドレスフォーマットに対応していることを確認してください.一部のウォレットは特定のアドレスフォーマットにのみ対応している場合があります."}, - {"receive_btc_more_t_desc3", "1. プライバシー:アドレスの再利用はトランザクションの追跡可能性を高め、プライバシーを危険にさらします.新しいアドレスはトランザクションのプライバシーを維持するのに役立ちます.\r\n2. トランザクション効率:1つのアドレスにリンクされた複数のUTXOは統合によるコスト増加を引き起こし、ウォレットの効率に影響を与える可能性があります.\r\n3. セキュリティ:アドレスの繰り返し使用はプライベートキーの公開リスクを高め、侵害された場合には損失をもたらす可能性があります.\r\n要するに、アドレスの再利用をしないことは、UTXOモデル内でのプライバシーの保護、トランザクションの最適化、およびセキュリティリスクの低減を実現します."}, + {"receive_btc_more_t_desc1", "ビットコイン(BTC)は資金受領用に以下の3つのアドレス形式を使用しています:\n1. Native SegWitは、最も効率的で安全なビットコインアドレス形式です。従来のアドレス形式に比べてコスト削減とセキュリティの向上を提供し、通常は「bc1」で始まります。\n2. Legacy形式はビットコインの最も初期のバージョンの一つで、通常は「1」で始まります。\n3. Nested SegWitは、スムーズにNative SegWitへの移行を促進するために設計されたソリューションで、通常は「3」で始まります"}, + {"receive_btc_more_t_desc2", "はい、3つの異なるBitcoinアドレスフォーマットは互いに資金を送金するために使用することができます.ただし、以下の点に注意することが重要です:\n1. 異なるトランザクション手数料:アドレスフォーマットの選択はトランザクション手数料に影響を与える可能性があります.ネイティブSegWitアドレスは通常、より低い手数料で使用できます.\n2. ウォレットと取引所の互換性:使用しているウォレットや取引所が選択したアドレスフォーマットに対応していることを確認してください.一部のウォレットは特定のアドレスフォーマットにのみ対応している場合があります."}, + {"receive_btc_more_t_desc3", "1. プライバシー:アドレスの再利用はトランザクションの追跡可能性を高め、プライバシーを危険にさらします.新しいアドレスはトランザクションのプライバシーを維持するのに役立ちます.\n2. トランザクション効率:1つのアドレスにリンクされた複数のUTXOは統合によるコスト増加を引き起こし、ウォレットの効率に影響を与える可能性があります.\n3. セキュリティ:アドレスの繰り返し使用はプライベートキーの公開リスクを高め、侵害された場合には損失をもたらす可能性があります.\n要するに、アドレスの再利用をしないことは、UTXOモデル内でのプライバシーの保護、トランザクションの最適化、およびセキュリティリスクの低減を実現します."}, {"receive_btc_more_t_title1", "BTCのための3つの異なるアドレス形式は何ですか?"}, {"receive_btc_more_t_title2", "3つの異なるアドレス形式を使用して、お互いに資金を送金することはできますか?"}, {"receive_btc_more_t_title3", "再利用しないアドレスの利点"}, @@ -3356,19 +3327,19 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "レジャシーレジャシー"}, {"receive_eth_more_derivation_path_ledger_live", "Ledger Live"}, {"receive_eth_more_derivation_path_title2", "アカウント例:"}, - {"receive_eth_more_t_desc1", "1. 標準パス:このパスは、アドレスの生成に多くのソフトウェアウォレットで広く使用されています.このようなウォレットの例には、MetaMask、Rabby、BitKeep、およびCore Walletが含まれます.\r\n2. Ledger Live:Ledger Liveからシードフレーズをインポートする場合は、このパスを選択してください.Keystoneは、この形式を使用して初期の10個のアドレスのみ同期サポートしていることに注意してください.\r\n3. Ledger Legacy:デジタル資産をLedger Legacyで管理する場合は、このパスに移行してください."}, + {"receive_eth_more_t_desc1", "1. 標準パス:このパスは、アドレスの生成に多くのソフトウェアウォレットで広く使用されています.このようなウォレットの例には、MetaMask、Rabby、BitKeep、およびCore Walletが含まれます.\n2. Ledger Live:Ledger Liveからシードフレーズをインポートする場合は、このパスを選択してください.Keystoneは、この形式を使用して初期の10個のアドレスのみ同期サポートしていることに注意してください.\n3. Ledger Legacy:デジタル資産をLedger Legacyで管理する場合は、このパスに移行してください."}, {"receive_eth_more_t_title1", "異なるアプローチの探索:イーサリアムにおける標準、Ledger Live、およびレガシー派生パス"}, {"receive_eth_receive_main_title", "ETHを受け取る"}, {"receive_generate_new_address", "新しいアドレスを作成する"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "アカウントベースのパス"}, - {"receive_sol_more_t_desc1", "1. アカウントベースのパス:多くのSolanaウォレットで広く採用されています.このようなウォレットの例はSolflareです.\r\n2. 単一アカウントパス:Sollet / MathWalletからシードフレーズをインポートする場合は、このパスを選択してください.Keystoneは、この形式を使用して最初の10個のアドレスのみを同期することができることに注意してください.\r\n3. サブアカウントパス:Phantom / Exodusなどのソフトウェアウォレットでデジタル資産を管理している場合は、このパスに移行してください."}, + {"receive_sol_more_t_desc1", "1. アカウントベースのパス:多くのSolanaウォレットで広く採用されています.このようなウォレットの例はSolflareです.\n2. 単一アカウントパス:Sollet / MathWalletからシードフレーズをインポートする場合は、このパスを選択してください.Keystoneは、この形式を使用して最初の10個のアドレスのみを同期することができることに注意してください.\n3. サブアカウントパス:Phantom / Exodusなどのソフトウェアウォレットでデジタル資産を管理している場合は、このパスに移行してください."}, {"receive_sol_more_t_single_path", "単一アカウントパス"}, {"receive_sol_more_t_sub_path", "サブアカウントパス"}, {"receive_sol_more_t_title1", "ソラナのパスオプションを探る"}, {"receive_ton_hint", "Keystoneのデフォルトアドレス形式はV4R2です。Tonkeeperと一致しない場合は、Tonkeeperで確認して切り替えてください。このアドレスはTON取引専用です。このアドレスに他の種類のデジタル資産を送ると、紛失することになります。"}, {"receive_trx_hint", "このアドレスはTRX、TRC-20トークン、およびTRC-10トークンのみに対応しています.このアドレスに送信された他のデジタル資産は失われます."}, - {"receive_xmr_more_t_desc1", "1.プライマリアカウントは、あなたの主要なモネロアカウントで、主要な残高を保有し、直接資金を受け取ることができます。\r\n2.サブアドレスは、あなたのプライマリアカウントにリンクされた二次アドレスで、プライベートに支払いを受けるために設計されています。各サブアドレスは取引を別々に保持し、あなたのメインアカウントの残高を隠します。\r\n3.大きな資金や長期的な資金にはプライマリアカウントを使用してください。メインの残高やアカウントの詳細を明かさずに支払いを受け取りたい場合は、サブアドレスを使用してください。"}, + {"receive_xmr_more_t_desc1", "1.プライマリアカウントは、あなたの主要なモネロアカウントで、主要な残高を保有し、直接資金を受け取ることができます。\n2.サブアドレスは、あなたのプライマリアカウントにリンクされた二次アドレスで、プライベートに支払いを受けるために設計されています。各サブアドレスは取引を別々に保持し、あなたのメインアカウントの残高を隠します。\n3.大きな資金や長期的な資金にはプライマリアカウントを使用してください。メインの残高やアカウントの詳細を明かさずに支払いを受け取りたい場合は、サブアドレスを使用してください。"}, {"receive_xmr_more_t_title1", "プライマリアカウントとサブアドレスの違いを知る"}, {"repeat_passcode_desc", "入力したPINコードをダブルチェックしてください."}, {"repeat_passcode_title", "PINコードを再入力してください"}, @@ -3620,7 +3591,7 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"wallet_profile_default_desc", "現在のウォレット"}, {"wallet_profile_export_title", "エクスポート(Ext)公開鍵"}, {"wallet_profile_export_to_sdcard_title", "マイクロSDカードにxPubをエクスポートする"}, - {"wallet_profile_import_multi_wallet", "Import MultiSig Wallet\r\nマルチシグウォレットをインポート"}, + {"wallet_profile_import_multi_wallet", "Import MultiSig Wallet\nマルチシグウォレットをインポート"}, {"wallet_profile_import_multi_wallet_desc", "マルチサインウォレットのインポート方法を選択してください."}, {"wallet_profile_mid_btn", "ウォレットプロファイル"}, {"wallet_profile_multi_sign_title", "マルチサインウォレット"}, @@ -3847,7 +3818,7 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr (확장)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -4030,7 +4001,7 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"firmware_update_no_upgradable_firmware_desc", "장치의 현재 버전이 MicroSD 카드의 펌웨어 버전보다 높거나 같습니다."}, {"firmware_update_no_upgradable_firmware_title", "업그레이드 가능한 펌웨어를 찾을 수 없습니다."}, {"firmware_update_sd_checksum_desc", "#F5870A 체크섬 표시#"}, - {"firmware_update_sd_checksum_done", "체크섬\r\n"}, + {"firmware_update_sd_checksum_done", "체크섬\n"}, {"firmware_update_sd_checksum_fmt", "#F5870A 체크섬 표시 (%d%%)#"}, {"firmware_update_sd_checksum_notice", "보안성을 더욱 높일 수 있는 옵션 기능입니다.아래 체크섬과 공식 홈페이지에서 다운로드한 패키지의 체크섬을 비교하여 동일하게 유지하여 주시기 바랍니다."}, {"firmware_update_sd_copying_desc", "업그레이드 중에는 microSD 카드를 제거하지 마십시오."}, @@ -4232,7 +4203,7 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"purpose_title", "새 지갑"}, {"receive_ada_enterprise_address", "주소(위임되지 않음)"}, {"receive_ada_more_t_desc1", "카르다노 블록체인에서 24개의 계정을 제공하고 있으며, 각 계정은 사용할 수 있는 수많은 주소를 생성할 수 있다. 필요한 계정을 쉽게 전환할 수 있다."}, - {"receive_ada_more_t_desc2", "\"1. Payment & Stake Key: Cardano의 모든 계정에는 정기적인 ADA 거래(전송 및 수신)를 위한 Payment Key와 Stake and Reception을 위한 Stake Key가 있습니다.\r\n 2. 기본 주소(Base Address): 기본 주소는 결제 키와 지분 키 모두에서 파생됩니다. 정기적인 거래와 스테이킹에 모두 사용할 수 있습니다. \"외부 주소(Delegated)\"라고도 합니다\r\n 3. 기업 주소: 이 주소는 결제 키만 포함되어 있으며, 일반 거래에만 사용되며, 거래소와 같이 지분이 포함되지 않는 \"비즈니스\" 시나리오를 위해 설계되었으며, \"외부 주소(위임되지 않음)\"라고도 합니다\r\n 4. Stake & Reward Address: Stake Key는 스테이킹에 사용되며, 관련된 Stake Address는 스테이킹 보상을 받는 데 사용되는 Reward Address라고도 합니다.\""}, + {"receive_ada_more_t_desc2", "\"1. Payment & Stake Key: Cardano의 모든 계정에는 정기적인 ADA 거래(전송 및 수신)를 위한 Payment Key와 Stake and Reception을 위한 Stake Key가 있습니다.\n 2. 기본 주소(Base Address): 기본 주소는 결제 키와 지분 키 모두에서 파생됩니다. 정기적인 거래와 스테이킹에 모두 사용할 수 있습니다. \"외부 주소(Delegated)\"라고도 합니다\n 3. 기업 주소: 이 주소는 결제 키만 포함되어 있으며, 일반 거래에만 사용되며, 거래소와 같이 지분이 포함되지 않는 \"비즈니스\" 시나리오를 위해 설계되었으며, \"외부 주소(위임되지 않음)\"라고도 합니다\n 4. Stake & Reward Address: Stake Key는 스테이킹에 사용되며, 관련된 Stake Address는 스테이킹 보상을 받는 데 사용되는 Reward Address라고도 합니다.\""}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano 原生"}, {"receive_ada_more_t_title1", "키스톤의 여러 카르다노 계정"}, @@ -4245,9 +4216,9 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"receive_btc_extended_public_key", "공개 키 확장 "}, {"receive_btc_more_address_settings", "주소 설정"}, {"receive_btc_more_export_xpub", "XPub 내보내기"}, - {"receive_btc_more_t_desc1", "비트코인(BTC)은 자금을 받기 위해 세 가지 주소 형식을 사용합니다:\r\n 1. 네이티브 세그윗(Native SegWit)은 가장 효율적이고 안전한 비트코인 주소 포맷이다. 일반적으로 \"bc1\"로 시작하는 다른 전통적인 주소 포맷에 비해 비용 절감 및 향상된 보안을 제공한다\r\n 2. 레거시 형식은 일반적으로 \"1\"로 시작하는 비트코인의 초기 버전 중 하나이다\r\n 3. Nested SegWit은 Native SegWit으로 원활하게 전환할 수 있도록 설계된 솔루션으로, 일반적으로 \"3\"으로 시작한다"}, - {"receive_btc_more_t_desc2", "\"그렇다. 서로 다른 세 가지 비트코인 주소 형식을 사용하여 자금을 이체할 수 있다. 그러나 다음과 같은 측면을 염두에 두어야 한다:\r\n 1. 거래 수수료 차이: 주소 형식의 선택은 거래 수수료에 영향을 미칠 수 있으며, 네이티브 세그윗 주소는 일반적으로 수수료가 저렴하다.\r\n 2. 지갑과 교환의 호환성: 당신이 사용하고 있는 지갑이나 교환이 당신이 선택한 주소 형식을 지원하는지 확인하세요. 일부 지갑은 특정 주소 형식과만 호환될 수 있습니다.\""}, - {"receive_btc_more_t_desc3", "\"1. Privacy: 주소를 재사용하면 트랜잭션 추적성이 향상되어 프라이버시가 위험해진다. 새로운 주소는 트랜잭션 프라이버시를 유지하는 데 도움이 된다.\r\n 2. 트랜잭션 효율성: 하나의 주소에 연결된 여러 UTXO는 통합 비용을 증가시켜 지갑 효율성에 영향을 줄 수 있습니다.\r\n 3. 보안: 주소를 반복적으로 사용하면 개인 키가 노출될 위험이 높아져 손상될 경우 손실이 발생할 수 있습니다.\r\n 간단히 말해서, 주소를 재사용하지 않으면 사생활이 보호되고 트랜잭션이 최적화되며 UTXO 모델 내의 보안 위험이 감소합니다.\""}, + {"receive_btc_more_t_desc1", "비트코인(BTC)은 자금을 받기 위해 세 가지 주소 형식을 사용합니다:\n 1. 네이티브 세그윗(Native SegWit)은 가장 효율적이고 안전한 비트코인 주소 포맷이다. 일반적으로 \"bc1\"로 시작하는 다른 전통적인 주소 포맷에 비해 비용 절감 및 향상된 보안을 제공한다\n 2. 레거시 형식은 일반적으로 \"1\"로 시작하는 비트코인의 초기 버전 중 하나이다\n 3. Nested SegWit은 Native SegWit으로 원활하게 전환할 수 있도록 설계된 솔루션으로, 일반적으로 \"3\"으로 시작한다"}, + {"receive_btc_more_t_desc2", "\"그렇다. 서로 다른 세 가지 비트코인 주소 형식을 사용하여 자금을 이체할 수 있다. 그러나 다음과 같은 측면을 염두에 두어야 한다:\n 1. 거래 수수료 차이: 주소 형식의 선택은 거래 수수료에 영향을 미칠 수 있으며, 네이티브 세그윗 주소는 일반적으로 수수료가 저렴하다.\n 2. 지갑과 교환의 호환성: 당신이 사용하고 있는 지갑이나 교환이 당신이 선택한 주소 형식을 지원하는지 확인하세요. 일부 지갑은 특정 주소 형식과만 호환될 수 있습니다.\""}, + {"receive_btc_more_t_desc3", "\"1. Privacy: 주소를 재사용하면 트랜잭션 추적성이 향상되어 프라이버시가 위험해진다. 새로운 주소는 트랜잭션 프라이버시를 유지하는 데 도움이 된다.\n 2. 트랜잭션 효율성: 하나의 주소에 연결된 여러 UTXO는 통합 비용을 증가시켜 지갑 효율성에 영향을 줄 수 있습니다.\n 3. 보안: 주소를 반복적으로 사용하면 개인 키가 노출될 위험이 높아져 손상될 경우 손실이 발생할 수 있습니다.\n 간단히 말해서, 주소를 재사용하지 않으면 사생활이 보호되고 트랜잭션이 최적화되며 UTXO 모델 내의 보안 위험이 감소합니다.\""}, {"receive_btc_more_t_title1", "BTC의 세 가지 주소 형식은 무엇입니까?"}, {"receive_btc_more_t_title2", "세 가지 다른 주소 형식을 사용하여 서로 자금을 송금할 수 있습니까?"}, {"receive_btc_more_t_title3", "주소를 재사용하지 않을 경우의 이점"}, @@ -4263,19 +4234,19 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "레저 레거시"}, {"receive_eth_more_derivation_path_ledger_live", "레저 라이브"}, {"receive_eth_more_derivation_path_title2", "계정 예:"}, - {"receive_eth_more_t_desc1", "\"1. 표준 경로: 이 경로는 주소 생성을 위해 수많은 소프트웨어 지갑에서 널리 사용되고 있다. 이러한 지갑의 예로는 메타마스크, 래비, 비트킵, 코어 지갑 등이 있다.\r\n 2. 레저 라이브: 레저 라이브에서 시드 프레이즈를 가져오려면 이 경로를 선택하십시오. 키스톤은 이 형식을 사용하여 초기 10개의 주소만 동기화할 수 있습니다.\r\n 3. 원장 레거시: 원장 레거시로 디지털 자산을 관리하는 경우 이 경로로 전환\""}, + {"receive_eth_more_t_desc1", "\"1. 표준 경로: 이 경로는 주소 생성을 위해 수많은 소프트웨어 지갑에서 널리 사용되고 있다. 이러한 지갑의 예로는 메타마스크, 래비, 비트킵, 코어 지갑 등이 있다.\n 2. 레저 라이브: 레저 라이브에서 시드 프레이즈를 가져오려면 이 경로를 선택하십시오. 키스톤은 이 형식을 사용하여 초기 10개의 주소만 동기화할 수 있습니다.\n 3. 원장 레거시: 원장 레거시로 디지털 자산을 관리하는 경우 이 경로로 전환\""}, {"receive_eth_more_t_title1", "차이점 탐색: 표준, 원장 라이브 및 이더리움의 레거시 도출 경로"}, {"receive_eth_receive_main_title", "ETH 받기"}, {"receive_generate_new_address", "새 주소 생성"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "계정 기반 경로"}, - {"receive_sol_more_t_desc1", "\"1. 계정 기반 경로: 수많은 솔라나 지갑에 널리 채택되고 있습니다. 그러한 지갑의 예로는 솔프라레가 있습니다.\r\n 2. 단일 계정 경로: Sollet / MathWallet에서 시드 구문을 가져오려면 이 경로를 선택하십시오. Keystone은 이 형식을 사용하여 초기 10개 주소만 동기화할 수 있습니다.\r\n 3. 하위 계정 경로: 팬텀/엑소더스와 같은 소프트웨어 지갑으로 디지털 자산을 관리하면 이 경로로 전환하십시오.\""}, + {"receive_sol_more_t_desc1", "\"1. 계정 기반 경로: 수많은 솔라나 지갑에 널리 채택되고 있습니다. 그러한 지갑의 예로는 솔프라레가 있습니다.\n 2. 단일 계정 경로: Sollet / MathWallet에서 시드 구문을 가져오려면 이 경로를 선택하십시오. Keystone은 이 형식을 사용하여 초기 10개 주소만 동기화할 수 있습니다.\n 3. 하위 계정 경로: 팬텀/엑소더스와 같은 소프트웨어 지갑으로 디지털 자산을 관리하면 이 경로로 전환하십시오.\""}, {"receive_sol_more_t_single_path", "단일 계정 경로"}, {"receive_sol_more_t_sub_path", "서브 계정 경로"}, {"receive_sol_more_t_title1", "Solana 경로 옵션 탐색"}, {"receive_ton_hint", "Keystone 기본 주소 형식은 V4R2입니다. Tonkeeper와 일치하지 않는 경우 Tonkeeper에서 확인하고 전환하십시오. 이 주소는 TON 거래에만 사용됩니다. 이 주소로 다른 종류의 디지털 자산을 보내면 손실됩니다."}, {"receive_trx_hint", "이 주소는 TRX, TRC-20 토큰 및 TRC-10 토큰만을 위한 것이며, 이 주소로 전송된 다른 디지털 자산은 손실됩니다."}, - {"receive_xmr_more_t_desc1", "1. 기본 계정은 귀하의 주요 모네로 계정으로, 주요 잔액을 보유하고 직접 자금을 받을 수 있습니다.\r\n2. 서브어드레스는 귀하의 기본 계정에 연결된 보조 주소로, 개인적으로 지불을 받기 위해 설계되었습니다. 각 서브어드레스는 거래를 별도로 유지하여 귀하의 주요 계정 잔액을 숨깁니다.\r\n3. 큰 금액이나 장기 자금의 경우 기본 계정을 사용하세요. 주요 잔액이나 계정 상세 정보를 공개하지 않고 지불을 받고 싶을 때 서브어드레스를 사용하세요."}, + {"receive_xmr_more_t_desc1", "1. 기본 계정은 귀하의 주요 모네로 계정으로, 주요 잔액을 보유하고 직접 자금을 받을 수 있습니다.\n2. 서브어드레스는 귀하의 기본 계정에 연결된 보조 주소로, 개인적으로 지불을 받기 위해 설계되었습니다. 각 서브어드레스는 거래를 별도로 유지하여 귀하의 주요 계정 잔액을 숨깁니다.\n3. 큰 금액이나 장기 자금의 경우 기본 계정을 사용하세요. 주요 잔액이나 계정 상세 정보를 공개하지 않고 지불을 받고 싶을 때 서브어드레스를 사용하세요."}, {"receive_xmr_more_t_title1", "기본 계정과 서브어드레스의 차이를 알아보세요"}, {"repeat_passcode_desc", "입력한 PIN 코드를 다시 확인합니다."}, {"repeat_passcode_title", "PIN 코드 다시 입력하십시오."}, @@ -4754,7 +4725,7 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr (Расширение)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -4937,7 +4908,7 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"firmware_update_no_upgradable_firmware_desc", "Обновляемой прошивки не обнаружено"}, {"firmware_update_no_upgradable_firmware_title", "Обновляемой прошивки не обнаружено"}, {"firmware_update_sd_checksum_desc", "#F5870A Показать контрольную сумму#"}, - {"firmware_update_sd_checksum_done", "Контрольная сумма:\r\n"}, + {"firmware_update_sd_checksum_done", "Контрольная сумма:\n"}, {"firmware_update_sd_checksum_fmt", "#F5870A Показать контрольную сумму(%d%%)#"}, {"firmware_update_sd_checksum_notice", "Это дополнительная функция, предназначенная для дальнейшего повышения безопасности. Сравните следующую контрольную сумму с контрольной суммой вашего загружаемого пакета на официальном сайте и убедитесь, что они совпадают"}, {"firmware_update_sd_copying_desc", "Не доставайте MicroSD карту во время загрузки прошивки."}, @@ -4998,7 +4969,7 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"import_wallet_phrase_desc", "Введите слова вашей сид фразы в поля представленные ниже."}, {"import_wallet_phrase_title", "Введите сид фразу"}, {"import_wallet_shamir_backup", "Фраза Шамира"}, - {"import_wallet_shamir_backup_desc", "Вам понадобится несколько сид фраз\r\nдля восстановления кошелька"}, + {"import_wallet_shamir_backup_desc", "Вам понадобится несколько сид фраз\nдля восстановления кошелька"}, {"import_wallet_share_success_desc", "Эта часть сид фразы соответствует вашему кошельку."}, {"import_wallet_single_backup_desc", "Восстановите кошелек выбрав тип сид фразы, Пожалуйста, завершите процесс установки сразу, чтобы избежать риска для безопасности"}, {"import_wallet_single_phrase", "Стандартная фраза"}, @@ -5139,7 +5110,7 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"purpose_title", "Новый кошелек"}, {"receive_ada_enterprise_address", "Адрес (Не делегированный)"}, {"receive_ada_more_t_desc1", "В блокчейне Cardano мы предоставляем 24 счета. Каждый счет может генерировать множество адресов. Вы можете легко переключаться между нужными вам счетами."}, - {"receive_ada_more_t_desc2", "1. Ключи для платежей и делегирования: В Cardano каждая учетная запись имеет платежный ключ для обычных транзакций ADA (отправка и получение) и ключ для стейкинга и получения вознаграждений.\r\n2. Базовый адрес: Базовый адрес получается как из платежного ключа, так и из ключа делегирования. Его можно использовать как для обычных транзакций, так и для стейкинга. Также известен как «Внешний адрес (делегированный)».\r\n3. Адрес предприятия: Этот адрес содержит только платежный ключ и используется исключительно для обычных транзакций, а не для стейкинга. Он предназначен для «бизнес-сценариев», которые не требуют стейкинга, например, бирж. Также известен как «Внешний адрес (не делегированный)».\r\n4. Адреса стейкинга и вознаграждений: Ключи для стейкинга используется для стейкинга, а связанный с ним адрес стейкинга также называется адресом вознаграждения и используется для получения вознаграждений за стейкинг."}, + {"receive_ada_more_t_desc2", "1. Ключи для платежей и делегирования: В Cardano каждая учетная запись имеет платежный ключ для обычных транзакций ADA (отправка и получение) и ключ для стейкинга и получения вознаграждений.\n2. Базовый адрес: Базовый адрес получается как из платежного ключа, так и из ключа делегирования. Его можно использовать как для обычных транзакций, так и для стейкинга. Также известен как «Внешний адрес (делегированный)».\n3. Адрес предприятия: Этот адрес содержит только платежный ключ и используется исключительно для обычных транзакций, а не для стейкинга. Он предназначен для «бизнес-сценариев», которые не требуют стейкинга, например, бирж. Также известен как «Внешний адрес (не делегированный)».\n4. Адреса стейкинга и вознаграждений: Ключи для стейкинга используется для стейкинга, а связанный с ним адрес стейкинга также называется адресом вознаграждения и используется для получения вознаграждений за стейкинг."}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano 네이티브"}, {"receive_ada_more_t_title1", "Несколько счетов Cardano на Keystone"}, @@ -5152,9 +5123,9 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"receive_btc_extended_public_key", "Расширенный Открытый ключ"}, {"receive_btc_more_address_settings", "Настройки адресов"}, {"receive_btc_more_export_xpub", "Экспорт XPub"}, - {"receive_btc_more_t_desc1", "Bitcoin (BTC) поддерживает три формата адресов: \r\n1. Native SegWit это наиболее эффективный и безопасный формат, который уменьшает комиссии в сети в отличие от других адресов. Адреса этого формата начинаются с символов «bc1». \r\n2. Устаревший формат одна из самых ранних версий адресов Bitcoin, обычно начинающаяся с «1».\r\n3. Nested SegWit это решение, предназначенное для плавного перехода на Native SegWit, обычно начинается с «3». "}, - {"receive_btc_more_t_desc2", "Да, три различных формата Bitcoin адресов могут использоваться для перевода средств друг другу. Однако важно учитывать следующие аспекты:\r\n1. Различная комиссия за транзакцию. Выбор формата адреса может влиять на комиссию за транзакцию, при этом оригинальные адреса SegWit обычно имеют более низкую комиссию.\r\n2. Совместимость кошелька и биржи. Убедитесь, что используемый вами кошелек или биржа поддерживает выбранный формат адреса. Некоторые кошельки могут быть совместимы только с определенными форматами адресов."}, - {"receive_btc_more_t_desc3", "1. Конфиденциальность: повторное использование адресов повышает отслеживаемость транзакций и уменьшает вашу конфиденциальность. Новые адреса помогают поддерживать конфиденциальность транзакций.\r\n2. Эффективность транзакций. Несколько UTXO, связанных с одним адресом, могут повысить затраты на консолидацию, что повлияет на эффективность кошелька.\r\n3. Безопасность. Повторное использование адреса повышает риск раскрытия приватного ключа, что потенциально может привести к потерям в случае компрометации своих секретов.\r\nОтказ от повторного использования адресов защищает конфиденциальность, оптимизирует транзакции и снижает риски безопасности в рамках модели UTXO»"}, + {"receive_btc_more_t_desc1", "Bitcoin (BTC) поддерживает три формата адресов: \n1. Native SegWit это наиболее эффективный и безопасный формат, который уменьшает комиссии в сети в отличие от других адресов. Адреса этого формата начинаются с символов «bc1». \n2. Устаревший формат одна из самых ранних версий адресов Bitcoin, обычно начинающаяся с «1».\n3. Nested SegWit это решение, предназначенное для плавного перехода на Native SegWit, обычно начинается с «3». "}, + {"receive_btc_more_t_desc2", "Да, три различных формата Bitcoin адресов могут использоваться для перевода средств друг другу. Однако важно учитывать следующие аспекты:\n1. Различная комиссия за транзакцию. Выбор формата адреса может влиять на комиссию за транзакцию, при этом оригинальные адреса SegWit обычно имеют более низкую комиссию.\n2. Совместимость кошелька и биржи. Убедитесь, что используемый вами кошелек или биржа поддерживает выбранный формат адреса. Некоторые кошельки могут быть совместимы только с определенными форматами адресов."}, + {"receive_btc_more_t_desc3", "1. Конфиденциальность: повторное использование адресов повышает отслеживаемость транзакций и уменьшает вашу конфиденциальность. Новые адреса помогают поддерживать конфиденциальность транзакций.\n2. Эффективность транзакций. Несколько UTXO, связанных с одним адресом, могут повысить затраты на консолидацию, что повлияет на эффективность кошелька.\n3. Безопасность. Повторное использование адреса повышает риск раскрытия приватного ключа, что потенциально может привести к потерям в случае компрометации своих секретов.\nОтказ от повторного использования адресов защищает конфиденциальность, оптимизирует транзакции и снижает риски безопасности в рамках модели UTXO»"}, {"receive_btc_more_t_title1", "Чем отличаются три формата Bitcoin адресов?"}, {"receive_btc_more_t_title2", "Можно ли использовать три разных формата адресов для перевода средств между ними?"}, {"receive_btc_more_t_title3", "О недостатках повторного использования адресов"}, @@ -5170,19 +5141,19 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "Ledger устаревшие"}, {"receive_eth_more_derivation_path_ledger_live", "Ledger Live"}, {"receive_eth_more_derivation_path_title2", "Пример адресов"}, - {"receive_eth_more_t_desc1", "1. Стандартный путь: этот путь широко используется популярными программными кошельками для генерации адресов. Примеры таких кошельков: MetaMask, Rabby, BitKeep и Core Wallet. \r\n2. Ledger Live: выберите этот путь, если вы собираетесь импортировать сид фразу из Ledger Live. Обратите внимание, что Keystone поддерживает синхронизацию только первых 10 адресов в этом формате. \r\n3. Ledger устаревшие: переходите на этот путь, если вы управляете своими цифровыми активами с помощью устаревших приложений Ledger"}, + {"receive_eth_more_t_desc1", "1. Стандартный путь: этот путь широко используется популярными программными кошельками для генерации адресов. Примеры таких кошельков: MetaMask, Rabby, BitKeep и Core Wallet. \n2. Ledger Live: выберите этот путь, если вы собираетесь импортировать сид фразу из Ledger Live. Обратите внимание, что Keystone поддерживает синхронизацию только первых 10 адресов в этом формате. \n3. Ledger устаревшие: переходите на этот путь, если вы управляете своими цифровыми активами с помощью устаревших приложений Ledger"}, {"receive_eth_more_t_title1", "Ledger Live и устаревших путей вывода в Ethereum\""}, {"receive_eth_receive_main_title", "Получить ETH"}, {"receive_generate_new_address", "Создать новый адрес"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "Путь основного счета"}, - {"receive_sol_more_t_desc1", "1. Путь на основе учетной записи: широко применяется во многих кошельках Solana. Примером такого кошелька является Solflare.\r\n2. Путь к единой учетной записи: выберите этот путь, если вы собираетесь импортировать исходную фразу из Sollet/MathWallet. Обратите внимание, что Keystone поддерживает синхронизацию только первых 10 адресов в этом формате.\r\n3. Путь субсчета: перейдите на этот путь, если вы управляете своими цифровыми активами с помощью программных кошельков, таких как Phantom/Exodus."}, + {"receive_sol_more_t_desc1", "1. Путь на основе учетной записи: широко применяется во многих кошельках Solana. Примером такого кошелька является Solflare.\n2. Путь к единой учетной записи: выберите этот путь, если вы собираетесь импортировать исходную фразу из Sollet/MathWallet. Обратите внимание, что Keystone поддерживает синхронизацию только первых 10 адресов в этом формате.\n3. Путь субсчета: перейдите на этот путь, если вы управляете своими цифровыми активами с помощью программных кошельков, таких как Phantom/Exodus."}, {"receive_sol_more_t_single_path", "Путь к единому счету"}, {"receive_sol_more_t_sub_path", "Путь суб-счета"}, {"receive_sol_more_t_title1", "Узнать о путях вывода Solana"}, {"receive_ton_hint", "Формат адреса по умолчанию для Keystone - V4R2. Если они не совпадают с Tonkeeper, пожалуйста, проверьте и переключите в Tonkeeper. Этот адрес используется исключительно для транзакций TON. Отправка других типов цифровых активов на этот адрес приведет к их потере."}, {"receive_trx_hint", "Этот адрес предназначен только для TRX, TRC-20 и TRC-10 токенов, другие цифровые активы, отправленные на этот адрес, будут потеряны."}, - {"receive_xmr_more_t_desc1", "1. Основной счет — это ваш основной счет Monero, на котором хранится ваш основной баланс и который может напрямую получать средства.\r\n2. Субадрес — это второстепенный адрес, связанный с вашим основным счетом, предназначенный для частного получения платежей. Каждый субадрес держит транзакции отдельно, скрывая баланс вашего основного счета.\r\n3. Используйте основной счет для больших или долгосрочных средств. Используйте субадреса, когда вы хотите получать платежи, не раскрывая основной баланс или детали счета."}, + {"receive_xmr_more_t_desc1", "1. Основной счет — это ваш основной счет Monero, на котором хранится ваш основной баланс и который может напрямую получать средства.\n2. Субадрес — это второстепенный адрес, связанный с вашим основным счетом, предназначенный для частного получения платежей. Каждый субадрес держит транзакции отдельно, скрывая баланс вашего основного счета.\n3. Используйте основной счет для больших или долгосрочных средств. Используйте субадреса, когда вы хотите получать платежи, не раскрывая основной баланс или детали счета."}, {"receive_xmr_more_t_title1", "Знайте разницу: Основной счет и субадрес"}, {"repeat_passcode_desc", "Введите PIN-код второй раз для подтверждения."}, {"repeat_passcode_title", "Подтвердите PIN-код"}, @@ -5480,12 +5451,9 @@ const static lv_i18n_phrase_t ru_singulars[] = { static uint8_t ru_plural_fn(int32_t num) { - uint32_t n = op_n(num); - UNUSED(n); - uint32_t v = op_v(n); - UNUSED(v); - uint32_t i = op_i(n); - UNUSED(i); + uint32_t n = op_n(num); UNUSED(n); + uint32_t v = op_v(n); UNUSED(v); + uint32_t i = op_i(n); UNUSED(i); uint32_t i10 = i % 10; uint32_t i100 = i % 100; if ((v == 0 && i10 == 1 && i100 != 11)) return LV_I18N_PLURAL_TYPE_ONE; @@ -5669,7 +5637,7 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"connect_keplr_link", "https://keyst.one/t/3rd/keplr"}, {"connect_keplr_title", "Keplr(扩展程序端)"}, {"connect_keystone_link", "https://keyst.one/t/3rd/keystone"}, - {"connect_keystone_title", "Keystone"}, + {"connect_keystone_title", "Keystone Nexus"}, {"connect_leap_link", "https://keyst.one/t/3rd/leap"}, {"connect_leap_title", "Leap"}, {"connect_mintscan_link", "https://keyst.one/t/3rd/mintscan"}, @@ -5852,7 +5820,7 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"firmware_update_no_upgradable_firmware_desc", "设备当前版本已高于或等于 microSD 卡上的固件版本."}, {"firmware_update_no_upgradable_firmware_title", "未检测到可升级固件"}, {"firmware_update_sd_checksum_desc", "#F5870A 展示校验和#"}, - {"firmware_update_sd_checksum_done", "校验和\r\n"}, + {"firmware_update_sd_checksum_done", "校验和\n"}, {"firmware_update_sd_checksum_fmt", "#F5870A 展示校验和 (%d%%)#"}, {"firmware_update_sd_checksum_notice", "这是一个可选的功能,可以进一步提高安全性.将以下校验和在官方网站上的下载软件包的校验和签到,请确保它们保持一致."}, {"firmware_update_sd_copying_desc", "升级过程中,请勿移除 microSD 卡."}, @@ -6054,7 +6022,7 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"purpose_title", "新建钱包"}, {"receive_ada_enterprise_address", "地址(未委派)"}, {"receive_ada_more_t_desc1", "在 Cardano 区块链上,我们提供了 24 个 ADA 帐户,每个帐户都可以生成无数新地址.您可以在所需帐户之间轻松切换."}, - {"receive_ada_more_t_desc2", "1. Payment & Stake Keys:在Cardano中,每个帐户都有一个发送或接收常规ADA交易的付款密钥(Payment Key),以及用于积分和获得奖励的质押密钥(Stake Key).\r\n2. Base Address:基本地址(Base Address)是由付款密钥和股份密钥派生而来.它可以用于常规交易和质押,也被称为\"外部地址(External Addresses)\".\r\n3. Enterprise Address:此地址仅包含付款密钥,仅用于常规交易,而不是用于质押.它是为不涉及既有既定的\"业务\"场景而设计的,例如交流.也称为\"外部地址(未授权)\".\r\n4. Stake & Reward Addresses:质押密钥(Stake Key)用于质押;与之相关的质押地址(Stake Addresses)也被称为奖励地址(Reward Addresses),用于接收质押奖励."}, + {"receive_ada_more_t_desc2", "1. Payment & Stake Keys:在Cardano中,每个帐户都有一个发送或接收常规ADA交易的付款密钥(Payment Key),以及用于积分和获得奖励的质押密钥(Stake Key).\n2. Base Address:基本地址(Base Address)是由付款密钥和股份密钥派生而来.它可以用于常规交易和质押,也被称为\"外部地址(External Addresses)\".\n3. Enterprise Address:此地址仅包含付款密钥,仅用于常规交易,而不是用于质押.它是为不涉及既有既定的\"业务\"场景而设计的,例如交流.也称为\"外部地址(未授权)\".\n4. Stake & Reward Addresses:质押密钥(Stake Key)用于质押;与之相关的质押地址(Stake Addresses)也被称为奖励地址(Reward Addresses),用于接收质押奖励."}, {"receive_ada_more_t_ledger", "Ledger/BitBox02"}, {"receive_ada_more_t_standard", "Cardano 原生"}, {"receive_ada_more_t_title1", "Keystone上的多个 Cardano 帐户"}, @@ -6067,9 +6035,9 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"receive_btc_extended_public_key", "扩展公钥"}, {"receive_btc_more_address_settings", "地址设置"}, {"receive_btc_more_export_xpub", "导出 XPUB"}, - {"receive_btc_more_t_desc1", "比特币(BTC)的三种地址格式:\r\n1. Native SegWit 是当前主流的地址类型,交易费较低,地址以\" bc1\"开头.\r\n2. Nested SegWit 兼容 \"Legacy\" 和 \"Segwit\" 地址类型,交易费中等,地址以\" 3\"开头.\r\n3. Legacy 属于最初的比特币地址格式,交易费较高,地址以\" 1\"开头."}, - {"receive_btc_more_t_desc2", "是的,三种不同的比特币地址格式可用于彼此转移资金.但是,请务必牢记以下方面:\r\n1.交易费不同:选择不同的地址格式会产生不同的交易费.通常 Native Segwit 的交易费较低.\r\n2.钱包或交易所的兼容性:请确保您使用的钱包或交易所支持您选择的地址格式.某些钱包可能仅支持特定地址格式."}, - {"receive_btc_more_t_desc3", "1.隐私:重复使用同一地址增加了交易可追溯性,容易暴露隐私.每笔交易使用新地址有利于保持您的隐私.\r\n2.交易效率:链接到一个地址的多个UTXO会提高整合成本,从而影响转账速度.\r\n简而言之,不重复使用同一地址有利于保障隐私、优化交易速度."}, + {"receive_btc_more_t_desc1", "比特币(BTC)的三种地址格式:\n1. Native SegWit 是当前主流的地址类型,交易费较低,地址以\" bc1\"开头.\n2. Nested SegWit 兼容 \"Legacy\" 和 \"Segwit\" 地址类型,交易费中等,地址以\" 3\"开头.\n3. Legacy 属于最初的比特币地址格式,交易费较高,地址以\" 1\"开头."}, + {"receive_btc_more_t_desc2", "是的,三种不同的比特币地址格式可用于彼此转移资金.但是,请务必牢记以下方面:\n1.交易费不同:选择不同的地址格式会产生不同的交易费.通常 Native Segwit 的交易费较低.\n2.钱包或交易所的兼容性:请确保您使用的钱包或交易所支持您选择的地址格式.某些钱包可能仅支持特定地址格式."}, + {"receive_btc_more_t_desc3", "1.隐私:重复使用同一地址增加了交易可追溯性,容易暴露隐私.每笔交易使用新地址有利于保持您的隐私.\n2.交易效率:链接到一个地址的多个UTXO会提高整合成本,从而影响转账速度.\n简而言之,不重复使用同一地址有利于保障隐私、优化交易速度."}, {"receive_btc_more_t_title1", "BTC 的三种不同地址格式是什么?"}, {"receive_btc_more_t_title2", "这三种不同的地址格式可以相互接受资产吗?"}, {"receive_btc_more_t_title3", "不重复使用同一地址的好处"}, @@ -6085,19 +6053,19 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"receive_eth_more_derivation_path_ledger_legacy", "Ledger Legacy"}, {"receive_eth_more_derivation_path_ledger_live", "Ledger Live"}, {"receive_eth_more_derivation_path_title2", "例如:"}, - {"receive_eth_more_t_desc1", "1.标准路径:此路径被许多软件钱包广泛用于地址生成,比如 Metamask,Rabby,Bitkeep和Core Wallet.\r\n2. Ledger Live:如果您曾在Ledger Live下管理您的资产,请选择此派生路径.请注意,Keystone 仅支持此路径下的前10个地址.\r\n3. Ledger Legacy:如果您曾在Ledger Legacy下管理您的资产,请选择此派生路径."}, + {"receive_eth_more_t_desc1", "1.标准路径:此路径被许多软件钱包广泛用于地址生成,比如 Metamask,Rabby,Bitkeep和Core Wallet.\n2. Ledger Live:如果您曾在Ledger Live下管理您的资产,请选择此派生路径.请注意,Keystone 仅支持此路径下的前10个地址.\n3. Ledger Legacy:如果您曾在Ledger Legacy下管理您的资产,请选择此派生路径."}, {"receive_eth_more_t_title1", "了解以太坊中的标准路径、Ledger Live和Ledger Legacy的派生路径"}, {"receive_eth_receive_main_title", "接收 ETH"}, {"receive_generate_new_address", "生成新地址"}, {"receive_more_t_qr_link", "https://keyst.one/t/3rd/faq"}, {"receive_sol_more_t_base_path", "基于帐户的路径"}, - {"receive_sol_more_t_desc1", "1. Account-based 路径:被许多 Solana 钱包采用,比如 Solflare.\r\n2. Single Account 路径:如果您将 Sollet 或者 MathWallet钱包的助记词导入到 Keystone,则选择此路径.请注意,Keystone 仅支持此路径下的前10个地址.\r\n3. Sub-account 路径:如果您将 Phantom 或者 Exodus 钱包的助记词导入到 Keystone,则选择此路径."}, + {"receive_sol_more_t_desc1", "1. Account-based 路径:被许多 Solana 钱包采用,比如 Solflare.\n2. Single Account 路径:如果您将 Sollet 或者 MathWallet钱包的助记词导入到 Keystone,则选择此路径.请注意,Keystone 仅支持此路径下的前10个地址.\n3. Sub-account 路径:如果您将 Phantom 或者 Exodus 钱包的助记词导入到 Keystone,则选择此路径."}, {"receive_sol_more_t_single_path", "单账户路径"}, {"receive_sol_more_t_sub_path", "子账户路径"}, {"receive_sol_more_t_title1", "了解 Solana 的各派生路径"}, {"receive_ton_hint", "Keystone 默认地址格式为 V4R2。如果它们与 Tonkeeper 不匹配,请在 Tonkeeper 中检查并切换。此地址仅用于 TON 交易。将其他类型的数字资产发送到此地址将导致其丢失。"}, {"receive_trx_hint", "此地址仅适用于 TRX,TRC-20 和 TRC-10 代币,将其他数字货币发送到该地址将会造成丢失."}, - {"receive_xmr_more_t_desc1", "1.主账户是您的主要门罗币账户,持有您的主要余额,并能直接接收资金。\r\n2.子地址是与您的主账户关联的次要地址,设计用于私密接收支付。每个子地址将交易保持独立,隐藏您的主账户余额。\r\n3.使用主账户用于较大或长期资金。当您想要接收支付而不显示您的主要余额或账户详情时,使用子地址。"}, + {"receive_xmr_more_t_desc1", "1.主账户是您的主要门罗币账户,持有您的主要余额,并能直接接收资金。\n2.子地址是与您的主账户关联的次要地址,设计用于私密接收支付。每个子地址将交易保持独立,隐藏您的主账户余额。\n3.使用主账户用于较大或长期资金。当您想要接收支付而不显示您的主要余额或账户详情时,使用子地址。"}, {"receive_xmr_more_t_title1", "了解差异:主账户与子地址"}, {"repeat_passcode_desc", "再次确认您输入的 PIN 码."}, {"repeat_passcode_title", "重新输入 PIN 码"}, @@ -6442,8 +6410,8 @@ void __lv_i18n_reset(void) */ int lv_i18n_init(const lv_i18n_language_pack_t * langs) { - if (langs == NULL) return -1; - if (langs[0] == NULL) return -1; + if(langs == NULL) return -1; + if(langs[0] == NULL) return -1; current_lang_pack = langs; current_lang = langs[0]; /*Automatically select the first language*/ @@ -6456,13 +6424,13 @@ int lv_i18n_init(const lv_i18n_language_pack_t * langs) */ int lv_i18n_set_locale(const char * l_name) { - if (current_lang_pack == NULL) return -1; + if(current_lang_pack == NULL) return -1; uint16_t i; - for (i = 0; current_lang_pack[i] != NULL; i++) { + for(i = 0; current_lang_pack[i] != NULL; i++) { // Found -> finish - if (strcmp(current_lang_pack[i]->locale_name, l_name) == 0) { + if(strcmp(current_lang_pack[i]->locale_name, l_name) == 0) { current_lang = current_lang_pack[i]; return 0; } @@ -6475,10 +6443,10 @@ int lv_i18n_set_locale(const char * l_name) static const char * __lv_i18n_get_text_core(lv_i18n_phrase_t * trans, const char * msg_id) { uint16_t i; - for (i = 0; trans[i].msg_id != NULL; i++) { - if (strcmp(trans[i].msg_id, msg_id) == 0) { + for(i = 0; trans[i].msg_id != NULL; i++) { + if(strcmp(trans[i].msg_id, msg_id) == 0) { /*The msg_id has found. Check the translation*/ - if (trans[i].translation) return trans[i].translation; + if(trans[i].translation) return trans[i].translation; } } @@ -6493,23 +6461,23 @@ static const char * __lv_i18n_get_text_core(lv_i18n_phrase_t * trans, const char */ const char * lv_i18n_get_text(const char * msg_id) { - if (current_lang == NULL) return msg_id; + if(current_lang == NULL) return msg_id; const lv_i18n_lang_t * lang = current_lang; const void * txt; // Search in current locale - if (lang->singulars != NULL) { + if(lang->singulars != NULL) { txt = __lv_i18n_get_text_core(lang->singulars, msg_id); if (txt != NULL) return txt; } // Try to fallback - if (lang == current_lang_pack[0]) return msg_id; + if(lang == current_lang_pack[0]) return msg_id; lang = current_lang_pack[0]; // Repeat search for default locale - if (lang->singulars != NULL) { + if(lang->singulars != NULL) { txt = __lv_i18n_get_text_core(lang->singulars, msg_id); if (txt != NULL) return txt; } @@ -6525,31 +6493,31 @@ const char * lv_i18n_get_text(const char * msg_id) */ const char * lv_i18n_get_text_plural(const char * msg_id, int32_t num) { - if (current_lang == NULL) return msg_id; + if(current_lang == NULL) return msg_id; const lv_i18n_lang_t * lang = current_lang; const void * txt; lv_i18n_plural_type_t ptype; // Search in current locale - if (lang->locale_plural_fn != NULL) { + if(lang->locale_plural_fn != NULL) { ptype = lang->locale_plural_fn(num); - if (lang->plurals[ptype] != NULL) { + if(lang->plurals[ptype] != NULL) { txt = __lv_i18n_get_text_core(lang->plurals[ptype], msg_id); if (txt != NULL) return txt; } } // Try to fallback - if (lang == current_lang_pack[0]) return msg_id; + if(lang == current_lang_pack[0]) return msg_id; lang = current_lang_pack[0]; // Repeat search for default locale - if (lang->locale_plural_fn != NULL) { + if(lang->locale_plural_fn != NULL) { ptype = lang->locale_plural_fn(num); - if (lang->plurals[ptype] != NULL) { + if(lang->plurals[ptype] != NULL) { txt = __lv_i18n_get_text_core(lang->plurals[ptype], msg_id); if (txt != NULL) return txt; } @@ -6564,6 +6532,6 @@ const char * lv_i18n_get_text_plural(const char * msg_id, int32_t num) */ const char * lv_i18n_get_current_locale(void) { - if (!current_lang) return NULL; + if(!current_lang) return NULL; return current_lang->locale_name; } From 54bb6afe19d0304fffb59f04782247ef468996af Mon Sep 17 00:00:00 2001 From: ZhenQian Date: Tue, 4 Mar 2025 14:16:27 +0800 Subject: [PATCH 4/7] chore: run rust fmt --- external/ctaes | 2 +- rust/apps/wallets/src/lib.rs | 2 +- rust/rust_c/src/wallet/multi_coins_wallet/mod.rs | 2 +- src/device_setting.h | 1 + src/ui/gui_assets/images_hash.txt | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/external/ctaes b/external/ctaes index 8012b062e..3b10b89b0 160000 --- a/external/ctaes +++ b/external/ctaes @@ -1 +1 @@ -Subproject commit 8012b062ea4931f10cc2fd2075fddc3782a57ee4 +Subproject commit 3b10b89b05ca1ef5fff33316777249df25c8b930 diff --git a/rust/apps/wallets/src/lib.rs b/rust/apps/wallets/src/lib.rs index 3bfb96c6b..8744e991e 100644 --- a/rust/apps/wallets/src/lib.rs +++ b/rust/apps/wallets/src/lib.rs @@ -22,6 +22,7 @@ pub mod companion_app; pub mod core_wallet; pub mod keplr; pub mod keystone; +pub mod keystone_connect; pub mod metamask; pub mod okx; pub mod solana; @@ -32,7 +33,6 @@ mod utils; pub mod xbull; pub mod xrp_toolkit; pub mod zcash; -pub mod keystone_connect; //TODO: get these value from device pub const DEVICE_TYPE: &str = "Keystone 3 Pro"; diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs index 9fd574e06..d314e2c46 100644 --- a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs +++ b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs @@ -5,6 +5,7 @@ pub mod bitget; mod imtoken; pub mod keplr; pub mod keystone; +pub mod keystone_connect; pub mod okx; pub mod solana; pub mod structs; @@ -13,7 +14,6 @@ pub mod tonkeeper; mod utils; pub mod xbull; pub mod xrp_toolkit; -pub mod keystone_connect; pub mod core_wallet; pub mod thor_wallet; diff --git a/src/device_setting.h b/src/device_setting.h index b8f8b15ee..342408ebd 100644 --- a/src/device_setting.h +++ b/src/device_setting.h @@ -52,4 +52,5 @@ void DeviceSettingsTest(int argc, char *argv[]); bool GetEnableBlindSigning(void); void SetEnableBlindSigning(bool enable); void SetBootSecureCheckFlag(bool isSet); +bool GetBootSecureCheckFlag(void); #endif diff --git a/src/ui/gui_assets/images_hash.txt b/src/ui/gui_assets/images_hash.txt index 2a0936d70..df4aa2da0 100644 --- a/src/ui/gui_assets/images_hash.txt +++ b/src/ui/gui_assets/images_hash.txt @@ -1 +1 @@ -2d0b63d974652e3681292274a77162db \ No newline at end of file +078707a02508f8a8fde177fbd923e28f \ No newline at end of file From b4461463426bb44481e50222a41b4b9dd96314b6 Mon Sep 17 00:00:00 2001 From: ZhenQian Date: Tue, 4 Mar 2025 14:18:45 +0800 Subject: [PATCH 5/7] fix: rm uncessary code --- src/ui/gui_wallet/multi/web3/gui_wallet.c | 78 ++++++----------------- src/ui/gui_wallet/multi/web3/gui_wallet.h | 1 - 2 files changed, 20 insertions(+), 59 deletions(-) diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.c b/src/ui/gui_wallet/multi/web3/gui_wallet.c index 98d0024ac..a0db67874 100644 --- a/src/ui/gui_wallet/multi/web3/gui_wallet.c +++ b/src/ui/gui_wallet/multi/web3/gui_wallet.c @@ -387,64 +387,6 @@ UREncodeResult *GuiGetXrpToolkitDataByIndex(uint16_t index) return g_urEncode; } -UREncodeResult *GuiGetKeystoneWalletData(void) -{ - uint8_t mfp[4] = {0}; - GetMasterFingerPrint(mfp); - PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey)); - // btc 3 - // + eth 1 - // + bch 1 - // + dash 1 - // + dot 1 - // + ltc 1 - // + trx 1 - // + xrp 1 - - // total xpub = 9 - uint8_t XPUB_AMMOUNT = 9; - ExtendedPublicKey keys[XPUB_AMMOUNT]; - public_keys->data = keys; - public_keys->size = XPUB_AMMOUNT; - - keys[0].path = "m/44'/0'/0'"; - keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY); - - keys[1].path = "m/49'/0'/0'"; - keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC); - - keys[2].path = "m/84'/0'/0'"; - keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT); - - keys[3].path = GetXPubPath(XPUB_TYPE_BCH); - keys[3].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BCH); - - keys[4].path = GetXPubPath(XPUB_TYPE_DASH); - keys[4].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_DASH); - - keys[5].path = GetXPubPath(XPUB_TYPE_LTC); - keys[5].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_LTC); - - keys[6].path = GetXPubPath(XPUB_TYPE_TRX); - keys[6].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX); - - keys[7].path = GetXPubPath(XPUB_TYPE_XRP); - keys[7].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_XRP); - - keys[8].path = GetXPubPath(XPUB_TYPE_ETH_BIP44_STANDARD); - keys[8].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_ETH_BIP44_STANDARD); - - char serialNumber[256]; - GetSerialNumber(serialNumber); - char firmwareVersion[BUFFER_SIZE_32]; - GetSoftWareVersionNumber(firmwareVersion); - g_urEncode = get_keystone_wallet_ur(mfp, sizeof(mfp), serialNumber, public_keys, "Keystone 3 Pro", firmwareVersion); - - CHECK_CHAIN_PRINT(g_urEncode); - SRAM_FREE(public_keys); - return g_urEncode; -} - UREncodeResult *GuiGetKeystoneConnectWalletData(void) { uint8_t mfp[4] = {0}; @@ -477,6 +419,26 @@ UREncodeResult *GuiGetKeystoneConnectWalletData(void) keys[5].path = GetXPubPath(XPUB_TYPE_TRX); keys[5].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX); + + + // keys[3].path = GetXPubPath(XPUB_TYPE_BCH); + // keys[3].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BCH); + + // keys[4].path = GetXPubPath(XPUB_TYPE_DASH); + // keys[4].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_DASH); + + // keys[5].path = GetXPubPath(XPUB_TYPE_LTC); + // keys[5].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_LTC); + + // keys[6].path = GetXPubPath(XPUB_TYPE_TRX); + // keys[6].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX); + + // keys[7].path = GetXPubPath(XPUB_TYPE_XRP); + // keys[7].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_XRP); + + // keys[8].path = GetXPubPath(XPUB_TYPE_ETH_BIP44_STANDARD); + // keys[8].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_ETH_BIP44_STANDARD); + char serialNumber[256]; GetSerialNumber(serialNumber); char firmwareVersion[12]; diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.h b/src/ui/gui_wallet/multi/web3/gui_wallet.h index 04be18654..603453cb7 100644 --- a/src/ui/gui_wallet/multi/web3/gui_wallet.h +++ b/src/ui/gui_wallet/multi/web3/gui_wallet.h @@ -29,7 +29,6 @@ UREncodeResult *GuiGetXrpToolkitDataByIndex(uint16_t index); UREncodeResult *GuiGetADADataByIndex(char *walletName); UREncodeResult *GuiGetImTokenData(void); UREncodeResult *GuiGetCoreWalletData(void); -UREncodeResult *GuiGetKeystoneWalletData(void); UREncodeResult *GuiGetThorWalletBtcData(void); UREncodeResult *GuiGetKeystoneConnectWalletData(void); #endif From caecdf1a09971e0cb17be8c5ec1190e1f45425cc Mon Sep 17 00:00:00 2001 From: ZhenQian Date: Tue, 4 Mar 2025 15:39:45 +0800 Subject: [PATCH 6/7] fix: fix unit test --- rust/apps/wallets/src/keystone_connect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/apps/wallets/src/keystone_connect.rs b/rust/apps/wallets/src/keystone_connect.rs index fc9f842e5..6c66fe481 100644 --- a/rust/apps/wallets/src/keystone_connect.rs +++ b/rust/apps/wallets/src/keystone_connect.rs @@ -388,7 +388,7 @@ mod tests { let cbor: Vec = account.try_into().unwrap(); assert_eq!(hex::encode(cbor).to_lowercase(), - "a5011a52744703028ed9012fa802f4035821034c729aa638b3261640a8f06a5eabbfe4c04d2e0aac434b344147a1a5fa3555a304582096672bdd3ee7212fe7947040e703cddbaab5b498815787a601476c75e7e7899d06d90130a30186182cf5183cf500f5021a52744703030307d90130a2018400f480f40300081ae18decc809684b657973746f6e650a706163636f756e742e7374616e64617264d9012fa802f4035821034c729aa638b3261640a8f06a5eabbfe4c04d2e0aac434b344147a1a5fa3555a304582096672bdd3ee7212fe7947040e703cddbaab5b498815787a601476c75e7e7899d06d90130a30186182cf5183cf500f5021a52744703030307d90130a2018280f40300081ae18decc809684b657973746f6e650a756163636f756e742e6c65646765725f6c6567616379d9012fa602f4035821039f4e693730f116e7ab01dac46b94ad4fcabc3ca7d91a6b121cc26782a8f2b8b206d90130a3018a182cf5183cf500f500f400f4021a527447030303081aaea3081709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102f6cb8d18cef477defff35eae0d4fbfdb7e929fcf124056642bb52005121f2b8206d90130a3018a182cf5183cf501f500f400f4021a527447030303081afbdad0f009684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821025bac93928fb3a1b42abd1ef04a9df7152c3e3ac9784b0adeb8c74f02d6e081a706d90130a3018a182cf5183cf502f500f400f4021a527447030303081a127d09a409684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821031c4731b1d0f2813f25732a07bc8634a1d43678fb5f3e339e31868e7a3e161b3106d90130a3018a182cf5183cf503f500f400f4021a527447030303081aaa7ae17b09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103ee66c1903304ae22499bb7236ed9afe9de557ae4aa8756660bd13468e016ebfe06d90130a3018a182cf5183cf504f500f400f4021a527447030303081a53cb808a09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103b36c22174290c6ce6edb10df4386f7a4dee680313a7daecab7ceb48edb41d0d406d90130a3018a182cf5183cf505f500f400f4021a527447030303081a37d6210c09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f40358210301e2533680aceb0eea3cd0c23ca1fcec7ef0c085c4ba89986b56d919c6e775c106d90130a3018a182cf5183cf506f500f400f4021a527447030303081a14ff4a1509684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102a54598a178b1153c19a3678851c4e35162c018a1b5f354ad9cbf169fc365e6e106d90130a3018a182cf5183cf507f500f400f4021a527447030303081af4cff0d209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103934334794763b31983061359e7c5de9aa400083fcdffbb7c3c8791bda35700fe06d90130a3018a182cf5183cf508f500f400f4021a527447030303081a4267812709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821026f95e551487e0c75ebfdbdcf6c68d4cf3596729f6b0700e4b789f161dd41557906d90130a3018a182cf5183cf509f500f400f4021a527447030303081aa109680309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa702f403582103ebd552027b73adb1de1aa494ca7cedfe781434d6f102a55355b118a0c5da78bc045820517438aec2b78e81c275a41be63df6083358070cbefdb59de69bd2f99c003e8a06d90130a30186182cf500f500f5021a52744703030307d90130a2018280f40300081a7441f35c09684b657973746f6e65d9012fa702f403582102f3b97cf3f3387e2c4d8c7141a21529a90e0585e9f032706798d18f988a56e3f1045820ac31dee4dd3f4632f984e0a41e8728edc3ec67f614c8f03181490c8945d19d7406d90130a301861831f500f500f5021a52744703030307d90130a2018280f40300081a59fcb26509684b657973746f6e65036e4b657973746f6e6520332050726f047828626635353461326136316463336362303366656362303031333335323563353561356138316433310565312e312e30") + "a5011a52744703028ed9012fa802f4035821034c729aa638b3261640a8f06a5eabbfe4c04d2e0aac434b344147a1a5fa3555a304582096672bdd3ee7212fe7947040e703cddbaab5b498815787a601476c75e7e7899d06d90130a30186182cf5183cf500f5021a52744703030307d90130a2018400f480f40300081ae18decc809684b657973746f6e650a706163636f756e742e7374616e64617264d9012fa602f4035821036b287717eb691cb108d23293fbef416906fa564942ebfeb659a506ed39d9a07f06d90130a30188182cf5183cf500f500f4021a527447030303081a87be59b409684b657973746f6e650a756163636f756e742e6c65646765725f6c6567616379d9012fa602f4035821039f4e693730f116e7ab01dac46b94ad4fcabc3ca7d91a6b121cc26782a8f2b8b206d90130a3018a182cf5183cf500f500f400f4021a527447030303081aaea3081709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102f6cb8d18cef477defff35eae0d4fbfdb7e929fcf124056642bb52005121f2b8206d90130a3018a182cf5183cf501f500f400f4021a527447030303081afbdad0f009684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821025bac93928fb3a1b42abd1ef04a9df7152c3e3ac9784b0adeb8c74f02d6e081a706d90130a3018a182cf5183cf502f500f400f4021a527447030303081a127d09a409684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821031c4731b1d0f2813f25732a07bc8634a1d43678fb5f3e339e31868e7a3e161b3106d90130a3018a182cf5183cf503f500f400f4021a527447030303081aaa7ae17b09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103ee66c1903304ae22499bb7236ed9afe9de557ae4aa8756660bd13468e016ebfe06d90130a3018a182cf5183cf504f500f400f4021a527447030303081a53cb808a09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103b36c22174290c6ce6edb10df4386f7a4dee680313a7daecab7ceb48edb41d0d406d90130a3018a182cf5183cf505f500f400f4021a527447030303081a37d6210c09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f40358210301e2533680aceb0eea3cd0c23ca1fcec7ef0c085c4ba89986b56d919c6e775c106d90130a3018a182cf5183cf506f500f400f4021a527447030303081a14ff4a1509684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102a54598a178b1153c19a3678851c4e35162c018a1b5f354ad9cbf169fc365e6e106d90130a3018a182cf5183cf507f500f400f4021a527447030303081af4cff0d209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103934334794763b31983061359e7c5de9aa400083fcdffbb7c3c8791bda35700fe06d90130a3018a182cf5183cf508f500f400f4021a527447030303081a4267812709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821026f95e551487e0c75ebfdbdcf6c68d4cf3596729f6b0700e4b789f161dd41557906d90130a3018a182cf5183cf509f500f400f4021a527447030303081aa109680309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa702f403582103ebd552027b73adb1de1aa494ca7cedfe781434d6f102a55355b118a0c5da78bc045820517438aec2b78e81c275a41be63df6083358070cbefdb59de69bd2f99c003e8a06d90130a30186182cf500f500f5021a52744703030307d90130a2018280f40300081a7441f35c09684b657973746f6e65d9012fa702f403582102f3b97cf3f3387e2c4d8c7141a21529a90e0585e9f032706798d18f988a56e3f1045820ac31dee4dd3f4632f984e0a41e8728edc3ec67f614c8f03181490c8945d19d7406d90130a301861831f500f500f5021a52744703030307d90130a2018280f40300081a59fcb26509684b657973746f6e65036e4b657973746f6e6520332050726f047828626635353461326136316463336362303366656362303031333335323563353561356138316433310565312e312e30") } #[test] From a8bbcfbd3e6640017773acd62978c5ab02bb571d Mon Sep 17 00:00:00 2001 From: ZhenQian Date: Tue, 4 Mar 2025 15:45:52 +0800 Subject: [PATCH 7/7] fix: fix unit test --- rust/apps/wallets/src/keystone_connect.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rust/apps/wallets/src/keystone_connect.rs b/rust/apps/wallets/src/keystone_connect.rs index 6c66fe481..d2e20c638 100644 --- a/rust/apps/wallets/src/keystone_connect.rs +++ b/rust/apps/wallets/src/keystone_connect.rs @@ -413,13 +413,12 @@ mod tests { ExtendedPublicKey::new(DerivationPath::from_str("m/49'/0'/0'").unwrap(), hex::decode("0488b21e03197077c880000000bad8f929afd65c4b3ff78db1a386062374f2d2e6552e9fdc59aa7dd9b5db6e2c03ab6a1908b437179b914dc3cf4b829d7387adf60fdee483e9c748d5ee79ba4be4").unwrap()), ExtendedPublicKey::new(DerivationPath::from_str("m/84'/0'/0'").unwrap(), hex::decode("0488b21e039f6b7e4b80000000de47dd17679605b84abf439bdf5477c6cb94ff5a541d3cb1734afebfa3d3fdb90262ba42544acc4223c74511b37bae54de22565f25f8034f5af8aa10a04c3621b9").unwrap()), ExtendedPublicKey::new(DerivationPath::from_str("m/86'/0'/0'").unwrap(), hex::decode("0488b21e030484004d80000000a75805b89c5079ba74e9002c3e587f7c97ea8018ab1d5245638a45de3c845e0b03e0db6ca7c71e72a40091141b9dc4596ab3a9192ac41eebe1f2b048c654423ecb").unwrap()), - ExtendedPublicKey::new(DerivationPath::from_str("m/44'/607'/0'").unwrap(), hex::decode("895881fe5bab8b88e450055ff6916bf2bf41bc315325cee7975f33069beb079c").unwrap()), ]; let account = generate_crypto_multi_accounts(mfp, serial_number, keys, device_type, device_version) .unwrap(); let cbor: Vec = account.try_into().unwrap(); - assert_eq!(hex::encode(cbor), "a5011a1250b6bc0291d9012fa802f403582103c4ad25226a98764f7b753b6c763be112c940182e0b6698944c9def253cec4676045820bf103cfabcab325a7463ab5c432a4042109279d6c3531c8c5ea712684cf31f3706d90130a30186182cf5183cf500f5021a1250b6bc030307d90130a2018400f480f40300081a63c5ea6709684b657973746f6e650a706163636f756e742e7374616e64617264d9012fa802f403582103c4ad25226a98764f7b753b6c763be112c940182e0b6698944c9def253cec4676045820bf103cfabcab325a7463ab5c432a4042109279d6c3531c8c5ea712684cf31f3706d90130a30186182cf5183cf500f5021a1250b6bc030307d90130a2018280f40300081a63c5ea6709684b657973746f6e650a756163636f756e742e6c65646765725f6c6567616379d9012fa602f403582103de2f443b5070e839d6a209ed1afaadfd43daf7bc610a1fefef201a3aca5350ee06d90130a3018a182cf5183cf500f500f400f4021a1250b6bc0303081a769cd41a09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103a96bae34b46e82eee9c5beae52e446693b5c2e365714b223adea7caae47e1b7f06d90130a3018a182cf5183cf501f500f400f4021a1250b6bc0303081a998dec6209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821029299ea371a1c6cdcc75b91d26322a2dbdfedb58285e33760a2af82cfee1a7a6e06d90130a3018a182cf5183cf502f500f400f4021a1250b6bc0303081ac49452d709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821030f1808f972aed2b8e01d92b09b9c0d55b994592fb5599557e0d4828705204a4106d90130a3018a182cf5183cf503f500f400f4021a1250b6bc0303081a0823c44c09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821021c885e79f19ba2658755952801366f00f5304db8597eb72a78a6886d8175037d06d90130a3018a182cf5183cf504f500f400f4021a1250b6bc0303081aef4e5bae09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821037653d3a64a3d1fce16d5693e044e9aea644082371f4d31f6eb83096b5b84d97b06d90130a3018a182cf5183cf505f500f400f4021a1250b6bc0303081a364c571b09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103ded46d3bc515112c1c99b5f5b5f6c4abc76cc40d98ba4c1808c97038fe976ff606d90130a3018a182cf5183cf506f500f400f4021a1250b6bc0303081a456759fc09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102447d94e1937819a79a0ef56cd7b7a29de7c80a45b34480ef0b593083e418557906d90130a3018a182cf5183cf507f500f400f4021a1250b6bc0303081a09f362d709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103d94fb59028252ab9353ee376e868cfd59e9d0bc24ef35fe1b06310cd0e4e908b06d90130a3018a182cf5183cf508f500f400f4021a1250b6bc0303081a4e09767009684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821034d53b1c2630e12b853b96d70fb671363d5d4ec9406f722b4deea1f2a9eb6e76406d90130a3018a182cf5183cf509f500f400f4021a1250b6bc0303081ac418564209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa702f40358210246696468fa5c46647bdd186f568983e2a26773dc5b4c174790fee7ef9b9a7c9904582051872c7bb8270a7655ae15d738bb21379962ff11fb048b55630395afcfef442806d90130a30186182cf500f500f5021a1250b6bc030307d90130a2018280f40300081ab5d6f45009684b657973746f6e65d9012fa702f403582103ab6a1908b437179b914dc3cf4b829d7387adf60fdee483e9c748d5ee79ba4be4045820bad8f929afd65c4b3ff78db1a386062374f2d2e6552e9fdc59aa7dd9b5db6e2c06d90130a301861831f500f500f5021a1250b6bc030307d90130a2018280f40300081a197077c809684b657973746f6e65d9012fa702f40358210262ba42544acc4223c74511b37bae54de22565f25f8034f5af8aa10a04c3621b9045820de47dd17679605b84abf439bdf5477c6cb94ff5a541d3cb1734afebfa3d3fdb906d90130a301861854f500f500f5021a1250b6bc030307d90130a2018280f40300081a9f6b7e4b09684b657973746f6e65d9012fa702f403582103e0db6ca7c71e72a40091141b9dc4596ab3a9192ac41eebe1f2b048c654423ecb045820a75805b89c5079ba74e9002c3e587f7c97ea8018ab1d5245638a45de3c845e0b06d90130a301861856f500f500f5021a1250b6bc030307d90130a2018280f40300081a0484004d09684b657973746f6e65d9012fa2035820895881fe5bab8b88e450055ff6916bf2bf41bc315325cee7975f33069beb079c06d90130a20186182cf519025ff500f5021a1250b6bc036e4b657973746f6e6520332050726f047828626339633466373135376165363937643433346163383536323332306564353335653737373638300565312e372e30"); + assert_eq!(hex::encode(cbor), "a5011a1250b6bc0290d9012fa802f403582103c4ad25226a98764f7b753b6c763be112c940182e0b6698944c9def253cec4676045820bf103cfabcab325a7463ab5c432a4042109279d6c3531c8c5ea712684cf31f3706d90130a30186182cf5183cf500f5021a1250b6bc030307d90130a2018400f480f40300081a63c5ea6709684b657973746f6e650a706163636f756e742e7374616e64617264d9012fa602f403582103346d8362d8b3c348cc821abe96e79bbc005af54567d0742c9052215322eaa08a06d90130a30188182cf5183cf500f500f4021a1250b6bc0303081a6e7c9e1809684b657973746f6e650a756163636f756e742e6c65646765725f6c6567616379d9012fa602f403582103de2f443b5070e839d6a209ed1afaadfd43daf7bc610a1fefef201a3aca5350ee06d90130a3018a182cf5183cf500f500f400f4021a1250b6bc0303081a769cd41a09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103a96bae34b46e82eee9c5beae52e446693b5c2e365714b223adea7caae47e1b7f06d90130a3018a182cf5183cf501f500f400f4021a1250b6bc0303081a998dec6209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821029299ea371a1c6cdcc75b91d26322a2dbdfedb58285e33760a2af82cfee1a7a6e06d90130a3018a182cf5183cf502f500f400f4021a1250b6bc0303081ac49452d709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821030f1808f972aed2b8e01d92b09b9c0d55b994592fb5599557e0d4828705204a4106d90130a3018a182cf5183cf503f500f400f4021a1250b6bc0303081a0823c44c09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821021c885e79f19ba2658755952801366f00f5304db8597eb72a78a6886d8175037d06d90130a3018a182cf5183cf504f500f400f4021a1250b6bc0303081aef4e5bae09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821037653d3a64a3d1fce16d5693e044e9aea644082371f4d31f6eb83096b5b84d97b06d90130a3018a182cf5183cf505f500f400f4021a1250b6bc0303081a364c571b09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103ded46d3bc515112c1c99b5f5b5f6c4abc76cc40d98ba4c1808c97038fe976ff606d90130a3018a182cf5183cf506f500f400f4021a1250b6bc0303081a456759fc09684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582102447d94e1937819a79a0ef56cd7b7a29de7c80a45b34480ef0b593083e418557906d90130a3018a182cf5183cf507f500f400f4021a1250b6bc0303081a09f362d709684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f403582103d94fb59028252ab9353ee376e868cfd59e9d0bc24ef35fe1b06310cd0e4e908b06d90130a3018a182cf5183cf508f500f400f4021a1250b6bc0303081a4e09767009684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa602f4035821034d53b1c2630e12b853b96d70fb671363d5d4ec9406f722b4deea1f2a9eb6e76406d90130a3018a182cf5183cf509f500f400f4021a1250b6bc0303081ac418564209684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa702f40358210246696468fa5c46647bdd186f568983e2a26773dc5b4c174790fee7ef9b9a7c9904582051872c7bb8270a7655ae15d738bb21379962ff11fb048b55630395afcfef442806d90130a30186182cf500f500f5021a1250b6bc030307d90130a2018280f40300081ab5d6f45009684b657973746f6e65d9012fa702f403582103ab6a1908b437179b914dc3cf4b829d7387adf60fdee483e9c748d5ee79ba4be4045820bad8f929afd65c4b3ff78db1a386062374f2d2e6552e9fdc59aa7dd9b5db6e2c06d90130a301861831f500f500f5021a1250b6bc030307d90130a2018280f40300081a197077c809684b657973746f6e65d9012fa702f40358210262ba42544acc4223c74511b37bae54de22565f25f8034f5af8aa10a04c3621b9045820de47dd17679605b84abf439bdf5477c6cb94ff5a541d3cb1734afebfa3d3fdb906d90130a301861854f500f500f5021a1250b6bc030307d90130a2018280f40300081a9f6b7e4b09684b657973746f6e65d9012fa702f403582103e0db6ca7c71e72a40091141b9dc4596ab3a9192ac41eebe1f2b048c654423ecb045820a75805b89c5079ba74e9002c3e587f7c97ea8018ab1d5245638a45de3c845e0b06d90130a301861856f500f500f5021a1250b6bc030307d90130a2018280f40300081a0484004d09684b657973746f6e65036e4b657973746f6e6520332050726f047828626339633466373135376165363937643433346163383536323332306564353335653737373638300565312e372e30"); } }