From ed7c21a84f7287fc9e28501d6bc2d6a9e5cdccb3 Mon Sep 17 00:00:00 2001 From: ww3512687 <15809188520@163.com> Date: Fri, 10 Jan 2025 14:46:18 +0800 Subject: [PATCH 1/3] merge avax --- rust/Cargo.lock | 27 +- rust/Cargo.toml | 6 +- rust/apps/arweave/src/data_item.rs | 1 - rust/apps/arweave/src/lib.rs | 4 - rust/apps/avalanche/Cargo.toml | 33 ++ rust/apps/avalanche/src/address.rs | 116 ++++++ rust/apps/avalanche/src/constants.rs | 34 ++ rust/apps/avalanche/src/encode/cb58.rs | 27 ++ rust/apps/avalanche/src/errors.rs | 87 ++++ rust/apps/avalanche/src/lib.rs | 75 ++++ rust/apps/avalanche/src/network.rs | 65 +++ rust/apps/avalanche/src/ripple_keypair.rs | 21 + .../src/transactions/C_chain/evm_export.rs | 161 ++++++++ .../src/transactions/C_chain/evm_import.rs | 149 +++++++ .../P_chain/add_permissionless_delegator.rs | 124 ++++++ .../P_chain/add_permissionless_validator.rs | 140 +++++++ .../src/transactions/P_chain/node_id.rs | 30 ++ .../src/transactions/P_chain/output_owner.rs | 40 ++ .../src/transactions/P_chain/signer.rs | 24 ++ .../src/transactions/P_chain/validator.rs | 59 +++ .../avalanche/src/transactions/asset_id.rs | 14 + .../avalanche/src/transactions/base_tx.rs | 244 ++++++++++++ .../apps/avalanche/src/transactions/export.rs | 128 ++++++ .../apps/avalanche/src/transactions/import.rs | 115 ++++++ .../inputs/secp256k1_transfer_input.rs | 67 ++++ rust/apps/avalanche/src/transactions/mod.rs | 31 ++ .../outputs/secp256k1_transfer_output.rs | 86 ++++ .../avalanche/src/transactions/structs.rs | 135 +++++++ .../avalanche/src/transactions/subnet_auth.rs | 20 + .../avalanche/src/transactions/subnet_id.rs | 20 + .../src/transactions/transferable.rs | 271 +++++++++++++ .../avalanche/src/transactions/tx_header.rs | 39 ++ .../avalanche/src/transactions/type_id.rs | 48 +++ rust/apps/bitcoin/src/addresses/address.rs | 15 +- rust/apps/bitcoin/src/lib.rs | 1 + rust/apps/bitcoin/src/network.rs | 6 +- .../src/transactions/psbt/parsed_psbt.rs | 47 +++ .../src/transactions/psbt/wrapped_psbt.rs | 27 +- rust/apps/ethereum/src/address.rs | 50 +++ rust/apps/ethereum/src/lib.rs | 50 +++ rust/apps/monero/src/transfer_key.rs | 13 +- rust/apps/monero/src/utils/mod.rs | 2 +- rust/apps/wallets/src/core_wallet.rs | 142 +++++++ rust/apps/wallets/src/lib.rs | 1 + rust/commands.sh | 2 + rust/rust_c/Cargo.toml | 3 + rust/rust_c/build.rs | 3 + rust/rust_c/cbindgen.toml | 1 + rust/rust_c/src/avalanche/address.rs | 25 ++ rust/rust_c/src/avalanche/mod.rs | 211 ++++++++++ rust/rust_c/src/avalanche/structs.rs | 192 +++++++++ rust/rust_c/src/common/errors.rs | 46 +++ rust/rust_c/src/common/macros.rs | 12 + rust/rust_c/src/common/ur.rs | 17 + rust/rust_c/src/common/ur_ext.rs | 9 + rust/rust_c/src/kt_allocator | 3 + rust/rust_c/src/lib.rs | 3 + rust/rust_c/src/wallet/mod.rs | 2 +- .../wallet/multi_coins_wallet/core_wallet.rs | 58 +++ .../src/wallet/multi_coins_wallet/mod.rs | 1 + .../src/wallet/multi_coins_wallet/structs.rs | 2 +- src/crypto/account_public_info.c | 2 + src/crypto/account_public_info.h | 2 + src/driver/drv_rtc.c | 15 +- src/driver/drv_rtc.h | 2 +- src/main.c | 3 +- src/ui/gui_analyze/gui_resolve_ur.c | 8 +- .../multi/web3/gui_general_analyze.c | 4 + .../multi/web3/gui_general_analyze.h | 8 +- src/ui/gui_assets/font/cn/cnIllustrate.c | 15 +- src/ui/gui_assets/font/cn/cnLittleTitle.c | 15 +- src/ui/gui_assets/font/cn/cnText.c | 15 +- src/ui/gui_assets/font/cn/cnTitle.c | 15 +- src/ui/gui_assets/font/de/deIllustrate.c | 3 +- src/ui/gui_assets/font/de/deLittleTitle.c | 3 +- src/ui/gui_assets/font/de/deText.c | 3 +- src/ui/gui_assets/font/de/deTitle.c | 3 +- src/ui/gui_assets/font/es/esIllustrate.c | 3 +- src/ui/gui_assets/font/es/esLittleTitle.c | 3 +- src/ui/gui_assets/font/es/esText.c | 3 +- src/ui/gui_assets/font/es/esTitle.c | 3 +- src/ui/gui_assets/font/ja/jaIllustrate.c | 370 +++++++++--------- src/ui/gui_assets/font/ja/jaLittleTitle.c | 302 +++++++------- src/ui/gui_assets/font/ja/jaText.c | 320 +++++++-------- src/ui/gui_assets/font/ja/jaTitle.c | 264 +++++++------ src/ui/gui_assets/font/ko/koIllustrate.c | 15 +- src/ui/gui_assets/font/ko/koLittleTitle.c | 15 +- src/ui/gui_assets/font/ko/koText.c | 15 +- src/ui/gui_assets/font/ko/koTitle.c | 15 +- src/ui/gui_assets/font/ru/ruIllustrate.c | 3 +- src/ui/gui_assets/font/ru/ruLittleTitle.c | 3 +- src/ui/gui_assets/font/ru/ruText.c | 3 +- src/ui/gui_assets/font/ru/ruTitle.c | 3 +- src/ui/gui_chain/gui_chain.c | 5 +- src/ui/gui_chain/gui_chain.h | 3 + src/ui/gui_chain/gui_chain_components.c | 107 +++++ src/ui/gui_chain/gui_chain_components.h | 6 + src/ui/gui_chain/multi/web3/gui_avax.c | 238 +++++++++++ src/ui/gui_chain/multi/web3/gui_avax.h | 18 + src/ui/gui_chain/multi/web3/gui_eth.c | 2 +- src/ui/gui_chain/multi/web3/gui_sol.c | 4 +- src/ui/gui_chain/multi/web3/gui_ton.c | 27 +- src/ui/gui_components/gui_status_bar.c | 1 + src/ui/gui_frame/gui_obj.c | 3 + src/ui/gui_model/gui_model.c | 5 +- src/ui/gui_model/gui_model.h | 1 + src/ui/gui_views/gui_scan_view.c | 2 +- src/ui/gui_wallet/multi/web3/gui_wallet.c | 23 ++ src/ui/gui_wallet/multi/web3/gui_wallet.h | 1 + .../gui_widgets/gui_connect_wallet_widgets.h | 1 + src/ui/gui_widgets/gui_global_resources.c | 2 +- src/ui/gui_widgets/gui_global_resources.h | 1 + .../gui_transaction_detail_widgets.c | 1 + .../multi/web3/gui_connect_wallet_widgets.c | 4 + .../multi/web3/gui_general_home_widgets.c | 4 +- .../multi/web3/gui_general_home_widgets.h | 8 + .../gui_multi_path_coin_receive_widgets.c | 84 +++- src/ui/lv_i18n/data.csv | 4 +- src/ui/lv_i18n/lv_i18n.c | 116 +++--- test/test_cmd.c | 1 - ui_simulator/simulator_model.c | 121 +++--- ui_simulator/simulator_model.h | 9 +- 122 files changed, 4756 insertions(+), 887 deletions(-) create mode 100644 rust/apps/avalanche/Cargo.toml create mode 100644 rust/apps/avalanche/src/address.rs create mode 100644 rust/apps/avalanche/src/constants.rs create mode 100644 rust/apps/avalanche/src/encode/cb58.rs create mode 100644 rust/apps/avalanche/src/errors.rs create mode 100644 rust/apps/avalanche/src/lib.rs create mode 100644 rust/apps/avalanche/src/network.rs create mode 100644 rust/apps/avalanche/src/ripple_keypair.rs create mode 100644 rust/apps/avalanche/src/transactions/C_chain/evm_export.rs create mode 100644 rust/apps/avalanche/src/transactions/C_chain/evm_import.rs create mode 100644 rust/apps/avalanche/src/transactions/P_chain/add_permissionless_delegator.rs create mode 100644 rust/apps/avalanche/src/transactions/P_chain/add_permissionless_validator.rs create mode 100644 rust/apps/avalanche/src/transactions/P_chain/node_id.rs create mode 100644 rust/apps/avalanche/src/transactions/P_chain/output_owner.rs create mode 100644 rust/apps/avalanche/src/transactions/P_chain/signer.rs create mode 100644 rust/apps/avalanche/src/transactions/P_chain/validator.rs create mode 100644 rust/apps/avalanche/src/transactions/asset_id.rs create mode 100644 rust/apps/avalanche/src/transactions/base_tx.rs create mode 100644 rust/apps/avalanche/src/transactions/export.rs create mode 100644 rust/apps/avalanche/src/transactions/import.rs create mode 100644 rust/apps/avalanche/src/transactions/inputs/secp256k1_transfer_input.rs create mode 100644 rust/apps/avalanche/src/transactions/mod.rs create mode 100644 rust/apps/avalanche/src/transactions/outputs/secp256k1_transfer_output.rs create mode 100644 rust/apps/avalanche/src/transactions/structs.rs create mode 100644 rust/apps/avalanche/src/transactions/subnet_auth.rs create mode 100644 rust/apps/avalanche/src/transactions/subnet_id.rs create mode 100644 rust/apps/avalanche/src/transactions/transferable.rs create mode 100644 rust/apps/avalanche/src/transactions/tx_header.rs create mode 100644 rust/apps/avalanche/src/transactions/type_id.rs create mode 100644 rust/apps/wallets/src/core_wallet.rs create mode 100644 rust/rust_c/src/avalanche/address.rs create mode 100644 rust/rust_c/src/avalanche/mod.rs create mode 100644 rust/rust_c/src/avalanche/structs.rs create mode 100644 rust/rust_c/src/kt_allocator create mode 100644 rust/rust_c/src/wallet/multi_coins_wallet/core_wallet.rs create mode 100644 src/ui/gui_chain/multi/web3/gui_avax.c create mode 100644 src/ui/gui_chain/multi/web3/gui_avax.h diff --git a/rust/Cargo.lock b/rust/Cargo.lock index f9655c1c7..4eb3e4c87 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -166,6 +166,28 @@ dependencies = [ "thiserror-core", ] +[[package]] +name = "app_avalanche" +version = "0.1.0" +dependencies = [ + "app_utils", + "base64 0.11.0", + "bech32 0.11.0", + "bitcoin", + "bytes", + "core2", + "cryptoxide", + "either", + "hex", + "itertools 0.13.0", + "keystore", + "rust_tools", + "serde", + "serde_json", + "thiserror-core", + "ur-registry", +] + [[package]] name = "app_bitcoin" version = "0.1.0" @@ -3578,6 +3600,7 @@ dependencies = [ "aes", "app_aptos", "app_arweave", + "app_avalanche", "app_bitcoin", "app_cardano", "app_cosmos", @@ -4482,7 +4505,7 @@ dependencies = [ [[package]] name = "ur-parse-lib" version = "0.2.0" -source = "git+https://git@github.com/KeystoneHQ/keystone-sdk-rust.git?tag=0.0.45#42f5e05834c395b8d7ce5d1a233b371d2b74fa21" +source = "git+https://git@github.com/KeystoneHQ/keystone-sdk-rust.git?tag=0.0.46#1177ced5da2121414810fdd46ff42fc56c8497ca" dependencies = [ "hex", "ur", @@ -4492,7 +4515,7 @@ dependencies = [ [[package]] name = "ur-registry" version = "0.1.1" -source = "git+https://git@github.com/KeystoneHQ/keystone-sdk-rust.git?tag=0.0.45#42f5e05834c395b8d7ce5d1a233b371d2b74fa21" +source = "git+https://git@github.com/KeystoneHQ/keystone-sdk-rust.git?tag=0.0.46#1177ced5da2121414810fdd46ff42fc56c8497ca" dependencies = [ "bs58 0.5.1", "core2", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index be63c6220..a5999cd40 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -18,6 +18,7 @@ members = [ "apps/wallets", "apps/xrp", "apps/zcash", + "apps/avalanche", # C interface entry "rust_c", @@ -36,6 +37,7 @@ app_bitcoin = { path = "apps/bitcoin" } app_cardano = { path = "apps/cardano" } app_cosmos = { path = "apps/cosmos", default-features = false } app_ethereum = { path = "apps/ethereum" } +app_avalanche = { path = "apps/avalanche" } app_near = { path = "apps/near" } app_solana = { path = "apps/solana" } app_stellar = { path = "apps/stellar" } @@ -70,8 +72,8 @@ core2 = { version = "0.3.3", default_features = false, features = ["alloc"] } thiserror = { version = "1.0", package = "thiserror-core", default-features = false } rsa = { version = "0.8.2", default-features = false } sha1 = { version = "0.10.5", default-features = false } -ur-registry = { git = "https://git@github.com/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.45" } -ur-parse-lib = { git = "https://git@github.com/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.45" } +ur-registry = { git = "https://git@github.com/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.46" } +ur-parse-lib = { git = "https://git@github.com/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.46" } ed25519-bip32-core = { version = "0.1.1", default-features = false } cryptoxide = "0.4" arrayref = "0.3.6" diff --git a/rust/apps/arweave/src/data_item.rs b/rust/apps/arweave/src/data_item.rs index d0372659f..3be77cffa 100644 --- a/rust/apps/arweave/src/data_item.rs +++ b/rust/apps/arweave/src/data_item.rs @@ -190,7 +190,6 @@ mod tests { //01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a999bac8b7906c0bc94f7d163ea9e7fe6ef34045b6a27035e5298aaaddeea05355c50efd30da262c97a68b5aa7219726754bf8501818429e60b9f8175ed66a23349757dc8b3f126abc199272c91174bdb96a9a13aad43b9b6195583188c222002d29b105169dc237dccb0e371895aa10b9263e0b6fbe2d03d3a0073fa7f278ecfa890e75a3fe812ca86eb44f134a7edaa664a5582e72fa43b7accdfeb03f0492c118235b9ff7784106ca1a2f6e7bc4bcc6e1ed98775b7c023a1ae1e332f42e3183ab17c43c58e6605353a47331452ebf659fb267d27492b961ecdafcde9657a0a623aec761f6b3130f89ff7136cae26ebc58aaaa0c6c2264d8e0aa7c78cb46b5210cd69be2ffca64fd3cb0990116034c582828dd22d0235edf9ad999ef0b25afbcab802330d03e9653eff2dbee7f9e0a695a63e04d2aaef73152c255a1d8e5f9cc525cbcfd796ffff337f21d846ae7091037e2bfd06efaf262375100323335e62c79ca63aa31226e3655acab5f2861913630be567210d3d0d5b0f0a6bdc7edfc986e9c14b28b9d32deab5041872a26f8b95341a8cdf6326207d0c2f728ef85554f18c9e285c9f3e01e1d1cb1adf2546eeb9ddfc81a51b0fdf94c9f9116adcd5878815d21038968cbef2b51cc4a27fb1911008c6d1d587830645aca9ca775cf1d67dd9901aadb830a1e8abe0548a47619b8d80083316a645c646820640067653101c54f73164ab75f6650ea8970355bebd6f5162237379174d6afbc4a403e9d875d000800000000000000b100000000000000100c416374696f6e105472616e7366657212526563697069656e745671667a34427465626f714d556f4e536c74457077394b546462663736665252446667783841693644474a77105175616e746974791631303030303030303030301a446174612d50726f746f636f6c04616f0e56617269616e740e616f2e544e2e3108547970650e4d6573736167650653444b12616f636f6e6e65637418436f6e74656e742d5479706514746578742f706c61696e0037373037 let binary = hex::decode("01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a999bac8b7906c0bc94f7d163ea9e7fe6ef34045b6a27035e5298aaaddeea05355c50efd30da262c97a68b5aa7219726754bf8501818429e60b9f8175ed66a23349757dc8b3f126abc199272c91174bdb96a9a13aad43b9b6195583188c222002d29b105169dc237dccb0e371895aa10b9263e0b6fbe2d03d3a0073fa7f278ecfa890e75a3fe812ca86eb44f134a7edaa664a5582e72fa43b7accdfeb03f0492c118235b9ff7784106ca1a2f6e7bc4bcc6e1ed98775b7c023a1ae1e332f42e3183ab17c43c58e6605353a47331452ebf659fb267d27492b961ecdafcde9657a0a623aec761f6b3130f89ff7136cae26ebc58aaaa0c6c2264d8e0aa7c78cb46b5210cd69be2ffca64fd3cb0990116034c582828dd22d0235edf9ad999ef0b25afbcab802330d03e9653eff2dbee7f9e0a695a63e04d2aaef73152c255a1d8e5f9cc525cbcfd796ffff337f21d846ae7091037e2bfd06efaf262375100323335e62c79ca63aa31226e3655acab5f2861913630be567210d3d0d5b0f0a6bdc7edfc986e9c14b28b9d32deab5041872a26f8b95341a8cdf6326207d0c2f728ef85554f18c9e285c9f3e01e1d1cb1adf2546eeb9ddfc81a51b0fdf94c9f9116adcd5878815d21038968cbef2b51cc4a27fb1911008c6d1d587830645aca9ca775cf1d67dd9901aadb830a1e8abe0548a47619b8d80083316a645c646820640067653101c54f73164ab75f6650ea8970355bebd6f5162237379174d6afbc4a403e9d875d000800000000000000b100000000000000100c416374696f6e105472616e7366657212526563697069656e745671667a34427465626f714d556f4e536c74457077394b546462663736665252446667783841693644474a77105175616e746974791631303030303030303030301a446174612d50726f746f636f6c04616f0e56617269616e740e616f2e544e2e3108547970650e4d6573736167650653444b12616f636f6e6e65637418436f6e74656e742d5479706514746578742f706c61696e0037373037").unwrap(); let result = DataItem::deserialize(&binary).unwrap(); - println!("{:?}", result); assert_eq!(result.signature_type, 1); assert_eq!(result.owner, "nSkowCiV4VBZJVyI2UK2wT_6g9LVX5BLZvYSTjd0bVQ"); assert_eq!( diff --git a/rust/apps/arweave/src/lib.rs b/rust/apps/arweave/src/lib.rs index 7d874490d..e32a74699 100644 --- a/rust/apps/arweave/src/lib.rs +++ b/rust/apps/arweave/src/lib.rs @@ -11,10 +11,6 @@ pub mod transaction; #[macro_use] extern crate alloc; -#[cfg(test)] -#[macro_use] -extern crate std; - use crate::errors::{ArweaveError, Result}; use aes::cipher::block_padding::Pkcs7; use aes::cipher::{generic_array::GenericArray, BlockDecryptMut, BlockEncryptMut, KeyIvInit}; diff --git a/rust/apps/avalanche/Cargo.toml b/rust/apps/avalanche/Cargo.toml new file mode 100644 index 000000000..a3d9b0f17 --- /dev/null +++ b/rust/apps/avalanche/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "app_avalanche" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +keystore = { workspace = true, default-features = false } +app_utils = { workspace = true } +rust_tools = { workspace = true } +either = { workspace = true, default-features = false } +itertools = { workspace = true } +thiserror = { workspace = true } +core2 = { workspace = true } +bech32 = { workspace = true } +hex = { workspace = true } +ur-registry = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +base64 = { workspace = true } +cryptoxide = { workspace = true } +bitcoin = { workspace = true } +bytes = {version = "1.4.0", default-features = false} + +[features] +no_std = [] +default = ["std"] +std = [] +testnet = [] + +[dev-dependencies] +keystore = { workspace = true } diff --git a/rust/apps/avalanche/src/address.rs b/rust/apps/avalanche/src/address.rs new file mode 100644 index 000000000..571a07736 --- /dev/null +++ b/rust/apps/avalanche/src/address.rs @@ -0,0 +1,116 @@ +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +#[cfg(feature = "testnet")] +use crate::network::TESTNET_ID; +use crate::network::{Network, MAINNET_ID}; +use crate::ripple_keypair::hash160; +use crate::transactions::structs::ParsedSizeAble; +use alloc::string::{String, ToString}; +use bech32::{self, Bech32}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; +use keystore::algorithms::secp256k1::derive_public_key; + +#[derive(Debug, Clone)] +pub struct Address { + address: [u8; ADDRESS_LEN], +} + +impl ParsedSizeAble for Address { + fn parsed_size(&self) -> usize { + ADDRESS_LEN as usize + } +} + +impl Address { + pub fn encode(&self) -> String { + bech32::encode::(bech32::Hrp::parse_unchecked("avax"), &self.address).unwrap() + } + + pub fn to_evm_address(&self) -> String { + format!("0x{}", hex::encode(&self.address)) + } +} + +impl TryFrom for Address { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let mut address = [0u8; ADDRESS_LEN]; + bytes.copy_to_slice(&mut address); + Ok(Address { address }) + } +} + +pub fn get_address( + network: Network, + hd_path: &str, + root_x_pub: &str, + root_path: &str, +) -> Result { + let mut prefix = "avax"; + match network { + Network::AvaxMainNet => {} + #[cfg(feature = "testnet")] + Network::AvaxTestNet => { + prefix = "fuji"; + } + _ => { + return Err(AvaxError::UnsupportedNetwork(format!("{:?}", network))); + } + } + + let root_path = if !root_path.ends_with('/') { + root_path.to_string() + "/" + } else { + root_path.to_string() + }; + + let public_key = derive_public_key( + &root_x_pub.to_string(), + &format!( + "m/{}", + hd_path + .strip_prefix(&root_path) + .ok_or(AvaxError::InvalidHDPath(hd_path.to_string()))? + ), + ) + .map_err(|e| AvaxError::InvalidHex(format!("derive public key error: {}", e)))?; + bech32::encode::( + bech32::Hrp::parse_unchecked(prefix), + &hash160(&public_key.serialize()), + ) + .map_err(|e| AvaxError::InvalidHex(format!("bech32 encode error: {}", e))) +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::string::ToString; + extern crate std; + + #[test] + fn get_avax_address_test() { + { + let hd_path = "m/44'/9000'/0'/0/0"; + let root_x_pub = "xpub6CPE4bhTujy9CeJJbyskjJsp8FGgyWBsWV2W9GfZwuP9aeDBEoPRBsLk3agq32Gp5gkb9nJSjCn9fgZmuvmV3nPLk5Bc2wfKUQZREp4eG13"; + let root_path = "m/44'/9000'/0'"; + let address = get_address(Network::AvaxMainNet, &hd_path, &root_x_pub, &root_path); + assert_eq!( + address.unwrap(), + "avax1fmlmwakmgkezcg95lk97m8p3tgc9anuxemenwh" + ); + } + { + let prefix = "fuji"; + let data = [ + 9, 105, 234, 98, 226, 187, 48, 230, 109, 130, 232, 47, 226, 103, 237, 246, 135, 30, + 165, 247, + ]; + assert_eq!( + "fuji1p9575chzhvcwvmvzaqh7yeld76r3af0h3x77mq", + bech32::encode::(bech32::Hrp::parse_unchecked(prefix), &data).unwrap() + ); + } + } +} diff --git a/rust/apps/avalanche/src/constants.rs b/rust/apps/avalanche/src/constants.rs new file mode 100644 index 000000000..745768bb8 --- /dev/null +++ b/rust/apps/avalanche/src/constants.rs @@ -0,0 +1,34 @@ +pub const BLOCKCHAIN_ID_LEN: usize = 32; +pub const SUBNET_ID_LEN: usize = 32; +pub const SUBNET_AUTH_LEN: usize = 4; +pub const NODE_ID_LEN: usize = 20; +pub const PROOF_OF_POSESSION_PUBKEY_LEN: usize = 48; +pub const PROOF_OF_POSESSION_SIGNATURE_LEN: usize = 100; +pub const C_CHAIN_ADDRESS_LEN: usize = 20; +pub const ASSET_ID_LEN: usize = 32; +pub const ADDRESS_LEN: usize = 20; +pub const NAVAX_TO_AVAX_RATIO: f64 = 1_000_000_000.0; + +pub const X_BLOCKCHAIN_ID: [u8; BLOCKCHAIN_ID_LEN] = [ + 237, 95, 56, 52, 30, 67, 110, 93, 70, 226, 187, 0, 180, 93, 98, 174, 151, 209, 176, 80, 198, + 75, 198, 52, 174, 16, 98, 103, 57, 227, 92, 75, +]; + +pub const X_TEST_BLOCKCHAIN_ID: [u8; BLOCKCHAIN_ID_LEN] = [ + 171, 104, 235, 30, 225, 66, 160, 92, 254, 118, 140, 54, 225, 31, 11, 89, 109, 181, 163, 198, + 199, 122, 171, 230, 101, 218, 217, 230, 56, 202, 148, 247, +]; + +pub const P_BLOCKCHAIN_ID: [u8; BLOCKCHAIN_ID_LEN] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +pub const C_BLOCKCHAIN_ID: [u8; BLOCKCHAIN_ID_LEN] = [ + 4, 39, 212, 178, 42, 42, 120, 188, 221, 212, 86, 116, 44, 175, 145, 181, 107, 173, 191, 249, + 133, 238, 25, 174, 241, 69, 115, 231, 52, 63, 214, 82, +]; + +pub const C_TEST_BLOCKCHAIN_ID: [u8; BLOCKCHAIN_ID_LEN] = [ + 127, 201, 61, 133, 198, 214, 44, 91, 42, 192, 181, 25, 200, 112, 16, 234, 82, 148, 1, 45, 30, + 64, 112, 48, 214, 172, 208, 2, 28, 172, 16, 213, +]; diff --git a/rust/apps/avalanche/src/encode/cb58.rs b/rust/apps/avalanche/src/encode/cb58.rs new file mode 100644 index 000000000..971cff1f5 --- /dev/null +++ b/rust/apps/avalanche/src/encode/cb58.rs @@ -0,0 +1,27 @@ +use alloc::string::String; +use alloc::string::ToString; +use bitcoin::base58; +use cryptoxide::digest::Digest; +use cryptoxide::sha2::Sha256; + +pub trait Cb58Encodable { + fn get_prefix(&self) -> &'static str; + fn get_data(&self) -> &[u8]; + + fn to_cb58(&self) -> String { + let data = self.get_data(); + let mut hasher = Sha256::new(); + let mut checksum = [0u8; 32]; + hasher.input(data); + hasher.result(&mut checksum); + + let mut with_checksum = data.to_vec(); + with_checksum.extend_from_slice(&checksum[checksum.len() - 4..]); + + format!( + "{}-{}", + self.get_prefix(), + base58::encode(&with_checksum).to_string() + ) + } +} diff --git a/rust/apps/avalanche/src/errors.rs b/rust/apps/avalanche/src/errors.rs new file mode 100644 index 000000000..4fc79d68c --- /dev/null +++ b/rust/apps/avalanche/src/errors.rs @@ -0,0 +1,87 @@ +use alloc::string::{String, ToString}; +use bitcoin::address::error; +use core2::io; +use keystore::errors::KeystoreError; +use thiserror; +use thiserror::Error; + +pub type Result = core::result::Result; + +#[derive(Error, Debug, PartialEq)] +pub enum AvaxError { + #[error("invalid input")] + InvalidInput, + + #[error("invalid output")] + InvalidOutput, + + #[error("invalid transaction, reason: {0}")] + InvalidTransaction(String), + + #[error("sign failed, reason: {0}")] + SignFailure(String), + + #[error("get addresses failed, reason: {0}")] + AddressError(String), + + #[error("get key error: {0}")] + GetKeyError(String), + + #[error("unsupported: {0}")] + UnsupportedTransaction(String), + + #[error("unsupported network")] + UnsupportedNetwork(String), + + #[error("consensus encode error, reason: {0}")] + TransactionConsensusEncodeError(String), + + #[error("invalid hex: {0}")] + InvalidHex(String), + + #[error("bech32 decode failed, reason: {0}")] + Bech32DecodeError(String), + + #[error("keystore operation failed, reason: {0}")] + KeystoreError(String), + + #[error("derive public key error: {0}")] + DerivePublicKeyError(String), + + #[error("unknown type id: {0}")] + UnknownTypeId(u32), + + #[error("Invalid hd_Path: {0}")] + InvalidHDPath(String), + + #[error("Bech32 error")] + Bech32Error, +} + +impl From for AvaxError { + fn from(value: io::Error) -> Self { + Self::TransactionConsensusEncodeError(format!("{}", value)) + } +} + +impl From for AvaxError { + fn from(value: bech32::segwit::DecodeError) -> Self { + Self::Bech32DecodeError(format!("{}", value)) + } +} + +impl From for AvaxError { + fn from(value: KeystoreError) -> Self { + match value { + KeystoreError::DerivePubKey(data) => Self::KeystoreError(format!("{}", data)), + KeystoreError::InvalidDerivationPath(data) => Self::KeystoreError(format!("{}", data)), + KeystoreError::XPubError(data) => Self::KeystoreError(data), + KeystoreError::SeedError(data) => Self::KeystoreError(data), + KeystoreError::DerivationError(data) => Self::KeystoreError(data), + KeystoreError::GenerateSigningKeyError(data) => Self::KeystoreError(data), + KeystoreError::RSASignError => Self::KeystoreError("rsa sign error".to_string()), + KeystoreError::RSAVerifyError => Self::KeystoreError("rsa verify error".to_string()), + _ => Self::KeystoreError(value.to_string()), + } + } +} diff --git a/rust/apps/avalanche/src/lib.rs b/rust/apps/avalanche/src/lib.rs new file mode 100644 index 000000000..70ac95aba --- /dev/null +++ b/rust/apps/avalanche/src/lib.rs @@ -0,0 +1,75 @@ +#![no_std] +#![feature(error_in_core)] + +#[allow(unused_imports)] +#[macro_use] +extern crate alloc; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; + +pub use address::get_address; +use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; +use bytes::{Buf, Bytes}; +use hex; +use transactions::base_tx::BaseTx; +use transactions::tx_header::Header; +use ur_registry::pb::protoc; + +use crate::errors::{AvaxError, Result}; +use core::{ + convert::TryFrom, + fmt::{self, Debug}, +}; + +pub mod constants; +pub mod errors; +pub mod transactions; +pub mod encode { + pub mod cb58; +} +mod address; +pub mod network; +mod ripple_keypair; +pub struct PsbtSignStatus { + pub sign_status: Option, + pub is_completed: bool, +} + +use transactions::type_id::TypeId; + +pub fn parse_avax_tx(data: Vec) -> Result +where + T: TryFrom, +{ + let bytes = Bytes::from(data); + match T::try_from(bytes) { + Ok(data) => Ok(data), + Err(e) => Err(AvaxError::InvalidInput), + } +} + +pub fn get_avax_tx_type_id(data: Vec) -> Result { + let mut bytes = Bytes::from(data); + // codec_id 2 bytes + bytes.advance(2); + let type_id = TypeId::try_from(bytes.get_u32())?; + Ok(type_id) +} + +pub fn get_avax_tx_header(data: Vec) -> Result
{ + let mut bytes = Bytes::from(data); + // codec_id 2 bytes + bytes.advance(2); + + // type id + bytes.advance(4); + + // tx header + let tx_header = Header::try_from(bytes.clone())?; + bytes.advance(tx_header.parsed_size()); + + Ok(tx_header) +} diff --git a/rust/apps/avalanche/src/network.rs b/rust/apps/avalanche/src/network.rs new file mode 100644 index 000000000..60e820255 --- /dev/null +++ b/rust/apps/avalanche/src/network.rs @@ -0,0 +1,65 @@ +use crate::errors::AvaxError; +use alloc::string::{String, ToString}; +use core::str::FromStr; + +pub trait NetworkT { + fn get_unit(&self) -> String; + fn normalize(&self) -> String; +} + +#[derive(Debug, Clone)] +pub enum Network { + AvaxMainNet, + + #[cfg(feature = "testnet")] + AvaxTestNet, + // @todo: Add Local and CustomNewNetwork +} + +pub const MAINNET_ID: u32 = 1; +#[cfg(feature = "testnet")] +pub const FUJI_ID: u32 = 5; + +pub const AVAX_COIN_TYPE: u32 = 9000; + +pub const MAINNET_HRP: &str = "avax"; +pub const FUJI_HRP: &str = "fuji"; +pub const LOCAL_HRP: &str = "local"; + +impl NetworkT for Network { + fn get_unit(&self) -> String { + match self { + Network::AvaxMainNet => "AVAX", + #[cfg(feature = "testnet")] + Network::AvaxTestNet => "tAVAX", + } + .to_string() + } + + fn normalize(&self) -> String { + match self { + Network::AvaxMainNet => "Avax Mainnet", + #[cfg(feature = "testnet")] + Network::AvaxTestNet => "Avax Testnet", + } + .to_string() + } +} + +impl Network { + pub fn bip44_coin_type(&self) -> String { + AVAX_COIN_TYPE.to_string() + } +} + +impl FromStr for Network { + type Err = AvaxError; + fn from_str(network: &str) -> Result { + match network { + "avax" => Ok(Network::AvaxMainNet), + #[cfg(feature = "testnet")] + "fuji" => Ok(Network::AvaxTestNet), + _ => Err(AvaxError::UnsupportedNetwork(format!("{:?}", network))), + } + } +} diff --git a/rust/apps/avalanche/src/ripple_keypair.rs b/rust/apps/avalanche/src/ripple_keypair.rs new file mode 100644 index 000000000..4059674ca --- /dev/null +++ b/rust/apps/avalanche/src/ripple_keypair.rs @@ -0,0 +1,21 @@ +use alloc::string::String; +use alloc::vec::Vec; +use cryptoxide::digest::Digest; +use cryptoxide::hashing; +use cryptoxide::ripemd160::Ripemd160; + +pub(crate) fn sha256_digest(data: &[u8]) -> Vec { + hashing::sha256(&data).to_vec() +} + +fn ripemd160_digest(data: &[u8]) -> [u8; 20] { + let mut hasher = Ripemd160::new(); + hasher.input(data); + let mut output = [0u8; 20]; + hasher.result(&mut output); + output +} + +pub fn hash160(data: &[u8]) -> [u8; 20] { + ripemd160_digest(&sha256_digest(data)) +} diff --git a/rust/apps/avalanche/src/transactions/C_chain/evm_export.rs b/rust/apps/avalanche/src/transactions/C_chain/evm_export.rs new file mode 100644 index 000000000..4777e21fd --- /dev/null +++ b/rust/apps/avalanche/src/transactions/C_chain/evm_export.rs @@ -0,0 +1,161 @@ +use crate::address::Address; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use crate::transactions::structs::{ + AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec, ParsedSizeAble, +}; +use crate::transactions::transferable::TransferableOutput; +use crate::transactions::tx_header::Header; +use crate::transactions::{asset_id::AssetId, type_id::TypeId}; + +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct EvmInput { + address: Address, + amount: u64, + asset_id: AssetId, + nonce: u64, +} + +impl TryFrom for EvmInput { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let address = Address::try_from(bytes.split_to(C_CHAIN_ADDRESS_LEN))?; + let amount = bytes.get_u64(); + let asset_id = AssetId::try_from(bytes.split_to(ASSET_ID_LEN))?; + let nonce = bytes.get_u64(); + Ok(EvmInput { + address, + amount, + asset_id, + nonce, + }) + } +} + +impl ParsedSizeAble for EvmInput { + fn parsed_size(&self) -> usize { + C_CHAIN_ADDRESS_LEN + 8 + ASSET_ID_LEN + 8 + } +} + +impl EvmInput { + pub fn get_amount(&self) -> u64 { + self.amount + } +} + +#[derive(Debug, Clone)] +pub struct ExportTx { + codec_id: u16, + type_id: TypeId, + tx_header: Header, + dest_chain: [u8; BLOCKCHAIN_ID_LEN], + inputs: LengthPrefixedVec, + outputs: LengthPrefixedVec, +} + +impl AvaxTxInfo for ExportTx { + fn get_total_input_amount(&self) -> u64 { + self.inputs + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_total_output_amount(&self) -> u64 { + self.outputs + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_outputs_addresses(&self) -> Vec { + self.outputs + .iter() + .map(|output| { + AvaxFromToInfo::from( + format!("{} AVAX", output.get_amount() as f64 / NAVAX_TO_AVAX_RATIO), + output.get_addresses(), + ) + }) + .collect() + } + + fn get_method_info(&self) -> Option { + let method = match (self.type_id, self.dest_chain) { + (TypeId::CchainExportTx, chain) => { + let dest = match chain { + X_BLOCKCHAIN_ID | X_TEST_BLOCKCHAIN_ID => "X", + P_BLOCKCHAIN_ID => "P", + C_BLOCKCHAIN_ID | C_TEST_BLOCKCHAIN_ID => "C", + _ => "Unknown", + }; + format!("C to {} Export", dest) + } + _ => "Unknown".to_string(), + }; + Some(AvaxMethodInfo::from_string(method).with_method_key("Export Tx".to_string())) + } + + fn get_network_key(&self) -> String { + "Export Tx".to_string() + } +} + +impl TryFrom for ExportTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let codec_id = bytes.get_u16(); + let type_id = TypeId::try_from(bytes.get_u32())?; + let tx_header = Header::try_from(bytes.clone())?; + bytes.advance(tx_header.parsed_size()); + + let mut dest_chain = [0u8; 32]; + bytes.copy_to_slice(&mut dest_chain); + + let inputs = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(inputs.parsed_size()); + + let outputs = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(outputs.parsed_size()); + + Ok(ExportTx { + codec_id, + type_id, + tx_header, + dest_chain, + inputs, + outputs, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_avax_c_export() { + // f22ATVQT11pSdMwvWLwXgeHNshauTDZxzErFKT5nd64esWXjU + let input_bytes = "000000000001000000057fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000000000000000000000000000000000000000000000000000000000000000000001a9b548da818607e83cbcf6802370691948cbd4160000000005f60cde3d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000005f5e1000000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab000000010000000900000001683728d1c682680aa80e702dcc8e349f79b5da8cac4b7fb59b28750f1c4c977014a70f69d5ef97dec616a21d69e3560cf2db78257710af3c03f959a487bcab04000218c13e"; + let binary_data = hex::decode(input_bytes).expect("Failed to decode hex string"); + let mut bytes = Bytes::from(binary_data); + let result = ExportTx::try_from(bytes.clone()).unwrap(); + assert_eq!(result.codec_id, 0); + assert_eq!(result.type_id, TypeId::CchainExportTx); + assert_eq!(result.dest_chain, P_BLOCKCHAIN_ID); + assert_eq!(result.inputs.get_len(), 1); + assert_eq!(result.outputs.get_len(), 1); + assert_eq!(result.inputs.get(0).unwrap().amount, 100011230); + } +} diff --git a/rust/apps/avalanche/src/transactions/C_chain/evm_import.rs b/rust/apps/avalanche/src/transactions/C_chain/evm_import.rs new file mode 100644 index 000000000..b65df4326 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/C_chain/evm_import.rs @@ -0,0 +1,149 @@ +use crate::address::Address; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use crate::transactions::structs::{ + AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec, ParsedSizeAble, +}; +use crate::transactions::transferable::TransferableInput; +use crate::transactions::tx_header::Header; +use crate::transactions::{asset_id::AssetId, type_id::TypeId}; + +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct EvmOutput { + address: Address, + amount: u64, + asset_id: AssetId, +} + +impl TryFrom for EvmOutput { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let address = Address::try_from(bytes.split_to(C_CHAIN_ADDRESS_LEN))?; + let amount = bytes.get_u64(); + let asset_id = AssetId::try_from(bytes.split_to(ASSET_ID_LEN))?; + Ok(EvmOutput { + address, + amount, + asset_id, + }) + } +} + +impl ParsedSizeAble for EvmOutput { + fn parsed_size(&self) -> usize { + C_CHAIN_ADDRESS_LEN + 8 + ASSET_ID_LEN + } +} + +#[derive(Debug, Clone)] +pub struct ImportTx { + codec_id: u16, + type_id: TypeId, + tx_header: Header, + source_chain: [u8; BLOCKCHAIN_ID_LEN], + inputs: LengthPrefixedVec, + outputs: LengthPrefixedVec, +} + +impl AvaxTxInfo for ImportTx { + fn get_total_input_amount(&self) -> u64 { + self.inputs + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_total_output_amount(&self) -> u64 { + self.outputs.iter().fold(0, |acc, item| acc + item.amount) + } + + fn get_outputs_addresses(&self) -> Vec { + self.outputs + .iter() + .map(|output| { + AvaxFromToInfo::from( + format!("{} AVAX", output.amount as f64 / NAVAX_TO_AVAX_RATIO), + vec![output.address.encode()], + ) + }) + .collect() + } + + fn get_network_key(&self) -> String { + "Import Tx".to_string() + } + + fn get_method_info(&self) -> Option { + let method = match self.source_chain { + X_BLOCKCHAIN_ID | X_TEST_BLOCKCHAIN_ID => "Sending from X-Chain", + P_BLOCKCHAIN_ID => "Sending from P-Chain", + C_BLOCKCHAIN_ID | C_TEST_BLOCKCHAIN_ID => "Sending from C-Chain", + _ => "Unknown", + }; + + Some( + AvaxMethodInfo::from_string(method.to_string()) + .with_method_key("Import Tx".to_string()), + ) + } +} + +impl TryFrom for ImportTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let codec_id = bytes.get_u16(); + let type_id = TypeId::try_from(bytes.get_u32())?; + let tx_header = Header::try_from(bytes.clone())?; + bytes.advance(tx_header.parsed_size()); + + let mut source_chain = [0u8; 32]; + bytes.copy_to_slice(&mut source_chain); + + let inputs = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(inputs.parsed_size()); + + let outputs = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(outputs.parsed_size()); + + Ok(ImportTx { + codec_id, + type_id, + tx_header, + source_chain, + inputs, + outputs, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_avax_c_import() { + let input_bytes = "000000000000000000057fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013f407c793a9a31b5f281623e479bcaee760be3da54969b85f44ffc51a67c1c64000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000005f5e1000000000100000000000000013fe51338992d913b6a999693d7c345646ca3bb4c0000000005f5b5223d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000100000009000000017e79e5f2fba29e48d9d329f23e8e27bf20d79714555bb04a175e57136b95b282528654583b1fd568e7f8322962fb31e4174896a50114511d124bf74a92559c1f0048c457c5"; + let binary_data = hex::decode(input_bytes).expect("Failed to decode hex string"); + let mut bytes = Bytes::from(binary_data); + let result = ImportTx::try_from(bytes.clone()).unwrap(); + assert_eq!(result.type_id, TypeId::BaseTx); + assert_eq!(result.codec_id, 0); + assert_eq!(result.inputs.get_len(), 1); + assert_eq!(result.outputs.get_len(), 1); + + assert_eq!(result.source_chain, X_BLOCKCHAIN_ID); + assert_eq!(result.get_total_output_amount(), 99988770); + assert_eq!(result.get_total_input_amount(), 100000000); + } +} diff --git a/rust/apps/avalanche/src/transactions/P_chain/add_permissionless_delegator.rs b/rust/apps/avalanche/src/transactions/P_chain/add_permissionless_delegator.rs new file mode 100644 index 000000000..be3247a57 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/P_chain/add_permissionless_delegator.rs @@ -0,0 +1,124 @@ +use super::{output_owner::OutputOwner, validator::Validator}; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use crate::transactions::base_tx::BaseTx; +use crate::transactions::structs::{ + AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec, ParsedSizeAble, +}; +use crate::transactions::subnet_auth::SubnetAuth; +use crate::transactions::subnet_id::SubnetId; +use crate::transactions::transferable::TransferableOutput; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug)] +pub struct AddPermissLessionDelegatorTx { + base_tx: BaseTx, + validator: Validator, + subnet_id: SubnetId, + stake_out: LengthPrefixedVec, + delegator_owner: OutputOwner, +} + +impl AvaxTxInfo for AddPermissLessionDelegatorTx { + fn get_total_input_amount(&self) -> u64 { + self.base_tx.get_total_input_amount() + } + + fn get_total_output_amount(&self) -> u64 { + self.base_tx.get_total_output_amount() + + self + .stake_out + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_outputs_addresses(&self) -> Vec { + self.base_tx + .get_outputs_addresses() + .into_iter() + .chain(self.stake_out.iter().map(|output| { + AvaxFromToInfo::from( + format!("{} AVAX", output.get_amount() as f64 / NAVAX_TO_AVAX_RATIO), + output.get_addresses(), + ) + })) + .collect() + } + + fn get_method_info(&self) -> Option { + Some(AvaxMethodInfo::from( + "AddPermlessDelegator".to_string(), + self.validator.start_time, + self.validator.end_time, + )) + } + + fn get_network(&self) -> Option { + Some("Avalanche P-Chain".to_string()) + } + + fn get_subnet_id(&self) -> Option { + Some("Primary Subnet".to_string()) + } + + fn get_reward_address(&self) -> Option { + Some( + self.delegator_owner + .addresses + .get(0) + .and_then(|addr| Some(addr.encode())) + .unwrap_or_default(), + ) + } +} + +impl TryFrom for AddPermissLessionDelegatorTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let base_tx = BaseTx::try_from(bytes.clone())?; + bytes.advance(base_tx.parsed_size()); + + let validator = Validator::try_from(bytes.clone())?; + bytes.advance(validator.parsed_size()); + + let subnet_id = SubnetId::try_from(bytes.clone())?; + bytes.advance(SUBNET_ID_LEN); + + let stake_out = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(stake_out.parsed_size()); + + let delegator_owner = OutputOwner::try_from(bytes.clone())?; + bytes.advance(delegator_owner.parsed_size()); + + Ok(AddPermissLessionDelegatorTx { + base_tx, + validator, + subnet_id, + stake_out, + delegator_owner, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_add_permissionless_delegator() { + let input_bytes = "00000000001a000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9a9e0400000000000000000000000100000001e0beb088f94b8224eb5d6f1115561d7173cd6e7f00000002295a7b15e26c6cafda8883afd0f724e0e0b1dad4517148711434cb96fb3c8a61000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b9aca0000000001000000006109bc613691602ca0811312357676416252412a87ded6c56c240baba1afe042000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b9aca000000000100000000000000007072a3df0cd056d9b9ef00c09630bad3027dc312000000006760c3b100000000676215a9000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca0000000000000000000000000100000001e0beb088f94b8224eb5d6f1115561d7173cd6e7f0000000b00000000000000000000000100000001a0f4d4d9a0ea219da5ed5499ad083e1942a0846a000000020000000900000001438c3a393f49bb27791ca830effec456c2642a487ee4ce89300dd2e591fc22ab6b2aa8e08515ca229f2a2f14168700e05a1f96bd61d1fc3ab31e9e71ef9f16bb000000000900000001438c3a393f49bb27791ca830effec456c2642a487ee4ce89300dd2e591fc22ab6b2aa8e08515ca229f2a2f14168700e05a1f96bd61d1fc3ab31e9e71ef9f16bb005c3d047c"; + let mut bytes = Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let result = AddPermissLessionDelegatorTx::try_from(bytes.clone()).unwrap(); + println!("result: {:?}", result); + assert_eq!(result.base_tx.get_blockchain_id(), P_BLOCKCHAIN_ID); + } +} diff --git a/rust/apps/avalanche/src/transactions/P_chain/add_permissionless_validator.rs b/rust/apps/avalanche/src/transactions/P_chain/add_permissionless_validator.rs new file mode 100644 index 000000000..b64c13f1b --- /dev/null +++ b/rust/apps/avalanche/src/transactions/P_chain/add_permissionless_validator.rs @@ -0,0 +1,140 @@ +use super::output_owner::OutputOwner; +use super::signer::Signer; +use super::validator::Validator; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use crate::transactions::base_tx::BaseTx; +use crate::transactions::structs::{ + AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec, ParsedSizeAble, +}; +use crate::transactions::subnet_id::SubnetId; +use crate::transactions::transferable::TransferableOutput; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug)] +pub struct AddPermissLessionValidatorTx { + base_tx: BaseTx, + validator: Validator, + subnet_id: SubnetId, + signer: Signer, + stake_out: LengthPrefixedVec, + validator_owner: OutputOwner, + delegator_owner: OutputOwner, + delegator_share: u32, +} + +impl AvaxTxInfo for AddPermissLessionValidatorTx { + fn get_total_input_amount(&self) -> u64 { + self.base_tx.get_total_input_amount() + } + + fn get_total_output_amount(&self) -> u64 { + self.base_tx.get_total_output_amount() + + self + .stake_out + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_outputs_addresses(&self) -> Vec { + self.base_tx + .get_outputs_addresses() + .into_iter() + .chain(self.stake_out.iter().map(|output| { + AvaxFromToInfo::from( + format!("{} AVAX", output.get_amount() as f64 / NAVAX_TO_AVAX_RATIO), + output.get_addresses(), + ) + })) + .collect() + } + + fn get_method_info(&self) -> Option { + Some(AvaxMethodInfo::from( + "AddPermlessValidator".to_string(), + self.validator.start_time, + self.validator.end_time, + )) + } + + fn get_subnet_id(&self) -> Option { + Some("Primary Subnet".to_string()) + } + + fn get_network(&self) -> Option { + Some("Avalanche P-Chain".to_string()) + } + + fn get_reward_address(&self) -> Option { + Some( + self.delegator_owner + .addresses + .get(0) + .and_then(|addr| Some(addr.encode())) + .unwrap_or_default(), + ) + } +} + +impl TryFrom for AddPermissLessionValidatorTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let base_tx = BaseTx::try_from(bytes.clone())?; + bytes.advance(base_tx.parsed_size()); + + let validator = Validator::try_from(bytes.clone())?; + bytes.advance(validator.parsed_size()); + + let subnet_id = SubnetId::try_from(bytes.clone())?; + bytes.advance(SUBNET_ID_LEN); + + let signer = Signer::try_from(bytes.clone())?; + bytes.advance(PROOF_OF_POSESSION_PUBKEY_LEN + PROOF_OF_POSESSION_SIGNATURE_LEN); + + let stake_out = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(stake_out.parsed_size()); + + let validator_owner = OutputOwner::try_from(bytes.clone())?; + bytes.advance(validator_owner.parsed_size()); + + let delegator_owner = OutputOwner::try_from(bytes.clone())?; + bytes.advance(delegator_owner.parsed_size()); + + let delegator_share = bytes.get_u32(); + + Ok(AddPermissLessionValidatorTx { + base_tx, + validator, + subnet_id, + signer, + stake_out, + validator_owner, + delegator_owner, + delegator_share, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add_permissionless_validator() { + // 23HbZUQ7ijjrDHfqnjKpd4MTMRY18Gc2JxCz79ZBwZAsCLfntb + let input_bytes = "000000000019000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000005e57a370000000000000000000000010000000161cd7d26c72edc631d4114d6eef2c4e069ec9206000000020033b7653ffbf19a2352591e8b6aea8e7c75f38d8e8f5f781cf15aad8425010a000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b9ab9d9000000010000000029ec95b1c9df6cd2598852d78fea7766c1aece1a7b5d24f6cf58adc98107f927000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b8ab46a0000000100000000000000009e843011540909cc62c64dc85a8a1507813777410000000067614160000000006851245000000000713fb30000000000000000000000000000000000000000000000000000000000000000000000001c87c87cef2e92bface778c711c752168a6e858d58ba62463e8bab336f9b05c98c695acf3c7da02b05c667ce5627e63a60ad53ad7da84734084394dedf6b3c4bb6c85922c2b08b09c55508d49d348ad0dcd9678be58197fef69bad862b1d170f4b0c24f189d9d4b6b5103d28b5e8146d305e28d3dcfb3279f089c7152535a24800c7a1a212868a5c76e3559ea9d4a64d9d000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000700000000713fb3000000000000000000000000010000000161cd7d26c72edc631d4114d6eef2c4e069ec92060000000b0000000000000000000000010000000161cd7d26c72edc631d4114d6eef2c4e069ec92060000000b0000000000000000000000010000000161cd7d26c72edc631d4114d6eef2c4e069ec92060000c350000000020000000900000001b52c42f9bfd2c417d2e4c3251f3ea17ce969ae0579011989a57a3e023793d2226103151470494540b3386a10907ec483c6678ae0fd2681b22a57025632321407000000000900000001b52c42f9bfd2c417d2e4c3251f3ea17ce969ae0579011989a57a3e023793d2226103151470494540b3386a10907ec483c6678ae0fd2681b22a5702563232140700f62a80bf"; + let mut bytes = Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let result = AddPermissLessionValidatorTx::try_from(bytes.clone()).unwrap(); + assert_eq!( + "fuji1v8xh6fk89mwxx82pzntwaukyup57eysxj5xrzz".to_string(), + result.get_reward_address().unwrap() + ); + } +} diff --git a/rust/apps/avalanche/src/transactions/P_chain/node_id.rs b/rust/apps/avalanche/src/transactions/P_chain/node_id.rs new file mode 100644 index 000000000..08865aafb --- /dev/null +++ b/rust/apps/avalanche/src/transactions/P_chain/node_id.rs @@ -0,0 +1,30 @@ +use crate::constants::*; +use crate::encode::cb58::Cb58Encodable; +use crate::errors::{AvaxError, Result}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct NodeId { + node_id: [u8; NODE_ID_LEN], +} + +impl Cb58Encodable for NodeId { + fn get_prefix(&self) -> &'static str { + "Node" + } + + fn get_data(&self) -> &[u8] { + &self.node_id + } +} + +impl TryFrom for NodeId { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let mut node_id = [0u8; NODE_ID_LEN]; + bytes.copy_to_slice(&mut node_id); + Ok(NodeId { node_id }) + } +} diff --git a/rust/apps/avalanche/src/transactions/P_chain/output_owner.rs b/rust/apps/avalanche/src/transactions/P_chain/output_owner.rs new file mode 100644 index 000000000..4fe76d339 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/P_chain/output_owner.rs @@ -0,0 +1,40 @@ +use crate::address::Address; +use crate::errors::{AvaxError, Result}; +use crate::transactions::{ + structs::{LengthPrefixedVec, ParsedSizeAble}, + type_id::TypeId, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct OutputOwner { + type_id: TypeId, + locktime: u64, + threshold: u32, + pub addresses: LengthPrefixedVec
, +} + +impl ParsedSizeAble for OutputOwner { + fn parsed_size(&self) -> usize { + 4 + 8 + 4 + self.addresses.parsed_size() + } +} + +impl TryFrom for OutputOwner { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let type_id = TypeId::try_from(bytes.get_u32())?; + let locktime = bytes.get_u64(); + let threshold = bytes.get_u32(); + let addresses = LengthPrefixedVec::
::try_from(bytes.clone())?; + bytes.advance(addresses.parsed_size()); + Ok(OutputOwner { + type_id, + locktime, + threshold, + addresses, + }) + } +} diff --git a/rust/apps/avalanche/src/transactions/P_chain/signer.rs b/rust/apps/avalanche/src/transactions/P_chain/signer.rs new file mode 100644 index 000000000..62d5a291c --- /dev/null +++ b/rust/apps/avalanche/src/transactions/P_chain/signer.rs @@ -0,0 +1,24 @@ +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use alloc::string::ToString; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct Signer { + pubkey: [u8; PROOF_OF_POSESSION_PUBKEY_LEN], + signature: [u8; PROOF_OF_POSESSION_SIGNATURE_LEN], +} + +impl TryFrom for Signer { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let mut pubkey = [0u8; PROOF_OF_POSESSION_PUBKEY_LEN]; + bytes.copy_to_slice(&mut pubkey); + + let mut signature = [0u8; PROOF_OF_POSESSION_SIGNATURE_LEN]; + bytes.copy_to_slice(&mut signature); + Ok(Signer { pubkey, signature }) + } +} diff --git a/rust/apps/avalanche/src/transactions/P_chain/validator.rs b/rust/apps/avalanche/src/transactions/P_chain/validator.rs new file mode 100644 index 000000000..5fd988954 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/P_chain/validator.rs @@ -0,0 +1,59 @@ +use super::node_id::{self, NodeId}; +use crate::constants::*; +use crate::encode::cb58::Cb58Encodable; +use crate::errors::{AvaxError, Result}; +use crate::transactions::base_tx::BaseTx; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct Validator { + pub node_id: NodeId, + pub start_time: i64, + pub end_time: i64, + pub weight: u64, +} + +impl Validator { + pub fn parsed_size(&self) -> usize { + 20 + 8 + 8 + 8 + } +} + +impl TryFrom for Validator { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let node_id = NodeId::try_from(bytes.clone())?; + bytes.advance(NODE_ID_LEN); + Ok(Validator { + node_id, + start_time: bytes.get_i64(), + end_time: bytes.get_i64(), + weight: bytes.get_u64(), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + + #[test] + fn test_validator_parse() { + let input_bytes = "000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000005f5e100000000000000000000000001000000018771921301d5bffff592dae86695a615bdb4a4413d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000017c771d2000000000000000000000001000000010969ea62e2bb30e66d82e82fe267edf6871ea5f7"; + let binary_data = hex::decode(input_bytes).expect("Failed to decode hex string"); + let mut bytes = Bytes::from(binary_data); + let result = Validator::try_from(bytes.clone()).unwrap(); + assert_eq!( + "Node-1118zVrK8tN1ic5wUb5dcsECsf2BtfQ", + result.node_id.to_cb58() + ); + } +} diff --git a/rust/apps/avalanche/src/transactions/asset_id.rs b/rust/apps/avalanche/src/transactions/asset_id.rs new file mode 100644 index 000000000..7a03e292d --- /dev/null +++ b/rust/apps/avalanche/src/transactions/asset_id.rs @@ -0,0 +1,14 @@ +use crate::errors::AvaxError; +use bytes::Bytes; +use core::convert::TryFrom; + +#[derive(Clone, Debug)] +pub struct AssetId(Bytes); + +impl TryFrom for AssetId { + type Error = AvaxError; + + fn try_from(bytes: Bytes) -> Result { + Ok(AssetId(bytes)) + } +} diff --git a/rust/apps/avalanche/src/transactions/base_tx.rs b/rust/apps/avalanche/src/transactions/base_tx.rs new file mode 100644 index 000000000..88c6a0946 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/base_tx.rs @@ -0,0 +1,244 @@ +use super::structs::{AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec}; +use super::transferable::{TransferableInput, TransferableOutput}; +use super::tx_header::Header; +use super::type_id::TypeId; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bitcoin::secp256k1::{Message, Secp256k1}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; +use cryptoxide::hashing::sha256; + +#[derive(Debug, Clone)] +pub struct BaseTx { + codec_id: u16, + pub type_id: TypeId, + pub tx_header: Header, + outputs: LengthPrefixedVec, + inputs: LengthPrefixedVec, + pub memo_len: u32, + pub memo: Vec, + tx_size: usize, +} + +impl BaseTx { + pub fn get_blockchain_id(&self) -> [u8; BLOCKCHAIN_ID_LEN] { + self.tx_header.get_blockchain_id() + } + + pub fn get_inputs_len(&self) -> u32 { + self.inputs.get_len() as u32 + } + pub fn get_outputs_len(&self) -> u32 { + self.outputs.get_len() as u32 + } + + pub fn parsed_size(&self) -> usize { + self.tx_size + } +} + +pub fn avax_base_sign(seed: &[u8], path: String, unsigned_data: Vec) -> Result<[u8; 65]> { + let mut bytes: [u8; 65] = [0; 65]; + + let sig = Secp256k1::new() + .sign_ecdsa_recoverable( + &Message::from_slice(&sha256(unsigned_data.as_slice())).expect("Invalid hash length"), + &keystore::algorithms::secp256k1::get_private_key_by_seed(&seed, &path.to_string()) + .map_err(|_| AvaxError::InvalidHex(format!("get private key error")))?, + ) + .serialize_compact(); + + bytes[..64].copy_from_slice(&sig.1); + bytes[64] = sig.0.to_i32() as u8; + Ok(bytes) +} + +impl AvaxTxInfo for BaseTx { + fn get_total_output_amount(&self) -> u64 { + self.outputs + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_total_input_amount(&self) -> u64 { + self.inputs + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_network(&self) -> Option { + match self.get_blockchain_id() { + X_BLOCKCHAIN_ID | X_TEST_BLOCKCHAIN_ID => Some("Avalanche X-Chain".to_string()), + C_BLOCKCHAIN_ID | C_TEST_BLOCKCHAIN_ID => Some("Avalanche C-Chain".to_string()), + P_BLOCKCHAIN_ID => Some("Avalanche P-Chain".to_string()), + _ => None, + } + } + + fn get_method_info(&self) -> Option { + match self.type_id { + TypeId::BaseTx => Some(AvaxMethodInfo::from_string("Send".to_string())), + _ => Some(AvaxMethodInfo::from_string("Unknown".to_string())), + } + } + + fn get_outputs_addresses(&self) -> Vec { + self.outputs + .iter() + .map(|output| { + AvaxFromToInfo::from( + format!("{} AVAX", output.get_amount() as f64 / NAVAX_TO_AVAX_RATIO), + output.get_addresses(), + ) + }) + .collect() + } +} + +impl TryFrom for BaseTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let initial_len = bytes.len(); + let codec_id = bytes.get_u16(); + let type_id = TypeId::try_from(bytes.get_u32())?; + let tx_header = Header::try_from(bytes.clone())?; + bytes.advance(tx_header.parsed_size()); + + let outputs = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(outputs.parsed_size()); + + let inputs = LengthPrefixedVec::::try_from(bytes.clone())?; + bytes.advance(inputs.parsed_size()); + + let memo_len = bytes.get_u32(); + let memo = bytes.split_to(memo_len as usize).to_vec(); + let tx_size = initial_len - bytes.len(); + + Ok(BaseTx { + codec_id, + type_id, + tx_header, + outputs, + inputs, + memo_len, + memo, + tx_size, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_avax_base_transaction() { + { + // x-chain fuji test case + let input_bytes = "00000000000000000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000bbdfb400000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab3d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000002faf08000000000000000000000000010000000132336f8715dd313a426155cccc15ba27c3033dae0000000163c5b29498bf6a9f1e2a5d20f8eeddaf92096c0ce1c9c2cf6b93fd9a0d12f725000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b7c4580000000010000000000000000"; + let input_bytes = "00000000000000000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000bbdfb400000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab3d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000002faf0800000000000000000000000001000000016498cb45e255f5937b816a59c34a7559a2d437b10000000163c5b29498bf6a9f1e2a5d20f8eeddaf92096c0ce1c9c2cf6b93fd9a0d12f725000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b7c4580000000010000000000000000"; + + // x-chain mainnet test case + // let input_bytes = "00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000221e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000070000000218711a00000000000000000000000001000000017c949a8013befa47e992078764ff735b18a26b5b21e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000700000003cf87a80c00000000000000000000000100000001d5ae9a7d5b31660f08c0aefc1547fb195fbfc85d000000021ddbc2d7d67f14df1e36111bbeef2adae97067c4ceb9db94b73e8883a5a6dd640000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000050000000395e95a000000000100000000885eea33e82eff5130de90152c0ebb98f5cfdc7c7529596fe2473a35654aac830000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000500000002522030ec00000001000000000000000400000000000000020000000900000001a6810c96af6f4e4281031b795f78c37f3395b6d35806179d37b40603d547e2f262969f5363e168c064712607679b01ed13a76daab84addc94a3745b0549a53e5000000000900000001cefe480034588db7b5e0993410b6dbdd2e37e3ec94e75b450dd4c56c32f3b4c61cd9dab507232eb1211a846165336a7d7d975b39612df8d88174e1a92c27535f004a454d1e"; + // let mut bytes = + // Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + // let result = BaseTx::try_from(bytes).unwrap(); + + // assert_eq!(result.get_blockchain_id(), X_BLOCKCHAIN_ID); + // assert_eq!( + // "fuji1dx7fkkmvhw75jz4m67dr0ttv6epmapat8vwcu4", + // result + // .get_outputs_addresses() + // .get(0) + // .unwrap() + // .address + // .get(0) + // .unwrap() + // ); + // assert_eq!(result.get_inputs_len(), 1); + // assert_eq!(result.get_outputs_len(), 2); + } + + // x chain base tx + { + let input_bytes = "00000000000000000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000001312d00000000000000000000000001000000018771921301d5bffff592dae86695a615bdb4a4413d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000004b571c0000000000000000000000001000000010969ea62e2bb30e66d82e82fe267edf6871ea5f7000000019eae34633c2103aaee5253bb3ca3046c2ab4718a109ffcdb77b51d0427be6bb7000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000005f5e100000000010000000000000000"; + let input_bytes = "00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000007000000000089544000000000000000000000000100000001512e7191685398f00663e12197a3d8f6012d9ea300000001db720ad6707915cc4751fb7e5491a3af74e127a1d81817abe9438590c0833fe10000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000050000000000989680000000010000000000000000"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + match BaseTx::try_from(bytes) { + Ok(result) => { + assert_eq!( + result.get_network().unwrap(), + "Avalanche X-Chain".to_string() + ); + assert_eq!( + result.get_blockchain_id(), + [ + 171, 104, 235, 30, 225, 66, 160, 92, 254, 118, 140, 54, 225, 31, 11, + 89, 109, 181, 163, 198, 199, 122, 171, 230, 101, 218, 217, 230, 56, + 202, 148, 247 + ] + ); + assert_eq!(result.get_outputs_len(), 2); + } + Err(e) => match e { + AvaxError::InvalidHex(msg) => { + assert_eq!( + msg, "Unsupported output type found in input bytes.", + "Unexpected error message" + ); + } + _ => {} + }, + } + } + } + + #[test] + fn test_sign_base_tx() { + let seed = hex::decode("b75a396d4965e5352b6c2c83e4a59ad3d243fbd58133ea9fe0631e5c1576808cb7c1a578099f35278ba00fccd2709a2ef73d7e31380898a63a15b5b3f4532010").unwrap(); + + // c chain import 2NqkXZiNn9KkcM8AzRApymjbp556LRWhTeF6icL5BovqdRL39j + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/60'/0'/0/5"), + hex::decode("000000000000000000057fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000000000000000000000000000000000000000000000000000000000000000000001281937d79ec913734e3705754b5a930b2b1899ab47dce7ecb002fca77e16dffb000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000005f5e100000000010000000000000001a9b548da818607e83cbcf6802370691948cbd4160000000005f589443d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa").unwrap()).unwrap()), + "8e8d5d48956752364d1f5deac5dc32e9034cbc0c94d077934fff59dcb2f468ba7448aa4f3a13ae7907254770c4914c078ee90c5ab856eff8c679daeeee92dc7500".to_string()); + + // c chain export 2JrHpYEKKwQuFxDg51uNk8pCAzEbYp3UUiAZeEsFrjEEjZVT1A + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/60'/0'/0/5"), + hex::decode("000000000001000000057fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000000000000000000000000000000000000000000000000000000000000000000001a9b548da818607e83cbcf6802370691948cbd416000000005371d2663d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000000000001000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000053717aaa0000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab").unwrap()).unwrap()), + "0a5dd882621638bad2c76f5c88ccf23d08a17d00b12eafe6e0c0de4a4268edbb0c774e850cc77823edf6afcf51975b8f37e99dc394e5f929d77be2c239a1720500".to_string()); + + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/9000'/0'/0/0"), + hex::decode("000000000022000000050000000000000000000000000000000000000000000000000000000000000000000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000700000000000f42400000000000000000000000010000000132336f8715dd313a426155cccc15ba27c3033dae3d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000004d58ade90000000000000000000000010000000132336f8715dd313a426155cccc15ba27c3033dae00000001410b47f7c7aa13f88122be58735c5e985edc65d86fb0baf0b016359c22253d75000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000004d680464000000010000000000000000").unwrap()).unwrap()), + "a3b62b557e703e59c2e63f0124c8d12b13f50ba695b234ff2d39def50df2f7ad255d161ce088d318f4dad1a8df5321387461e56af72621d4074ff6459cbd09bc00".to_string()); + + // p-chain send + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/9000'/0'/0/5"), + hex::decode("a3b62b557e703e59c2e63f0124c8d12b13f50ba695b234ff2d39def50df2f7ad255d161ce088d318f4dad1a8df5321387461e56af72621d4074ff6459cbd09bc00").unwrap()).unwrap()), + "02baf08b64b33b8bf017cc15a4ddd1c48b9e4231b900b74b2026b4fae9a512885bc8dc2110d5aad04424b91caa0b7263c4aab41ae74f4c783f8e505182b026b300".to_string()); + + // p-chain import + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/9000'/0'/0/5"), + hex::decode("000000000011000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000053716a830000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab00000000000000007fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d500000001ac39ef990eb8b9dec7df7a8c0accd6203fa22ff354442aa5626b54ef2d58f42d000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000053717aaa0000000100000000").unwrap()).unwrap()), + "0d4d8d482ca9e206fd60ffb0000e52fd56693dd7c5a688da4e5fa620b3fcd1155210ce8ef5efeceae3d53657de0cb8ac17a5e35fecb1d6732c48ed30c4b1031501".to_string()); + + // p-chain export + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/9000'/0'/0/5"), + hex::decode("000000000012000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000017d68c240000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab00000001b9376e9a05dac917513e5385e64bf2dfb1cee8a29848a80ada96ebe6d6a04050000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000053716a83000000010000000000000000ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9aca000000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab").unwrap()).unwrap()), + "9efee613e2cdbca7c70d197913a402f2ff93e070e7edf5ca60d5e441579403e33687bf6c2632fc40dc6fdacd07a4d6383fc6eec35f6173251a3afd26176ad9d500".to_string()); + + // x-chain import + assert_eq!(hex::encode(avax_base_sign(&seed, String::from("m/44'/9000'/0'/0/5"), + hex::decode("00000000000300000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b8b87c00000000000000000000000010000000169bc9b5b6cbbbd490abbd79a37ad6cd643be87ab000000000000000000000000000000000000000000000000000000000000000000000000000000000000000143286d1ed254c32dbdd03fdd0935a1324788f5de8f87e8f2d809206472575dba000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b9aca000000000100000000").unwrap()).unwrap()), + "5a5bc0444e1a18bc730694618a0d10ba320796d66b2c6bb9aab0cdda77fc31502ed22ed50454935f8914c2e036f9e38280d08dc36b83c59f2b9ba31e9c16914101".to_string()); + } +} diff --git a/rust/apps/avalanche/src/transactions/export.rs b/rust/apps/avalanche/src/transactions/export.rs new file mode 100644 index 000000000..e18ef2bce --- /dev/null +++ b/rust/apps/avalanche/src/transactions/export.rs @@ -0,0 +1,128 @@ +use super::base_tx::BaseTx; +use super::structs::{AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec}; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use crate::transactions::{transferable::TransferableOutput, type_id::TypeId}; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug)] +pub struct ExportTx { + base_tx: BaseTx, + dest_chain: [u8; BLOCKCHAIN_ID_LEN], + transfer_out: LengthPrefixedVec, +} + +impl AvaxTxInfo for ExportTx { + fn get_total_input_amount(&self) -> u64 { + self.base_tx.get_total_input_amount() + } + + fn get_total_output_amount(&self) -> u64 { + self.base_tx.get_total_output_amount() + + self + .transfer_out + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_outputs_addresses(&self) -> Vec { + self.base_tx + .get_outputs_addresses() + .into_iter() + .chain(self.transfer_out.iter().map(|output| { + AvaxFromToInfo::from( + format!("{} AVAX", output.get_amount() as f64 / NAVAX_TO_AVAX_RATIO), + output.get_addresses(), + ) + })) + .collect() + } + + fn get_method_info(&self) -> Option { + let method = match (self.base_tx.type_id, self.dest_chain) { + (TypeId::XchainExportTx, chain) | (TypeId::PchainExportTx, chain) => { + let source = if matches!(self.base_tx.type_id, TypeId::XchainExportTx) { + "X" + } else { + "P" + }; + let dest = match chain { + X_BLOCKCHAIN_ID | X_TEST_BLOCKCHAIN_ID => "X", + P_BLOCKCHAIN_ID => "P", + C_BLOCKCHAIN_ID => "C", + _ => "Unknown", + }; + format!("{} to {} Export", source, dest) + } + _ => "Unknown".to_string(), + }; + Some(AvaxMethodInfo::from_string(method).with_method_key("Export Tx".to_string())) + } + + fn get_network_key(&self) -> String { + "Export Tx".to_string() + } +} + +impl ExportTx { + fn get_base_tx(&self) -> &BaseTx { + &self.base_tx + } + + fn get_dest_chain(&self) -> [u8; BLOCKCHAIN_ID_LEN] { + self.dest_chain + } + + fn get_transfer_out(&self) -> &LengthPrefixedVec { + &self.transfer_out + } +} + +impl TryFrom for ExportTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let base_tx = BaseTx::try_from(bytes.clone())?; + bytes.advance(base_tx.parsed_size()); + let mut dest_chain = [0u8; BLOCKCHAIN_ID_LEN]; + bytes.copy_to_slice(&mut dest_chain); + + Ok(ExportTx { + base_tx, + dest_chain, + transfer_out: LengthPrefixedVec::::try_from(bytes.clone())?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::transactions::type_id::TypeId; + extern crate std; + use std::println; + + #[test] + fn test_avax_base_export_tx() { + { + // export to C + let input_bytes = "00000000000400000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000057eab6c0000000000000000000000001000000013d200933d192f824fc532519e8ae826990fee64000000001d3f3594499a1e5ce4fcf9aeb139dafb51c1ba18b89c5dc5cefe380a39ca9ba04000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000058928f800000000100000000000000007fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000000098968000000000000000000000000100000001d6178ba78d772ea8a01782488a6d1937a4a5cc2b000000010000000900000001d2c31dc8565f8b70438abd550dc7ecfc8f33e23c7bd2b3954c31572b991eeb8d6c2990148f8a59b33b3481719c759355c6036f1eaf2e6210313cfae6d6cfe87600d44e2649"; + + // x export to p + let input_bytes = "00000000000400000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000005742de00000000000000000000000001000000013d200933d192f824fc532519e8ae826990fee64000000001bb4002f89f58f40649a197e557549cc9a2481f54c62b720e5289d5b8d44e2649000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000057eab6c00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000000989680000000000000000000000001000000013d200933d192f824fc532519e8ae826990fee640000000010000000900000001a0d23a3d847854238fdc20fcd55f280f144dead9b4ac5e7704efcedce789970e1cce1656d5d603bbb9fe268bff5b99b13a6390b0eec8608fed7696372d1a2f58007d974fba"; + + // p chain export to x + let input_bytes = "000000000012000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000700000000001e848000000000000000000000000100000001cc4822028594f008045b77cf8342e8f62db1a1da000000011ebc7d69c8e7d50ce59dac9c0de8c1f22a76274d8454d3427be44d5776335156000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000500000000004c4b400000000100000000000000007fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000700000000001e84800000000000000000000000010000000100739a08d627492cea5abec92998ddc891cd6177000000010000000900000001cda36ebb7b114f0479bfa2eec2ccda8030fd9fd088a1ba19109971c0ffccc9293e21f827502d0210dc7a2a8af11ff7d63f1f858777709e9053b6296287f7abde00e89a6479"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let result = ExportTx::try_from(bytes).unwrap(); + assert_eq!(result.get_dest_chain(), X_BLOCKCHAIN_ID); + } + } +} diff --git a/rust/apps/avalanche/src/transactions/import.rs b/rust/apps/avalanche/src/transactions/import.rs new file mode 100644 index 000000000..19385df9a --- /dev/null +++ b/rust/apps/avalanche/src/transactions/import.rs @@ -0,0 +1,115 @@ +use super::base_tx::BaseTx; +use super::structs::{AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo, LengthPrefixedVec}; +use super::transferable::TransferableInput; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug)] +pub struct ImportTx { + base_tx: BaseTx, + source_chain: [u8; BLOCKCHAIN_ID_LEN], + transfer_in: LengthPrefixedVec, +} + +impl AvaxTxInfo for ImportTx { + fn get_total_input_amount(&self) -> u64 { + self.transfer_in + .iter() + .fold(0, |acc, item| acc + item.get_amount()) + } + + fn get_total_output_amount(&self) -> u64 { + self.base_tx.get_total_output_amount() + } + + fn get_outputs_addresses(&self) -> Vec { + self.base_tx.get_outputs_addresses() + } + + fn get_network_key(&self) -> String { + "Import Tx".to_string() + } + + fn get_method_info(&self) -> Option { + let method = match self.source_chain { + X_BLOCKCHAIN_ID | X_TEST_BLOCKCHAIN_ID => "Sending from X-Chain", + P_BLOCKCHAIN_ID => "Sending from P-Chain", + C_BLOCKCHAIN_ID => "Sending from C-Chain", + _ => "Unknown", + }; + + Some( + AvaxMethodInfo::from_string(method.to_string()) + .with_method_key("Import Tx".to_string()), + ) + } +} + +impl ImportTx { + fn get_base_tx(&self) -> &BaseTx { + &self.base_tx + } +} + +impl TryFrom for ImportTx { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let base_tx = BaseTx::try_from(bytes.clone())?; + bytes.advance(base_tx.parsed_size()); + let mut source_chain = [0u8; BLOCKCHAIN_ID_LEN]; + bytes.copy_to_slice(&mut source_chain); + Ok(ImportTx { + base_tx, + source_chain, + transfer_in: LengthPrefixedVec::::try_from(bytes)?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::transactions::type_id::TypeId; + extern crate std; + use core::result; + use std::println; + + #[test] + fn test_avax_base_import_tx() { + // x chain import tx from p chain + { + let input_bytes = "00000000000300000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b8b87c00000000000000000000000010000000132336f8715dd313a426155cccc15ba27c3033dae00000000000000007fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000011fbfcaa954ca294e4754e75b4c1232cd5e7539a1286027d395a136e57cc6e917000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b9aca000000000100000000000000010000000900000001257ee33547f045cdf50b1811a52f82bd3087e6ca99d16a0461e09d667d0814c01e43d705cedb99728d08341b2550751e79d4c396d9554b99319a2140b5b9677d012e783c9a"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let result = ImportTx::try_from(bytes).unwrap(); + println!("result = {:?}", result); + assert_eq!(result.base_tx.get_blockchain_id(), X_BLOCKCHAIN_ID); + } + + // x-chain import from c-chain + { + let input_bytes = "00000000000300000005ab68eb1ee142a05cfe768c36e11f0b596db5a3c6c77aabe665dad9e638ca94f7000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000005e69ec0000000000000000000000001000000014effb776db45b22c20b4fd8bed9c315a305ecf8600000000000000007fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d50000000178479532682bda3cca3ecd79a19a60ead0b929632fa6652b88ae39f4771b2ace000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000050000000005f5e10000000001000000000000000100000009000000018133ecce7737d6449415f7a532c4314fd005d89fc1d4b1d239fe5275673162f86d06852bb1a0881a5454c7646c586d55f422f695532accc3bd7e4a387c745259011c1b1afd"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let result = ImportTx::try_from(bytes).unwrap(); + assert_eq!(result.source_chain, C_BLOCKCHAIN_ID); + } + + // p-chain import form c-chain xZAN6Dr6snqq3LzAhQsCJWpXntGaMVrQRDqDE1ZdCsCgBkwWS + { + let input_bytes = "000000000011000000050000000000000000000000000000000000000000000000000000000000000000000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000003b9ab9d900000000000000000000000100000001d45b64545e31a4159cab2e9ebd51a56e60fb418300000000000000007fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5000000011d2fe74495f92313aed48d73aef1b540730870a21f44b1b3fbb833994d8f9a79000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000003b9aca0000000001000000000000000100000009000000017eeec21ac8841dec1f0782889a9fd9ae9509888b2f1b38e912ebfe189be371420b1c1d0a0868647fa82824e07a48271658bcf57f68eb5e1d6c31adcc604263e6002ac028d9"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let result = ImportTx::try_from(bytes).unwrap(); + assert_eq!(result.get_fee_amount(), 4135); + assert_eq!(result.get_total_input_amount(), 1_000_000_000); + } + } +} diff --git a/rust/apps/avalanche/src/transactions/inputs/secp256k1_transfer_input.rs b/rust/apps/avalanche/src/transactions/inputs/secp256k1_transfer_input.rs new file mode 100644 index 000000000..9e55bd67a --- /dev/null +++ b/rust/apps/avalanche/src/transactions/inputs/secp256k1_transfer_input.rs @@ -0,0 +1,67 @@ +use crate::errors::{AvaxError, Result}; +use crate::transactions::transferable::InputTrait; +use alloc::string::ToString; +use alloc::vec::Vec; +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use core::{convert::TryFrom, fmt, str::FromStr}; + +#[derive(Debug, Clone)] +pub struct SECP256K1TransferInput { + pub type_id: u32, + pub amount: u64, + pub addresses_len: u32, + pub address_indices: Vec, +} + +impl InputTrait for SECP256K1TransferInput { + fn get_transfer_input_len(&self) -> usize { + 16 + self.addresses_len as usize * 4 + } + + fn get_amount(&self) -> u64 { + self.amount + } +} + +impl TryFrom for SECP256K1TransferInput { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + if bytes.remaining() < 20 { + return Err(AvaxError::InvalidHex("Insufficient data".to_string())); + } + + let type_id = bytes.get_u32(); + let amount = bytes.get_u64(); + let addresses_len = bytes.get_u32(); + let mut addresses_indices = Vec::with_capacity(addresses_len as usize); + for _ in 0..addresses_len { + addresses_indices.push(bytes.get_u32()); + } + + Ok(SECP256K1TransferInput { + type_id, + amount, + addresses_len, + address_indices: addresses_indices, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_secp256k1_transfer_input_try_from() { + let input_bytes = "00000005000000001dbd670d0000000100000000"; + let binary_data = hex::decode(input_bytes).expect("Failed to decode hex string"); + let mut bytes = Bytes::from(binary_data); + let result = SECP256K1TransferInput::try_from(bytes.clone()).unwrap(); + assert_eq!(result.type_id, 5); + assert_eq!(result.amount, 498951949); + assert_eq!(result.addresses_len, 1); + } +} diff --git a/rust/apps/avalanche/src/transactions/mod.rs b/rust/apps/avalanche/src/transactions/mod.rs new file mode 100644 index 000000000..aa37b2fe1 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/mod.rs @@ -0,0 +1,31 @@ +pub mod asset_id; +pub mod base_tx; +pub mod export; +pub mod import; +pub mod structs; +pub mod subnet_auth; +pub mod subnet_id; +pub mod transferable; +pub mod tx_header; +pub mod type_id; + +pub mod inputs { + pub mod secp256k1_transfer_input; +} +pub mod outputs { + pub mod secp256k1_transfer_output; +} + +pub mod C_chain { + pub mod evm_export; + pub mod evm_import; +} + +pub mod P_chain { + pub mod add_permissionless_delegator; + pub mod add_permissionless_validator; + pub mod node_id; + mod output_owner; + mod signer; + mod validator; +} diff --git a/rust/apps/avalanche/src/transactions/outputs/secp256k1_transfer_output.rs b/rust/apps/avalanche/src/transactions/outputs/secp256k1_transfer_output.rs new file mode 100644 index 000000000..896024c10 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/outputs/secp256k1_transfer_output.rs @@ -0,0 +1,86 @@ +use crate::address::Address; +use crate::errors::{AvaxError, Result}; +use crate::transactions::structs::{LengthPrefixedVec, ParsedSizeAble}; +use crate::transactions::transferable::OutputTrait; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use core::{convert::TryFrom, fmt, str::FromStr}; + +#[derive(Debug, Clone)] +pub struct SECP256K1TransferOutput { + pub type_id: u32, + pub amount: u64, + pub locktime: u64, + pub threshold: u32, + addresses: LengthPrefixedVec
, +} + +impl OutputTrait for SECP256K1TransferOutput { + fn get_addresses(&self) -> Vec { + self.addresses.iter().map(|item| item.encode()).collect() + } + + fn get_addresses_len(&self) -> usize { + self.addresses.get_len() + } + + fn get_transfer_output_len(&self) -> usize { + 28 + self.addresses.get_len() * 20 + } + + fn get_amount(&self) -> u64 { + self.amount + } +} + +impl TryFrom for SECP256K1TransferOutput { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + if bytes.remaining() < 28 { + return Err(AvaxError::InvalidHex("Insufficient data".to_string())); + } + + let type_id = bytes.get_u32(); + let amount = bytes.get_u64(); + let locktime = bytes.get_u64(); + let threshold = bytes.get_u32(); + + let addresses = LengthPrefixedVec::
::try_from(bytes.clone())?; + bytes.advance(addresses.parsed_size()); + + Ok(SECP256K1TransferOutput { + type_id, + amount, + locktime, + threshold, + addresses, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_secp256k1_transfer_output() { + let input_bytes = "000000070000000005f5e100000000000000000000000001000000018771921301d5bffff592dae86695a615bdb4a441"; + let result = SECP256K1TransferOutput::try_from(Bytes::from( + hex::decode(input_bytes).expect("Failed to decode hex string"), + )) + .unwrap(); + assert_eq!(result.type_id, 7); + assert_eq!(result.amount, 100000000); + assert_eq!(result.locktime, 0); + assert_eq!(result.threshold, 1); + assert_eq!(result.addresses.get_len(), 1); + assert_eq!( + result.addresses.get(0).unwrap().encode(), + "avax1saceyycp6klllavjmt5xd9dxzk7mffzp6fzwtu" + ); + } +} diff --git a/rust/apps/avalanche/src/transactions/structs.rs b/rust/apps/avalanche/src/transactions/structs.rs new file mode 100644 index 000000000..82ffed1b8 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/structs.rs @@ -0,0 +1,135 @@ +use crate::errors::{AvaxError, Result}; +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; +#[derive(Debug, Clone)] +pub struct LengthPrefixedVec { + len: usize, + items: Vec, +} + +pub trait ParsedSizeAble { + fn parsed_size(&self) -> usize; +} + +impl LengthPrefixedVec { + pub fn get_len(&self) -> usize { + self.len + } + + pub fn get(&self, index: usize) -> Option<&T> { + self.items.get(index) + } + + pub fn parsed_size(&self) -> usize { + 4 + self + .items + .iter() + .fold(0, |acc, item| acc + item.parsed_size()) + } + + pub fn iter(&self) -> impl Iterator { + self.items.iter() + } +} + +impl TryFrom for LengthPrefixedVec +where + T: TryFrom + ParsedSizeAble, +{ + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + if bytes.len() < 4 { + return Err(AvaxError::InvalidHex( + "Insufficient data for LengthPrefixedVec".to_string(), + )); + } + + let len = bytes.get_u32() as usize; + + let mut items = Vec::with_capacity(len); + + for _ in 0..len { + let item = T::try_from(bytes.clone())?; + bytes.advance(item.parsed_size()); + items.push(item); + } + + Ok(LengthPrefixedVec { len, items }) + } +} + +pub trait AvaxTxInfo { + fn get_total_input_amount(&self) -> u64; + fn get_total_output_amount(&self) -> u64; + fn get_fee_amount(&self) -> u64 { + self.get_total_input_amount() - self.get_total_output_amount() + } + fn get_outputs_addresses(&self) -> Vec; + fn get_network(&self) -> Option { + None + } + fn get_network_key(&self) -> String { + "Network".to_string() + } + + fn get_subnet_id(&self) -> Option { + None + } + + fn get_method_info(&self) -> Option { + None + } + + fn get_reward_address(&self) -> Option { + None + } +} + +pub struct AvaxMethodInfo { + pub method_key: String, + pub method: String, + pub start_time: i64, + pub end_time: i64, +} + +impl AvaxMethodInfo { + pub fn from_string(method: String) -> Self { + AvaxMethodInfo { + method_key: "Method".to_string(), + method, + start_time: 0, + end_time: 0, + } + } + + pub fn with_method_key(mut self, method_key: String) -> Self { + self.method_key = method_key; + self + } + + pub fn from(method: String, start_time: i64, end_time: i64) -> Self { + AvaxMethodInfo { + method_key: "Method".to_string(), + method, + start_time, + end_time, + } + } +} + +#[derive(Debug, Clone)] +pub struct AvaxFromToInfo { + pub amount: String, + pub address: Vec, +} + +impl AvaxFromToInfo { + pub fn from(amount: String, address: Vec) -> Self { + AvaxFromToInfo { amount, address } + } +} diff --git a/rust/apps/avalanche/src/transactions/subnet_auth.rs b/rust/apps/avalanche/src/transactions/subnet_auth.rs new file mode 100644 index 000000000..883af8c80 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/subnet_auth.rs @@ -0,0 +1,20 @@ +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use alloc::string::ToString; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct SubnetAuth { + subnet_auth: [u8; SUBNET_AUTH_LEN], +} + +impl TryFrom for SubnetAuth { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let mut subnet_auth = [0u8; SUBNET_AUTH_LEN]; + bytes.copy_to_slice(&mut subnet_auth); + Ok(SubnetAuth { subnet_auth }) + } +} diff --git a/rust/apps/avalanche/src/transactions/subnet_id.rs b/rust/apps/avalanche/src/transactions/subnet_id.rs new file mode 100644 index 000000000..f5a47680e --- /dev/null +++ b/rust/apps/avalanche/src/transactions/subnet_id.rs @@ -0,0 +1,20 @@ +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use alloc::string::ToString; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +#[derive(Debug, Clone)] +pub struct SubnetId { + subnet_id: [u8; SUBNET_ID_LEN], +} + +impl TryFrom for SubnetId { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let mut subnet_id = [0u8; SUBNET_ID_LEN]; + bytes.copy_to_slice(&mut subnet_id); + Ok(SubnetId { subnet_id }) + } +} diff --git a/rust/apps/avalanche/src/transactions/transferable.rs b/rust/apps/avalanche/src/transactions/transferable.rs new file mode 100644 index 000000000..528008518 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/transferable.rs @@ -0,0 +1,271 @@ +use super::asset_id::AssetId; +use super::inputs::secp256k1_transfer_input::SECP256K1TransferInput; +use super::outputs::secp256k1_transfer_output::SECP256K1TransferOutput; +use super::structs::ParsedSizeAble; +use super::type_id::TypeId; +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use bytes::{Buf, Bytes}; +use core::{convert::TryFrom, fmt}; +pub const TX_ID_LEN: usize = 32; +pub type TxId = [u8; TX_ID_LEN]; + +#[derive(Debug, Clone)] +enum OutputType { + SECP256K1(SECP256K1TransferOutput), + //todo other output types +} + +impl OutputTrait for OutputType { + fn get_addresses_len(&self) -> usize { + match self { + OutputType::SECP256K1(output) => output.get_addresses_len(), + } + } + + fn get_addresses(&self) -> Vec { + match self { + OutputType::SECP256K1(output) => output.get_addresses(), + } + } + + fn get_transfer_output_len(&self) -> usize { + match self { + OutputType::SECP256K1(output) => output.get_transfer_output_len(), + } + } + + fn get_amount(&self) -> u64 { + match self { + OutputType::SECP256K1(output) => output.get_amount(), + } + } +} + +impl TryFrom for OutputType { + type Error = AvaxError; + + fn try_from(bytes: Bytes) -> Result { + let mut type_bytes = bytes.clone(); + let type_id = type_bytes.get_u32(); + match TypeId::try_from(type_id)? { + TypeId::CchainExportTx => { + todo!() + } + TypeId::Secp256k1TransferOutput => { + SECP256K1TransferOutput::try_from(bytes).map(OutputType::SECP256K1) + } + TypeId::XchainImportTx => { + todo!() + } + _ => { + return Err(AvaxError::InvalidHex( + "Unsupported output type found in input bytes.".to_string(), + )) + } + } + } +} + +pub trait OutputTrait { + fn get_addresses(&self) -> Vec; + fn get_addresses_len(&self) -> usize; + fn get_transfer_output_len(&self) -> usize; + fn get_amount(&self) -> u64; +} + +#[derive(Debug, Clone)] +pub struct TransferableOutput { + asset_id: AssetId, + pub output: OutputType, +} + +impl TransferableOutput { + pub fn asset_id(&self) -> AssetId { + self.asset_id.clone() + } + + pub fn get_amount(&self) -> u64 { + self.output.get_amount() + } + + pub fn get_addresses(&self) -> Vec { + self.output.get_addresses() + } +} + +impl ParsedSizeAble for TransferableOutput { + fn parsed_size(&self) -> usize { + self.output.get_transfer_output_len() + ASSET_ID_LEN as usize + } +} + +impl TryFrom for TransferableOutput { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let asset_id = AssetId::try_from(bytes.split_to(ASSET_ID_LEN))?; + Ok(TransferableOutput { + asset_id, + output: OutputType::try_from(bytes)?, + }) + } +} + +pub trait InputTrait { + fn get_transfer_input_len(&self) -> usize; + fn get_amount(&self) -> u64; +} + +#[derive(Debug, Clone)] +pub struct TransferableInput { + pub tx_id: TxId, + pub utxo_index: u32, + pub asset_id: AssetId, + pub input: InputType, +} + +impl TransferableInput { + pub fn get_amount(&self) -> u64 { + self.input.get_amount() + } +} + +impl TryFrom for TransferableInput { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let tx_id: [u8; TX_ID_LEN] = bytes.split_to(TX_ID_LEN)[..] + .try_into() + .map_err(|_| AvaxError::InvalidHex(format!("error data to tx_id")))?; + let utxo_index = bytes.get_u32(); + let asset_id = AssetId::try_from(bytes.split_to(ASSET_ID_LEN))?; + Ok(TransferableInput { + tx_id, + utxo_index, + asset_id, + input: InputType::try_from(bytes)?, + }) + } +} + +impl ParsedSizeAble for TransferableInput { + fn parsed_size(&self) -> usize { + self.input.get_transfer_input_len() + TX_ID_LEN as usize + ASSET_ID_LEN as usize + 4 + } +} + +#[derive(Debug, Clone)] +enum InputType { + SECP256K1(SECP256K1TransferInput), + //todo other input types +} + +impl TryFrom for InputType { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + let mut type_bytes = bytes.clone(); + let type_id = type_bytes.get_u32(); + match TypeId::try_from(type_id)? { + TypeId::Secp256k1TransferInput => Ok(InputType::SECP256K1( + SECP256K1TransferInput::try_from(bytes)?, + )), + _ => { + return Err(AvaxError::InvalidHex( + "Unsupported input type found in input bytes.".to_string(), + )) + } + } + } +} + +impl InputTrait for InputType { + fn get_transfer_input_len(&self) -> usize { + match self { + InputType::SECP256K1(input) => input.get_transfer_input_len(), + } + } + + fn get_amount(&self) -> u64 { + match self { + InputType::SECP256K1(input) => input.get_amount(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + extern crate std; + use std::println; + + #[test] + fn test_transferable_output() { + let input_bytes = "000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000005f5e100000000000000000000000001000000018771921301d5bffff592dae86695a615bdb4a4413d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa000000070000000017c771d2000000000000000000000001000000010969ea62e2bb30e66d82e82fe267edf6871ea5f7"; + let binary_data = hex::decode(input_bytes).expect("Failed to decode hex string"); + let mut bytes = Bytes::from(binary_data); + let output_len = bytes.get_u32(); + for _ in 0..output_len { + let result = TransferableOutput::try_from(bytes.clone()).unwrap(); + } + assert!(false); + } + + #[test] + fn test_transferable_intput() { + // secp256k1 transfer intput + { + let input_bytes = "0000000157d5e23e2e1f460b618bba1b55913ff3ceb315f0d1acc41fe6408edc4de9facd000000003d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000001dbd670d0000000100000000"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let input_len = bytes.get_u32(); + for _ in 0..input_len { + let result = TransferableInput::try_from(bytes.clone()); + match result { + Ok(_) => {} + Err(e) => match e { + AvaxError::InvalidHex(msg) => { + assert_eq!( + msg, "Unsupported input type found in input bytes.", + "Unexpected error message" + ); + } + _ => {} + }, + } + } + } + + // x-chain import transferin + { + let input_bytes = "00000001dcf4ca85474e87a743ec8feb54836d2b403b36c7c738c3e2498fdd346dac4774000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000000bebc20000000001000000000000000100000009000000013494447c558e20adc5a9985a7acf9ed5b7ff12011406af213db033bb2b2271504c8224787b352e19db896d3350321487c08dba13c973009aaf682183b0d5f99f00f10c7fe4"; + let mut bytes = + Bytes::from(hex::decode(input_bytes).expect("Failed to decode hex string")); + let input_len = bytes.get_u32(); + for _ in 0..input_len { + let result = TransferableInput::try_from(bytes.clone()); + match result { + Ok(_) => { + println!("{:?}", result); + } + Err(e) => match e { + AvaxError::InvalidHex(msg) => { + assert_eq!( + msg, "Unsupported output type found in input bytes.", + "Unexpected error message" + ); + } + _ => {} + }, + } + } + assert!(false); + } + } +} diff --git a/rust/apps/avalanche/src/transactions/tx_header.rs b/rust/apps/avalanche/src/transactions/tx_header.rs new file mode 100644 index 000000000..8cf7dcb3c --- /dev/null +++ b/rust/apps/avalanche/src/transactions/tx_header.rs @@ -0,0 +1,39 @@ +use crate::constants::*; +use crate::errors::{AvaxError, Result}; +use bytes::{Buf, Bytes}; +use core::convert::TryFrom; + +pub type BlockChainId = [u8; BLOCKCHAIN_ID_LEN]; + +#[derive(Debug, Clone)] +pub struct Header { + pub network_id: u32, + pub blockchain_id: BlockChainId, +} + +impl Header { + pub fn get_network_id(&self) -> u32 { + self.network_id + } + + pub fn get_blockchain_id(&self) -> BlockChainId { + self.blockchain_id.clone() + } + + pub fn parsed_size(&self) -> usize { + 4 + BLOCKCHAIN_ID_LEN + } +} + +impl TryFrom for Header { + type Error = AvaxError; + + fn try_from(mut bytes: Bytes) -> Result { + Ok(Header { + network_id: bytes.get_u32(), + blockchain_id: bytes[..32] + .try_into() + .map_err(|_| AvaxError::InvalidHex(format!("error data to blockchain_id")))?, + }) + } +} diff --git a/rust/apps/avalanche/src/transactions/type_id.rs b/rust/apps/avalanche/src/transactions/type_id.rs new file mode 100644 index 000000000..5f4dd2208 --- /dev/null +++ b/rust/apps/avalanche/src/transactions/type_id.rs @@ -0,0 +1,48 @@ +use crate::errors::{AvaxError, Result}; + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum TypeId { + BaseTx = 0, + CchainExportTx = 0x0000_0001, + XchainImportTx = 0x0000_0003, + XchainExportTx = 0x0000_0004, + Secp256k1TransferInput = 0x0000_0005, + Secp256k1MintOutput = 0x0000_0006, + Secp256k1TransferOutput = 0x0000_0007, + Secp256k1MintOperation = 0x0000_0008, + Secp256k1Credential = 0x00000009, + ValidatorRewardsOwner = 0x0000_000B, + NftMintOperation = 0x0000000C, + NftTransferOperation = 0x0000000D, + PchainImportTx = 0x00000011, + PchainExportTx = 0x00000012, + AddPermissLessionValidator = 0x00000019, + AddPermissLessionDelegator = 0x0000001A, +} + +impl TryFrom for TypeId { + type Error = AvaxError; + + fn try_from(value: u32) -> Result { + match value { + // the code and documentation are not fully consistent. + 0 | 0x0000_0022 => Ok(TypeId::BaseTx), + 0x0000_0001 => Ok(TypeId::CchainExportTx), + 0x0000_0003 => Ok(TypeId::XchainImportTx), + 0x0000_0004 => Ok(TypeId::XchainExportTx), + 0x0000_0005 => Ok(TypeId::Secp256k1TransferInput), + 0x0000_0006 => Ok(TypeId::Secp256k1MintOutput), + 0x0000_0007 => Ok(TypeId::Secp256k1TransferOutput), + 0x0000_0008 => Ok(TypeId::Secp256k1MintOperation), + 0x0000_0009 => Ok(TypeId::Secp256k1Credential), + 0x0000_000B => Ok(TypeId::ValidatorRewardsOwner), + 0x0000_000C => Ok(TypeId::NftMintOperation), + 0x0000_000D => Ok(TypeId::NftTransferOperation), + 0x0000_0011 => Ok(TypeId::PchainImportTx), + 0x0000_0012 => Ok(TypeId::PchainExportTx), + 0x0000_0019 => Ok(TypeId::AddPermissLessionValidator), + 0x0000_001A => Ok(TypeId::AddPermissLessionDelegator), + _ => Err(AvaxError::UnknownTypeId(value)), + } + } +} diff --git a/rust/apps/bitcoin/src/addresses/address.rs b/rust/apps/bitcoin/src/addresses/address.rs index 8f5accf4a..05992c789 100644 --- a/rust/apps/bitcoin/src/addresses/address.rs +++ b/rust/apps/bitcoin/src/addresses/address.rs @@ -45,12 +45,16 @@ impl Address { pubkey_hash: pk.pubkey_hash(), }, }), + _ => Err(BitcoinError::AddressError(format!( + "Invalid network for p2pkh {:?}", + network + ))), } } pub fn p2wpkh(pk: &PublicKey, network: Network) -> Result { match network { - Network::Bitcoin | Network::BitcoinTestnet => { + Network::Bitcoin | Network::BitcoinTestnet | Network::AvaxBtcBridge => { let payload = Payload::Segwit { witness_program: WitnessProgram::p2wpkh( &CompressedPublicKey::try_from(pk.clone()).map_err(|e| { @@ -223,6 +227,15 @@ impl fmt::Display for Address { }; encoding.fmt(fmt) } + Network::AvaxBtcBridge => { + let encoding = BTCAddressEncoding { + payload: &self.payload, + p2pkh_prefix: PUBKEY_ADDRESS_PREFIX_BTC, + p2sh_prefix: SCRIPT_ADDRESS_PREFIX_BTC, + bech32_hrp: "bc", + }; + encoding.fmt(fmt) + } } } } diff --git a/rust/apps/bitcoin/src/lib.rs b/rust/apps/bitcoin/src/lib.rs index 955fc914c..540cc4ad6 100644 --- a/rust/apps/bitcoin/src/lib.rs +++ b/rust/apps/bitcoin/src/lib.rs @@ -412,6 +412,7 @@ mod test { fn test_parse_legacy_btc_native_segwit_tx() { // tube let hex = "1f8b0800000000000003658d3b4b42611c87f5d07070e9e4244e22412188effdb29517caa130921ae5ffbee73d8a17f498e6e553b4340611f8151a823e41d027696b288820ad31f80dcff27b1edf4b6f9f8d2bc3d0e51ae3e1646887fdec97e77b695f2259ab554525ffe6a576cacd4aebf4b059bfa8b5ce6b4797f5667a5771ee8cc3bc4811124566382d2ab05004ee2270cc1029c36c22f7f8f9bdfa40fb3e5979fe6b2678d8cadf275307c2027296600c587050a112064ba4003bc3a5c004bbc882309a6b4d210a29a20c21b329291552428264f6385546c49ad051a5b1a2c2ad554e6bc04681d09668ceb4e31b00bb4ea9b5433106045b4c8120c443a121f37e97ce072725c5f64ae877b8444981a50ac6e2b877153398ebee288e07d3c12ceab439eb4d661da20591cb482a42e56c14dcbc2433897ca250fd7bcdf56241898d05a1f162acd4a2ddebb6afbbedfe14f59642f0100d74a483dba72093fcd7a6b9e7c60f67e05bf594010000"; + let pubkey_str = "zpub6rQ4BxDEb1xJE2RJTyaoZT2NEr7FkGCgeEwkbgpBfPUTd6KmtBstbP9G81dPnJZJVAmbg2ZmfSc55FkrcHcKPvmNkLGmXAFqERtiUCn25LH"; let payload = prepare_payload(hex); let context = prepare_parse_context(pubkey_str); diff --git a/rust/apps/bitcoin/src/network.rs b/rust/apps/bitcoin/src/network.rs index 94f91d551..75b72083c 100644 --- a/rust/apps/bitcoin/src/network.rs +++ b/rust/apps/bitcoin/src/network.rs @@ -14,12 +14,13 @@ pub enum Network { Litecoin, Dash, BitcoinCash, + AvaxBtcBridge, } impl NetworkT for Network { fn get_unit(&self) -> String { match self { - Network::Bitcoin => "BTC", + Network::Bitcoin | Network::AvaxBtcBridge => "BTC", Network::BitcoinTestnet => "tBTC", Network::Litecoin => "LTC", Network::Dash => "DASH", @@ -35,6 +36,7 @@ impl NetworkT for Network { Network::Litecoin => "Litecoin", Network::Dash => "Dash", Network::BitcoinCash => "Bitcoin Cash", + Network::AvaxBtcBridge => "Avalanche BTC", } .to_string() } @@ -48,6 +50,7 @@ impl Network { Network::Litecoin => 2, Network::Dash => 5, Network::BitcoinCash => 145, + Network::AvaxBtcBridge => 60, } .to_string() } @@ -65,6 +68,7 @@ impl FromStr for Network { "BTC_NATIVE_SEGWIT" => Ok(Self::Bitcoin), "BTC_SEGWIT" => Ok(Self::Bitcoin), "BTC_LEGACY" => Ok(Self::Bitcoin), + "AVAX" => Ok(Self::AvaxBtcBridge), _ => Err(BitcoinError::UnsupportedNetwork(format!("{:?}", network))), } } diff --git a/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs b/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs index 2c89133c2..ed95df598 100644 --- a/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs +++ b/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs @@ -64,6 +64,7 @@ impl TxParser for WrappedPsbt { ChildNumber::Hardened { index } => match index { 0 => Ok(Network::Bitcoin), 1 => Ok(Network::BitcoinTestnet), + 60 => Ok(Network::AvaxBtcBridge), _ => Err(BitcoinError::InvalidTransaction(format!( "unknown network {}", index @@ -302,4 +303,50 @@ mod tests { assert_eq!(false, first_output.path.is_some()); assert_eq!(1880, first_output.value); } + + #[test] + fn test_parse_avax_bridge_psbt() { + let psbt_hex = "70736274ff01009a02000000026e1f0958c35751b405afbe041bad35dd3fad44b1dee3f44b12507de02e56e6550300000000ffffffff16dd85d17640b078f2e24c7e2ac7ae982710a00a8a09228cc85d3879a3be59231700000000ffffffff0280bb0000000000001600143cf8355a260de70076823225ff364bb4a24ebd09a411000000000000160014d5a4faf473f4fb0269975c81f4552271b5890f2e000000000001011f76bb000000000000160014d5a4faf473f4fb0269975c81f4552271b5890f2e220603b67b96642e75b5be0e44a1280bec81e11874f6c1acd9dfc32487f4ec1dbdf98e18eb16731f2c0000803c0000800000008000000000000000000001011f2413000000000000160014d5a4faf473f4fb0269975c81f4552271b5890f2e220603b67b96642e75b5be0e44a1280bec81e11874f6c1acd9dfc32487f4ec1dbdf98e18eb16731f2c0000803c000080000000800000000000000000000000"; + let psbt = Psbt::deserialize(&Vec::from_hex(psbt_hex).unwrap()).unwrap(); + let wpsbt = WrappedPsbt { psbt }; + let master_fingerprint = Fingerprint::from_str("eb16731f").unwrap(); + let extended_pubkey = Xpub::from_str("tpubDCjjMQRn1nNw3GW5wM46t3RJtKhF8fDeJenk1tvAMNzZFKi2QjpdjL7oz7r22Zw2McweSH4CwmLQJysqeqzatbiqDbXkeG2QccFRAfzYJhF").unwrap(); + let path = DerivationPath::from_str("m/44'/60'/0'").unwrap(); + let mut keys = BTreeMap::new(); + keys.insert(path, extended_pubkey); + + let result = wpsbt + .parse(Some(&ParseContext { + master_fingerprint, + extended_public_keys: keys, + verify_code: None, + multisig_wallet_config: None, + })) + .unwrap(); + assert_eq!("0.0005289 BTC", result.detail.total_input_amount); + assert_eq!("0.00052516 BTC", result.detail.total_output_amount); + assert_eq!("0.00000374 BTC", result.detail.fee_amount); + + assert_eq!("52516 sats", result.overview.total_output_sat); + assert_eq!("374 sats", result.overview.fee_sat); + + assert_eq!("Avalanche BTC", result.overview.network); + + println!("{:?}", result); + let first_input = result.detail.from.get(0).unwrap(); + assert_eq!( + "bc1q6kj04arn7nasy6vhtjqlg4fzwx6cjrewgdczdt", + first_input.address.clone().unwrap() + ); + assert_eq!(true, first_input.path.is_some()); + assert_eq!(47990, first_input.value); + + let first_output = result.detail.to.get(0).unwrap(); + assert_eq!( + "bc1q8nur2k3xphnsqa5zxgjl7djtkj3ya0gf6rpqa9", + first_output.address + ); + assert_eq!(false, first_output.path.is_some()); + assert_eq!(48000, first_output.value); + } } diff --git a/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs b/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs index 3a5105926..bef01c257 100644 --- a/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs +++ b/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs @@ -586,13 +586,26 @@ impl WrappedPsbt { //call generate address here match derivation_path.index(0) { ChildNumber::Hardened { index: _i } => match _i { - 44 => Ok(Some( - Address::p2pkh( - &bitcoin::PublicKey::new(pubkey.clone()), - network.clone(), - )? - .to_string(), - )), + 44 => match derivation_path.index(1) { + ChildNumber::Hardened { index: _i } => match _i { + 0 => Ok(Some( + Address::p2pkh( + &bitcoin::PublicKey::new(pubkey.clone()), + network.clone(), + )? + .to_string(), + )), + 60 => Ok(Some( + Address::p2wpkh( + &bitcoin::PublicKey::new(pubkey.clone()), + network.clone(), + )? + .to_string(), + )), + _ => Ok(None), + }, + _ => Ok(None), + }, 49 => Ok(Some( Address::p2shp2wpkh( &bitcoin::PublicKey::new(pubkey.clone()), diff --git a/rust/apps/ethereum/src/address.rs b/rust/apps/ethereum/src/address.rs index 356bbab19..3d93aa212 100644 --- a/rust/apps/ethereum/src/address.rs +++ b/rust/apps/ethereum/src/address.rs @@ -52,6 +52,9 @@ pub fn derive_address(hd_path: &str, root_x_pub: &str, root_path: &str) -> Resul mod tests { use super::*; + extern crate std; + use core::str::FromStr; + use std::println; #[test] fn test_generate_address() { @@ -75,4 +78,51 @@ mod tests { let result = derive_address(hd_path, root_x_pub, root_path).unwrap(); assert_eq!("0x31eA4a0976ceE79AF136B1Cfa914e20E87546156", result); } + + fn get_avax_address(public_key: &PublicKey) -> String { + // 初始化 secp256k1 + // let secp = Secp256k1::new(); + + // 从私钥生成公钥 + // let secret_key = SecretKey::from_slice(private_key).unwrap(); + // let public_key = PublicKey::from_secret_key(&secp, &secret_key); + // println!("public_key11 = {:?}", public_key); + + // 序列化公钥并去掉第一个字节 + // let pub_key_bytes = public_key.serialize_uncompressed(); + // let pub_key_without_prefix = &pub_key_bytes[1..]; + + // 计算 Keccak-256 哈希 + // let mut keccak = Keccak::v256(); + // let mut hash = [0u8; 32]; + // keccak.update(pub_key_without_prefix); + // keccak.finalize(&mut hash); + let hash: [u8; 32] = keccak256(&public_key.serialize_uncompressed()[1..]); + println!("hash = {}", hex::encode(hash)); + + // 取最后20字节作为地址 + let address = &hash[12..]; + + let address = [ + 63, 229, 19, 56, 153, 45, 145, 59, 106, 153, 150, 147, 215, 195, 69, 100, 108, 163, + 187, 76, + ]; + + // 转换为16进制并添加0x前缀 + format!("0x{}", hex::encode(&address)) + } + + #[test] + fn test_avax_address() { + let pubkey = PublicKey::from_str( + "02f01fe98afe9db6a160ec7fd57d4de1dcf9848c97307c4e4babc29ee34074a606", + ) + .unwrap(); + println!("{}", pubkey); + let address = get_avax_address(&pubkey); + println!("address = {}", address); + let result = generate_address(pubkey).unwrap(); + println!("{}", result); + assert_eq!(2, 1); + } } diff --git a/rust/apps/ethereum/src/lib.rs b/rust/apps/ethereum/src/lib.rs index 7080f5424..a1003c50d 100644 --- a/rust/apps/ethereum/src/lib.rs +++ b/rust/apps/ethereum/src/lib.rs @@ -238,6 +238,56 @@ mod tests { assert_eq!(result.input, "3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000"); } + #[test] + fn test_parse_native_avax_tx() { + let sign_data = hex::decode("f8b182a86902841dcd6500843b9aca0082a02a945425890298aed601595a70ab815c96711a31bc6580b844a9059cbb000000000000000000000000dba1d159ccdf86fb35e55c0b29a5a41428153ae700000000000000000000000000000000000000000000000000000000000186a0c080a07ce11f564e85f5e35d079856dc0f421e544889ece981de823daa50cdb4d1b0a3a07c137e1026bc3cc5137e081d64ef005d4547a9f940645b900f1d5365268d7c74").unwrap(); + let path = "m/44'/60'/0'/0/0".to_string(); + //to: 3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad + //data: 3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000 + let seed = hex::decode("a5004bb4331238ebd23b3176bf121b773d8ada011b68351f5f59ddd47152a0a95fdef5cebd2da9e243d4e18ea02530bb6068077176bab81964e3ffd366032573").unwrap(); + let pubkey = get_public_key_by_seed(&seed, &path).unwrap(); + let result = parse_fee_market_tx(sign_data, pubkey); + // println!("{:?}", result.un wrap()); + assert!(false); + // assert_eq!(31, result.nonce); + // assert_eq!(1, result.chain_id); + // assert_eq!("0x9858EfFD232B4033E47d90003D41EC34EcaEda94", result.from); + // assert_eq!("0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", result.to); + // assert_eq!("0.01", result.value); + // assert_eq!(None, result.gas_price); + // assert_eq!("15.669800712 Gwei", result.max_fee_per_gas.unwrap()); + // assert_eq!("0.1 Gwei", result.max_priority_fee_per_gas.unwrap()); + // assert_eq!("0.002483224", result.max_fee.unwrap()); + // assert_eq!("0.000015847", result.max_priority.unwrap()); + // assert_eq!("158472", result.gas_limit); + // assert_eq!("0.002483224", result.max_txn_fee); + // assert_eq!(result.input, "3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000"); + } + + #[test] + fn test_parse_avax_tx() { + let sign_data = hex::decode("f90290820eae850702198d00831e8480948186359af5f57fbb40c6b14a588d2a59c0c2988080b9022457ecfd280000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000f8000000000000000400000001000000000001153a00000000000000000000000057d4eaf1091577a6b7d121202afbd2808134f1170000000000000000000000006b25532e1060ce10cc3b0a99e5683b91bfde6982000000000000000000000000000000000000000000000000000000000000000000000000487039debedbf32d260137b0a6f66b90962bec777250910d253781de326a716d0000000000000000000000006b0ecb6102b99e96e04441604e9812d7fe6be99c0000000000000000000000000000000000000000000000000000000387f3be4000000000000000000000000099a0e1a8d7b123678d7aa07bd5845271f68a3683000000000000000000000000000000000000000000000000000000000000000000000000000000822039d546fff3d9a766a9f789ebadd4b63c10a5bd0046672b21ca997c6f09eb22023fe4acedddfb56647a40615f3692c8c9bb222b1b14fcdc3363630dee90b7421ba783a0d2dc6c8e1e8aade40777d231bd8c1eb55145fffa512cc02e5e3ac8afff5eb97278cbac2e9b3c8bf460f25a0819596413c39ed2f95d06c58599a7fdd3061c000000000000000000000000000000000000000000000000000000000000830150f8a0ec5e6e186a6c3c83116cb2df2fb80b36598bfb4e05d6464dc1e2bdcda1ad5c4ba02fb72a377c3be3c70e4b1692f0494f7b667e9154fda71c99d1bb16d574b2da28").unwrap(); + let path = "m/44'/60'/0'/0/0".to_string(); + //to: 3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad + //data: 3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000 + let seed = hex::decode("a5004bb4331238ebd23b3176bf121b773d8ada011b68351f5f59ddd47152a0a95fdef5cebd2da9e243d4e18ea02530bb6068077176bab81964e3ffd366032573").unwrap(); + let pubkey = get_public_key_by_seed(&seed, &path).unwrap(); + let result = parse_fee_market_tx(sign_data, pubkey).unwrap(); + assert_eq!(31, result.nonce); + assert_eq!(1, result.chain_id); + assert_eq!("0x9858EfFD232B4033E47d90003D41EC34EcaEda94", result.from); + assert_eq!("0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", result.to); + assert_eq!("0.01", result.value); + assert_eq!(None, result.gas_price); + assert_eq!("15.669800712 Gwei", result.max_fee_per_gas.unwrap()); + assert_eq!("0.1 Gwei", result.max_priority_fee_per_gas.unwrap()); + assert_eq!("0.002483224", result.max_fee.unwrap()); + assert_eq!("0.000015847", result.max_priority.unwrap()); + assert_eq!("158472", result.gas_limit); + assert_eq!("0.002483224", result.max_txn_fee); + assert_eq!(result.input, "3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000"); + } + #[test] fn test_parse_typed_data() { let sign_data = "7b227479706573223a7b22454950373132446f6d61696e223a5b7b226e616d65223a226e616d65222c2274797065223a22737472696e67227d2c7b226e616d65223a2276657273696f6e222c2274797065223a22737472696e67227d2c7b226e616d65223a22636861696e4964222c2274797065223a2275696e74323536227d2c7b226e616d65223a22766572696679696e67436f6e7472616374222c2274797065223a2261646472657373227d5d2c224f72646572436f6d706f6e656e7473223a5b7b226e616d65223a226f666665726572222c2274797065223a2261646472657373227d2c7b226e616d65223a227a6f6e65222c2274797065223a2261646472657373227d2c7b226e616d65223a226f66666572222c2274797065223a224f666665724974656d5b5d227d2c7b226e616d65223a22737461727454696d65222c2274797065223a2275696e74323536227d2c7b226e616d65223a22656e6454696d65222c2274797065223a2275696e74323536227d2c7b226e616d65223a227a6f6e6548617368222c2274797065223a2262797465733332227d2c7b226e616d65223a2273616c74222c2274797065223a2275696e74323536227d2c7b226e616d65223a22636f6e647569744b6579222c2274797065223a2262797465733332227d2c7b226e616d65223a22636f756e746572222c2274797065223a2275696e74323536227d5d2c224f666665724974656d223a5b7b226e616d65223a22746f6b656e222c2274797065223a2261646472657373227d5d2c22436f6e73696465726174696f6e4974656d223a5b7b226e616d65223a22746f6b656e222c2274797065223a2261646472657373227d2c7b226e616d65223a226964656e7469666965724f724372697465726961222c2274797065223a2275696e74323536227d2c7b226e616d65223a227374617274416d6f756e74222c2274797065223a2275696e74323536227d2c7b226e616d65223a22656e64416d6f756e74222c2274797065223a2275696e74323536227d2c7b226e616d65223a22726563697069656e74222c2274797065223a2261646472657373227d5d7d2c227072696d61727954797065223a224f72646572436f6d706f6e656e7473222c22646f6d61696e223a7b226e616d65223a22536561706f7274222c2276657273696f6e223a22312e31222c22636861696e4964223a2231222c22766572696679696e67436f6e7472616374223a22307830303030303030303030366333383532636245663365303845386446323839313639456445353831227d2c226d657373616765223a7b226f666665726572223a22307866333946643665353161616438384636463463653661423838323732373963666646623932323636222c226f66666572223a5b7b22746f6b656e223a22307841363034303630383930393233466634303065386336663532393034363141383341454441436563227d5d2c22737461727454696d65223a2231363538363435353931222c22656e6454696d65223a2231363539323530333836222c227a6f6e65223a22307830303443303035303030303061443130344437444264303065336165304135433030353630433030222c227a6f6e6548617368223a22307830303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c2273616c74223a223136313738323038383937313336363138222c22636f6e647569744b6579223a22307830303030303037623032323330303931613765643031323330303732663730303661303034643630613864346537316435393962383130343235306630303030222c22746f74616c4f726967696e616c436f6e73696465726174696f6e4974656d73223a2232222c22636f756e746572223a2230227d7d"; diff --git a/rust/apps/monero/src/transfer_key.rs b/rust/apps/monero/src/transfer_key.rs index 3c7970fc3..7df2934f1 100644 --- a/rust/apps/monero/src/transfer_key.rs +++ b/rust/apps/monero/src/transfer_key.rs @@ -1,8 +1,8 @@ use crate::extra::*; use crate::key::*; use crate::transfer::{TxConstructionData, TxDestinationEntry}; -use crate::utils::*; use crate::utils::hash::*; +use crate::utils::*; use alloc::vec; use alloc::vec::Vec; use curve25519_dalek::edwards::EdwardsPoint; @@ -132,11 +132,18 @@ impl TxConstructionData { extra.serialize() } - pub fn shared_key_derivations(&self, keypair: &KeyPair) -> Vec> { + pub fn shared_key_derivations( + &self, + keypair: &KeyPair, + ) -> Vec> { let ecdhs = self.ecdhs(keypair); let mut res = Vec::with_capacity(self.splitted_dsts.len()); for (i, (_, ecdh)) in self.splitted_dsts.iter().zip(ecdhs).enumerate() { - res.push(SharedKeyDerivations::output_derivations(None, Zeroizing::new(ecdh), i)); + res.push(SharedKeyDerivations::output_derivations( + None, + Zeroizing::new(ecdh), + i, + )); } res diff --git a/rust/apps/monero/src/utils/mod.rs b/rust/apps/monero/src/utils/mod.rs index c5217258e..9f6c13102 100644 --- a/rust/apps/monero/src/utils/mod.rs +++ b/rust/apps/monero/src/utils/mod.rs @@ -9,10 +9,10 @@ use alloc::vec; use alloc::vec::Vec; use chacha20::cipher::{generic_array::GenericArray, KeyIvInit, StreamCipher}; use chacha20::{ChaCha20, ChaCha20Legacy}; +use cuprate_cryptonight::cryptonight_hash_v0; use curve25519_dalek::edwards::EdwardsPoint; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::{IsIdentity, MultiscalarMul}; -use cuprate_cryptonight::cryptonight_hash_v0; use monero_serai::transaction::Input; use rand_core::{CryptoRng, RngCore, SeedableRng}; diff --git a/rust/apps/wallets/src/core_wallet.rs b/rust/apps/wallets/src/core_wallet.rs new file mode 100644 index 000000000..f84ff58be --- /dev/null +++ b/rust/apps/wallets/src/core_wallet.rs @@ -0,0 +1,142 @@ +use core::str::FromStr; + +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use { + bitcoin::bip32::{ChildNumber, DerivationPath}, + bitcoin::secp256k1::Secp256k1, + 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 AVAX_STANDARD_PREFIX: &str = "m/44'/60'/0'"; +const AVAX_X_P_PREFIX: &str = "m/44'/9000'/0'"; + +pub fn generate_crypto_multi_accounts( + master_fingerprint: [u8; 4], + extended_public_keys: Vec, + device_type: &str, +) -> URResult { + let mut keys = vec![]; + for ele in extended_public_keys { + match ele.get_path() { + _path if _path.to_string().to_lowercase().eq(AVAX_STANDARD_PREFIX) => { + keys.push(generate_k1_normal_key( + master_fingerprint, + ele.clone(), + Some("account.standard".to_string()), + )?); + } + _path + if _path + .to_string() + .to_lowercase() + .starts_with(AVAX_X_P_PREFIX) => + { + keys.push(generate_k1_normal_key( + master_fingerprint, + ele, + Some("account.x&p".to_string()), + )?); + } + _ => { + return Err(URError::UrEncodeError(format!( + "Unknown key path: {}", + ele.path.to_string() + ))) + } + } + } + + Ok(CryptoMultiAccounts::new( + master_fingerprint, + keys, + Some(device_type.to_string()), + None, + None, + )) +} + +fn generate_k1_normal_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 key_path = CryptoKeyPath::new( + path.into_iter() + .map(|v| match v { + ChildNumber::Normal { index } => get_path_component(Some(index.clone()), false), + ChildNumber::Hardened { index } => get_path_component(Some(index.clone()), true), + }) + .collect::>>()?, + Some(mfp), + Some(xpub.depth as u32), + ); + 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), + None, + 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.clone()), false), + ChildNumber::Hardened { index } => get_path_component(Some(index.clone()), 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, + )) +} diff --git a/rust/apps/wallets/src/lib.rs b/rust/apps/wallets/src/lib.rs index 0d6f1224c..ff9fd1896 100644 --- a/rust/apps/wallets/src/lib.rs +++ b/rust/apps/wallets/src/lib.rs @@ -19,6 +19,7 @@ pub mod bitget; pub mod blue_wallet; mod common; pub mod companion_app; +pub mod core_wallet; pub mod keplr; pub mod keystone; pub mod metamask; diff --git a/rust/commands.sh b/rust/commands.sh index fcc693bb5..c6348a701 100755 --- a/rust/commands.sh +++ b/rust/commands.sh @@ -20,9 +20,11 @@ DIRS=( "apps/utils" "apps/ton" "apps/stellar" + "apps/avalanche" "keystore" "rust_c" "rust_c/src/aptos" + "rust_c/src/avalanche" "rust_c/src/bitcoin" "rust_c/src/cardano" "rust_c/src/common" diff --git a/rust/rust_c/Cargo.toml b/rust/rust_c/Cargo.toml index 8788710e6..a5a2d5693 100644 --- a/rust/rust_c/Cargo.toml +++ b/rust/rust_c/Cargo.toml @@ -53,6 +53,7 @@ app_stellar = { workspace = true, optional = true } app_ton = { workspace = true, optional = true } app_zcash = { workspace = true, optional = true } app_monero = { workspace = true, optional = true } +app_avalanche = { workspace = true, optional = true } [lib] crate-type = ["staticlib"] @@ -79,6 +80,7 @@ tron = ["dep:app_tron"] xrp = ["dep:app_xrp"] zcash = ["dep:app_zcash", "dep:zcash_vendor"] monero = ["dep:app_monero"] +avalanche = ["dep:app_avalanche"] test_cmd = [] debug-memory = ["multi-coins"] @@ -100,6 +102,7 @@ multi-coins = [ "ton", "tron", "xrp", + "avalanche", ] btc-only = ["bitcoin"] diff --git a/rust/rust_c/build.rs b/rust/rust_c/build.rs index 7418951ed..494680fde 100644 --- a/rust/rust_c/build.rs +++ b/rust/rust_c/build.rs @@ -23,6 +23,7 @@ fn main() { #[cfg(feature = "production-cypherpunk")] "production-cypherpunk", ]; + //feature toggle config.after_includes = config.after_includes.map(|mut v| { #[cfg(feature = "cypherpunk")] @@ -60,6 +61,8 @@ fn main() { v.push_str("#define FEATURE_TRON\n"); #[cfg(feature = "xrp")] v.push_str("#define FEATURE_XRP\n"); + #[cfg(feature = "avalanche")] + v.push_str("#define FEATURE_AVAX\n"); #[cfg(feature = "zcash")] v.push_str("#define FEATURE_ZCASH\n"); #[cfg(feature = "monero")] diff --git a/rust/rust_c/cbindgen.toml b/rust/rust_c/cbindgen.toml index c53c6976d..bd8f76bf3 100644 --- a/rust/rust_c/cbindgen.toml +++ b/rust/rust_c/cbindgen.toml @@ -25,6 +25,7 @@ language = "C" "feature = xrp" = "FEATURE_XRP" "feature = zcash" = "FEATURE_ZCASH" "feature = monero" = "FEATURE_MONERO" +"feature = avax" = "FEATURE_AVAX" [parse] extra_bindings = ["rust_c"] diff --git a/rust/rust_c/src/avalanche/address.rs b/rust/rust_c/src/avalanche/address.rs new file mode 100644 index 000000000..e52f1341a --- /dev/null +++ b/rust/rust_c/src/avalanche/address.rs @@ -0,0 +1,25 @@ +use alloc::format; +use app_avalanche; +use cty::c_char; + +use crate::common::structs::{SimpleResponse, TransactionCheckResult, TransactionParseResult}; +use crate::common::types::{PtrString, PtrT}; +use crate::common::utils::{convert_c_char, recover_c_char}; +use app_avalanche::{errors::AvaxError, network::Network}; + +#[no_mangle] +pub extern "C" fn avalanche_get_x_p_address( + hd_path: PtrString, + root_x_pub: PtrString, + root_path: PtrString, +) -> *mut SimpleResponse { + let hd_path = recover_c_char(hd_path); + let root_x_pub = recover_c_char(root_x_pub); + let root_path = recover_c_char(root_path); + let address = + app_avalanche::get_address(Network::AvaxMainNet, &hd_path, &root_x_pub, &root_path); + match address { + Ok(result) => SimpleResponse::success(convert_c_char(result) as *mut c_char).simple_c_ptr(), + Err(e) => SimpleResponse::from(e).simple_c_ptr(), + } +} diff --git a/rust/rust_c/src/avalanche/mod.rs b/rust/rust_c/src/avalanche/mod.rs new file mode 100644 index 000000000..65fe607e5 --- /dev/null +++ b/rust/rust_c/src/avalanche/mod.rs @@ -0,0 +1,211 @@ +#![no_std] +#![feature(vec_into_raw_parts)] + +extern crate alloc; + +pub mod address; +pub mod structs; + +use crate::common::{ + errors::RustCError, + ffi::{CSliceFFI, VecFFI}, + structs::{ExtendedPublicKey, SimpleResponse, TransactionCheckResult, TransactionParseResult}, + types::{Ptr, PtrBytes, PtrString, PtrT, PtrUR}, + ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT, FRAGMENT_UNLIMITED_LENGTH}, + utils::recover_c_char, +}; +use crate::{extract_ptr_with_type, impl_c_ptr}; +use alloc::{ + format, slice, + string::{String, ToString}, + vec::Vec, +}; +use app_avalanche::{ + constants::{ + C_BLOCKCHAIN_ID, C_TEST_BLOCKCHAIN_ID, P_BLOCKCHAIN_ID, X_BLOCKCHAIN_ID, + X_TEST_BLOCKCHAIN_ID, + }, + errors::AvaxError, + get_avax_tx_header, get_avax_tx_type_id, parse_avax_tx, + transactions::{ + base_tx::{avax_base_sign, BaseTx}, + export::ExportTx, + import::ImportTx, + type_id::TypeId, + C_chain::{evm_export::ExportTx as CchainExportTx, evm_import::ImportTx as CchainImportTx}, + P_chain::{ + add_permissionless_delegator::AddPermissLessionDelegatorTx, + add_permissionless_validator::AddPermissLessionValidatorTx, + }, + }, +}; +use bitcoin::ecdsa::Signature; +use structs::DisplayAvaxTx; +use { + hex, + ur_registry::{ + avalanche::{avax_sign_request::AvaxSignRequest, avax_signature::AvaxSignature}, + traits::RegistryItem, + }, +}; + +#[no_mangle] +pub extern "C" fn avax_parse_transaction( + ptr: PtrUR, + mfp: PtrBytes, + mfp_len: u32, + public_keys: PtrT>, +) -> PtrT> { + let avax_sign_request = extract_ptr_with_type!(ptr, AvaxSignRequest); + + match get_avax_tx_type_id(avax_sign_request.get_tx_data()) { + Ok(type_id) => parse_transaction_by_type(type_id, avax_sign_request.get_tx_data()), + Err(_) => { + TransactionParseResult::from(RustCError::InvalidData("Invalid tx type".to_string())) + .c_ptr() + } + } +} + +fn parse_transaction_by_type( + type_id: TypeId, + tx_data: Vec, +) -> PtrT> { + macro_rules! parse_tx { + ($tx_type:ty) => { + parse_avax_tx::<$tx_type>(tx_data) + .map(|parse_data| { + TransactionParseResult::success(DisplayAvaxTx::from(parse_data).c_ptr()).c_ptr() + }) + .unwrap_or_else(|_| { + TransactionParseResult::from(RustCError::InvalidMasterFingerprint).c_ptr() + }) + }; + } + + match type_id { + TypeId::BaseTx => { + let header = get_avax_tx_header(tx_data.clone()).unwrap(); + if header.get_blockchain_id() == C_BLOCKCHAIN_ID + || header.get_blockchain_id() == C_TEST_BLOCKCHAIN_ID + { + return parse_tx!(CchainImportTx); + } else { + return parse_tx!(BaseTx); + } + } + TypeId::PchainExportTx | TypeId::XchainExportTx => parse_tx!(ExportTx), + TypeId::XchainImportTx | TypeId::PchainImportTx => parse_tx!(ImportTx), + TypeId::CchainExportTx => parse_tx!(CchainExportTx), + TypeId::AddPermissLessionValidator => parse_tx!(AddPermissLessionValidatorTx), + TypeId::AddPermissLessionDelegator => parse_tx!(AddPermissLessionDelegatorTx), + _ => TransactionParseResult::from(RustCError::InvalidData(format!( + "{:?} not support", + type_id + ))) + .c_ptr(), + } +} + +#[no_mangle] +fn avax_sign_dynamic( + ptr: PtrUR, + seed: PtrBytes, + seed_len: u32, + fragment_length: usize, +) -> PtrT { + let seed = unsafe { alloc::slice::from_raw_parts(seed, seed_len as usize) }; + build_sign_result(ptr, &seed) + .map(|v: AvaxSignature| v.try_into()) + .map_or_else( + |e| UREncodeResult::from(e).c_ptr(), + |v| { + v.map_or_else( + |e| UREncodeResult::from(e).c_ptr(), + |data| { + UREncodeResult::encode( + data, + AvaxSignature::get_registry_type().get_type(), + fragment_length, + ) + .c_ptr() + }, + ) + }, + ) +} + +fn handle_base_tx_path( + sign_request: &AvaxSignRequest, + wallet_index: u64, +) -> Result { + let blockchain_id = get_avax_tx_header(sign_request.get_tx_data())?.get_blockchain_id(); + + let path = match blockchain_id { + id if id == C_BLOCKCHAIN_ID || id == C_TEST_BLOCKCHAIN_ID => { + format!("m/44'/60'/0'/0/{}", wallet_index) + } + _ => format!("m/44'/9000'/0'/0/{}", wallet_index), + }; + + Ok(path) +} + +fn determine_derivation_path( + type_id: TypeId, + sign_request: &AvaxSignRequest, + wallet_index: u64, +) -> Result { + Ok(match type_id { + TypeId::CchainExportTx => format!("m/44'/60'/0'/0/{}", wallet_index), + TypeId::BaseTx => handle_base_tx_path(sign_request, wallet_index)?, + _ => format!("m/44'/9000'/0'/0/{}", wallet_index), + }) +} + +fn build_sign_result(ptr: PtrUR, seed: &[u8]) -> Result { + let sign_request = extract_ptr_with_type!(ptr, AvaxSignRequest); + + let path = get_avax_tx_type_id(sign_request.get_tx_data()) + .map_err(|_| AvaxError::InvalidInput) + .and_then(|type_id| { + determine_derivation_path(type_id, &sign_request, sign_request.get_wallet_index()) + })?; + + avax_base_sign(seed, path, sign_request.get_tx_data()) + .map(|signature| AvaxSignature::new(sign_request.get_request_id(), signature.to_vec())) +} + +#[no_mangle] +pub extern "C" fn avax_sign(ptr: PtrUR, seed: PtrBytes, seed_len: u32) -> PtrT { + avax_sign_dynamic(ptr, seed, seed_len, FRAGMENT_MAX_LENGTH_DEFAULT.clone()) +} + +#[no_mangle] +pub extern "C" fn avax_sign_unlimited( + ptr: PtrUR, + seed: PtrBytes, + seed_len: u32, +) -> PtrT { + avax_sign_dynamic(ptr, seed, seed_len, FRAGMENT_UNLIMITED_LENGTH.clone()) +} + +#[no_mangle] +pub extern "C" fn avax_check_transaction( + ptr: PtrUR, + mfp: PtrBytes, + mfp_len: u32, +) -> PtrT { + let avax_tx = extract_ptr_with_type!(ptr, AvaxSignRequest); + let mfp: [u8; 4] = match unsafe { slice::from_raw_parts(mfp, mfp_len as usize) }.try_into() { + Ok(mfp) => mfp, + Err(_) => { + return TransactionCheckResult::from(RustCError::InvalidMasterFingerprint).c_ptr(); + } + }; + if avax_tx.get_master_fingerprint() == mfp { + TransactionCheckResult::new().c_ptr() + } else { + TransactionCheckResult::from(RustCError::MasterFingerprintMismatch).c_ptr() + } +} diff --git a/rust/rust_c/src/avalanche/structs.rs b/rust/rust_c/src/avalanche/structs.rs new file mode 100644 index 000000000..34f939d51 --- /dev/null +++ b/rust/rust_c/src/avalanche/structs.rs @@ -0,0 +1,192 @@ +use alloc::boxed::Box; +use alloc::format; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use app_avalanche::constants::NAVAX_TO_AVAX_RATIO; +use core::ptr::null_mut; + +use app_avalanche::transactions::{ + base_tx::BaseTx, + structs::{AvaxFromToInfo, AvaxMethodInfo, AvaxTxInfo}, +}; + +use crate::common::{ + errors::RustCError, + ffi::{CSliceFFI, VecFFI}, + free::{free_ptr_string, Free}, + structs::{ExtendedPublicKey, SimpleResponse, TransactionCheckResult, TransactionParseResult}, + types::{Ptr, PtrBytes, PtrString, PtrT, PtrUR}, + ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT, FRAGMENT_UNLIMITED_LENGTH}, + utils::{convert_c_char, recover_c_char}, +}; + +use crate::{ + check_and_free_ptr, extract_ptr_with_type, free_str_ptr, impl_c_ptr, impl_new_error, + impl_response, impl_simple_c_ptr, impl_simple_new_error, make_free_method, +}; + +#[repr(C)] +pub struct DisplayAvaxTx { + data: *mut DisplayTxAvaxData, +} + +impl_c_ptr!(DisplayAvaxTx); + +#[repr(C)] +pub struct DisplayTxAvaxData { + network: PtrString, + network_key: PtrString, + subnet_id: PtrString, + total_output_amount: PtrString, + total_input_amount: PtrString, + fee_amount: PtrString, + reward_address: PtrString, + method: PtrT, + // from: PtrT>, + to: PtrT>, +} + +impl_c_ptr!(DisplayTxAvaxData); + +#[repr(C)] +pub struct DisplayAvaxFromToInfo { + address: PtrString, + amount: PtrString, + path: PtrString, +} + +impl Free for DisplayAvaxFromToInfo { + fn free(&self) { + unsafe { + free_ptr_string(self.address); + free_ptr_string(self.amount); + free_ptr_string(self.path); + } + } +} + +impl_c_ptr!(DisplayAvaxFromToInfo); + +impl From<&AvaxFromToInfo> for DisplayAvaxFromToInfo { + fn from(value: &AvaxFromToInfo) -> Self { + DisplayAvaxFromToInfo { + address: convert_c_char(value.address.get(0).unwrap().clone()), + amount: convert_c_char(value.amount.clone()), + path: convert_c_char("".to_string()), + } + } +} + +#[repr(C)] +pub struct DisplayAvaxMethodInfo { + method_key: PtrString, + method: PtrString, + start_time: i64, + end_time: i64, +} + +impl_c_ptr!(DisplayAvaxMethodInfo); + +impl Free for DisplayAvaxMethodInfo { + fn free(&self) { + unsafe { + free_ptr_string(self.method_key); + free_ptr_string(self.method); + } + } +} + +impl From for DisplayAvaxMethodInfo { + fn from(value: AvaxMethodInfo) -> Self { + DisplayAvaxMethodInfo { + method_key: convert_c_char(value.method_key), + method: convert_c_char(value.method), + start_time: value.start_time, + end_time: value.end_time, + } + } +} + +impl From for DisplayAvaxTx { + fn from(value: T) -> Self { + DisplayAvaxTx { + data: DisplayTxAvaxData::from(value).c_ptr(), + } + } +} + +impl From for DisplayTxAvaxData { + fn from(value: T) -> Self { + DisplayTxAvaxData { + total_input_amount: convert_c_char(format!( + "{} AVAX", + value.get_total_input_amount() as f64 / NAVAX_TO_AVAX_RATIO + )), + total_output_amount: convert_c_char(format!( + "{} AVAX", + value.get_total_output_amount() as f64 / NAVAX_TO_AVAX_RATIO + )), + fee_amount: convert_c_char(format!( + "{} AVAX", + value.get_fee_amount() as f64 / NAVAX_TO_AVAX_RATIO + )), + to: VecFFI::from( + value + .get_outputs_addresses() + .iter() + .map(|v| DisplayAvaxFromToInfo::from(v)) + .collect::>(), + ) + .c_ptr(), + network_key: convert_c_char(value.get_network_key()), + subnet_id: value + .get_subnet_id() + .map_or(core::ptr::null_mut(), convert_c_char), + network: value + .get_network() + .map_or(core::ptr::null_mut(), convert_c_char), + reward_address: value + .get_reward_address() + .map_or(core::ptr::null_mut(), convert_c_char), + method: value.get_method_info().map_or(core::ptr::null_mut(), |v| { + DisplayAvaxMethodInfo::from(v).c_ptr() + }), + } + } +} + +impl Free for DisplayTxAvaxData { + fn free(&self) { + unsafe { + // let x = Box::from_raw(self.from); + // let ve = Vec::from_raw_parts(x.data, x.size, x.cap); + // ve.iter().for_each(|v| { + // v.free(); + // }); + let x = Box::from_raw(self.to); + let ve = Vec::from_raw_parts(x.data, x.size, x.cap); + ve.iter().for_each(|v| { + v.free(); + }); + + free_ptr_string(self.network); + free_ptr_string(self.network_key); + free_ptr_string(self.subnet_id); + free_ptr_string(self.total_output_amount); + free_ptr_string(self.total_input_amount); + free_ptr_string(self.fee_amount); + free_ptr_string(self.reward_address); + Box::from_raw(self.method); + } + } +} + +impl Free for DisplayAvaxTx { + fn free(&self) { + unsafe { + Box::from_raw(self.data).free(); + } + } +} + +make_free_method!(TransactionParseResult); diff --git a/rust/rust_c/src/common/errors.rs b/rust/rust_c/src/common/errors.rs index 73654a43a..f2bed0e39 100644 --- a/rust/rust_c/src/common/errors.rs +++ b/rust/rust_c/src/common/errors.rs @@ -8,6 +8,8 @@ use ur_registry::error::URError; use app_aptos::errors::AptosError; #[cfg(feature = "arweave")] use app_arweave::errors::ArweaveError; +#[cfg(feature = "avalanche")] +use app_avalanche::errors::AvaxError; #[cfg(feature = "bitcoin")] use app_bitcoin::errors::BitcoinError; #[cfg(feature = "cardano")] @@ -210,6 +212,24 @@ pub enum ErrorCodes { // Monero MoneroUnknownError = 1600, + + //Avax + AvaxInvalidInput = 1700, + AvaxInvalidOutput, + AvaxInvalidTransaction, + AvaxSignFailure, + AvaxAddressError, + AvaxUnsupportedTransaction, + AvaxGetKeyError, + AvaxUnsupportedNetwork, + AvaxTransactionConsensusEncodeError, + AvaxInvalidHex, + AvaxBech32DecodeError, + AvaxKeystoreError, + AvaxDerivePublicKeyError, + AvaxUnknownTypeId, + AvaxInvalidHDPath, + AvaxBech32Error, } impl ErrorCodes { @@ -486,6 +506,32 @@ impl From<&TonError> for ErrorCodes { } } +#[cfg(feature = "avalanche")] +impl From<&AvaxError> for ErrorCodes { + fn from(value: &AvaxError) -> Self { + match value { + AvaxError::InvalidInput => Self::AvaxInvalidInput, + AvaxError::InvalidOutput => Self::AvaxInvalidOutput, + AvaxError::InvalidTransaction(_) => Self::AvaxInvalidTransaction, + AvaxError::SignFailure(_) => Self::AvaxSignFailure, + AvaxError::AddressError(_) => Self::AvaxAddressError, + AvaxError::GetKeyError(_) => Self::AvaxGetKeyError, + AvaxError::UnsupportedTransaction(_) => Self::AvaxUnsupportedTransaction, + AvaxError::UnsupportedNetwork(_) => Self::AvaxUnsupportedNetwork, + AvaxError::TransactionConsensusEncodeError(_) => { + Self::AvaxTransactionConsensusEncodeError + } + AvaxError::InvalidHex(_) => Self::AvaxInvalidHex, + AvaxError::Bech32DecodeError(_) => Self::AvaxBech32DecodeError, + AvaxError::KeystoreError(_) => Self::AvaxAddressError, + AvaxError::DerivePublicKeyError(_) => Self::AvaxDerivePublicKeyError, + AvaxError::UnknownTypeId(_) => Self::AvaxUnknownTypeId, + AvaxError::InvalidHDPath(_) => Self::AvaxInvalidHDPath, + AvaxError::Bech32Error => Self::AvaxBech32Error, + } + } +} + #[cfg(feature = "zcash")] impl From<&ZcashError> for ErrorCodes { fn from(value: &ZcashError) -> Self { diff --git a/rust/rust_c/src/common/macros.rs b/rust/rust_c/src/common/macros.rs index 7e4ba57d4..f882639f1 100644 --- a/rust/rust_c/src/common/macros.rs +++ b/rust/rust_c/src/common/macros.rs @@ -118,6 +118,12 @@ macro_rules! impl_new_error { Self::error(ErrorCodes::from(&value), value.to_string()) } } + #[cfg(feature = "avalanche")] + impl From for $name { + fn from(value: app_avalanche::errors::AvaxError) -> Self { + Self::error(ErrorCodes::from(&value), value.to_string()) + } + } #[cfg(feature = "solana")] impl From for $name { fn from(value: app_solana::errors::SolanaError) -> Self { @@ -362,6 +368,12 @@ macro_rules! impl_simple_new_error { Self::error(ErrorCodes::from(&value), value.to_string()) } } + #[cfg(feature = "avalanche")] + impl<$t> From for $name<$t> { + fn from(value: app_avalanche::errors::AvaxError) -> Self { + Self::error(ErrorCodes::from(&value), value.to_string()) + } + } #[cfg(feature = "solana")] impl<$t> From for $name<$t> { fn from(value: app_solana::errors::SolanaError) -> Self { diff --git a/rust/rust_c/src/common/ur.rs b/rust/rust_c/src/common/ur.rs index 7ddce91f0..fd7621b58 100644 --- a/rust/rust_c/src/common/ur.rs +++ b/rust/rust_c/src/common/ur.rs @@ -22,6 +22,8 @@ use ur_registry::traits::RegistryItem; use ur_registry::aptos::aptos_sign_request::AptosSignRequest; #[cfg(feature = "arweave")] use ur_registry::arweave::arweave_sign_request::ArweaveSignRequest; +#[cfg(feature = "avalanche")] +use ur_registry::avalanche::avax_sign_request::AvaxSignRequest; #[cfg(feature = "bitcoin")] use ur_registry::bitcoin::btc_sign_request::BtcSignRequest; #[cfg(feature = "cardano")] @@ -259,6 +261,8 @@ pub enum ViewType { XmrOutput, #[cfg(feature = "monero")] XmrTxUnsigned, + #[cfg(feature = "avalanche")] + AvaxTx, WebAuthResult, #[cfg(not(feature = "btc-only"))] KeyDerivationRequest, @@ -317,6 +321,8 @@ pub enum QRCodeType { StellarSignRequest, #[cfg(feature = "ton")] TonSignRequest, + #[cfg(feature = "avalanche")] + AvaxSignRequest, #[cfg(feature = "zcash")] ZcashPczt, #[cfg(feature = "monero")] @@ -377,6 +383,8 @@ impl QRCodeType { InnerURType::XmrTxUnsigned(_) => Ok(QRCodeType::XmrTxUnsignedRequest), #[cfg(feature = "monero")] InnerURType::XmrOutput(_) => Ok(QRCodeType::XmrOutputSignRequest), + #[cfg(feature = "avalanche")] + InnerURType::AvaxSignRequest(_) => Ok(QRCodeType::AvaxSignRequest), #[cfg(not(feature = "btc-only"))] InnerURType::QRHardwareCall(_) => Ok(QRCodeType::QRHardwareCall), _ => Err(URError::NotSupportURTypeError(value.get_type_str())), @@ -538,6 +546,11 @@ fn free_ur(ur_type: &QRCodeType, data: PtrUR) { QRCodeType::XmrTxUnsignedRequest => { free_ptr_with_type!(data, XmrTxUnsigned); } + #[cfg(feature = "avalanche")] + // todo + QRCodeType::AvaxSignRequest => { + free_ptr_with_type!(data, AvaxSignRequest); + } #[cfg(not(feature = "btc-only"))] QRCodeType::QRHardwareCall => { free_ptr_with_type!(data, QRHardwareCall); @@ -703,6 +716,8 @@ pub fn decode_ur(ur: String) -> URParseResult { QRCodeType::XmrOutputSignRequest => _decode_ur::(ur, ur_type), #[cfg(feature = "monero")] QRCodeType::XmrTxUnsignedRequest => _decode_ur::(ur, ur_type), + #[cfg(feature = "avalanche")] + QRCodeType::AvaxSignRequest => _decode_ur::(ur, ur_type), #[cfg(not(feature = "btc-only"))] QRCodeType::QRHardwareCall => _decode_ur::(ur, ur_type), QRCodeType::URTypeUnKnown | QRCodeType::SeedSignerMessage => URParseResult::from( @@ -799,6 +814,8 @@ fn receive_ur(ur: String, decoder: &mut KeystoneURDecoder) -> URParseMultiResult QRCodeType::XmrOutputSignRequest => _receive_ur::(ur, ur_type, decoder), #[cfg(feature = "monero")] QRCodeType::XmrTxUnsignedRequest => _receive_ur::(ur, ur_type, decoder), + #[cfg(feature = "avalanche")] + QRCodeType::AvaxSignRequest => _receive_ur::(ur, ur_type, decoder), QRCodeType::URTypeUnKnown | QRCodeType::SeedSignerMessage => URParseMultiResult::from( URError::NotSupportURTypeError("UnKnown ur type".to_string()), ), diff --git a/rust/rust_c/src/common/ur_ext.rs b/rust/rust_c/src/common/ur_ext.rs index ff0099624..99cf4f9a8 100644 --- a/rust/rust_c/src/common/ur_ext.rs +++ b/rust/rust_c/src/common/ur_ext.rs @@ -8,6 +8,8 @@ use serde_json::{from_slice, from_value, Value}; use ur_registry::aptos::aptos_sign_request::AptosSignRequest; #[cfg(feature = "arweave")] use ur_registry::arweave::arweave_sign_request::{ArweaveSignRequest, SignType}; +#[cfg(feature = "avalanche")] +use ur_registry::avalanche::avax_sign_request::AvaxSignRequest; #[cfg(feature = "bitcoin")] use ur_registry::bitcoin::btc_sign_request::BtcSignRequest; use ur_registry::bytes::Bytes; @@ -176,6 +178,13 @@ impl InferViewType for ZcashPczt { } } +#[cfg(feature = "avalanche")] +impl InferViewType for AvaxSignRequest { + fn infer(&self) -> Result { + Ok(ViewType::AvaxTx) + } +} + fn get_view_type_from_keystone(bytes: Vec) -> Result { let unzip_data = unzip(bytes) .map_err(|_| URError::NotSupportURTypeError("bytes can not unzip".to_string()))?; diff --git a/rust/rust_c/src/kt_allocator b/rust/rust_c/src/kt_allocator new file mode 100644 index 000000000..705188d24 --- /dev/null +++ b/rust/rust_c/src/kt_allocator @@ -0,0 +1,3 @@ +indent_style="Block" +reorder_imports=true +binop_separator="Front" \ No newline at end of file diff --git a/rust/rust_c/src/lib.rs b/rust/rust_c/src/lib.rs index 28b519b69..0571796f1 100644 --- a/rust/rust_c/src/lib.rs +++ b/rust/rust_c/src/lib.rs @@ -28,6 +28,9 @@ mod aptos; #[cfg(feature = "arweave")] #[allow(unused)] mod arweave; +#[cfg(feature = "avalanche")] +#[allow(unused)] +mod avalanche; #[cfg(feature = "bitcoin")] #[allow(unused)] mod bitcoin; diff --git a/rust/rust_c/src/wallet/mod.rs b/rust/rust_c/src/wallet/mod.rs index 7db6702c2..1d604e2b2 100644 --- a/rust/rust_c/src/wallet/mod.rs +++ b/rust/rust_c/src/wallet/mod.rs @@ -1,10 +1,10 @@ pub mod btc_only_wallet; pub use btc_only_wallet::*; -mod structs; #[cfg(feature = "cypherpunk")] pub mod cypherpunk_wallet; #[cfg(feature = "multi-coins")] pub mod multi_coins_wallet; +mod structs; use alloc::format; use alloc::string::String; diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/core_wallet.rs b/rust/rust_c/src/wallet/multi_coins_wallet/core_wallet.rs new file mode 100644 index 000000000..c7f28e155 --- /dev/null +++ b/rust/rust_c/src/wallet/multi_coins_wallet/core_wallet.rs @@ -0,0 +1,58 @@ +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_core_wallet_ur( + master_fingerprint: PtrBytes, + master_fingerprint_length: u32, + public_keys: Ptr>, + device_type: 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 device_type = recover_c_char(device_type); + match normalize_xpub(keys) { + Ok(_keys) => { + match app_wallets::core_wallet::generate_crypto_multi_accounts( + mfp, + _keys, + &device_type, + ) { + Ok(data) => match data.try_into() { + Ok(_v) => UREncodeResult::encode( + _v, + CryptoMultiAccounts::get_registry_type().get_type(), + FRAGMENT_MAX_LENGTH_DEFAULT.clone(), + ) + .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 3bfd502cd..a91bacd0b 100644 --- a/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs +++ b/rust/rust_c/src/wallet/multi_coins_wallet/mod.rs @@ -14,6 +14,7 @@ mod utils; pub mod xbull; pub mod xrp_toolkit; +pub mod core_wallet; pub mod thor_wallet; use alloc::format; diff --git a/rust/rust_c/src/wallet/multi_coins_wallet/structs.rs b/rust/rust_c/src/wallet/multi_coins_wallet/structs.rs index 9194eafdc..e0fd894a8 100644 --- a/rust/rust_c/src/wallet/multi_coins_wallet/structs.rs +++ b/rust/rust_c/src/wallet/multi_coins_wallet/structs.rs @@ -37,4 +37,4 @@ impl From<&KeplrAccount> for SyncInfo { xpub: recover_c_char(value.xpub), } } -} \ No newline at end of file +} diff --git a/src/crypto/account_public_info.c b/src/crypto/account_public_info.c index c4e3df08f..b294ad97c 100644 --- a/src/crypto/account_public_info.c +++ b/src/crypto/account_public_info.c @@ -109,6 +109,8 @@ static const ChainItem_t g_chainTable[] = { {XPUB_TYPE_TERRA, SECP256K1, "terra", "M/44'/330'/0'" }, {XPUB_TYPE_XRP, SECP256K1, "xrp", "M/44'/144'/0'" }, {XPUB_TYPE_THOR, SECP256K1, "thor", "M/44'/931'/0'" }, + {XPUB_TYPE_AVAX_BIP44_STANDARD, SECP256K1, "avax_c", "M/44'/60'/0'" }, + {XPUB_TYPE_AVAX_X_P, SECP256K1, "avax_x_p", "M/44'/9000'/0'" }, {XPUB_TYPE_SOL_BIP44_0, ED25519, "sol_bip44_0", "M/44'/501'/0'" }, {XPUB_TYPE_SOL_BIP44_1, ED25519, "sol_bip44_1", "M/44'/501'/1'" }, {XPUB_TYPE_SOL_BIP44_2, ED25519, "sol_bip44_2", "M/44'/501'/2'" }, diff --git a/src/crypto/account_public_info.h b/src/crypto/account_public_info.h index 1e6e78496..9faff9ef8 100644 --- a/src/crypto/account_public_info.h +++ b/src/crypto/account_public_info.h @@ -44,6 +44,8 @@ typedef enum { XPUB_TYPE_TERRA, XPUB_TYPE_XRP, XPUB_TYPE_THOR, + XPUB_TYPE_AVAX_BIP44_STANDARD, + XPUB_TYPE_AVAX_X_P, XPUB_TYPE_SOL_BIP44_0, XPUB_TYPE_SOL_BIP44_1, XPUB_TYPE_SOL_BIP44_2, diff --git a/src/driver/drv_rtc.c b/src/driver/drv_rtc.c index 947050ecc..b917b9294 100644 --- a/src/driver/drv_rtc.c +++ b/src/driver/drv_rtc.c @@ -7,9 +7,7 @@ #include "time.h" #define USE_EXTERN_32K -static void stampTimeToRealTime(uint32_t stampTime, Times *standardTime); - -static char g_currentTimeBuf[BUFFER_SIZE_32]; +static void stampTimeToRealTime(int64_t stampTime, Times *standardTime); void SetCurrentStampTime(uint32_t stampTime) { @@ -27,7 +25,7 @@ uint32_t GetRtcCounter(void) return RTC_GetCounter(); } -static void stampTimeToRealTime(uint32_t stampTime, Times *standardTime) +static void stampTimeToRealTime(int64_t stampTime, Times *standardTime) { time_t tick = (time_t)stampTime; struct tm tm; @@ -43,16 +41,13 @@ static void stampTimeToRealTime(uint32_t stampTime, Times *standardTime) standardTime->Second = atoi(tempBuf + 17); } -const char *GetCurrentTime(void) +void StampTimeToUtcTime(int64_t timeStamp, char *utcTime, int maxLen) { Times standardTime; - uint32_t stampTime = RTC_GetCounter() + RTC_GetRefRegister(); - stampTimeToRealTime(stampTime, &standardTime); + stampTimeToRealTime(timeStamp, &standardTime); - snprintf_s(g_currentTimeBuf, BUFFER_SIZE_32, "%04d-%02d-%02d %02d:%02d:%02d", standardTime.Year, standardTime.Mon, standardTime.Day, + snprintf_s(utcTime, maxLen, "%04d-%02d-%02d %02d:%02d:%02d UTC", standardTime.Year, standardTime.Mon, standardTime.Day, (standardTime.Hour + 8) > 24 ? standardTime.Hour + 8 - 24 : standardTime.Hour + 8, standardTime.Min, standardTime.Second); - - return g_currentTimeBuf; } static void RtcNvicConfiguration(void) diff --git a/src/driver/drv_rtc.h b/src/driver/drv_rtc.h index 16d8b2104..877e322cc 100644 --- a/src/driver/drv_rtc.h +++ b/src/driver/drv_rtc.h @@ -10,11 +10,11 @@ typedef struct times { int Second; } Times; -const char *GetCurrentTime(void); void SetCurrentStampTime(uint32_t stampTime); uint32_t GetRtcCounter(void); uint32_t GetCurrentStampTime(void); void RtcInit(void); +void StampTimeToUtcTime(int64_t timeStamp, char *utcTime, int maxLen); #endif /* _DRV_RTC_H */ diff --git a/src/main.c b/src/main.c index 5289f043e..2dcd24539 100644 --- a/src/main.c +++ b/src/main.c @@ -116,7 +116,8 @@ int _write(int fd, char *pBuffer, int size) for (int i = 0; i < size; i++) { while (!UART_IsTXEmpty(UART0)); #ifdef BUILD_PRODUCTION - UART_SendData(UART0, '-'); + // UART_SendData(UART0, '-'); + UART_SendData(UART0, (uint8_t) pBuffer[i]); #else UART_SendData(UART0, (uint8_t) pBuffer[i]); #endif diff --git a/src/ui/gui_analyze/gui_resolve_ur.c b/src/ui/gui_analyze/gui_resolve_ur.c index fffed5d6a..234abb6db 100644 --- a/src/ui/gui_analyze/gui_resolve_ur.c +++ b/src/ui/gui_analyze/gui_resolve_ur.c @@ -8,6 +8,7 @@ #include "user_delay.h" #include "gui_api.h" #include "gui_views.h" +#include "gui_chain.h" #ifdef BTC_ONLY #include "gui_import_multisig_wallet_info_widgets.h" @@ -51,14 +52,19 @@ static SetChainData_t g_chainViewArray[] = { {REMAPVIEW_STELLAR_HASH, (SetChainDataFunc)GuiSetStellarUrData}, {REMAPVIEW_TON, (SetChainDataFunc)GuiSetTonUrData}, {REMAPVIEW_TON_SIGNPROOF, (SetChainDataFunc)GuiSetTonUrData}, + {REMAPVIEW_AVAX, (SetChainDataFunc)GuiSetAvaxUrData}, #endif }; void HandleDefaultViewType(URParseResult *urResult, URParseMultiResult *urMultiResult, UrViewType_t urViewType, bool is_multi) { + printf("%s %d.\n", __func__,__LINE__); GuiRemapViewType viewType = ViewTypeReMap(urViewType.viewType); + printf("%s %d.\n", __func__,__LINE__); + printf("viewType=%d\r\n", viewType); for (int i = 0; i < NUMBER_OF_ARRAYS(g_chainViewArray); i++) { if (g_chainViewArray[i].chain == viewType) { + printf("%s %d.\n", __func__,__LINE__); printf("g_chainViewArray[i].type=%d\r\n", g_chainViewArray[i].chain); g_chainViewArray[viewType].func(urResult, urMultiResult, is_multi); break; @@ -102,10 +108,8 @@ void handleURResult(URParseResult *urResult, URParseMultiResult *urMultiResult, || urViewType.viewType == MultisigCryptoImportXpub #endif || viewType != REMAPVIEW_BUTT) { -#ifndef COMPILE_SIMULATOR StopQrDecode(); UserDelay(500); -#endif GuiApiEmitSignal(SIG_QRCODE_VIEW_SCAN_PASS, &urViewType, sizeof(urViewType)); } else { printf("unhandled viewType=%d\r\n", urViewType.viewType); diff --git a/src/ui/gui_analyze/multi/web3/gui_general_analyze.c b/src/ui/gui_analyze/multi/web3/gui_general_analyze.c index 51168c9cf..c6f930daf 100644 --- a/src/ui/gui_analyze/multi/web3/gui_general_analyze.c +++ b/src/ui/gui_analyze/multi/web3/gui_general_analyze.c @@ -96,6 +96,10 @@ GetCustomContainerFunc GetOtherChainCustomFunc(char *funcName) return GuiShowAdaSignTxHashOverview; } else if (!strcmp(funcName, "GuiShowAdaSignTxHashDetails")) { return GuiShowAdaSignTxHashDetails; + } else if (!strcmp(funcName, "GuiAvaxTxOverview")) { + return GuiAvaxTxOverview; + } else if (!strcmp(funcName, "GuiAvaxTxRawData")) { + return GuiAvaxTxRawData; } return NULL; diff --git a/src/ui/gui_analyze/multi/web3/gui_general_analyze.h b/src/ui/gui_analyze/multi/web3/gui_general_analyze.h index d2496f927..4e4054cdd 100644 --- a/src/ui/gui_analyze/multi/web3/gui_general_analyze.h +++ b/src/ui/gui_analyze/multi/web3/gui_general_analyze.h @@ -156,7 +156,13 @@ GuiGetTonProofGUIData, \ NULL, \ FreeArMemory, \ + }, \ + { \ + REMAPVIEW_AVAX, \ + "{\"name\":\"avax_page\",\"type\":\"tabview\",\"pos\":[36,0],\"size\":[408,900],\"bg_color\":0,\"children\":[{\"type\":\"tabview_child\",\"index\":1,\"tab_name\":\"Overview\",\"font\":\"openSansEnIllustrate\",\"children\":[{\"type\":\"custom_container\",\"bg_color\":0,\"bg_opa\":0,\"pos\":[0,12],\"custom_show_func\":\"GuiAvaxTxOverview\"}]},{\"type\":\"tabview_child\",\"index\":2,\"tab_name\":\"RawData\",\"text_color\":16777215,\"font\":\"openSansEnIllustrate\",\"children\":[{\"type\":\"custom_container\",\"bg_color\":0,\"bg_opa\":0,\"pos\":[0,12],\"custom_show_func\":\"GuiAvaxTxRawData\"}]}]}", \ + GuiGetAvaxGUIData, \ + NULL, \ + FreeAvaxMemory, \ } - #endif #endif \ No newline at end of file diff --git a/src/ui/gui_assets/font/cn/cnIllustrate.c b/src/ui/gui_assets/font/cn/cnIllustrate.c index da1b82d46..63611f19f 100644 --- a/src/ui/gui_assets/font/cn/cnIllustrate.c +++ b/src/ui/gui_assets/font/cn/cnIllustrate.c @@ -10228,7 +10228,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -10245,7 +10246,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -10342,7 +10344,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -10439,7 +10442,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -42, 0, -42, 0, 0, 0, 0, -20, 0, -35, -4, 0, 0, 0, 0, -4, 0, 0, 0, 0, @@ -10658,7 +10662,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/cn/cnLittleTitle.c b/src/ui/gui_assets/font/cn/cnLittleTitle.c index 9627cf898..ace0e3969 100644 --- a/src/ui/gui_assets/font/cn/cnLittleTitle.c +++ b/src/ui/gui_assets/font/cn/cnLittleTitle.c @@ -3756,7 +3756,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -3773,7 +3774,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -3818,7 +3820,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -3863,7 +3866,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -59, 0, -59, 0, 0, 0, 0, -28, 0, -48, -6, 0, 0, 0, 0, -6, 0, 0, 0, 0, @@ -4082,7 +4086,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/cn/cnText.c b/src/ui/gui_assets/font/cn/cnText.c index eaa9984a7..0be88e453 100644 --- a/src/ui/gui_assets/font/cn/cnText.c +++ b/src/ui/gui_assets/font/cn/cnText.c @@ -6332,7 +6332,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -6349,7 +6350,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -6400,7 +6402,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -6451,7 +6454,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -50, 0, -50, 0, 0, 0, 0, -24, 0, -41, -5, 0, 0, 0, 0, -5, 0, 0, 0, 0, @@ -6670,7 +6674,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/cn/cnTitle.c b/src/ui/gui_assets/font/cn/cnTitle.c index 0e94bbad7..cadd7f5f3 100644 --- a/src/ui/gui_assets/font/cn/cnTitle.c +++ b/src/ui/gui_assets/font/cn/cnTitle.c @@ -2071,7 +2071,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -2088,7 +2089,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -2112,7 +2114,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -2136,7 +2139,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -75, 0, -75, 0, 0, 0, 0, -36, 0, -62, -8, 0, 0, 0, 0, -8, 0, 0, 0, 0, @@ -2355,7 +2359,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/de/deIllustrate.c b/src/ui/gui_assets/font/de/deIllustrate.c index 97c538823..51649a2b9 100644 --- a/src/ui/gui_assets/font/de/deIllustrate.c +++ b/src/ui/gui_assets/font/de/deIllustrate.c @@ -879,7 +879,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/de/deLittleTitle.c b/src/ui/gui_assets/font/de/deLittleTitle.c index 5ac08cad7..11c86a2cb 100644 --- a/src/ui/gui_assets/font/de/deLittleTitle.c +++ b/src/ui/gui_assets/font/de/deLittleTitle.c @@ -794,7 +794,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/de/deText.c b/src/ui/gui_assets/font/de/deText.c index 1ad754dca..d256164eb 100644 --- a/src/ui/gui_assets/font/de/deText.c +++ b/src/ui/gui_assets/font/de/deText.c @@ -1001,7 +1001,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/de/deTitle.c b/src/ui/gui_assets/font/de/deTitle.c index 9fc5b3b99..4cbf8a280 100644 --- a/src/ui/gui_assets/font/de/deTitle.c +++ b/src/ui/gui_assets/font/de/deTitle.c @@ -990,7 +990,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/es/esIllustrate.c b/src/ui/gui_assets/font/es/esIllustrate.c index 4ea2b66bd..2ffa120f7 100644 --- a/src/ui/gui_assets/font/es/esIllustrate.c +++ b/src/ui/gui_assets/font/es/esIllustrate.c @@ -876,7 +876,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/es/esLittleTitle.c b/src/ui/gui_assets/font/es/esLittleTitle.c index 4de5e4478..de17379d8 100644 --- a/src/ui/gui_assets/font/es/esLittleTitle.c +++ b/src/ui/gui_assets/font/es/esLittleTitle.c @@ -803,7 +803,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/es/esText.c b/src/ui/gui_assets/font/es/esText.c index 93945f3aa..374bd354c 100644 --- a/src/ui/gui_assets/font/es/esText.c +++ b/src/ui/gui_assets/font/es/esText.c @@ -1001,7 +1001,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/es/esTitle.c b/src/ui/gui_assets/font/es/esTitle.c index e2a370e30..b45ea1e55 100644 --- a/src/ui/gui_assets/font/es/esTitle.c +++ b/src/ui/gui_assets/font/es/esTitle.c @@ -990,7 +990,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/ja/jaIllustrate.c b/src/ui/gui_assets/font/ja/jaIllustrate.c index 5b1086cf5..38e0dfa45 100644 --- a/src/ui/gui_assets/font/ja/jaIllustrate.c +++ b/src/ui/gui_assets/font/ja/jaIllustrate.c @@ -9130,7 +9130,8 @@ static const uint16_t unicode_list_4[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -9159,7 +9160,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Pair left and right glyphs for kerning*/ -static const uint16_t kern_pair_glyph_ids[] = { +static const uint16_t kern_pair_glyph_ids[] = +{ 3, 13, 3, 15, 3, 34, @@ -10595,190 +10597,192 @@ static const uint16_t kern_pair_glyph_ids[] = { /* Kerning between the respective left and right glyphs * 4.4 format which needs to scaled with `kern_scale`*/ -static const int8_t kern_pair_values[] = { +static const int8_t kern_pair_values[] = +{ -42, -42, -20, -35, -4, -4, -12, -12, - -12, -12, -12, -8, -42, -42, -20, -35, - -4, -4, -12, -12, -12, -12, -12, -8, - -8, 28, -35, -35, -50, -36, -8, -24, - -13, -34, -5, -5, -5, 8, -5, -5, - -17, -13, -9, -8, -8, -7, -18, -8, - -4, -11, -24, -8, -10, -4, -6, -35, - -35, -50, -36, -8, -24, -13, -34, -5, - -5, -5, 8, -5, -5, -17, -13, -9, - -8, -15, -4, -4, -29, -4, -4, -9, - -12, -12, -12, -4, 8, 8, -12, -12, - 2, -8, -19, -10, 0, -19, -10, 0, - -20, -20, -35, -10, -3, -4, -4, -4, - -4, -20, -6, -6, 1, -6, -4, -15, - 7, -4, 7, -6, -3, -4, -2, -2, - -4, -9, -12, -6, -6, -9, -3, -2, - -2, -6, -2, -4, -6, -4, -4, -6, - -8, -10, -11, -11, -4, -11, -11, -9, - -7, -6, -2, -2, -2, -4, -4, -8, - -11, -4, -6, -4, -6, -20, -13, -7, - -4, -15, -9, -4, -3, -7, -8, -8, - -6, -4, -4, -4, -4, -4, -4, -9, - -4, -12, -4, -27, -27, -26, -14, -4, - -4, -51, -4, -4, -8, 1, 1, -9, - 0, -12, -13, -6, -6, -6, -9, -8, - -8, -6, -8, -6, -8, -8, -4, -6, - -8, -7, -10, -7, -11, -6, -11, -2, - -8, -6, -2, -9, -9, -15, -8, -8, - -15, -11, -4, -4, -8, -8, -8, -8, - -4, -7, -6, -5, -4, -7, -4, -4, - -4, -4, -4, -4, -13, -6, -8, -7, - -7, -8, -6, -17, -32, -32, -55, -20, - -12, -10, -10, -10, -10, -9, -44, -11, - -28, -21, -28, -29, -5, -5, -5, -6, - -2, -5, -5, -8, -4, -14, -13, -14, - -34, -13, -7, -4, -15, -9, -4, -3, - -7, -8, -8, -6, -4, -41, -13, -41, - -29, -19, -53, -4, -10, -9, -4, -30, - -16, -10, -10, -10, -12, -10, -10, -4, - -6, -8, -4, -13, -7, -4, -15, -9, - -4, -3, -7, -8, -8, -6, -4, -4, - -11, -2, -7, -6, -6, 1, 1, -2, - -1, -4, -2, -4, -4, -4, -2, -4, - -4, -4, -4, -4, -7, 4, -6, -6, - -8, -6, -9, -1, -5, -39, -27, -39, - -33, -8, -8, -15, -9, -9, -46, -9, - -9, -15, -8, -6, -20, -27, -24, -24, - -24, -7, -27, -18, -18, -24, -18, -24, - -18, -22, -7, -18, -13, -13, -15, -13, - -28, -24, -7, -7, -12, -7, -18, -4, - -2, -4, -6, -2, -4, -2, -4, -24, - -8, -24, -18, -6, -4, -4, -27, -4, - -4, -4, -4, 3, -8, -9, -6, -6, - -6, -9, -8, -8, -6, -8, -6, -8, - -5, -12, -4, -4, -6, -4, -10, -5, - -13, -4, -13, -12, -3, -3, -25, -3, - -3, -3, -3, -7, -5, -4, -4, -4, - -4, -11, -7, -7, -1, -7, -7, -6, - -8, -4, -4, -4, -4, -4, -7, -4, - -4, -7, -4, -7, -6, -4, -7, -6, - -15, -33, -24, -33, -25, -10, -10, -4, - -6, -6, -6, -36, -6, -6, -6, -6, - -4, -10, -25, -16, -16, -16, -22, -15, - -15, -16, -15, -16, -15, -16, -11, -13, - -6, -9, -13, -6, -18, -17, -13, -3, - -8, -8, -13, -8, -8, -12, -4, -3, - -3, -6, -7, -7, -9, -9, -9, -8, - -6, -9, -9, -6, -9, -7, -7, -9, - -7, -22, -8, 28, -32, -12, -20, -12, - -27, 11, 25, -8, -4, 4, -20, -5, - -9, -7, -2, -9, -6, -12, -12, -10, - -4, 1, -4, -5, -21, -8, -2, -17, - -10, -6, -2, -2, -7, -2, -2, -7, - -2, -3, -8, -8, -6, -9, -4, -9, - -9, -9, -4, -9, -9, -4, 1, 1, - 2, 1, -6, -13, 3, -4, -8, -8, - -9, -7, -4, -10, -8, -6, -2, -4, - -4, 1, 1, -4, 1, -1, -2, 4, - 13, 13, 17, -19, -6, -19, -6, 9, - 16, 23, 16, 11, 20, 21, 17, -8, - -4, -4, -4, -6, -4, -4, -4, -2, - 4, -2, -6, 17, -8, 4, -13, 16, - -14, -10, -6, 4, -6, -6, -6, -6, - 12, -6, -6, -2, -2, 4, -6, 4, - -4, -13, -4, -9, -4, -7, -9, 4, - -16, 4, 4, 4, -5, -13, -5, -4, - -7, -7, -7, -4, -4, -7, -7, -8, - -6, -4, -4, -10, 2, -13, -4, -9, - -4, -7, -13, -4, -9, -4, -7, -12, - -12, -10, -4, 1, -4, -5, -21, -8, - -2, -17, -10, -6, -2, -2, -7, -2, - -2, -7, -2, -3, -12, -12, -10, -4, - 1, -4, -5, -21, -8, -2, -17, -10, - -6, -2, -2, -7, -2, -2, -7, -2, - -3, -10, -8, -6, -12, -20, -9, -20, - -13, 8, 8, -6, -20, -4, 4, -9, - -4, -4, -4, -4, -4, -4, -2, 8, - 6, 8, -2, -7, -19, 3, -5, -9, - -4, -8, -8, 2, -10, 2, 3, 4, - 4, -10, -6, -2, -9, -6, -6, -6, - -4, -6, -6, -4, -8, -7, -8, -10, - -8, -6, -12, -5, -13, -4, -13, -8, - -5, -15, -8, -4, -6, -4, -8, -2, - -2, -2, -4, -2, -2, -9, -5, -14, - -14, -4, -2, -12, -9, -4, -6, -9, - -4, -2, -2, -2, -4, -2, -2, -7, - -6, -9, 2, -6, -4, 2, -4, -4, - -4, -4, -2, -13, -6, -4, -13, -4, - -7, -7, -7, -7, -7, -9, -1, -8, - -13, -13, -6, -15, -8, -2, -2, -4, - -8, -2, -2, -2, -4, -2, -2, -6, - -9, -7, -10, -12, -9, -4, -4, -4, - -3, -4, -4, -4, -2, -2, -5, -8, - 28, -9, -9, -24, -10, -10, -21, -14, - -8, -6, -6, -3, -6, -10, -10, -6, - -19, -6, -6, -6, -10, -10, -10, -10, - -10, -10, -16, -10, -22, -22, -10, -10, - -6, -6, -6, -6, -6, -6, -13, -16, - -6, -6, -16, -22, -16, -6, -13, -6, - -16, -16, 6, 6, -13, -6, -10, -10, - 13, -6, -10, -6, 3, 3, 10, -6, - -16, -16, -22, -16, -6, -6, -6, -22, - 3, 3, 3, 3, -13, -6, -6, -19, - -19, -10, -10, -3, -6, -26, -32, -13, - 3, 3, -6, -22, -22, -10, -19, -22, - -29, -22, -32, -3, -16, -16, -22, -22, - -22, -10, -19, -10, -10, -6, -19, -16, - 10, -13, -13, -10, -10, -16, -10, -10, - -10, -10, -10, -10, -10, -10, -10, -19, - -6, -6, -6, -6, -16, -16, -6, -13, - -13, -3, 6, -13, -10, -10, -10, -10, - -10, -10, -13, -13, -10, -10, -10, -3, - -16, -16, -16, -16, -10, -10, -10, -10, - -10, -10, -10, -10, -10, -10, -10, -10, - -6, -6, -6, -16, -16, -10, -10, -6, - -6, -6, -6, -6, -6, -6, 3, 3, - -6, -6, -10, -6, -6, 6, 3, -22, - -22, -16, -16, -13, -13, -13, -13, -13, - -10, -13, -10, -6, -10, -6, -6, -13, - -13, -13, -6, -6, -10, -3, -10, -6, - -10, -6, -6, -6, -10, -10, -13, -6, - 3, -13, -13, -13, 3, 3, -6, -6, - -10, -10, 3, -16, -6, -16, -16, -10, - -16, -16, -32, -32, -6, -10, -6, -16, - -16, -16, -13, -13, -6, -6, -6, -6, - -29, -13, -13, -6, -6, -6, -6, -22, - -16, -3, -13, -19, -6, -6, -3, -3, - -6, -6, -10, -10, -13, -13, -6, -6, - -6, -6, -6, -6, -6, -10, -6, -16, - -16, -19, -19, -6, -6, -10, -6, -6, - -13, -13, -10, -22, -10, -29, -26, -3, - -13, -13, -10, -6, -13, -13, -19, -16, - -16, -16, -26, -13, -10, -6, -22, -26, - -6, -6, -6, -6, -26, -29, -6, -6, - -6, -19, -13, -13, -13, -10, -10, -10, - -22, -10, -6, -10, -13, 6, 6, -29, - -29, -6, -6, -13, -13, -13, -6, -26, - -22, -3, -6, -6, -6, -6, -10, -10, - -10, -10, -10, -6, -6, -6, -19, -19, - -19, -16, -22, -22, -22, -10, -6, -19, - -19, -10, -6, -10, -10, -10, -10, -16, - -10, 6, 6, -10, -10, -19, -16, -10, - -6, -3, -3, -3, -10, -10, -19, -10, - -6, -10, -10, -10, -22, -6, -6, -6, - -13, -6, -6, -16, -16, -16, -10, -6, - -6, -6, -6, -6, -6, -6, -6, -13, - -6, -6, -10, -6, -6, -6, -6, 10, - 10, 10, 16, 10, 10, 16, -6, -13, - -13, -6, -10, 6, -10, -10, -10, -10, - -10, -10, -6, 6, 6, -16, -10, -10, - -19, -19, -19, -16, -6, -6, -6, -6, - -6, -6, -6, -6, -6, -6, -6, -6, - -3, -3, -3, -10, -10, -19, -13, -10, - -10, -6, -6, -6, -6, -6, -19, -19, - -10, -16, -3, -6, -6, -19, -19, -6, - -6, -6, -16, -10, -10, -10, -6, -10, - -3, -3, -19, -19, -13, -13, -13, -6, - -6, -6, -6, -16, -16, -19, -6, -3, - -3, -19, -19, -19, -10, -13, -16 - }; + -12, -12, -12, -8, -42, -42, -20, -35, + -4, -4, -12, -12, -12, -12, -12, -8, + -8, 28, -35, -35, -50, -36, -8, -24, + -13, -34, -5, -5, -5, 8, -5, -5, + -17, -13, -9, -8, -8, -7, -18, -8, + -4, -11, -24, -8, -10, -4, -6, -35, + -35, -50, -36, -8, -24, -13, -34, -5, + -5, -5, 8, -5, -5, -17, -13, -9, + -8, -15, -4, -4, -29, -4, -4, -9, + -12, -12, -12, -4, 8, 8, -12, -12, + 2, -8, -19, -10, 0, -19, -10, 0, + -20, -20, -35, -10, -3, -4, -4, -4, + -4, -20, -6, -6, 1, -6, -4, -15, + 7, -4, 7, -6, -3, -4, -2, -2, + -4, -9, -12, -6, -6, -9, -3, -2, + -2, -6, -2, -4, -6, -4, -4, -6, + -8, -10, -11, -11, -4, -11, -11, -9, + -7, -6, -2, -2, -2, -4, -4, -8, + -11, -4, -6, -4, -6, -20, -13, -7, + -4, -15, -9, -4, -3, -7, -8, -8, + -6, -4, -4, -4, -4, -4, -4, -9, + -4, -12, -4, -27, -27, -26, -14, -4, + -4, -51, -4, -4, -8, 1, 1, -9, + 0, -12, -13, -6, -6, -6, -9, -8, + -8, -6, -8, -6, -8, -8, -4, -6, + -8, -7, -10, -7, -11, -6, -11, -2, + -8, -6, -2, -9, -9, -15, -8, -8, + -15, -11, -4, -4, -8, -8, -8, -8, + -4, -7, -6, -5, -4, -7, -4, -4, + -4, -4, -4, -4, -13, -6, -8, -7, + -7, -8, -6, -17, -32, -32, -55, -20, + -12, -10, -10, -10, -10, -9, -44, -11, + -28, -21, -28, -29, -5, -5, -5, -6, + -2, -5, -5, -8, -4, -14, -13, -14, + -34, -13, -7, -4, -15, -9, -4, -3, + -7, -8, -8, -6, -4, -41, -13, -41, + -29, -19, -53, -4, -10, -9, -4, -30, + -16, -10, -10, -10, -12, -10, -10, -4, + -6, -8, -4, -13, -7, -4, -15, -9, + -4, -3, -7, -8, -8, -6, -4, -4, + -11, -2, -7, -6, -6, 1, 1, -2, + -1, -4, -2, -4, -4, -4, -2, -4, + -4, -4, -4, -4, -7, 4, -6, -6, + -8, -6, -9, -1, -5, -39, -27, -39, + -33, -8, -8, -15, -9, -9, -46, -9, + -9, -15, -8, -6, -20, -27, -24, -24, + -24, -7, -27, -18, -18, -24, -18, -24, + -18, -22, -7, -18, -13, -13, -15, -13, + -28, -24, -7, -7, -12, -7, -18, -4, + -2, -4, -6, -2, -4, -2, -4, -24, + -8, -24, -18, -6, -4, -4, -27, -4, + -4, -4, -4, 3, -8, -9, -6, -6, + -6, -9, -8, -8, -6, -8, -6, -8, + -5, -12, -4, -4, -6, -4, -10, -5, + -13, -4, -13, -12, -3, -3, -25, -3, + -3, -3, -3, -7, -5, -4, -4, -4, + -4, -11, -7, -7, -1, -7, -7, -6, + -8, -4, -4, -4, -4, -4, -7, -4, + -4, -7, -4, -7, -6, -4, -7, -6, + -15, -33, -24, -33, -25, -10, -10, -4, + -6, -6, -6, -36, -6, -6, -6, -6, + -4, -10, -25, -16, -16, -16, -22, -15, + -15, -16, -15, -16, -15, -16, -11, -13, + -6, -9, -13, -6, -18, -17, -13, -3, + -8, -8, -13, -8, -8, -12, -4, -3, + -3, -6, -7, -7, -9, -9, -9, -8, + -6, -9, -9, -6, -9, -7, -7, -9, + -7, -22, -8, 28, -32, -12, -20, -12, + -27, 11, 25, -8, -4, 4, -20, -5, + -9, -7, -2, -9, -6, -12, -12, -10, + -4, 1, -4, -5, -21, -8, -2, -17, + -10, -6, -2, -2, -7, -2, -2, -7, + -2, -3, -8, -8, -6, -9, -4, -9, + -9, -9, -4, -9, -9, -4, 1, 1, + 2, 1, -6, -13, 3, -4, -8, -8, + -9, -7, -4, -10, -8, -6, -2, -4, + -4, 1, 1, -4, 1, -1, -2, 4, + 13, 13, 17, -19, -6, -19, -6, 9, + 16, 23, 16, 11, 20, 21, 17, -8, + -4, -4, -4, -6, -4, -4, -4, -2, + 4, -2, -6, 17, -8, 4, -13, 16, + -14, -10, -6, 4, -6, -6, -6, -6, + 12, -6, -6, -2, -2, 4, -6, 4, + -4, -13, -4, -9, -4, -7, -9, 4, + -16, 4, 4, 4, -5, -13, -5, -4, + -7, -7, -7, -4, -4, -7, -7, -8, + -6, -4, -4, -10, 2, -13, -4, -9, + -4, -7, -13, -4, -9, -4, -7, -12, + -12, -10, -4, 1, -4, -5, -21, -8, + -2, -17, -10, -6, -2, -2, -7, -2, + -2, -7, -2, -3, -12, -12, -10, -4, + 1, -4, -5, -21, -8, -2, -17, -10, + -6, -2, -2, -7, -2, -2, -7, -2, + -3, -10, -8, -6, -12, -20, -9, -20, + -13, 8, 8, -6, -20, -4, 4, -9, + -4, -4, -4, -4, -4, -4, -2, 8, + 6, 8, -2, -7, -19, 3, -5, -9, + -4, -8, -8, 2, -10, 2, 3, 4, + 4, -10, -6, -2, -9, -6, -6, -6, + -4, -6, -6, -4, -8, -7, -8, -10, + -8, -6, -12, -5, -13, -4, -13, -8, + -5, -15, -8, -4, -6, -4, -8, -2, + -2, -2, -4, -2, -2, -9, -5, -14, + -14, -4, -2, -12, -9, -4, -6, -9, + -4, -2, -2, -2, -4, -2, -2, -7, + -6, -9, 2, -6, -4, 2, -4, -4, + -4, -4, -2, -13, -6, -4, -13, -4, + -7, -7, -7, -7, -7, -9, -1, -8, + -13, -13, -6, -15, -8, -2, -2, -4, + -8, -2, -2, -2, -4, -2, -2, -6, + -9, -7, -10, -12, -9, -4, -4, -4, + -3, -4, -4, -4, -2, -2, -5, -8, + 28, -9, -9, -24, -10, -10, -21, -14, + -8, -6, -6, -3, -6, -10, -10, -6, + -19, -6, -6, -6, -10, -10, -10, -10, + -10, -10, -16, -10, -22, -22, -10, -10, + -6, -6, -6, -6, -6, -6, -13, -16, + -6, -6, -16, -22, -16, -6, -13, -6, + -16, -16, 6, 6, -13, -6, -10, -10, + 13, -6, -10, -6, 3, 3, 10, -6, + -16, -16, -22, -16, -6, -6, -6, -22, + 3, 3, 3, 3, -13, -6, -6, -19, + -19, -10, -10, -3, -6, -26, -32, -13, + 3, 3, -6, -22, -22, -10, -19, -22, + -29, -22, -32, -3, -16, -16, -22, -22, + -22, -10, -19, -10, -10, -6, -19, -16, + 10, -13, -13, -10, -10, -16, -10, -10, + -10, -10, -10, -10, -10, -10, -10, -19, + -6, -6, -6, -6, -16, -16, -6, -13, + -13, -3, 6, -13, -10, -10, -10, -10, + -10, -10, -13, -13, -10, -10, -10, -3, + -16, -16, -16, -16, -10, -10, -10, -10, + -10, -10, -10, -10, -10, -10, -10, -10, + -6, -6, -6, -16, -16, -10, -10, -6, + -6, -6, -6, -6, -6, -6, 3, 3, + -6, -6, -10, -6, -6, 6, 3, -22, + -22, -16, -16, -13, -13, -13, -13, -13, + -10, -13, -10, -6, -10, -6, -6, -13, + -13, -13, -6, -6, -10, -3, -10, -6, + -10, -6, -6, -6, -10, -10, -13, -6, + 3, -13, -13, -13, 3, 3, -6, -6, + -10, -10, 3, -16, -6, -16, -16, -10, + -16, -16, -32, -32, -6, -10, -6, -16, + -16, -16, -13, -13, -6, -6, -6, -6, + -29, -13, -13, -6, -6, -6, -6, -22, + -16, -3, -13, -19, -6, -6, -3, -3, + -6, -6, -10, -10, -13, -13, -6, -6, + -6, -6, -6, -6, -6, -10, -6, -16, + -16, -19, -19, -6, -6, -10, -6, -6, + -13, -13, -10, -22, -10, -29, -26, -3, + -13, -13, -10, -6, -13, -13, -19, -16, + -16, -16, -26, -13, -10, -6, -22, -26, + -6, -6, -6, -6, -26, -29, -6, -6, + -6, -19, -13, -13, -13, -10, -10, -10, + -22, -10, -6, -10, -13, 6, 6, -29, + -29, -6, -6, -13, -13, -13, -6, -26, + -22, -3, -6, -6, -6, -6, -10, -10, + -10, -10, -10, -6, -6, -6, -19, -19, + -19, -16, -22, -22, -22, -10, -6, -19, + -19, -10, -6, -10, -10, -10, -10, -16, + -10, 6, 6, -10, -10, -19, -16, -10, + -6, -3, -3, -3, -10, -10, -19, -10, + -6, -10, -10, -10, -22, -6, -6, -6, + -13, -6, -6, -16, -16, -16, -10, -6, + -6, -6, -6, -6, -6, -6, -6, -13, + -6, -6, -10, -6, -6, -6, -6, 10, + 10, 10, 16, 10, 10, 16, -6, -13, + -13, -6, -10, 6, -10, -10, -10, -10, + -10, -10, -6, 6, 6, -16, -10, -10, + -19, -19, -19, -16, -6, -6, -6, -6, + -6, -6, -6, -6, -6, -6, -6, -6, + -3, -3, -3, -10, -10, -19, -13, -10, + -10, -6, -6, -6, -6, -6, -19, -19, + -10, -16, -3, -6, -6, -19, -19, -6, + -6, -6, -16, -10, -10, -10, -6, -10, + -3, -3, -19, -19, -13, -13, -13, -6, + -6, -6, -6, -16, -16, -19, -6, -3, + -3, -19, -19, -19, -10, -13, -16 +}; /*Collect the kern pair's data in one place*/ -static const lv_font_fmt_txt_kern_pair_t kern_pairs = { +static const lv_font_fmt_txt_kern_pair_t kern_pairs = +{ .glyph_ids = kern_pair_glyph_ids, .values = kern_pair_values, .pair_cnt = 1431, diff --git a/src/ui/gui_assets/font/ja/jaLittleTitle.c b/src/ui/gui_assets/font/ja/jaLittleTitle.c index fb55964c1..b901eeb2d 100644 --- a/src/ui/gui_assets/font/ja/jaLittleTitle.c +++ b/src/ui/gui_assets/font/ja/jaLittleTitle.c @@ -3485,7 +3485,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -3502,7 +3503,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Pair left and right glyphs for kerning*/ -static const uint16_t kern_pair_glyph_ids[] = { +static const uint16_t kern_pair_glyph_ids[] = +{ 3, 13, 3, 15, 3, 34, @@ -4664,156 +4666,158 @@ static const uint16_t kern_pair_glyph_ids[] = { /* Kerning between the respective left and right glyphs * 4.4 format which needs to scaled with `kern_scale`*/ -static const int8_t kern_pair_values[] = { +static const int8_t kern_pair_values[] = +{ -59, -59, -28, -48, -6, -6, -17, -17, - -17, -17, -17, -11, -59, -59, -28, -48, - -6, -6, -17, -17, -17, -17, -17, -11, - -11, 39, -48, -48, -69, -51, -11, -34, - -18, -47, -7, -7, -7, 12, -7, -7, - -24, -18, -12, -11, -11, -10, -25, -11, - -6, -15, -34, -11, -14, -5, -8, -48, - -48, -69, -51, -11, -34, -18, -47, -7, - -7, -7, 12, -7, -7, -24, -18, -12, - -11, -22, -6, -6, -41, -6, -6, -13, - -17, -17, -17, -6, 12, 12, -17, -17, - 3, -11, -26, -14, 0, -26, -14, 0, - -28, -28, -48, -14, -4, -6, -6, -6, - -6, -28, -9, -8, 1, -8, -5, -22, - 10, -6, 10, -8, -4, -5, -3, -3, - -5, -13, -17, -9, -8, -13, -4, -3, - -3, -8, -3, -6, -8, -6, -6, -8, - -11, -14, -15, -15, -6, -15, -15, -13, - -10, -8, -3, -3, -3, -5, -6, -11, - -15, -6, -8, -6, -8, -27, -18, -10, - -6, -21, -13, -6, -4, -10, -11, -11, - -8, -5, -6, -6, -6, -6, -6, -13, - -6, -17, -6, -37, -37, -37, -20, -6, - -6, -71, -6, -6, -11, 1, 1, -13, - 0, -17, -18, -8, -8, -8, -13, -11, - -11, -8, -11, -8, -11, -11, -6, -9, - -11, -9, -14, -9, -16, -8, -15, -3, - -11, -8, -3, -13, -13, -22, -12, -12, - -22, -16, -5, -6, -11, -11, -11, -11, - -5, -10, -8, -7, -6, -9, -5, -5, - -5, -6, -5, -5, -18, -9, -11, -9, - -9, -11, -8, -24, -44, -44, -77, -28, - -17, -14, -14, -14, -14, -13, -61, -15, - -39, -29, -39, -41, -7, -7, -7, -8, - -3, -7, -7, -11, -6, -19, -18, -19, - -47, -18, -10, -6, -21, -13, -6, -4, - -10, -11, -11, -8, -5, -57, -18, -57, - -40, -26, -75, -6, -13, -13, -6, -42, - -23, -13, -13, -13, -17, -13, -13, -6, - -8, -11, -5, -18, -10, -6, -21, -13, - -6, -4, -10, -11, -11, -8, -5, -6, - -16, -3, -10, -8, -8, 1, 2, -3, - -2, -6, -3, -6, -6, -6, -3, -6, - -6, -5, -5, -6, -9, 6, -8, -8, - -11, -8, -13, -1, -7, -54, -38, -54, - -47, -11, -11, -22, -13, -13, -65, -13, - -13, -22, -11, -8, -28, -38, -34, -34, - -34, -10, -38, -25, -25, -34, -25, -34, - -25, -30, -10, -25, -18, -18, -22, -18, - -39, -33, -9, -9, -17, -9, -25, -6, - -3, -6, -8, -3, -6, -3, -5, -34, - -11, -34, -25, -8, -6, -6, -38, -6, - -6, -6, -6, 4, -11, -12, -9, -9, - -9, -12, -11, -11, -9, -11, -9, -11, - -7, -17, -6, -6, -9, -6, -14, -7, - -18, -6, -18, -17, -4, -4, -34, -4, - -4, -4, -4, -9, -8, -6, -6, -6, - -6, -15, -10, -10, -2, -10, -10, -8, - -11, -6, -6, -5, -5, -5, -9, -5, - -5, -9, -6, -9, -8, -6, -9, -8, - -22, -46, -34, -46, -35, -13, -13, -5, - -8, -8, -8, -51, -8, -8, -9, -8, - -6, -14, -35, -22, -22, -22, -31, -22, - -22, -22, -22, -22, -22, -22, -15, -18, - -8, -13, -18, -8, -25, -24, -18, -4, - -11, -11, -18, -11, -11, -17, -6, -4, - -4, -8, -9, -9, -12, -12, -12, -11, - -9, -12, -12, -8, -13, -9, -9, -13, - -9, -31, -11, 39, -44, -17, -28, -17, - -38, 15, 35, -11, -6, 5, -28, -7, - -13, -9, -3, -13, -8, -17, -17, -14, - -6, 2, -6, -7, -30, -11, -3, -24, - -14, -9, -2, -2, -10, -3, -3, -10, - -3, -4, -11, -11, -8, -13, -6, -12, - -12, -12, -6, -12, -12, -6, 2, 2, - 3, 2, -8, -18, 4, -5, -11, -11, - -13, -9, -6, -14, -11, -9, -2, -6, - -6, 1, 1, -5, 1, -1, -3, 6, - 19, 19, 24, -26, -8, -26, -9, 12, - 22, 32, 22, 15, 29, 30, 24, -11, - -6, -6, -6, -9, -6, -6, -6, -3, - 5, -3, -8, 24, -11, 6, -18, 23, - -19, -14, -8, 6, -9, -8, -8, -8, - 17, -8, -8, -3, -3, 6, -8, 6, - -5, -18, -5, -13, -6, -9, -12, 5, - -22, 5, 5, 5, -7, -18, -7, -6, - -10, -10, -10, -6, -6, -10, -10, -12, - -8, -5, -5, -14, 3, -18, -5, -13, - -6, -9, -18, -5, -13, -6, -9, -17, - -17, -14, -6, 2, -6, -7, -30, -11, - -3, -24, -14, -9, -2, -2, -10, -3, - -3, -10, -3, -4, -17, -17, -14, -6, - 2, -6, -7, -30, -11, -3, -24, -14, - -9, -2, -2, -10, -3, -3, -10, -3, - -4, -13, -11, -8, -17, -29, -13, -29, - -18, 12, 12, -8, -28, -6, 5, -13, - -6, -6, -6, -6, -6, -6, -3, 12, - 9, 12, -3, -9, -26, 4, -7, -13, - -6, -11, -11, 2, -14, 2, 4, 6, - 6, -14, -8, -3, -12, -8, -8, -8, - -6, -8, -8, -6, -11, -9, -11, -13, - -11, -8, -17, -7, -18, -5, -18, -11, - -7, -22, -11, -6, -8, -6, -11, -3, - -3, -3, -6, -3, -3, -13, -7, -20, - -20, -5, -3, -17, -13, -6, -8, -13, - -6, -3, -3, -3, -6, -3, -3, -10, - -8, -13, 2, -8, -5, 2, -6, -6, - -6, -6, -3, -18, -9, -6, -18, -6, - -10, -10, -10, -10, -10, -13, -2, -11, - -18, -18, -9, -22, -11, -3, -3, -5, - -11, -3, -3, -3, -6, -3, -3, -8, - -13, -9, -14, -17, -13, -6, -6, -6, - -4, -6, -6, -6, -3, -3, -7, -11, - 39, -13, -13, -33, -14, -14, -30, -20, - -11, -13, -13, -13, -13, -13, -22, -13, - -13, -13, -9, -9, -9, -9, -18, -9, - -31, -9, -13, -13, 18, -9, -22, -9, - -9, -9, -27, -13, -13, -9, -36, 4, - 4, -13, -31, -13, -13, -9, -18, -22, - -13, -13, -13, -9, -9, -22, -9, -18, - -18, -13, -13, -18, -13, -13, -13, -4, - -13, -9, -9, -9, -9, 4, -13, -9, - -9, -18, -13, -9, -9, -13, -13, -18, - 4, -18, -9, -18, 4, -9, -13, -13, - -22, -9, -22, -22, -22, -45, -9, -22, - -22, -22, -18, -9, -9, -18, -9, -9, - -9, -31, -22, -4, -18, -27, -9, -4, - -9, -9, -13, -13, -18, -18, -9, -9, - -9, -9, -13, -22, -9, -18, -13, -13, - -40, -4, -18, -18, -13, -9, -18, -18, - -22, -22, -36, -18, -13, -31, -9, -9, - -9, -18, -40, -9, -18, -18, -9, -36, - -4, -9, -9, -13, -13, -31, -13, -9, - -13, -13, -22, 9, -13, -27, -9, -4, - -4, -36, -9, -13, -27, -13, -13, -31, - -9, -9, -18, -9, 13, 13, 22, 13, - 13, 22, -9, -18, -9, -13, 9, -13, - -13, -13, -13, -9, 9, 9, -22, -27, - -27, -27, -22, -9, -9, -9, -9, -9, - -9, -9, -9, -4, -4, -13, -13, -27, - -13, -9, -9, -9, -9, -27, -13, -9, - -9, -27, -9, -9, -9, -13, -13, -13, - -9, -13, -4, -27, -27, -18, -18, -9, - -9, -9, -22, -22, -9, -4, -4, -27, - -27, -27, -13, -18, -22 - }; + -17, -17, -17, -11, -59, -59, -28, -48, + -6, -6, -17, -17, -17, -17, -17, -11, + -11, 39, -48, -48, -69, -51, -11, -34, + -18, -47, -7, -7, -7, 12, -7, -7, + -24, -18, -12, -11, -11, -10, -25, -11, + -6, -15, -34, -11, -14, -5, -8, -48, + -48, -69, -51, -11, -34, -18, -47, -7, + -7, -7, 12, -7, -7, -24, -18, -12, + -11, -22, -6, -6, -41, -6, -6, -13, + -17, -17, -17, -6, 12, 12, -17, -17, + 3, -11, -26, -14, 0, -26, -14, 0, + -28, -28, -48, -14, -4, -6, -6, -6, + -6, -28, -9, -8, 1, -8, -5, -22, + 10, -6, 10, -8, -4, -5, -3, -3, + -5, -13, -17, -9, -8, -13, -4, -3, + -3, -8, -3, -6, -8, -6, -6, -8, + -11, -14, -15, -15, -6, -15, -15, -13, + -10, -8, -3, -3, -3, -5, -6, -11, + -15, -6, -8, -6, -8, -27, -18, -10, + -6, -21, -13, -6, -4, -10, -11, -11, + -8, -5, -6, -6, -6, -6, -6, -13, + -6, -17, -6, -37, -37, -37, -20, -6, + -6, -71, -6, -6, -11, 1, 1, -13, + 0, -17, -18, -8, -8, -8, -13, -11, + -11, -8, -11, -8, -11, -11, -6, -9, + -11, -9, -14, -9, -16, -8, -15, -3, + -11, -8, -3, -13, -13, -22, -12, -12, + -22, -16, -5, -6, -11, -11, -11, -11, + -5, -10, -8, -7, -6, -9, -5, -5, + -5, -6, -5, -5, -18, -9, -11, -9, + -9, -11, -8, -24, -44, -44, -77, -28, + -17, -14, -14, -14, -14, -13, -61, -15, + -39, -29, -39, -41, -7, -7, -7, -8, + -3, -7, -7, -11, -6, -19, -18, -19, + -47, -18, -10, -6, -21, -13, -6, -4, + -10, -11, -11, -8, -5, -57, -18, -57, + -40, -26, -75, -6, -13, -13, -6, -42, + -23, -13, -13, -13, -17, -13, -13, -6, + -8, -11, -5, -18, -10, -6, -21, -13, + -6, -4, -10, -11, -11, -8, -5, -6, + -16, -3, -10, -8, -8, 1, 2, -3, + -2, -6, -3, -6, -6, -6, -3, -6, + -6, -5, -5, -6, -9, 6, -8, -8, + -11, -8, -13, -1, -7, -54, -38, -54, + -47, -11, -11, -22, -13, -13, -65, -13, + -13, -22, -11, -8, -28, -38, -34, -34, + -34, -10, -38, -25, -25, -34, -25, -34, + -25, -30, -10, -25, -18, -18, -22, -18, + -39, -33, -9, -9, -17, -9, -25, -6, + -3, -6, -8, -3, -6, -3, -5, -34, + -11, -34, -25, -8, -6, -6, -38, -6, + -6, -6, -6, 4, -11, -12, -9, -9, + -9, -12, -11, -11, -9, -11, -9, -11, + -7, -17, -6, -6, -9, -6, -14, -7, + -18, -6, -18, -17, -4, -4, -34, -4, + -4, -4, -4, -9, -8, -6, -6, -6, + -6, -15, -10, -10, -2, -10, -10, -8, + -11, -6, -6, -5, -5, -5, -9, -5, + -5, -9, -6, -9, -8, -6, -9, -8, + -22, -46, -34, -46, -35, -13, -13, -5, + -8, -8, -8, -51, -8, -8, -9, -8, + -6, -14, -35, -22, -22, -22, -31, -22, + -22, -22, -22, -22, -22, -22, -15, -18, + -8, -13, -18, -8, -25, -24, -18, -4, + -11, -11, -18, -11, -11, -17, -6, -4, + -4, -8, -9, -9, -12, -12, -12, -11, + -9, -12, -12, -8, -13, -9, -9, -13, + -9, -31, -11, 39, -44, -17, -28, -17, + -38, 15, 35, -11, -6, 5, -28, -7, + -13, -9, -3, -13, -8, -17, -17, -14, + -6, 2, -6, -7, -30, -11, -3, -24, + -14, -9, -2, -2, -10, -3, -3, -10, + -3, -4, -11, -11, -8, -13, -6, -12, + -12, -12, -6, -12, -12, -6, 2, 2, + 3, 2, -8, -18, 4, -5, -11, -11, + -13, -9, -6, -14, -11, -9, -2, -6, + -6, 1, 1, -5, 1, -1, -3, 6, + 19, 19, 24, -26, -8, -26, -9, 12, + 22, 32, 22, 15, 29, 30, 24, -11, + -6, -6, -6, -9, -6, -6, -6, -3, + 5, -3, -8, 24, -11, 6, -18, 23, + -19, -14, -8, 6, -9, -8, -8, -8, + 17, -8, -8, -3, -3, 6, -8, 6, + -5, -18, -5, -13, -6, -9, -12, 5, + -22, 5, 5, 5, -7, -18, -7, -6, + -10, -10, -10, -6, -6, -10, -10, -12, + -8, -5, -5, -14, 3, -18, -5, -13, + -6, -9, -18, -5, -13, -6, -9, -17, + -17, -14, -6, 2, -6, -7, -30, -11, + -3, -24, -14, -9, -2, -2, -10, -3, + -3, -10, -3, -4, -17, -17, -14, -6, + 2, -6, -7, -30, -11, -3, -24, -14, + -9, -2, -2, -10, -3, -3, -10, -3, + -4, -13, -11, -8, -17, -29, -13, -29, + -18, 12, 12, -8, -28, -6, 5, -13, + -6, -6, -6, -6, -6, -6, -3, 12, + 9, 12, -3, -9, -26, 4, -7, -13, + -6, -11, -11, 2, -14, 2, 4, 6, + 6, -14, -8, -3, -12, -8, -8, -8, + -6, -8, -8, -6, -11, -9, -11, -13, + -11, -8, -17, -7, -18, -5, -18, -11, + -7, -22, -11, -6, -8, -6, -11, -3, + -3, -3, -6, -3, -3, -13, -7, -20, + -20, -5, -3, -17, -13, -6, -8, -13, + -6, -3, -3, -3, -6, -3, -3, -10, + -8, -13, 2, -8, -5, 2, -6, -6, + -6, -6, -3, -18, -9, -6, -18, -6, + -10, -10, -10, -10, -10, -13, -2, -11, + -18, -18, -9, -22, -11, -3, -3, -5, + -11, -3, -3, -3, -6, -3, -3, -8, + -13, -9, -14, -17, -13, -6, -6, -6, + -4, -6, -6, -6, -3, -3, -7, -11, + 39, -13, -13, -33, -14, -14, -30, -20, + -11, -13, -13, -13, -13, -13, -22, -13, + -13, -13, -9, -9, -9, -9, -18, -9, + -31, -9, -13, -13, 18, -9, -22, -9, + -9, -9, -27, -13, -13, -9, -36, 4, + 4, -13, -31, -13, -13, -9, -18, -22, + -13, -13, -13, -9, -9, -22, -9, -18, + -18, -13, -13, -18, -13, -13, -13, -4, + -13, -9, -9, -9, -9, 4, -13, -9, + -9, -18, -13, -9, -9, -13, -13, -18, + 4, -18, -9, -18, 4, -9, -13, -13, + -22, -9, -22, -22, -22, -45, -9, -22, + -22, -22, -18, -9, -9, -18, -9, -9, + -9, -31, -22, -4, -18, -27, -9, -4, + -9, -9, -13, -13, -18, -18, -9, -9, + -9, -9, -13, -22, -9, -18, -13, -13, + -40, -4, -18, -18, -13, -9, -18, -18, + -22, -22, -36, -18, -13, -31, -9, -9, + -9, -18, -40, -9, -18, -18, -9, -36, + -4, -9, -9, -13, -13, -31, -13, -9, + -13, -13, -22, 9, -13, -27, -9, -4, + -4, -36, -9, -13, -27, -13, -13, -31, + -9, -9, -18, -9, 13, 13, 22, 13, + 13, 22, -9, -18, -9, -13, 9, -13, + -13, -13, -13, -9, 9, 9, -22, -27, + -27, -27, -22, -9, -9, -9, -9, -9, + -9, -9, -9, -4, -4, -13, -13, -27, + -13, -9, -9, -9, -9, -27, -13, -9, + -9, -27, -9, -9, -9, -13, -13, -13, + -9, -13, -4, -27, -27, -18, -18, -9, + -9, -9, -22, -22, -9, -4, -4, -27, + -27, -27, -13, -18, -22 +}; /*Collect the kern pair's data in one place*/ -static const lv_font_fmt_txt_kern_pair_t kern_pairs = { +static const lv_font_fmt_txt_kern_pair_t kern_pairs = +{ .glyph_ids = kern_pair_glyph_ids, .values = kern_pair_values, .pair_cnt = 1157, diff --git a/src/ui/gui_assets/font/ja/jaText.c b/src/ui/gui_assets/font/ja/jaText.c index d7d346a1b..21cddabb3 100644 --- a/src/ui/gui_assets/font/ja/jaText.c +++ b/src/ui/gui_assets/font/ja/jaText.c @@ -5618,7 +5618,8 @@ static const uint16_t unicode_list_3[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -5643,7 +5644,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Pair left and right glyphs for kerning*/ -static const uint16_t kern_pair_glyph_ids[] = { +static const uint16_t kern_pair_glyph_ids[] = +{ 3, 13, 3, 15, 3, 34, @@ -6877,165 +6879,167 @@ static const uint16_t kern_pair_glyph_ids[] = { /* Kerning between the respective left and right glyphs * 4.4 format which needs to scaled with `kern_scale`*/ -static const int8_t kern_pair_values[] = { +static const int8_t kern_pair_values[] = +{ -50, -50, -24, -41, -5, -5, -14, -14, - -14, -14, -14, -10, -50, -50, -24, -41, - -5, -5, -14, -14, -14, -14, -14, -10, - -10, 33, -41, -41, -60, -43, -10, -29, - -15, -41, -6, -6, -6, 10, -6, -6, - -21, -15, -10, -10, -10, -8, -21, -9, - -5, -13, -29, -10, -12, -4, -7, -41, - -41, -60, -43, -10, -29, -15, -41, -6, - -6, -6, 10, -6, -6, -21, -15, -10, - -10, -18, -5, -5, -35, -5, -5, -11, - -15, -15, -15, -5, 10, 10, -15, -15, - 3, -10, -23, -12, 0, -23, -12, 0, - -24, -24, -41, -12, -3, -5, -5, -5, - -5, -24, -8, -7, 1, -7, -4, -18, - 9, -5, 9, -7, -3, -4, -3, -3, - -4, -11, -14, -8, -7, -11, -3, -3, - -3, -7, -3, -5, -7, -5, -5, -7, - -10, -12, -13, -13, -5, -13, -13, -11, - -8, -7, -3, -3, -3, -4, -5, -10, - -13, -5, -7, -5, -7, -23, -16, -8, - -5, -18, -11, -5, -3, -8, -10, -10, - -7, -4, -5, -5, -5, -5, -5, -11, - -5, -14, -5, -32, -32, -31, -17, -5, - -5, -61, -5, -5, -10, 1, 1, -11, - 0, -14, -15, -7, -7, -7, -11, -10, - -10, -7, -10, -7, -10, -10, -5, -8, - -10, -8, -12, -8, -13, -7, -13, -3, - -10, -7, -3, -11, -11, -18, -10, -10, - -18, -13, -4, -5, -10, -10, -10, -10, - -5, -8, -7, -6, -5, -8, -4, -4, - -4, -5, -4, -4, -15, -7, -10, -8, - -8, -10, -7, -21, -38, -38, -66, -24, - -15, -12, -12, -12, -12, -11, -53, -13, - -34, -25, -33, -35, -6, -6, -6, -7, - -3, -6, -6, -10, -5, -17, -15, -17, - -41, -16, -8, -5, -18, -11, -5, -3, - -8, -10, -10, -7, -4, -49, -15, -49, - -35, -23, -64, -5, -12, -11, -5, -36, - -20, -12, -12, -12, -14, -12, -12, -5, - -7, -10, -4, -16, -8, -5, -18, -11, - -5, -3, -8, -10, -10, -7, -4, -5, - -13, -3, -8, -7, -7, 1, 2, -3, - -2, -5, -3, -5, -5, -5, -3, -5, - -5, -4, -4, -5, -8, 5, -7, -7, - -10, -7, -11, -1, -6, -46, -32, -46, - -40, -10, -10, -18, -11, -11, -56, -11, - -11, -18, -10, -7, -24, -32, -29, -29, - -29, -8, -32, -21, -21, -29, -21, -29, - -21, -26, -8, -21, -15, -16, -18, -15, - -33, -28, -8, -8, -15, -8, -21, -5, - -3, -5, -7, -3, -5, -3, -4, -29, - -9, -29, -22, -7, -5, -5, -32, -5, - -5, -5, -5, 3, -9, -10, -7, -7, - -7, -10, -10, -10, -7, -10, -7, -10, - -6, -14, -5, -5, -7, -5, -12, -6, - -15, -5, -15, -14, -3, -3, -30, -3, - -3, -3, -3, -8, -7, -5, -5, -5, - -5, -13, -8, -8, -2, -8, -8, -7, - -10, -5, -5, -4, -4, -4, -8, -4, - -4, -8, -5, -8, -7, -5, -8, -7, - -18, -40, -29, -40, -30, -12, -12, -4, - -7, -7, -7, -44, -7, -7, -8, -7, - -5, -12, -30, -19, -19, -19, -27, -18, - -18, -19, -18, -19, -18, -19, -13, -15, - -7, -11, -15, -7, -21, -21, -16, -3, - -10, -10, -15, -10, -10, -14, -5, -3, - -3, -7, -8, -8, -10, -10, -10, -10, - -7, -10, -10, -7, -11, -8, -8, -11, - -8, -27, -10, 33, -38, -14, -24, -14, - -32, 13, 30, -10, -5, 5, -24, -6, - -11, -8, -3, -11, -7, -14, -14, -12, - -5, 2, -5, -6, -26, -9, -3, -21, - -12, -7, -2, -2, -8, -3, -3, -8, - -3, -3, -10, -10, -7, -11, -5, -10, - -10, -10, -5, -10, -10, -5, 2, 2, - 2, 2, -7, -16, 3, -4, -10, -10, - -11, -8, -5, -12, -10, -7, -2, -5, - -5, 1, 1, -4, 1, -1, -3, 5, - 16, 16, 20, -23, -7, -23, -7, 10, - 19, 28, 19, 13, 25, 26, 20, -10, - -5, -5, -5, -7, -5, -5, -5, -3, - 5, -3, -7, 20, -10, 5, -15, 20, - -17, -12, -7, 5, -8, -7, -7, -7, - 15, -7, -7, -3, -3, 5, -7, 5, - -4, -16, -4, -11, -5, -8, -10, 5, - -19, 5, 5, 5, -6, -16, -6, -5, - -9, -9, -9, -5, -5, -9, -9, -10, - -7, -4, -4, -12, 2, -16, -4, -11, - -5, -8, -16, -4, -11, -5, -8, -14, - -14, -12, -5, 2, -5, -6, -26, -9, - -3, -21, -12, -7, -2, -2, -8, -3, - -3, -8, -3, -3, -14, -14, -12, -5, - 2, -5, -6, -26, -9, -3, -21, -12, - -7, -2, -2, -8, -3, -3, -8, -3, - -3, -12, -10, -7, -14, -25, -11, -25, - -16, 10, 10, -7, -24, -5, 5, -11, - -5, -5, -5, -5, -5, -5, -3, 10, - 7, 10, -3, -8, -23, 3, -6, -11, - -5, -10, -10, 2, -12, 2, 3, 5, - 5, -12, -7, -3, -10, -7, -7, -7, - -5, -7, -7, -5, -10, -8, -10, -12, - -10, -7, -14, -6, -15, -4, -15, -10, - -6, -18, -10, -5, -7, -5, -10, -3, - -3, -3, -5, -3, -3, -11, -6, -17, - -17, -4, -3, -14, -11, -5, -7, -11, - -5, -3, -3, -3, -5, -3, -3, -8, - -7, -11, 2, -7, -4, 2, -5, -5, - -5, -5, -3, -15, -7, -5, -15, -5, - -8, -8, -8, -8, -8, -11, -2, -10, - -15, -15, -7, -18, -10, -3, -3, -4, - -10, -3, -3, -3, -5, -3, -3, -7, - -11, -8, -12, -14, -11, -5, -5, -5, - -3, -5, -5, -5, -3, -3, -6, -10, - 33, -11, -11, -28, -12, -12, -25, -17, - -10, -12, -12, -8, -8, -15, -19, -27, - -15, -8, -12, -12, 15, -8, -12, 4, - 4, 12, -8, -19, -8, -8, -27, -8, - -23, -12, -12, -8, -31, -15, 4, 4, - -12, -23, -27, -35, 8, 12, 12, -12, - -12, -8, -19, 12, -15, -19, -12, -12, - -12, -12, -23, -8, -8, -19, -8, -15, - 8, -15, -12, -12, -12, -15, -12, -12, - -12, -4, -12, -8, -8, -8, -8, 4, - -12, -8, -8, -15, -12, -12, -15, -12, - -8, -12, -8, -8, -8, -12, -12, -15, - 4, -15, -8, -15, 4, -8, -12, -12, - -19, -8, -19, -19, -19, -38, -8, -19, - -19, -19, -15, -15, -8, -8, -8, -35, - -15, -8, -8, -8, -8, -27, -19, -4, - -15, -23, -8, -4, -8, -8, -12, -12, - -15, -15, -8, -8, -8, -8, -8, -12, - -19, -23, -8, -8, -12, -8, -8, -15, - -12, -27, -12, -12, -15, -35, -4, -15, - -15, -12, -8, -15, -15, -23, -19, -19, - -31, -15, -12, -27, -8, -8, -8, -8, - -15, -35, -8, -8, -15, -15, -8, -31, - -4, -8, -8, -8, -12, -12, -12, -8, - -8, -8, -23, -23, -19, -27, -27, -27, - -12, -8, -23, -12, -8, -12, -12, -12, - -19, 8, 8, -12, -12, -23, -12, -8, - -4, -4, -31, -8, -12, -23, -12, -12, - -12, -27, -8, -8, -15, -8, -19, -19, - -12, -8, -8, -8, -8, -8, -15, -8, - -12, -8, -8, -8, 12, 12, 19, 12, - 12, 19, -8, -15, -8, -12, 8, -12, - -12, -12, -12, -8, 8, 8, -19, -12, - -23, -23, -23, -19, -8, -8, -8, -8, - -8, -8, -8, -8, -8, -8, -4, -4, - -12, -12, -23, -12, -12, -8, -8, -8, - -8, -23, -12, -19, -8, -8, -23, -8, - -8, -8, -19, -12, -12, -12, -8, -12, - -4, -23, -23, -15, -15, -8, -8, -8, - -8, -19, -19, -8, -23, -4, -4, -23, - -23, -23, -12, -15, -19 - }; + -14, -14, -14, -10, -50, -50, -24, -41, + -5, -5, -14, -14, -14, -14, -14, -10, + -10, 33, -41, -41, -60, -43, -10, -29, + -15, -41, -6, -6, -6, 10, -6, -6, + -21, -15, -10, -10, -10, -8, -21, -9, + -5, -13, -29, -10, -12, -4, -7, -41, + -41, -60, -43, -10, -29, -15, -41, -6, + -6, -6, 10, -6, -6, -21, -15, -10, + -10, -18, -5, -5, -35, -5, -5, -11, + -15, -15, -15, -5, 10, 10, -15, -15, + 3, -10, -23, -12, 0, -23, -12, 0, + -24, -24, -41, -12, -3, -5, -5, -5, + -5, -24, -8, -7, 1, -7, -4, -18, + 9, -5, 9, -7, -3, -4, -3, -3, + -4, -11, -14, -8, -7, -11, -3, -3, + -3, -7, -3, -5, -7, -5, -5, -7, + -10, -12, -13, -13, -5, -13, -13, -11, + -8, -7, -3, -3, -3, -4, -5, -10, + -13, -5, -7, -5, -7, -23, -16, -8, + -5, -18, -11, -5, -3, -8, -10, -10, + -7, -4, -5, -5, -5, -5, -5, -11, + -5, -14, -5, -32, -32, -31, -17, -5, + -5, -61, -5, -5, -10, 1, 1, -11, + 0, -14, -15, -7, -7, -7, -11, -10, + -10, -7, -10, -7, -10, -10, -5, -8, + -10, -8, -12, -8, -13, -7, -13, -3, + -10, -7, -3, -11, -11, -18, -10, -10, + -18, -13, -4, -5, -10, -10, -10, -10, + -5, -8, -7, -6, -5, -8, -4, -4, + -4, -5, -4, -4, -15, -7, -10, -8, + -8, -10, -7, -21, -38, -38, -66, -24, + -15, -12, -12, -12, -12, -11, -53, -13, + -34, -25, -33, -35, -6, -6, -6, -7, + -3, -6, -6, -10, -5, -17, -15, -17, + -41, -16, -8, -5, -18, -11, -5, -3, + -8, -10, -10, -7, -4, -49, -15, -49, + -35, -23, -64, -5, -12, -11, -5, -36, + -20, -12, -12, -12, -14, -12, -12, -5, + -7, -10, -4, -16, -8, -5, -18, -11, + -5, -3, -8, -10, -10, -7, -4, -5, + -13, -3, -8, -7, -7, 1, 2, -3, + -2, -5, -3, -5, -5, -5, -3, -5, + -5, -4, -4, -5, -8, 5, -7, -7, + -10, -7, -11, -1, -6, -46, -32, -46, + -40, -10, -10, -18, -11, -11, -56, -11, + -11, -18, -10, -7, -24, -32, -29, -29, + -29, -8, -32, -21, -21, -29, -21, -29, + -21, -26, -8, -21, -15, -16, -18, -15, + -33, -28, -8, -8, -15, -8, -21, -5, + -3, -5, -7, -3, -5, -3, -4, -29, + -9, -29, -22, -7, -5, -5, -32, -5, + -5, -5, -5, 3, -9, -10, -7, -7, + -7, -10, -10, -10, -7, -10, -7, -10, + -6, -14, -5, -5, -7, -5, -12, -6, + -15, -5, -15, -14, -3, -3, -30, -3, + -3, -3, -3, -8, -7, -5, -5, -5, + -5, -13, -8, -8, -2, -8, -8, -7, + -10, -5, -5, -4, -4, -4, -8, -4, + -4, -8, -5, -8, -7, -5, -8, -7, + -18, -40, -29, -40, -30, -12, -12, -4, + -7, -7, -7, -44, -7, -7, -8, -7, + -5, -12, -30, -19, -19, -19, -27, -18, + -18, -19, -18, -19, -18, -19, -13, -15, + -7, -11, -15, -7, -21, -21, -16, -3, + -10, -10, -15, -10, -10, -14, -5, -3, + -3, -7, -8, -8, -10, -10, -10, -10, + -7, -10, -10, -7, -11, -8, -8, -11, + -8, -27, -10, 33, -38, -14, -24, -14, + -32, 13, 30, -10, -5, 5, -24, -6, + -11, -8, -3, -11, -7, -14, -14, -12, + -5, 2, -5, -6, -26, -9, -3, -21, + -12, -7, -2, -2, -8, -3, -3, -8, + -3, -3, -10, -10, -7, -11, -5, -10, + -10, -10, -5, -10, -10, -5, 2, 2, + 2, 2, -7, -16, 3, -4, -10, -10, + -11, -8, -5, -12, -10, -7, -2, -5, + -5, 1, 1, -4, 1, -1, -3, 5, + 16, 16, 20, -23, -7, -23, -7, 10, + 19, 28, 19, 13, 25, 26, 20, -10, + -5, -5, -5, -7, -5, -5, -5, -3, + 5, -3, -7, 20, -10, 5, -15, 20, + -17, -12, -7, 5, -8, -7, -7, -7, + 15, -7, -7, -3, -3, 5, -7, 5, + -4, -16, -4, -11, -5, -8, -10, 5, + -19, 5, 5, 5, -6, -16, -6, -5, + -9, -9, -9, -5, -5, -9, -9, -10, + -7, -4, -4, -12, 2, -16, -4, -11, + -5, -8, -16, -4, -11, -5, -8, -14, + -14, -12, -5, 2, -5, -6, -26, -9, + -3, -21, -12, -7, -2, -2, -8, -3, + -3, -8, -3, -3, -14, -14, -12, -5, + 2, -5, -6, -26, -9, -3, -21, -12, + -7, -2, -2, -8, -3, -3, -8, -3, + -3, -12, -10, -7, -14, -25, -11, -25, + -16, 10, 10, -7, -24, -5, 5, -11, + -5, -5, -5, -5, -5, -5, -3, 10, + 7, 10, -3, -8, -23, 3, -6, -11, + -5, -10, -10, 2, -12, 2, 3, 5, + 5, -12, -7, -3, -10, -7, -7, -7, + -5, -7, -7, -5, -10, -8, -10, -12, + -10, -7, -14, -6, -15, -4, -15, -10, + -6, -18, -10, -5, -7, -5, -10, -3, + -3, -3, -5, -3, -3, -11, -6, -17, + -17, -4, -3, -14, -11, -5, -7, -11, + -5, -3, -3, -3, -5, -3, -3, -8, + -7, -11, 2, -7, -4, 2, -5, -5, + -5, -5, -3, -15, -7, -5, -15, -5, + -8, -8, -8, -8, -8, -11, -2, -10, + -15, -15, -7, -18, -10, -3, -3, -4, + -10, -3, -3, -3, -5, -3, -3, -7, + -11, -8, -12, -14, -11, -5, -5, -5, + -3, -5, -5, -5, -3, -3, -6, -10, + 33, -11, -11, -28, -12, -12, -25, -17, + -10, -12, -12, -8, -8, -15, -19, -27, + -15, -8, -12, -12, 15, -8, -12, 4, + 4, 12, -8, -19, -8, -8, -27, -8, + -23, -12, -12, -8, -31, -15, 4, 4, + -12, -23, -27, -35, 8, 12, 12, -12, + -12, -8, -19, 12, -15, -19, -12, -12, + -12, -12, -23, -8, -8, -19, -8, -15, + 8, -15, -12, -12, -12, -15, -12, -12, + -12, -4, -12, -8, -8, -8, -8, 4, + -12, -8, -8, -15, -12, -12, -15, -12, + -8, -12, -8, -8, -8, -12, -12, -15, + 4, -15, -8, -15, 4, -8, -12, -12, + -19, -8, -19, -19, -19, -38, -8, -19, + -19, -19, -15, -15, -8, -8, -8, -35, + -15, -8, -8, -8, -8, -27, -19, -4, + -15, -23, -8, -4, -8, -8, -12, -12, + -15, -15, -8, -8, -8, -8, -8, -12, + -19, -23, -8, -8, -12, -8, -8, -15, + -12, -27, -12, -12, -15, -35, -4, -15, + -15, -12, -8, -15, -15, -23, -19, -19, + -31, -15, -12, -27, -8, -8, -8, -8, + -15, -35, -8, -8, -15, -15, -8, -31, + -4, -8, -8, -8, -12, -12, -12, -8, + -8, -8, -23, -23, -19, -27, -27, -27, + -12, -8, -23, -12, -8, -12, -12, -12, + -19, 8, 8, -12, -12, -23, -12, -8, + -4, -4, -31, -8, -12, -23, -12, -12, + -12, -27, -8, -8, -15, -8, -19, -19, + -12, -8, -8, -8, -8, -8, -15, -8, + -12, -8, -8, -8, 12, 12, 19, 12, + 12, 19, -8, -15, -8, -12, 8, -12, + -12, -12, -12, -8, 8, 8, -19, -12, + -23, -23, -23, -19, -8, -8, -8, -8, + -8, -8, -8, -8, -8, -8, -4, -4, + -12, -12, -23, -12, -12, -8, -8, -8, + -8, -23, -12, -19, -8, -8, -23, -8, + -8, -8, -19, -12, -12, -12, -8, -12, + -4, -23, -23, -15, -15, -8, -8, -8, + -8, -19, -19, -8, -23, -4, -4, -23, + -23, -23, -12, -15, -19 +}; /*Collect the kern pair's data in one place*/ -static const lv_font_fmt_txt_kern_pair_t kern_pairs = { +static const lv_font_fmt_txt_kern_pair_t kern_pairs = +{ .glyph_ids = kern_pair_glyph_ids, .values = kern_pair_values, .pair_cnt = 1229, diff --git a/src/ui/gui_assets/font/ja/jaTitle.c b/src/ui/gui_assets/font/ja/jaTitle.c index bc2d12cea..96057492b 100644 --- a/src/ui/gui_assets/font/ja/jaTitle.c +++ b/src/ui/gui_assets/font/ja/jaTitle.c @@ -2337,7 +2337,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -2354,7 +2355,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Pair left and right glyphs for kerning*/ -static const uint8_t kern_pair_glyph_ids[] = { +static const uint8_t kern_pair_glyph_ids[] = +{ 3, 13, 3, 15, 3, 34, @@ -3362,137 +3364,139 @@ static const uint8_t kern_pair_glyph_ids[] = { /* Kerning between the respective left and right glyphs * 4.4 format which needs to scaled with `kern_scale`*/ -static const int8_t kern_pair_values[] = { +static const int8_t kern_pair_values[] = +{ -75, -75, -36, -62, -8, -8, -21, -21, - -21, -21, -21, -14, -75, -75, -36, -62, - -8, -8, -21, -21, -21, -21, -21, -14, - -14, 50, -62, -62, -89, -65, -14, -43, - -23, -61, -9, -9, -9, 15, -9, -9, - -31, -23, -16, -14, -14, -13, -32, -14, - -8, -19, -44, -14, -18, -6, -10, -62, - -62, -89, -65, -14, -43, -23, -61, -9, - -9, -9, 15, -9, -9, -31, -23, -16, - -14, -28, -8, -8, -53, -8, -8, -17, - -22, -22, -22, -8, 15, 15, -22, -22, - 4, -14, -34, -18, 1, -34, -18, 1, - -36, -36, -62, -18, -5, -8, -8, -8, - -8, -36, -12, -10, 1, -10, -6, -28, - 13, -8, 13, -10, -5, -6, -4, -4, - -6, -17, -21, -12, -10, -17, -5, -4, - -4, -10, -4, -8, -10, -8, -8, -10, - -14, -18, -20, -20, -8, -20, -20, -17, - -13, -10, -4, -4, -4, -6, -8, -14, - -19, -8, -10, -8, -10, -35, -24, -13, - -8, -27, -17, -8, -5, -13, -14, -14, - -10, -6, -8, -8, -8, -8, -8, -17, - -8, -21, -8, -48, -48, -47, -26, -8, - -8, -91, -8, -8, -14, 1, 1, -17, - -1, -21, -23, -10, -10, -10, -17, -14, - -14, -10, -14, -10, -14, -14, -8, -12, - -14, -12, -18, -12, -20, -10, -19, -4, - -14, -10, -4, -17, -17, -28, -15, -15, - -28, -20, -6, -8, -14, -14, -14, -14, - -7, -13, -10, -9, -8, -12, -6, -6, - -6, -8, -6, -6, -23, -11, -14, -12, - -12, -14, -10, -31, -57, -57, -99, -36, - -22, -18, -18, -18, -18, -16, -79, -20, - -51, -37, -50, -53, -9, -9, -9, -10, - -4, -9, -9, -14, -8, -25, -23, -25, - -61, -24, -13, -8, -27, -17, -8, -5, - -13, -14, -14, -10, -6, -74, -23, -74, - -52, -34, -96, -8, -17, -17, -8, -54, - -29, -17, -17, -17, -21, -17, -17, -8, - -10, -14, -6, -24, -13, -8, -27, -17, - -8, -5, -13, -14, -14, -10, -6, -8, - -20, -4, -13, -10, -10, 2, 2, -4, - -2, -8, -4, -8, -8, -8, -4, -8, - -8, -6, -6, -8, -12, 7, -10, -10, - -14, -10, -17, -2, -9, -70, -48, -70, - -60, -14, -14, -28, -17, -17, -84, -17, - -17, -28, -14, -10, -36, -48, -44, -44, - -44, -13, -48, -32, -32, -44, -32, -44, - -32, -39, -13, -32, -23, -24, -28, -23, - -50, -43, -12, -12, -22, -12, -32, -8, - -4, -8, -10, -4, -8, -4, -6, -43, - -14, -43, -32, -10, -8, -8, -48, -8, - -8, -8, -8, 5, -14, -16, -11, -11, - -11, -16, -14, -14, -11, -14, -11, -14, - -9, -21, -7, -7, -11, -7, -18, -9, - -23, -8, -23, -21, -5, -5, -44, -5, - -5, -5, -5, -12, -10, -8, -8, -8, - -8, -19, -13, -13, -2, -13, -13, -10, - -14, -8, -8, -6, -6, -6, -12, -6, - -6, -12, -8, -12, -10, -8, -12, -10, - -28, -59, -44, -59, -45, -17, -17, -6, - -10, -10, -10, -66, -10, -10, -12, -10, - -8, -18, -45, -28, -28, -28, -40, -28, - -28, -28, -28, -28, -28, -28, -20, -23, - -10, -17, -23, -10, -32, -31, -24, -5, - -14, -14, -23, -14, -14, -21, -8, -5, - -5, -10, -12, -12, -16, -16, -16, -14, - -11, -16, -16, -10, -17, -12, -12, -17, - -12, -40, -14, 50, -57, -21, -36, -21, - -48, 20, 46, -14, -8, 7, -36, -9, - -17, -12, -4, -17, -10, -21, -21, -18, - -8, 2, -8, -9, -39, -14, -4, -31, - -18, -11, -3, -3, -13, -4, -4, -13, - -4, -5, -14, -14, -10, -17, -8, -16, - -16, -16, -8, -16, -16, -8, 2, 2, - 3, 2, -10, -24, 5, -6, -14, -14, - -17, -12, -8, -18, -14, -11, -3, -8, - -8, 2, 2, -6, 2, -1, -4, 7, - 24, 24, 31, -34, -10, -34, -11, 16, - 28, 41, 28, 20, 37, 39, 31, -14, - -8, -8, -8, -11, -8, -8, -8, -4, - 7, -4, -10, 31, -14, 7, -23, 29, - -25, -18, -10, 7, -12, -10, -10, -10, - 22, -10, -10, -4, -4, 8, -10, 7, - -6, -24, -6, -17, -8, -12, -16, 7, - -28, 7, 7, 7, -9, -24, -9, -8, - -13, -13, -13, -8, -8, -13, -13, -15, - -10, -6, -6, -18, 3, -24, -6, -17, - -8, -12, -24, -6, -17, -8, -12, -21, - -21, -18, -8, 2, -8, -9, -39, -14, - -4, -31, -18, -11, -3, -3, -13, -4, - -4, -13, -4, -5, -21, -21, -18, -8, - 2, -8, -9, -39, -14, -4, -31, -18, - -11, -3, -3, -13, -4, -4, -13, -4, - -5, -17, -14, -10, -21, -37, -17, -37, - -24, 15, 15, -10, -36, -8, 7, -17, - -8, -8, -8, -8, -8, -8, -4, 15, - 11, 15, -4, -12, -34, 5, -9, -17, - -8, -14, -14, 3, -18, 3, 5, 7, - 7, -18, -10, -4, -16, -10, -10, -10, - -8, -10, -10, -8, -14, -12, -14, -17, - -14, -10, -21, -9, -23, -6, -23, -14, - -9, -28, -14, -7, -10, -8, -14, -4, - -4, -4, -8, -4, -4, -17, -9, -26, - -26, -6, -4, -21, -17, -7, -10, -17, - -8, -4, -4, -4, -8, -4, -4, -13, - -10, -16, 3, -10, -6, 3, -8, -8, - -8, -8, -4, -23, -11, -8, -23, -8, - -13, -13, -13, -13, -13, -17, -2, -14, - -23, -23, -11, -28, -14, -4, -4, -6, - -14, -4, -4, -4, -8, -4, -4, -10, - -17, -12, -18, -21, -17, -8, -8, -8, - -5, -8, -8, -8, -4, -4, -9, -14, - 50, -17, -17, -43, -18, -18, -38, -26, - -14, -17, -17, -12, -12, -17, -12, 6, - -17, -17, -17, -12, -12, -12, -17, -23, - -29, -29, -29, -23, -12, -23, -12, -40, - -6, -23, -35, -12, -12, -17, -12, -12, - -12, -12, -12, -17, -17, -17, -6, -23, - -23, -17, -29, -29, -46, -17, -12, -12, - -12, -23, -12, -23, -23, -12, -17, -17, - -17, -12, -12, -12, 17, 17, 29, 17, - 17, 29, -17, 12, -35, -35, -12, -12, - -12, -12, -12, -12, -12, -17, -17, -12, - -35, -23, -12, -12, -29, -6, -6, -35, - -35, -17, -29 - }; + -21, -21, -21, -14, -75, -75, -36, -62, + -8, -8, -21, -21, -21, -21, -21, -14, + -14, 50, -62, -62, -89, -65, -14, -43, + -23, -61, -9, -9, -9, 15, -9, -9, + -31, -23, -16, -14, -14, -13, -32, -14, + -8, -19, -44, -14, -18, -6, -10, -62, + -62, -89, -65, -14, -43, -23, -61, -9, + -9, -9, 15, -9, -9, -31, -23, -16, + -14, -28, -8, -8, -53, -8, -8, -17, + -22, -22, -22, -8, 15, 15, -22, -22, + 4, -14, -34, -18, 1, -34, -18, 1, + -36, -36, -62, -18, -5, -8, -8, -8, + -8, -36, -12, -10, 1, -10, -6, -28, + 13, -8, 13, -10, -5, -6, -4, -4, + -6, -17, -21, -12, -10, -17, -5, -4, + -4, -10, -4, -8, -10, -8, -8, -10, + -14, -18, -20, -20, -8, -20, -20, -17, + -13, -10, -4, -4, -4, -6, -8, -14, + -19, -8, -10, -8, -10, -35, -24, -13, + -8, -27, -17, -8, -5, -13, -14, -14, + -10, -6, -8, -8, -8, -8, -8, -17, + -8, -21, -8, -48, -48, -47, -26, -8, + -8, -91, -8, -8, -14, 1, 1, -17, + -1, -21, -23, -10, -10, -10, -17, -14, + -14, -10, -14, -10, -14, -14, -8, -12, + -14, -12, -18, -12, -20, -10, -19, -4, + -14, -10, -4, -17, -17, -28, -15, -15, + -28, -20, -6, -8, -14, -14, -14, -14, + -7, -13, -10, -9, -8, -12, -6, -6, + -6, -8, -6, -6, -23, -11, -14, -12, + -12, -14, -10, -31, -57, -57, -99, -36, + -22, -18, -18, -18, -18, -16, -79, -20, + -51, -37, -50, -53, -9, -9, -9, -10, + -4, -9, -9, -14, -8, -25, -23, -25, + -61, -24, -13, -8, -27, -17, -8, -5, + -13, -14, -14, -10, -6, -74, -23, -74, + -52, -34, -96, -8, -17, -17, -8, -54, + -29, -17, -17, -17, -21, -17, -17, -8, + -10, -14, -6, -24, -13, -8, -27, -17, + -8, -5, -13, -14, -14, -10, -6, -8, + -20, -4, -13, -10, -10, 2, 2, -4, + -2, -8, -4, -8, -8, -8, -4, -8, + -8, -6, -6, -8, -12, 7, -10, -10, + -14, -10, -17, -2, -9, -70, -48, -70, + -60, -14, -14, -28, -17, -17, -84, -17, + -17, -28, -14, -10, -36, -48, -44, -44, + -44, -13, -48, -32, -32, -44, -32, -44, + -32, -39, -13, -32, -23, -24, -28, -23, + -50, -43, -12, -12, -22, -12, -32, -8, + -4, -8, -10, -4, -8, -4, -6, -43, + -14, -43, -32, -10, -8, -8, -48, -8, + -8, -8, -8, 5, -14, -16, -11, -11, + -11, -16, -14, -14, -11, -14, -11, -14, + -9, -21, -7, -7, -11, -7, -18, -9, + -23, -8, -23, -21, -5, -5, -44, -5, + -5, -5, -5, -12, -10, -8, -8, -8, + -8, -19, -13, -13, -2, -13, -13, -10, + -14, -8, -8, -6, -6, -6, -12, -6, + -6, -12, -8, -12, -10, -8, -12, -10, + -28, -59, -44, -59, -45, -17, -17, -6, + -10, -10, -10, -66, -10, -10, -12, -10, + -8, -18, -45, -28, -28, -28, -40, -28, + -28, -28, -28, -28, -28, -28, -20, -23, + -10, -17, -23, -10, -32, -31, -24, -5, + -14, -14, -23, -14, -14, -21, -8, -5, + -5, -10, -12, -12, -16, -16, -16, -14, + -11, -16, -16, -10, -17, -12, -12, -17, + -12, -40, -14, 50, -57, -21, -36, -21, + -48, 20, 46, -14, -8, 7, -36, -9, + -17, -12, -4, -17, -10, -21, -21, -18, + -8, 2, -8, -9, -39, -14, -4, -31, + -18, -11, -3, -3, -13, -4, -4, -13, + -4, -5, -14, -14, -10, -17, -8, -16, + -16, -16, -8, -16, -16, -8, 2, 2, + 3, 2, -10, -24, 5, -6, -14, -14, + -17, -12, -8, -18, -14, -11, -3, -8, + -8, 2, 2, -6, 2, -1, -4, 7, + 24, 24, 31, -34, -10, -34, -11, 16, + 28, 41, 28, 20, 37, 39, 31, -14, + -8, -8, -8, -11, -8, -8, -8, -4, + 7, -4, -10, 31, -14, 7, -23, 29, + -25, -18, -10, 7, -12, -10, -10, -10, + 22, -10, -10, -4, -4, 8, -10, 7, + -6, -24, -6, -17, -8, -12, -16, 7, + -28, 7, 7, 7, -9, -24, -9, -8, + -13, -13, -13, -8, -8, -13, -13, -15, + -10, -6, -6, -18, 3, -24, -6, -17, + -8, -12, -24, -6, -17, -8, -12, -21, + -21, -18, -8, 2, -8, -9, -39, -14, + -4, -31, -18, -11, -3, -3, -13, -4, + -4, -13, -4, -5, -21, -21, -18, -8, + 2, -8, -9, -39, -14, -4, -31, -18, + -11, -3, -3, -13, -4, -4, -13, -4, + -5, -17, -14, -10, -21, -37, -17, -37, + -24, 15, 15, -10, -36, -8, 7, -17, + -8, -8, -8, -8, -8, -8, -4, 15, + 11, 15, -4, -12, -34, 5, -9, -17, + -8, -14, -14, 3, -18, 3, 5, 7, + 7, -18, -10, -4, -16, -10, -10, -10, + -8, -10, -10, -8, -14, -12, -14, -17, + -14, -10, -21, -9, -23, -6, -23, -14, + -9, -28, -14, -7, -10, -8, -14, -4, + -4, -4, -8, -4, -4, -17, -9, -26, + -26, -6, -4, -21, -17, -7, -10, -17, + -8, -4, -4, -4, -8, -4, -4, -13, + -10, -16, 3, -10, -6, 3, -8, -8, + -8, -8, -4, -23, -11, -8, -23, -8, + -13, -13, -13, -13, -13, -17, -2, -14, + -23, -23, -11, -28, -14, -4, -4, -6, + -14, -4, -4, -4, -8, -4, -4, -10, + -17, -12, -18, -21, -17, -8, -8, -8, + -5, -8, -8, -8, -4, -4, -9, -14, + 50, -17, -17, -43, -18, -18, -38, -26, + -14, -17, -17, -12, -12, -17, -12, 6, + -17, -17, -17, -12, -12, -12, -17, -23, + -29, -29, -29, -23, -12, -23, -12, -40, + -6, -23, -35, -12, -12, -17, -12, -12, + -12, -12, -12, -17, -17, -17, -6, -23, + -23, -17, -29, -29, -46, -17, -12, -12, + -12, -23, -12, -23, -23, -12, -17, -17, + -17, -12, -12, -12, 17, 17, 29, 17, + 17, 29, -17, 12, -35, -35, -12, -12, + -12, -12, -12, -12, -12, -17, -17, -12, + -35, -23, -12, -12, -29, -6, -6, -35, + -35, -17, -29 +}; /*Collect the kern pair's data in one place*/ -static const lv_font_fmt_txt_kern_pair_t kern_pairs = { +static const lv_font_fmt_txt_kern_pair_t kern_pairs = +{ .glyph_ids = kern_pair_glyph_ids, .values = kern_pair_values, .pair_cnt = 1003, diff --git a/src/ui/gui_assets/font/ko/koIllustrate.c b/src/ui/gui_assets/font/ko/koIllustrate.c index b55c98c11..941fdb4f7 100644 --- a/src/ui/gui_assets/font/ko/koIllustrate.c +++ b/src/ui/gui_assets/font/ko/koIllustrate.c @@ -6551,7 +6551,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -6568,7 +6569,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 3, 0, 0, 0, 4, 5, 4, 6, 0, 0, 0, 0, 0, 0, 0, @@ -6641,7 +6643,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -6714,7 +6717,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6976,7 +6980,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/ko/koLittleTitle.c b/src/ui/gui_assets/font/ko/koLittleTitle.c index f6e78ccd4..8583050b4 100644 --- a/src/ui/gui_assets/font/ko/koLittleTitle.c +++ b/src/ui/gui_assets/font/ko/koLittleTitle.c @@ -3223,7 +3223,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -3240,7 +3241,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -3283,7 +3285,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -3326,7 +3329,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -59, 0, -59, 0, 0, 0, 0, -28, 0, -48, -6, 0, 0, 0, 0, -6, 0, 0, 0, 0, @@ -3556,7 +3560,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/ko/koText.c b/src/ui/gui_assets/font/ko/koText.c index 3c0c3d7e3..5ba8bd1a0 100644 --- a/src/ui/gui_assets/font/ko/koText.c +++ b/src/ui/gui_assets/font/ko/koText.c @@ -5165,7 +5165,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -5182,7 +5183,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -5230,7 +5232,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -5278,7 +5281,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -50, 0, -50, 0, 0, 0, 0, -24, 0, -41, -5, 0, 0, 0, 0, -5, 0, 0, 0, 0, @@ -5508,7 +5512,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/ko/koTitle.c b/src/ui/gui_assets/font/ko/koTitle.c index 4b30c74ea..ba1ea5230 100644 --- a/src/ui/gui_assets/font/ko/koTitle.c +++ b/src/ui/gui_assets/font/ko/koTitle.c @@ -2173,7 +2173,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY @@ -2190,7 +2191,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, @@ -2216,7 +2218,8 @@ static const uint8_t kern_left_class_mapping[] = { }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 3, 4, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, @@ -2242,7 +2245,8 @@ static const uint8_t kern_right_class_mapping[] = { }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { +static const int8_t kern_class_values[] = +{ 0, 0, 0, 0, -75, 0, -75, 0, 0, 0, 0, -36, 0, -62, -8, 0, 0, 0, 0, -8, 0, 0, 0, 0, @@ -2472,7 +2476,8 @@ static const int8_t kern_class_values[] = { /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, diff --git a/src/ui/gui_assets/font/ru/ruIllustrate.c b/src/ui/gui_assets/font/ru/ruIllustrate.c index f075bacf1..60e3d9e2e 100644 --- a/src/ui/gui_assets/font/ru/ruIllustrate.c +++ b/src/ui/gui_assets/font/ru/ruIllustrate.c @@ -1291,7 +1291,8 @@ static const uint16_t unicode_list_4[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/ru/ruLittleTitle.c b/src/ui/gui_assets/font/ru/ruLittleTitle.c index a88f981fe..cdf43c73e 100644 --- a/src/ui/gui_assets/font/ru/ruLittleTitle.c +++ b/src/ui/gui_assets/font/ru/ruLittleTitle.c @@ -1146,7 +1146,8 @@ static const uint16_t unicode_list_3[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/ru/ruText.c b/src/ui/gui_assets/font/ru/ruText.c index 280f099c4..a4f1c7389 100644 --- a/src/ui/gui_assets/font/ru/ruText.c +++ b/src/ui/gui_assets/font/ru/ruText.c @@ -1468,7 +1468,8 @@ static const uint16_t unicode_list_3[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_assets/font/ru/ruTitle.c b/src/ui/gui_assets/font/ru/ruTitle.c index ab29f3aae..b805470cd 100644 --- a/src/ui/gui_assets/font/ru/ruTitle.c +++ b/src/ui/gui_assets/font/ru/ruTitle.c @@ -1359,7 +1359,8 @@ static const uint16_t unicode_list_1[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/src/ui/gui_chain/gui_chain.c b/src/ui/gui_chain/gui_chain.c index adbdaa343..1e560f421 100644 --- a/src/ui/gui_chain/gui_chain.c +++ b/src/ui/gui_chain/gui_chain.c @@ -52,7 +52,10 @@ static const ViewHandlerEntry g_viewHandlerMap[] = { {EthPersonalMessage, GuiGetEthSignQrCodeData, GuiGetEthSignUrDataUnlimited, GuiGetEthCheckResult, CHAIN_ETH, REMAPVIEW_ETH_PERSONAL_MESSAGE}, {EthTypedData, GuiGetEthSignQrCodeData, GuiGetEthSignUrDataUnlimited, GuiGetEthCheckResult, CHAIN_ETH, REMAPVIEW_ETH_TYPEDDATA}, - {TronTx, GuiGetTrxSignQrCodeData, NULL, GuiGetTrxCheckResult, CHAIN_TRX, CHAIN_TRX, REMAPVIEW_TRX}, + {TronTx, GuiGetTrxSignQrCodeData, NULL, GuiGetTrxCheckResult, CHAIN_TRX, REMAPVIEW_TRX}, + + // avax + {AvaxTx, GuiGetAvaxSignQrCodeData, GuiGetAvaxSignUrDataUnlimited, GuiGetAvaxCheckResult, CHAIN_AVAX, REMAPVIEW_AVAX}, // must get from GuiGetCosmosTxChain {CosmosTx, GuiGetCosmosSignQrCodeData, NULL, GuiGetCosmosCheckResult, CHAIN_ATOM, REMAPVIEW_COSMOS}, diff --git a/src/ui/gui_chain/gui_chain.h b/src/ui/gui_chain/gui_chain.h index b784ad614..242514530 100644 --- a/src/ui/gui_chain/gui_chain.h +++ b/src/ui/gui_chain/gui_chain.h @@ -16,6 +16,7 @@ #include "gui_ar.h" #include "gui_stellar.h" #include "gui_ton.h" +#include "gui_avax.h" #else #include "gui_zcash.h" #include "gui_monero.h" @@ -81,6 +82,7 @@ typedef enum { CHAIN_UMEE, CHAIN_QCK, CHAIN_TGD, + CHAIN_AVAX, // cosmos end #endif @@ -118,6 +120,7 @@ typedef enum { REMAPVIEW_STELLAR_HASH, REMAPVIEW_TON, REMAPVIEW_TON_SIGNPROOF, + REMAPVIEW_AVAX, #endif #ifdef CYPHERPUNK_VERSION diff --git a/src/ui/gui_chain/gui_chain_components.c b/src/ui/gui_chain/gui_chain_components.c index 6b2ba67c8..133c46fe4 100644 --- a/src/ui/gui_chain/gui_chain_components.c +++ b/src/ui/gui_chain/gui_chain_components.c @@ -82,4 +82,111 @@ lv_obj_t *CreateTransactionItemViewWithHint(lv_obj_t *parent, const char* title, lv_obj_t *CreateTransactionItemView(lv_obj_t *parent, const char* title, const char* value, lv_obj_t *lastView) { return CreateTransactionItemViewWithHint(parent, title, value, lastView, NULL); +} + +lv_obj_t *CreateValueOverviewValue(lv_obj_t *parent, char* value, char *fee) +{ + lv_obj_t *container = CreateContentContainer(parent, 408, 144); + + lv_obj_t *label = GuiCreateIllustrateLabel(container, _("Value")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 16); + lv_obj_set_style_text_opa(label, LV_OPA_64, LV_PART_MAIN); + + label = GuiCreateTextLabel(container, value); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 50); + lv_obj_set_style_text_color(label, ORANGE_COLOR, LV_PART_MAIN); + + label = GuiCreateIllustrateLabel(container, _("Fee")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 98); + lv_obj_set_style_text_opa(label, LV_OPA_64, LV_PART_MAIN); + + label = GuiCreateIllustrateLabel(container, fee); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 73, 98); + + return container; +} + +lv_obj_t *CreateValueDetailValue(lv_obj_t *parent, char* inputValue, char *outputValue, char *fee) +{ + lv_obj_t *container = CreateContentContainer(parent, 408, 138); + + lv_obj_t *label = GuiCreateIllustrateLabel(container, _("Input Value")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 16); + lv_obj_set_style_text_opa(label, LV_OPA_64, LV_PART_MAIN); + + label = GuiCreateIllustrateLabel(container, inputValue); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 147, 16); + + label = GuiCreateIllustrateLabel(container, _("Output Value")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 54); + lv_obj_set_style_text_opa(label, LV_OPA_64, LV_PART_MAIN); + + label = GuiCreateIllustrateLabel(container, outputValue); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 164, 54); + + label = GuiCreateIllustrateLabel(container, _("Fee")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 92); + lv_obj_set_style_text_opa(label, LV_OPA_64, LV_PART_MAIN); + + label = GuiCreateIllustrateLabel(container, fee); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 73, 92); + + return container; +} + +lv_obj_t *CreateSingleInfoView(lv_obj_t *parent, char* key, char *value) +{ + return CreateDynamicInfoView(parent, &key, &value, 1); +} + +lv_obj_t *CreateDynamicInfoView(lv_obj_t *parent, char *key[], char *value[], int keyLen) +{ + int height = (30 + 8) * keyLen - 8 + 16 + 16; + + lv_obj_t *container = CreateContentContainer(parent, 408, height); + + for (int i = 0; i < keyLen; i++) { + lv_obj_t *label = GuiCreateIllustrateLabel(container, _(key[i])); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 16 + 30 * i + 8 * i); + lv_obj_set_style_text_opa(label, LV_OPA_64, LV_PART_MAIN); + + label = GuiCreateIllustrateLabel(container, value[i]); + GuiAlignToPrevObj(label, LV_ALIGN_OUT_RIGHT_MID, 16, 0); + } + + return container; +} + +lv_obj_t *CreateContentContainer(lv_obj_t *parent, uint16_t w, uint16_t h) +{ + lv_obj_t *container = GuiCreateContainerWithParent(parent, w, h); + lv_obj_set_style_bg_color(container, WHITE_COLOR, LV_PART_MAIN); + lv_obj_set_style_bg_opa(container, LV_OPA_12, LV_PART_MAIN); + lv_obj_set_style_radius(container, 24, LV_PART_MAIN); + return container; +} + +lv_obj_t *CreateNoticeCard(lv_obj_t *parent, char *notice) +{ + uint16_t height = 24 + 36 + 8 + 24; + lv_obj_t* card = GuiCreateContainerWithParent(parent, 408, 24); + lv_obj_set_style_radius(card, 24, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(card, WHITE_COLOR, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(card, 30, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_t* noticeIcon = GuiCreateImg(card, &imgNotice); + lv_obj_align(noticeIcon, LV_ALIGN_TOP_LEFT, 24, 24); + + lv_obj_t* title_label = GuiCreateTextLabel(card, "Notice"); + lv_obj_set_style_text_color(title_label, lv_color_hex(0xF5870A), LV_PART_MAIN); + lv_obj_align_to(title_label, noticeIcon, LV_ALIGN_OUT_RIGHT_MID, 8, 0); + + lv_obj_t* content_label = GuiCreateIllustrateLabel(card, notice); + lv_obj_set_width(content_label, 360); + lv_obj_update_layout(content_label); + height += lv_obj_get_self_height(content_label); + lv_obj_set_height(card, height); + lv_obj_align(content_label, LV_ALIGN_TOP_LEFT, 24, 68); + + return card; } \ No newline at end of file diff --git a/src/ui/gui_chain/gui_chain_components.h b/src/ui/gui_chain/gui_chain_components.h index f4c03301b..117995d16 100644 --- a/src/ui/gui_chain/gui_chain_components.h +++ b/src/ui/gui_chain/gui_chain_components.h @@ -6,5 +6,11 @@ lv_obj_t *CreateTransactionContentContainer(lv_obj_t *parent, uint16_t w, uint16_t h); lv_obj_t *CreateTransactionItemView(lv_obj_t *parent, const char* title, const char* value, lv_obj_t *lastView); lv_obj_t *CreateTransactionItemViewWithHint(lv_obj_t *parent, const char* title, const char* value, lv_obj_t *lastView, const char* hint); +lv_obj_t *CreateValueOverviewValue(lv_obj_t *parent, char* value, char *fee); +lv_obj_t *CreateSingleInfoView(lv_obj_t *parent, char* key, char *value); +lv_obj_t *CreateContentContainer(lv_obj_t *parent, uint16_t w, uint16_t h); +lv_obj_t *CreateValueDetailValue(lv_obj_t *parent, char* inputValue, char *outputValue, char *fee); +lv_obj_t *CreateDynamicInfoView(lv_obj_t *parent, char *key[], char *value[], int keyLen); +lv_obj_t *CreateNoticeCard(lv_obj_t *parent, char* notice); #endif \ No newline at end of file diff --git a/src/ui/gui_chain/multi/web3/gui_avax.c b/src/ui/gui_chain/multi/web3/gui_avax.c new file mode 100644 index 000000000..7be4dc10e --- /dev/null +++ b/src/ui/gui_chain/multi/web3/gui_avax.c @@ -0,0 +1,238 @@ +#ifndef BTC_ONLY +#include "gui_avax.h" +#include "rust.h" +#include "account_manager.h" +#include "secret_cache.h" +#include "gui_chain.h" +#include "gui_chain_components.h" + +#define CHECK_FREE_PARSE_RESULT(result) \ + if (result != NULL) \ + { \ + free_TransactionParseResult_DisplayAvaxTx(g_parseResult); \ + g_parseResult = NULL; \ + } + +static URParseResult *g_urResult = NULL; +static URParseMultiResult *g_urMultiResult = NULL; +static void *g_parseResult = NULL; +static bool g_isMulti = false; +static ViewType g_viewType = ViewTypeUnKnown; + +static lv_obj_t *CreateOverviewAmountView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView); +static lv_obj_t *CreateOverviewActionView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView); +static lv_obj_t *CreateOverviewDestinationView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView); +static lv_obj_t *CreateOverviewContractDataView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView); +static lv_obj_t *CreateDetailsDataViewView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView); +static lv_obj_t *CreateDetailsRawDataView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView); +UREncodeResult *GetAvaxSignDataDynamic(bool isUnlimited); + +void GuiSetAvaxUrData(URParseResult *urResult, URParseMultiResult *urMultiResult, bool multi) +{ + g_urResult = urResult; + g_urMultiResult = urMultiResult; + g_isMulti = multi; + g_viewType = g_isMulti ? g_urMultiResult->t : g_urResult->t; +} + +UREncodeResult *GuiGetAvaxSignQrCodeData(void) +{ + return GetAvaxSignDataDynamic(false); +} + +UREncodeResult *GuiGetAvaxSignUrDataUnlimited(void) +{ + return GetAvaxSignDataDynamic(true); +} + +UREncodeResult *GetAvaxSignDataDynamic(bool isUnlimited) +{ + printf("%s %d.\n", __func__,__LINE__); + bool enable = IsPreviousLockScreenEnable(); + SetLockScreen(false); + UREncodeResult *encodeResult; + void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data; + do { + uint8_t seed[64]; + int len = GetMnemonicType() == MNEMONIC_TYPE_BIP39 ? sizeof(seed) : GetCurrentAccountEntropyLen(); + GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword()); + if (isUnlimited) { + encodeResult = avax_sign_unlimited(data, seed, len); + } else { + encodeResult = avax_sign(data, seed, len); + } + ClearSecretCache(); + CHECK_CHAIN_BREAK(encodeResult); + } while (0); + SetLockScreen(enable); + return encodeResult; +} + +PtrT_TransactionCheckResult GuiGetAvaxCheckResult(void) +{ + uint8_t mfp[4] = {0}; + void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data; + GetMasterFingerPrint(mfp); + return avax_check_transaction(data, mfp, sizeof(mfp)); +} + +void *GuiGetAvaxGUIData(void) +{ + printf("%s %d.\n", __func__,__LINE__); + CHECK_FREE_PARSE_RESULT(g_parseResult); + void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data; + do { + uint8_t mfp[4] = {0}; + GetMasterFingerPrint(mfp); + PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey)); + ExtendedPublicKey keys[2]; + public_keys->data = keys; + public_keys->size = NUMBER_OF_ARRAYS(keys); + keys[0].path = "m/44'/60'/0'"; + keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_AVAX_BIP44_STANDARD); + keys[1].path = "m/44'/9000'/0"; + keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_AVAX_X_P); + PtrT_TransactionParseResult_DisplayTonTransaction parseResult = avax_parse_transaction(data, mfp, sizeof(mfp), public_keys); + SRAM_FREE(public_keys); + CHECK_CHAIN_BREAK(parseResult); + g_parseResult = (void *)parseResult; + } while (0); + return g_parseResult; +} +typedef struct { + char *address; + char *amount; + char *path; +} DisplayUtxoFromTo; + +lv_obj_t *CreateTxOverviewFromTo(lv_obj_t *parent, void *from, int fromLen, void *to, int toLen) +{ + int height = 16 + 30 + 8 + (60 + 8) * fromLen - 8 + 16 + 30 + 8 + (60 + 8) * toLen + 16; + lv_obj_t *container = CreateContentContainer(parent, 408, height); + + DisplayUtxoFromTo *ptr = (DisplayUtxoFromTo *)from; + lv_obj_t *label = GuiCreateNoticeLabel(container, _("From")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 16); + for (int i = 0; i < fromLen; i++) { + lv_obj_t *label = GuiCreateIllustrateLabel(container, ptr[i].address); + lv_obj_set_width(label, 360); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 54 + 60 * i); + } + + ptr = (DisplayUtxoFromTo *)to; + uint16_t offset = 30 + 8 + (30 + 8) * fromLen + 16; + label = GuiCreateNoticeLabel(container, _("To")); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, offset); + for (int i = 0; i < toLen; i++) { + lv_obj_t *label = GuiCreateIllustrateLabel(container, ptr[i].address); + lv_obj_set_width(label, 360); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 38 + offset + 68 * i); + } + + return container; +} + +lv_obj_t *CreateTxDetailsFromTo(lv_obj_t *parent, char *tag, void *fromTo, int len) +{ + int height = 16 + 30 + 8 + (128 + 8) * len - 8 + 16; + lv_obj_t *container = CreateContentContainer(parent, 408, height); + + DisplayUtxoFromTo *ptr = (DisplayUtxoFromTo *)fromTo; + lv_obj_t *label = GuiCreateNoticeLabel(container, tag); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 16); + for (int i = 0; i < len; i++) { + lv_obj_t *label = GuiCreateIllustrateLabel(container, ""); + lv_label_set_recolor(label, true); + lv_label_set_text_fmt(label, "%d #F5870A %s#", i, ptr[i].amount); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 54 + (128 + 8) * i); + + label = GuiCreateIllustrateLabel(container, ptr[i].address); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 88 + (128 + 8) * i); + lv_obj_set_width(label, 360); + } + + return container; +} + +void GuiAvaxTxOverview(lv_obj_t *parent, void *totalData) +{ + DisplayAvaxTx *txData = (DisplayAvaxTx *)totalData; + lv_obj_set_size(parent, 408, 444); + lv_obj_add_flag(parent, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_flag(parent, LV_OBJ_FLAG_CLICKABLE); + lv_obj_clear_flag(parent, LV_OBJ_FLAG_SCROLL_ELASTIC); + + lv_obj_t *container = CreateValueOverviewValue(parent, txData->data->total_output_amount, txData->data->fee_amount); + + if (txData->data->network != NULL) { + char *key[] = {txData->data->network_key, "Subnet ID"}; + char *value[] = {txData->data->network, txData->data->subnet_id}; + container = CreateDynamicInfoView(parent, key, value, NUMBER_OF_ARRAYS(key) - (txData->data->subnet_id ? 0 : 1)); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + } + + if (txData->data->method != NULL) { + container = CreateSingleInfoView(parent, txData->data->method->method_key, txData->data->method->method); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + } + + printf("txData->data->from->size->address: %s\n", txData->data->to->data[0].address); + container = CreateTxOverviewFromTo(parent, NULL, 0, txData->data->to->data, txData->data->to->size); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + lv_obj_update_layout(parent); +} + +void GuiAvaxTxRawData(lv_obj_t *parent, void *totalData) +{ + DisplayAvaxTx *txData = (DisplayAvaxTx *)totalData; + lv_obj_set_size(parent, 408, 444); + lv_obj_add_flag(parent, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_flag(parent, LV_OBJ_FLAG_CLICKABLE); + lv_obj_clear_flag(parent, LV_OBJ_FLAG_SCROLL_ELASTIC); + + lv_obj_t *container = NULL; + if (txData->data->network != NULL) { + char *key[] = {txData->data->network_key, "Subnet ID"}; + char *value[] = {txData->data->network, txData->data->subnet_id}; + container = CreateDynamicInfoView(parent, key, value, NUMBER_OF_ARRAYS(key) - (txData->data->subnet_id ? 0 : 1)); + } + + if (txData->data->method != NULL) { + char startTime[BUFFER_SIZE_64] = {0}, endTime[BUFFER_SIZE_64] = {0}; + uint8_t keyLen = 1; + if (txData->data->method->start_time != 0 && txData->data->method->end_time != 0) { + StampTimeToUtcTime(txData->data->method->start_time, startTime, sizeof(startTime)); + StampTimeToUtcTime(txData->data->method->end_time, endTime, sizeof(endTime)); + keyLen = 3; + } + char *key[] = {txData->data->method->method_key, "Start time", "End Time"}; + char *value[] = {txData->data->method->method, startTime, endTime}; + container = CreateDynamicInfoView(parent, key, value, keyLen); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + } + + container = CreateValueDetailValue(parent, txData->data->total_input_amount, txData->data->total_output_amount, txData->data->fee_amount); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + + container = CreateTxDetailsFromTo(parent, "From", NULL, 0); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + + container = CreateTxDetailsFromTo(parent, "To", txData->data->to->data, txData->data->to->size); + GuiAlignToPrevObj(container, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); + lv_obj_update_layout(parent); +} + +static lv_obj_t *CreateDetailsDataViewView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView) +{ +} +static lv_obj_t *CreateDetailsRawDataView(lv_obj_t *parent, DisplayAvaxTx *data, lv_obj_t *lastView) +{ +} + +void FreeAvaxMemory(void) +{ + CHECK_FREE_UR_RESULT(g_urResult, false); + CHECK_FREE_UR_RESULT(g_urMultiResult, true); + CHECK_FREE_PARSE_RESULT(g_parseResult); +} +#endif \ No newline at end of file diff --git a/src/ui/gui_chain/multi/web3/gui_avax.h b/src/ui/gui_chain/multi/web3/gui_avax.h new file mode 100644 index 000000000..384f5d373 --- /dev/null +++ b/src/ui/gui_chain/multi/web3/gui_avax.h @@ -0,0 +1,18 @@ +#ifndef _GUI_AVAX_H +#define _GUI_AVAX_H + +#include "rust.h" +#include "stdbool.h" +#include "gui.h" + +void GuiSetAvaxUrData(URParseResult *urResult, URParseMultiResult *urMultiResult, bool multi); +void *GuiGetAvaxGUIData(void); +PtrT_TransactionCheckResult GuiGetAvaxCheckResult(void); +UREncodeResult *GuiGetAvaxSignQrCodeData(void); +UREncodeResult *GuiGetAvaxSignUrDataUnlimited(void); +void GuiAvaxTxOverview(lv_obj_t *parent, void *totalData); +void GuiAvaxTxRawData(lv_obj_t *parent, void *totalData); +void FreeAvaxMemory(void); +PtrT_TransactionCheckResult GuiGetAvaxCheckResult(void); + +#endif diff --git a/src/ui/gui_chain/multi/web3/gui_eth.c b/src/ui/gui_chain/multi/web3/gui_eth.c index 04eb5fe90..f4e4d122e 100644 --- a/src/ui/gui_chain/multi/web3/gui_eth.c +++ b/src/ui/gui_chain/multi/web3/gui_eth.c @@ -204,7 +204,7 @@ const static EvmNetwork_t NETWORKS[] = { {42220, "Celo Mainnet", "CELO"}, {43110, "Athereum", "ATH"}, {43113, "Avalanche Fuji Testnet", "AVAX"}, - {43114, "Avalanche Mainnet", "AVAX"}, + {43114, "Avalanche C-Chain", "AVAX"}, {44787, "Celo Alfajores Testnet", "CELO"}, {49797, "Energi Testnet", "NRG"}, {62320, "Celo Baklava Testnet", "CELO"}, diff --git a/src/ui/gui_chain/multi/web3/gui_sol.c b/src/ui/gui_chain/multi/web3/gui_sol.c index 47212a4e3..ede9d409c 100644 --- a/src/ui/gui_chain/multi/web3/gui_sol.c +++ b/src/ui/gui_chain/multi/web3/gui_sol.c @@ -472,7 +472,7 @@ static void GuiShowSolTxTransferOverview(lv_obj_t *parent, PtrT_DisplaySolanaTxO } -lv_obj_t* GuiCreateNoticeCard(lv_obj_t* parent) +lv_obj_t* GuiCreateSolNoticeCard(lv_obj_t* parent) { lv_obj_t* card = GuiCreateAutoHeightContainer(parent, 408, 24); SetContainerDefaultStyle(card); @@ -745,7 +745,7 @@ static void GuiShowSplTokenTransferOverview(lv_obj_t *parent, PtrT_DisplaySolana SetContainerDefaultStyle(container); PtrT_DisplaySolanaTxSplTokenTransferOverview splTokenTransfer = overviewData->spl_token_transfer; if (strcmp(splTokenTransfer->token_name, "Unknown") == 0) { - lv_obj_t *noticeCard = GuiCreateNoticeCard(parent); + lv_obj_t *noticeCard = GuiCreateSolNoticeCard(parent); lv_obj_align_to(tokenInfoCard, noticeCard, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); } lv_obj_align_to(container, tokenInfoCard, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); diff --git a/src/ui/gui_chain/multi/web3/gui_ton.c b/src/ui/gui_chain/multi/web3/gui_ton.c index 8862634bc..27d8ba0ba 100644 --- a/src/ui/gui_chain/multi/web3/gui_ton.c +++ b/src/ui/gui_chain/multi/web3/gui_ton.c @@ -25,7 +25,6 @@ static void *g_proofParseResult = NULL; static bool g_isMulti = false; static ViewType g_viewType = ViewTypeUnKnown; -static lv_obj_t *createContentContainer(lv_obj_t *parent, uint16_t w, uint16_t h); static lv_obj_t *CreateOverviewAmountView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView); static lv_obj_t *CreateOverviewActionView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView); static lv_obj_t *CreateOverviewDestinationView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView); @@ -177,18 +176,10 @@ void GuiTonTxRawData(lv_obj_t *parent, void *totalData) lastView = CreateDetailsRawDataView(parent, txData, lastView); } -static lv_obj_t *createContentContainer(lv_obj_t *parent, uint16_t w, uint16_t h) -{ - lv_obj_t *container = GuiCreateContainerWithParent(parent, w, h); - lv_obj_set_style_bg_color(container, WHITE_COLOR, LV_PART_MAIN); - lv_obj_set_style_bg_opa(container, LV_OPA_12, LV_PART_MAIN); - lv_obj_set_style_radius(container, 24, LV_PART_MAIN); - return container; -} static lv_obj_t *CreateOverviewAmountView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView) { - lv_obj_t *container = createContentContainer(parent, 408, 106); + lv_obj_t *container = CreateContentContainer(parent, 408, 106); lv_obj_t *label = GuiCreateIllustrateLabel(container, _("Amount")); lv_obj_align(label, LV_ALIGN_TOP_LEFT, 24, 16); @@ -203,7 +194,7 @@ static lv_obj_t *CreateOverviewAmountView(lv_obj_t *parent, DisplayTonTransactio static lv_obj_t *CreateOverviewActionView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView) { - lv_obj_t *container = createContentContainer(parent, 408, 64); + lv_obj_t *container = CreateContentContainer(parent, 408, 64); lv_obj_align_to(container, lastView, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); lv_obj_t *label = GuiCreateIllustrateLabel(container, _("Action")); @@ -217,7 +208,7 @@ static lv_obj_t *CreateOverviewActionView(lv_obj_t *parent, DisplayTonTransactio static lv_obj_t *CreateOverviewDestinationView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView) { - lv_obj_t *container = createContentContainer(parent, 408, 244); + lv_obj_t *container = CreateContentContainer(parent, 408, 244); lv_obj_align_to(container, lastView, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); bool isTonNative = GetMnemonicType() == MNEMONIC_TYPE_TON; char *xPub = NULL; @@ -257,7 +248,7 @@ static lv_obj_t *CreateOverviewDestinationView(lv_obj_t *parent, DisplayTonTrans static lv_obj_t *CreateOverviewCommentView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView) { - lv_obj_t *container = createContentContainer(parent, 408, 62); + lv_obj_t *container = CreateContentContainer(parent, 408, 62); lv_obj_align_to(container, lastView, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); lv_obj_t *label = GuiCreateIllustrateLabel(container, _("Comment")); @@ -302,7 +293,7 @@ static lv_obj_t *CreateOverviewContractDataView(lv_obj_t *parent, DisplayTonTran char* value = cJSON_GetObjectItem(data, "value")->valuestring; //100 = 16(padding top) + 16(padding bottom) + 30(title) + 8(margin) + 30(value one line) - lv_obj_t *container = createContentContainer(parent, 408, 100); + lv_obj_t *container = CreateContentContainer(parent, 408, 100); lv_obj_align_to(container, lastView, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 16); lv_obj_t *label = GuiCreateIllustrateLabel(container, title); @@ -328,7 +319,7 @@ static lv_obj_t *CreateOverviewContractDataView(lv_obj_t *parent, DisplayTonTran static lv_obj_t *CreateDetailsDataViewView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView) { - lv_obj_t *container = createContentContainer(parent, 408, 244); + lv_obj_t *container = CreateContentContainer(parent, 408, 244); lv_obj_add_flag(container, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(container, LV_OBJ_FLAG_CLICKABLE); @@ -345,7 +336,7 @@ static lv_obj_t *CreateDetailsDataViewView(lv_obj_t *parent, DisplayTonTransacti } static lv_obj_t *CreateDetailsRawDataView(lv_obj_t *parent, DisplayTonTransaction *data, lv_obj_t *lastView) { - lv_obj_t *container = createContentContainer(parent, 408, 244); + lv_obj_t *container = CreateContentContainer(parent, 408, 244); lv_obj_add_flag(container, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(container, LV_OBJ_FLAG_CLICKABLE); if (lastView != NULL) { @@ -372,7 +363,7 @@ void GuiTonProofOverview(lv_obj_t *parent, void *totalData) lv_obj_add_flag(parent, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(parent, LV_OBJ_FLAG_CLICKABLE); - lv_obj_t *container = createContentContainer(parent, 408, 382); + lv_obj_t *container = CreateContentContainer(parent, 408, 382); lv_obj_add_flag(container, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(container, LV_OBJ_FLAG_CLICKABLE); @@ -419,7 +410,7 @@ void GuiTonProofRawData(lv_obj_t *parent, void *totalData) lv_obj_add_flag(parent, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(parent, LV_OBJ_FLAG_CLICKABLE); - lv_obj_t *container = createContentContainer(parent, 408, 382); + lv_obj_t *container = CreateContentContainer(parent, 408, 382); lv_obj_add_flag(container, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(container, LV_OBJ_FLAG_CLICKABLE); diff --git a/src/ui/gui_components/gui_status_bar.c b/src/ui/gui_components/gui_status_bar.c index 01c126636..d0ecd11f4 100644 --- a/src/ui/gui_components/gui_status_bar.c +++ b/src/ui/gui_components/gui_status_bar.c @@ -356,6 +356,7 @@ const char *GetWalletNameByIndex(WALLET_LIST_INDEX_ENUM index) uint8_t GetCurrentDisplayPercent(void) { + return 100; #ifdef COMPILE_SIMULATOR return 100; #endif diff --git a/src/ui/gui_frame/gui_obj.c b/src/ui/gui_frame/gui_obj.c index 0e3f5a6ec..61e6744b6 100644 --- a/src/ui/gui_frame/gui_obj.c +++ b/src/ui/gui_frame/gui_obj.c @@ -391,6 +391,9 @@ void *GuiCreateSwitch(lv_obj_t *parent) void GuiAlignToPrevObj(lv_obj_t *obj, lv_align_t align, int16_t x, int16_t y) { + if (lv_obj_get_child_cnt(lv_obj_get_parent(obj)) == 1) { + return; + } lv_obj_align_to(obj, lv_obj_get_child(lv_obj_get_parent(obj), lv_obj_get_child_cnt(lv_obj_get_parent(obj)) - 2), align, x, y); } diff --git a/src/ui/gui_model/gui_model.c b/src/ui/gui_model/gui_model.c index 246c4d9ee..f902d996f 100644 --- a/src/ui/gui_model/gui_model.c +++ b/src/ui/gui_model/gui_model.c @@ -1188,7 +1188,9 @@ static int32_t ModeControlQrDecode(const void *inData, uint32_t inDataLen) PubValueMsg(QRDECODE_MSG_STOP, 0); } #else - read_qrcode(); + if (en) { + read_qrcode(); + } #endif SetLockScreen(enable); return SUCCESS_CODE; @@ -1235,6 +1237,7 @@ static int32_t ModelCheckTransaction(const void *inData, uint32_t inDataLen) { GuiApiEmitSignal(SIG_SHOW_TRANSACTION_LOADING, NULL, 0); ViewType viewType = *((ViewType *)inData); + printf("%s %d.\n", __func__,__LINE__); g_checkResult = CheckUrResult(viewType); if (g_checkResult != NULL && g_checkResult->error_code == 0) { GuiApiEmitSignal(SIG_TRANSACTION_CHECK_PASS, NULL, 0); diff --git a/src/ui/gui_model/gui_model.h b/src/ui/gui_model/gui_model.h index ba4137e05..fe170ce54 100644 --- a/src/ui/gui_model/gui_model.h +++ b/src/ui/gui_model/gui_model.h @@ -24,6 +24,7 @@ #include "drv_battery.h" #include "gui_animating_qrcode.h" #include "account_manager.h" +#include "drv_rtc.h" #define MAX_LOGIN_PASSWORD_ERROR_COUNT 10 #define MAX_CURRENT_PASSWORD_ERROR_COUNT_SHOW_HINTBOX 4 diff --git a/src/ui/gui_views/gui_scan_view.c b/src/ui/gui_views/gui_scan_view.c index eb850bd39..b2ab0ebb7 100644 --- a/src/ui/gui_views/gui_scan_view.c +++ b/src/ui/gui_views/gui_scan_view.c @@ -25,7 +25,7 @@ int32_t GuiScanViewEventProcess(void *self, uint16_t usEvent, void *param, uint1 GuiScanResult(true, param); break; case SIG_TRANSACTION_CHECK_PASS: - printf("chekx pass"); + printf("check pass...........\n"); GuiTransactionCheckPass(); break; case SIG_TRANSACTION_CHECK_FAIL: diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.c b/src/ui/gui_wallet/multi/web3/gui_wallet.c index cf5cad467..64e8eb4a6 100644 --- a/src/ui/gui_wallet/multi/web3/gui_wallet.c +++ b/src/ui/gui_wallet/multi/web3/gui_wallet.c @@ -149,6 +149,29 @@ UREncodeResult *GuiGetImTokenData(void) return g_urEncode; } +UREncodeResult *GuiGetCoreWalletData(void) +{ + uint8_t mfp[4] = {0}; + GetMasterFingerPrint(mfp); + PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey)); + ExtendedPublicKey keys[2]; + public_keys->data = keys; + public_keys->size = NUMBER_OF_ARRAYS(keys); + + keys[0].path = "m/44'/60'/0'"; + keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_ETH_BIP44_STANDARD); + keys[1].path = "m/44'/9000'/0'"; + keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_AVAX_X_P); + + g_urEncode = get_core_wallet_ur(mfp, sizeof(mfp), public_keys, "Keystone3"); + if (g_urEncode->error_code == 0) { + printf("g_urEncode: %s\n", g_urEncode->data); + } + CHECK_CHAIN_PRINT(g_urEncode); + SRAM_FREE(public_keys); + return g_urEncode; +} + UREncodeResult *GuiGetArConnectData(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 61dbe9c06..257d69d10 100644 --- a/src/ui/gui_wallet/multi/web3/gui_wallet.h +++ b/src/ui/gui_wallet/multi/web3/gui_wallet.h @@ -28,6 +28,7 @@ UREncodeResult *GuiGetBackpackData(void); UREncodeResult *GuiGetXrpToolkitDataByIndex(uint16_t index); UREncodeResult *GuiGetADADataByIndex(char *walletName); UREncodeResult *GuiGetImTokenData(void); +UREncodeResult *GuiGetCoreWalletData(void); UREncodeResult *GuiGetKeystoneWalletData(void); UREncodeResult *GuiGetThorWalletBtcData(void); #endif diff --git a/src/ui/gui_widgets/gui_connect_wallet_widgets.h b/src/ui/gui_widgets/gui_connect_wallet_widgets.h index ba30134c3..48ee3ad32 100644 --- a/src/ui/gui_widgets/gui_connect_wallet_widgets.h +++ b/src/ui/gui_widgets/gui_connect_wallet_widgets.h @@ -28,6 +28,7 @@ typedef enum { WALLET_LIST_SPARROW, WALLET_LIST_UNISAT, WALLET_LIST_IMTOKEN, + WALLET_LIST_CORE, WALLET_LIST_BLOCK_WALLET, WALLET_LIST_ZAPPER, WALLET_LIST_HELIUM, diff --git a/src/ui/gui_widgets/gui_global_resources.c b/src/ui/gui_widgets/gui_global_resources.c index 12e7390df..28cb72582 100644 --- a/src/ui/gui_widgets/gui_global_resources.c +++ b/src/ui/gui_widgets/gui_global_resources.c @@ -55,7 +55,7 @@ void DerivationPathDescsInit(void) char **GetDerivationPathDescs(uint8_t index) { DerivationPathDescsInit(); - if (index == ETH_DERIVATION_PATH_DESC) { + if (index == ETH_DERIVATION_PATH_DESC || index == AVAX_DERIVATION_PATH_DESC) { return (char **)g_ethDerivationPathDesc; } if (index == SOL_DERIVATION_PATH_DESC) { diff --git a/src/ui/gui_widgets/gui_global_resources.h b/src/ui/gui_widgets/gui_global_resources.h index adf6599ee..ceb425384 100644 --- a/src/ui/gui_widgets/gui_global_resources.h +++ b/src/ui/gui_widgets/gui_global_resources.h @@ -33,6 +33,7 @@ typedef enum { SOL_DERIVATION_PATH_DESC, BTC_DERIVATION_PATH_DESC, ADA_DERIVATION_PATH_DESC, + AVAX_DERIVATION_PATH_DESC, #ifdef BTC_ONLY BTC_TEST_NET_DERIVATION_PATH_DESC, #endif diff --git a/src/ui/gui_widgets/gui_transaction_detail_widgets.c b/src/ui/gui_widgets/gui_transaction_detail_widgets.c index cbbc7b19d..e67d7a0b6 100644 --- a/src/ui/gui_widgets/gui_transaction_detail_widgets.c +++ b/src/ui/gui_widgets/gui_transaction_detail_widgets.c @@ -162,6 +162,7 @@ void GuiTransactionDetailInit(uint8_t viewType) //btc multisig will change g_transactionType when parsing transaction; g_transactionType = TRANSACTION_TYPE_NORMAL; g_viewType = viewType; + printf("%s %d.\n", __func__, __LINE__); g_chainType = ViewTypeToChainTypeSwitch(g_viewType); g_pageWidget = CreatePageWidget(); g_needSign = true; 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 837f75662..9c74786b1 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 @@ -50,6 +50,7 @@ typedef struct ConnectWalletWidget { WalletListItem_t g_walletListArray[] = { {WALLET_LIST_KEYSTONE, &walletListKeystone, false}, + {WALLET_LIST_CORE, &walletListSushi, true}, {WALLET_LIST_OKX, &walletListOkx, true}, {WALLET_LIST_METAMASK, &walletListMetaMask, true}, {WALLET_LIST_BACKPACK, &walletListBackpack, true}, @@ -1152,6 +1153,9 @@ void GuiConnectWalletSetQrdata(WALLET_LIST_INDEX_ENUM index) func = GuiGetImTokenData; AddEthWalletCoins(); break; + case WALLET_LIST_CORE: + func = GuiGetCoreWalletData; + break; case WALLET_LIST_BITGET: func = GuiGetBitgetWalletData; AddBitgetWalletCoins(); diff --git a/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.c b/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.c index edb50c020..21683c01c 100644 --- a/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.c +++ b/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.c @@ -288,6 +288,7 @@ static void CoinDealHandler(HOME_WALLET_CARD_ENUM coin) case HOME_WALLET_CARD_ETH: case HOME_WALLET_CARD_SOL: case HOME_WALLET_CARD_HNT: + case HOME_WALLET_CARD_AVAX: GuiFrameOpenViewWithParam(&g_multiPathCoinReceiveView, &coin, sizeof(coin)); break; case HOME_WALLET_CARD_ADA: @@ -361,7 +362,6 @@ static void ManageCoinChainHandler(lv_event_t *e) bool state; WalletState_t *wallet = lv_event_get_user_data(e); if (wallet->index == HOME_WALLET_CARD_COSMOS) { - printf("cosmos\n"); state = g_walletBakState[wallet->index].state; if (state) { lv_img_set_src(g_cosmosPulldownImg, &imgArrowRight); @@ -477,8 +477,6 @@ static void OpenManageAssetsHandler(lv_event_t *e) ManageCoinChainHandler, &g_walletState[i]); g_walletButton[i] = button; if (IsCosmosChain(g_coinCardArray[i].index)) { - printf("g_coinCardArray[i].index = %d\n", g_coinCardArray[i].index); - printf("name = %s\n", g_coinCardArray[i].coin); lv_obj_add_flag(button, LV_OBJ_FLAG_HIDDEN); g_lastCosmosLine = GuiCreateDividerLine(checkBoxCont); lv_obj_add_flag(g_lastCosmosLine, LV_OBJ_FLAG_HIDDEN); diff --git a/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.h b/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.h index 28f555f5f..5c8c20557 100644 --- a/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.h +++ b/src/ui/gui_widgets/multi/web3/gui_general_home_widgets.h @@ -4,6 +4,7 @@ #define HOME_WIDGETS_SURPLUS_CARD_ENUM HOME_WALLET_CARD_ETH, \ HOME_WALLET_CARD_SOL, \ + HOME_WALLET_CARD_AVAX, \ HOME_WALLET_CARD_BNB, \ HOME_WALLET_CARD_HNT, \ HOME_WALLET_CARD_XRP, \ @@ -57,6 +58,7 @@ #define HOME_WALLET_STATE_SURPLUS {HOME_WALLET_CARD_ETH, false, "ETH", true}, \ {HOME_WALLET_CARD_SOL, false, "SOL", true}, \ + {HOME_WALLET_CARD_AVAX, false, "AVAX", true}, \ {HOME_WALLET_CARD_BNB, false, "BNB", false}, \ {HOME_WALLET_CARD_HNT, false, "HNT", true}, \ {HOME_WALLET_CARD_XRP, false, "XRP", true}, \ @@ -120,6 +122,12 @@ .chain = "Solana", \ .icon = &coinSol, \ }, \ + { \ + .index = HOME_WALLET_CARD_AVAX, \ + .coin = "Avax", \ + .chain = "Avalanche", \ + .icon = &coinAva, \ + }, \ { \ .index = HOME_WALLET_CARD_BNB, \ .coin = "BNB", \ diff --git a/src/ui/gui_widgets/multi/web3/gui_multi_path_coin_receive_widgets.c b/src/ui/gui_widgets/multi/web3/gui_multi_path_coin_receive_widgets.c index dcee15268..e44e820ad 100644 --- a/src/ui/gui_widgets/multi/web3/gui_multi_path_coin_receive_widgets.c +++ b/src/ui/gui_widgets/multi/web3/gui_multi_path_coin_receive_widgets.c @@ -132,6 +132,7 @@ static void GetChangePathLabelHint(char* hint); static void SetCurrentSelectIndex(uint32_t selectIndex); static uint32_t GetCurrentSelectIndex(); static void GetHint(char *hint); +static void ModelGetAvaxAddress(uint32_t index, AddressDataItem_t *item); static void ModelGetSolAddress(uint32_t index, AddressDataItem_t *item); static void ModelGetADAAddress(uint32_t index, AddressDataItem_t *item, uint8_t type); static void ModelGetAddress(uint32_t index, AddressDataItem_t *item); @@ -147,6 +148,10 @@ static void GuiCreateAddressDetailWidgets(lv_obj_t *parent); static MultiPathCoinReceiveWidgets_t g_multiPathCoinReceiveWidgets; static EthereumReceiveTile g_multiPathCoinReceiveTileNow; +static const PathItem_t g_avaxPaths[] = { + {"Avalanche C-Chain", "", "m/44'/60'/0'" }, + {"Avalanche X/P-Chain", "", "m/44'/9000'/0'"}, +}; static const PathItem_t g_ethPaths[] = { {"BIP44 Standard", "", "m/44'/60'/0'" }, {"Ledger Live", "", "m/44'/60'" }, @@ -174,6 +179,7 @@ static void InitDerivationPathDesc(uint8_t chain) { switch (chain) { case HOME_WALLET_CARD_ETH: + case HOME_WALLET_CARD_AVAX: g_derivationPathDescs = GetDerivationPathDescs(ETH_DERIVATION_PATH_DESC); break; case HOME_WALLET_CARD_SOL: @@ -190,6 +196,7 @@ static void InitDerivationPathDesc(uint8_t chain) void GuiMultiPathCoinReceiveInit(uint8_t chain) { + InitDerivationPathDesc(chain); if (chain == HOME_WALLET_CARD_ADA) { SetPathIndex(GetAccountReceivePath("ADA")); @@ -239,6 +246,9 @@ void GuiMultiPathCoinReceiveRefresh(void) case HOME_WALLET_CARD_ETH: SetCoinWallet(g_pageWidget->navBarWidget, CHAIN_ETH, _("receive_eth_receive_main_title")); break; + case HOME_WALLET_CARD_AVAX: + SetCoinWallet(g_pageWidget->navBarWidget, CHAIN_AVAX, _("receive_avax_receive_main_title")); + break; case HOME_WALLET_CARD_SOL: snprintf_s(walletTitle, BUFFER_SIZE_32, _("receive_coin_fmt"), "SOL"); SetCoinWallet(g_pageWidget->navBarWidget, CHAIN_SOL, walletTitle); @@ -468,6 +478,9 @@ static void GetHint(char *hint) case HOME_WALLET_CARD_ETH: strcpy_s(hint, BUFFER_SIZE_256, _("receive_eth_alert_desc")); break; + case HOME_WALLET_CARD_AVAX: + snprintf_s(hint, BUFFER_SIZE_256, _("receive_coin_hint_fmt"), "AVAX"); + break; case HOME_WALLET_CARD_SOL: snprintf_s(hint, BUFFER_SIZE_256, _("receive_coin_hint_fmt"), "SOL"); break; @@ -622,6 +635,7 @@ static void GetChangePathLabelHint(char* hint) { switch (g_chainCard) { case HOME_WALLET_CARD_ETH: + case HOME_WALLET_CARD_AVAX: snprintf_s(hint, BUFFER_SIZE_128, _("derivation_path_select_eth")); return; case HOME_WALLET_CARD_SOL: @@ -639,6 +653,8 @@ static void GetChangePathLabelHint(char* hint) static const char* GetChangePathItemTitle(uint32_t i) { switch (g_chainCard) { + case HOME_WALLET_CARD_AVAX: + return (char *)g_avaxPaths[i].title; case HOME_WALLET_CARD_ETH: return (char *)g_ethPaths[i].title; case HOME_WALLET_CARD_SOL: @@ -664,7 +680,6 @@ static const char* GetChangePathItemTitle(uint32_t i) static void ShowEgAddressCont(lv_obj_t *egCont) { - if (egCont == NULL) { printf("egCont is NULL, cannot show eg address\n"); return; @@ -737,6 +752,7 @@ static uint32_t GetDerivedPathTypeCount() case HOME_WALLET_CARD_HNT: return 3; case HOME_WALLET_CARD_ADA: + case HOME_WALLET_CARD_AVAX: return 2; default: return 3; @@ -938,6 +954,8 @@ static int GetADAMaxAddressIndex(void) static int GetMaxAddressIndex(void) { switch (g_chainCard) { + case HOME_WALLET_CARD_AVAX: + return GENERAL_ADDRESS_INDEX_MAX; case HOME_WALLET_CARD_ETH: return GetEthMaxAddressIndex(); case HOME_WALLET_CARD_SOL: @@ -1091,6 +1109,20 @@ static void OpenSwitchAddressHandler(lv_event_t *e) RefreshSwitchAccount(); } +static void GetAvaxPathItemSubTittle(char* subTitle, int index, uint32_t maxLen) +{ + switch (index) { + case 0: + strcpy_s(subTitle, maxLen, "m/44'/60'/0'/0/#F5870A X#"); + break; + case 1: + strcpy_s(subTitle, maxLen, "m/44'/9000'/0'/0'/#F5870A X#"); + break; + default: + break; + } +} + static void GetEthPathItemSubTittle(char* subTitle, int index, uint32_t maxLen) { switch (index) { @@ -1133,6 +1165,9 @@ static void GetADAPathItemSubTitle(char* subTitle, int index, uint32_t maxLen) static void GetPathItemSubTitle(char* subTitle, int index, uint32_t maxLen) { switch (g_chainCard) { + case HOME_WALLET_CARD_AVAX: + GetAvaxPathItemSubTittle(subTitle, index, maxLen); + break; case HOME_WALLET_CARD_ETH: GetEthPathItemSubTittle(subTitle, index, maxLen); break; @@ -1252,8 +1287,10 @@ static char *GetEthXpub(int index) static void ModelGetAddress(uint32_t index, AddressDataItem_t *item) { - switch (g_chainCard) { + case HOME_WALLET_CARD_AVAX: + ModelGetAvaxAddress(index, item); + break; case HOME_WALLET_CARD_ETH: ModelGetEthAddress(index, item); break; @@ -1310,9 +1347,9 @@ static void ModelGetSolAddress(uint32_t index, AddressDataItem_t *item) static void ModelGetEthAddress(uint32_t index, AddressDataItem_t *item) { - char *xPub, hdPath[BUFFER_SIZE_128], rootPath[BUFFER_SIZE_128]; - GetEthHdPath(hdPath, index, BUFFER_SIZE_128); - GetEthRootPath(rootPath, index, BUFFER_SIZE_128); + char *xPub, hdPath[BUFFER_SIZE_32], rootPath[BUFFER_SIZE_32]; + GetEthHdPath(hdPath, index, BUFFER_SIZE_32); + GetEthRootPath(rootPath, index, BUFFER_SIZE_32); xPub = GetEthXpub(index); ASSERT(xPub); SimpleResponse_c_char *result = eth_get_address(hdPath, xPub, rootPath); @@ -1324,6 +1361,43 @@ static void ModelGetEthAddress(uint32_t index, AddressDataItem_t *item) free_simple_response_c_char(result); } +static void ModelGetAvaxAddress(uint32_t index, AddressDataItem_t *item) +{ + char *xPub, hdPath[BUFFER_SIZE_32], rootPath[BUFFER_SIZE_32]; + SimpleResponse_c_char *result; + uint32_t selectType = GetPathIndex(); + if (g_multiPathCoinReceiveTileNow == RECEIVE_TILE_CHANGE_PATH) { + selectType = g_selectType; + } + if (selectType == 0) { + // c chain + GetEthRootPath(rootPath, index, BUFFER_SIZE_32); + GetEthHdPath(hdPath, index, BUFFER_SIZE_32); + xPub = GetEthXpub(index); + ASSERT(xPub); + result = eth_get_address(hdPath, xPub, rootPath); + if (result->error_code == 0) { + item->index = index; + strcpy_s(item->address, ADDRESS_MAX_LEN, result->data); + strcpy_s(item->path, PATH_ITEM_MAX_LEN, hdPath); + } + free_simple_response_c_char(result); + } else { + // x p chain address + xPub = GetCurrentAccountPublicKey(XPUB_TYPE_AVAX_X_P); + ASSERT(xPub); + snprintf_s(hdPath, sizeof(hdPath), "%s/0/%u", "m/44'/9000'/0'", index); + strcpy_s(rootPath, sizeof(rootPath), "m/44'/9000'/0'"); + SimpleResponse_c_char *result = avalanche_get_x_p_address(hdPath, xPub, rootPath); + if (result->error_code == 0) { + item->index = index; + strcpy_s(item->address, ADDRESS_MAX_LEN, result->data); + strcpy_s(item->path, PATH_ITEM_MAX_LEN, hdPath); + } + } + item->index = index; +} + void GuiResetCurrentEthAddressIndex(uint8_t index) { if (index > 2) { diff --git a/src/ui/lv_i18n/data.csv b/src/ui/lv_i18n/data.csv index 20b81d7d0..df831b8c0 100644 --- a/src/ui/lv_i18n/data.csv +++ b/src/ui/lv_i18n/data.csv @@ -1007,4 +1007,6 @@ Wallet Profile,24,wallet_profile_mid_btn,Wallet Profile,Профиль коше 3. 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.","1.プライマリアカウントは、あなたの主要なモネロアカウントで、主要な残高を保有し、直接資金を受け取ることができます。 2.サブアドレスは、あなたのプライマリアカウントにリンクされた二次アドレスで、プライベートに支払いを受けるために設計されています。各サブアドレスは取引を別々に保持し、あなたのメインアカウントの残高を隠します。 3.大きな資金や長期的な資金にはプライマリアカウントを使用してください。メインの残高やアカウントの詳細を明かさずに支払いを受け取りたい場合は、サブアドレスを使用してください。" -,20,check_ton_wallet_warning,"Since you are currently using the Cypherpunk firmware, your TON-Only wallet data will be deleted. Click 'Confirm' to proceed with the deletion.","Так как вы в данный момент используете прошивку Cypherpunk, данные вашего кошелька TON-Only будут удалены. Нажмите «Подтвердить», чтобы продолжить удаление.","현재 Cypherpunk 펌웨어를 사용 중이므로 TON-Only 지갑 데이터가 삭제됩니다. 삭제를 진행하려면 ‘확인’을 클릭하세요.","由于您当前使用的是Cypherpunk固件,您的TON-Only钱包数据将被删除。点击“确认”以继续删除操作。","Dado que actualmente está utilizando el firmware Cypherpunk, los datos de su billetera TON-Only se eliminarán. Haga clic en "Confirmar" para proceder con la eliminación.","Da Sie derzeit die Cypherpunk-Firmware verwenden, werden Ihre TON-Only-Wallet-Daten gelöscht. Klicken Sie auf „Bestätigen“, um die Löschung fortzusetzen.","現在Cypherpunkファームウェアを使用しているため、TON-Onlyウォレットのデータが削除されます。削除を進めるには「確認」をクリックしてください。" \ No newline at end of file +,20,check_ton_wallet_warning,"Since you are currently using the Cypherpunk firmware, your TON-Only wallet data will be deleted. Click 'Confirm' to proceed with the deletion.","Так как вы в данный момент используете прошивку Cypherpunk, данные вашего кошелька TON-Only будут удалены. Нажмите «Подтвердить», чтобы продолжить удаление.","현재 Cypherpunk 펌웨어를 사용 중이므로 TON-Only 지갑 데이터가 삭제됩니다. 삭제를 진행하려면 ‘확인’을 클릭하세요.","由于您当前使用的是Cypherpunk固件,您的TON-Only钱包数据将被删除。点击“确认”以继续删除操作。","Dado que actualmente está utilizando el firmware Cypherpunk, los datos de su billetera TON-Only se eliminarán. Haga clic en "Confirmar" para proceder con la eliminación.","Da Sie derzeit die Cypherpunk-Firmware verwenden, werden Ihre TON-Only-Wallet-Daten gelöscht. Klicken Sie auf „Bestätigen“, um die Löschung fortzusetzen.","現在Cypherpunkファームウェアを使用しているため、TON-Onlyウォレットのデータが削除されます。削除を進めるには「確認」をクリックしてください。" +,24,receive_avax_receive_main_title,Receive AVAX,Получить AVAX,AVAX 받기,接收 AVAX,Recibir AVAX,Erhalte AVAX,AVAXを受け取る +,20,btc_avalanche_notice,This transaction uses an Avalanche BTC address. Verify all details carefully to avoid errors or asset loss.,"Эта транзакция использует адрес Avalanche BTC. Внимательно проверьте все детали, чтобы избежать ошибок или потери активов.","이 트랜잭션은 Avalanche BTC 주소를 사용합니다. 오류나 자산 손실을 방지하기 위해 모든 세부 사항을 주의 깊게 확인하십시오.","此交易使用Avalanche BTC地址。请仔细验证所有详细信息,以避免错误或资产损失。", "Esta transacción utiliza una dirección BTC de Avalanche. Verifique cuidadosamente todos los detalles para evitar errores o pérdida de activos.","Diese Transaktion verwendet eine Avalanche BTC-Adresse. Überprüfen Sie alle Details sorgfältig, um Fehler oder Vermögensverluste zu vermeiden.","このトランザクションはAvalanche BTCアドレスを使用しています。エラーや資産の損失を避けるため、すべての詳細を慎重に確認してください。" diff --git a/src/ui/lv_i18n/lv_i18n.c b/src/ui/lv_i18n/lv_i18n.c index 509de091a..168ddbca4 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"}, @@ -146,6 +124,7 @@ const static lv_i18n_phrase_t en_singulars[] = { {"auto_shutdown_20", "Auto Shutdown"}, {"beta_version_notice_desc", "The current firmware is a beta version and may contain unknown bugs or risks. It is intended only for testing purposes."}, {"beta_version_notice_title", "Beta Version"}, + {"btc_avalanche_notice", "This transaction uses an Avalanche BTC address. Verify all details carefully to avoid errors or asset loss."}, {"calculat_modal_title", "Calculating"}, {"catalyst_transactions_notice", "Ensure the address matches. Please verify carefully."}, {"catalyst_voting_registration", "Confirm Catalyst Registration"}, @@ -591,6 +570,7 @@ const static lv_i18n_phrase_t en_singulars[] = { {"receive_ada_more_t_title2", "Key Concepts in Cardano's ADA Addresses"}, {"receive_ada_show_address_detail", "Show Address Detail"}, {"receive_ada_stake_address", "Reward Address"}, + {"receive_avax_receive_main_title", "Receive AVAX"}, {"receive_btc_address_type", "Address Type"}, {"receive_btc_alert_desc", "This address is exclusively for BTC transactions only. Sending other types of digital assets to this address will result in their loss."}, {"receive_btc_extended_public_key", "Extended Public Key"}, @@ -923,12 +903,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; @@ -1048,6 +1025,7 @@ const static lv_i18n_phrase_t de_singulars[] = { {"auto_shutdown_20", "Autoabschaltung"}, {"beta_version_notice_desc", "Die aktuelle Firmware ist eine Betaversion und kann unbekannte Fehler oder Risiken enthalten. Sie ist ausschließlich für Testzwecke vorgesehen."}, {"beta_version_notice_title", "Beta-Version"}, + {"btc_avalanche_notice", "Diese Transaktion verwendet eine Avalanche BTC-Adresse. Überprüfen Sie alle Details sorgfältig, um Fehler oder Vermögensverluste zu vermeiden."}, {"calculat_modal_title", "Berechnung"}, {"catalyst_transactions_notice", "Prüfen Sie die Adresse sorgfältig."}, {"catalyst_voting_registration", "Wahlregistrierung bestätigen"}, @@ -1493,6 +1471,7 @@ const static lv_i18n_phrase_t de_singulars[] = { {"receive_ada_more_t_title2", "Schlüsselkonzepte in Cardanos ADA-Adressen"}, {"receive_ada_show_address_detail", "Adresse anzeigen"}, {"receive_ada_stake_address", "Belohnungsadresse"}, + {"receive_avax_receive_main_title", "Erhalte AVAX"}, {"receive_btc_address_type", "Adresstyp"}, {"receive_btc_alert_desc", "Diese Adresse ist ausschließlich für BTC-Transaktionen bestimmt. Das Senden anderer Arten von digitalen Vermögenswerten an diese Adresse führt zu deren Verlust."}, {"receive_btc_extended_public_key", "Erweitertes öffentliches Schlüssel"}, @@ -1825,12 +1804,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; @@ -1950,6 +1926,7 @@ const static lv_i18n_phrase_t es_singulars[] = { {"auto_shutdown_20", "Apagado automático"}, {"beta_version_notice_desc", "La versión actual del firmware es una versión beta y puede contener errores o riesgos desconocidos. Está diseñada únicamente para fines de prueba"}, {"beta_version_notice_title", "Versión beta"}, + {"btc_avalanche_notice", " \"Esta transacción utiliza una dirección BTC de Avalanche. Verifique cuidadosamente todos los detalles para evitar errores o pérdida de activos.\""}, {"calculat_modal_title", "Calculando"}, {"catalyst_transactions_notice", "Asegúrese de que la dirección coincida. Verifique cuidadosamente."}, {"catalyst_voting_registration", "Confirmar registro de votación"}, @@ -2395,6 +2372,7 @@ const static lv_i18n_phrase_t es_singulars[] = { {"receive_ada_more_t_title2", "Conceptos clave en las direcciones ADA de Cardano"}, {"receive_ada_show_address_detail", "Mostrar detalle de dirección"}, {"receive_ada_stake_address", "Dirección de recompensa"}, + {"receive_avax_receive_main_title", "Recibir AVAX"}, {"receive_btc_address_type", "Tipo de dirección"}, {"receive_btc_alert_desc", "Esta dirección es exclusivamente para transacciones con BTC. Si se envían otros tipos de activos digitales a esta dirección, se perderán."}, {"receive_btc_extended_public_key", "Clave pública extendida"}, @@ -2727,8 +2705,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; @@ -2849,6 +2826,7 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"auto_shutdown_20", "自動シャットダウン"}, {"beta_version_notice_desc", "現在のファームウェアはベータ版であり、未知のバグやリスクが含まれている可能性があります.これはテスト目的のみを意図しています."}, {"beta_version_notice_title", "ベータ版"}, + {"btc_avalanche_notice", "このトランザクションはAvalanche BTCアドレスを使用しています。エラーや資産の損失を避けるため、すべての詳細を慎重に確認してください。"}, {"calculat_modal_title", "計算しています"}, {"catalyst_transactions_notice", "アドレスが一致することを確認してください。慎重に確認してください"}, {"catalyst_voting_registration", "投票登録を確認"}, @@ -3294,6 +3272,7 @@ const static lv_i18n_phrase_t ja_singulars[] = { {"receive_ada_more_t_title2", "カルダノのADAアドレスのキーコンセプト"}, {"receive_ada_show_address_detail", "住所の詳細を表示"}, {"receive_ada_stake_address", "報酬アドレス"}, + {"receive_avax_receive_main_title", "AVAXを受け取る"}, {"receive_btc_address_type", "住所タイプ"}, {"receive_btc_alert_desc", "このアドレスはBTCの取引のみに利用できます.他の種類のデジタル資産をこのアドレスに送信した場合、それらは失われます."}, {"receive_btc_extended_public_key", "拡張公開鍵"}, @@ -3746,6 +3725,7 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"auto_shutdown_20", "자동 종료 시간"}, {"beta_version_notice_desc", "현재 펌웨어는 베타 버전이며 알려지지 않은 버그 또는 위험을 포함할 수 있습니다. 테스트 목적으로만 사용되어야 합니다."}, {"beta_version_notice_title", "베타 버전"}, + {"btc_avalanche_notice", "이 트랜잭션은 Avalanche BTC 주소를 사용합니다. 오류나 자산 손실을 방지하기 위해 모든 세부 사항을 주의 깊게 확인하십시오."}, {"calculat_modal_title", "계산중 "}, {"catalyst_transactions_notice", "주소가 일치하는지 확인하세요. 주의깊게 검증해 주세요."}, {"catalyst_voting_registration", "투표 등록 확인"}, @@ -4191,6 +4171,7 @@ const static lv_i18n_phrase_t ko_singulars[] = { {"receive_ada_more_t_title2", "카르다노의 ADA 주소의 주요 개념"}, {"receive_ada_show_address_detail", "주소 상세 내역 표시"}, {"receive_ada_stake_address", "보상 주소"}, + {"receive_avax_receive_main_title", "AVAX 받기"}, {"receive_btc_address_type", "주소 유형"}, {"receive_btc_alert_desc", "이 주소는 BTC 거래만을 위한 것이다. 이 주소로 다른 종류의 디지털 자산을 전송하면 손실이 발생한다."}, {"receive_btc_extended_public_key", "공개 키 확장 "}, @@ -4643,6 +4624,7 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"auto_shutdown_20", "Выключение"}, {"beta_version_notice_desc", "Текущая прошивка является бета-версией и может содержать неизвестные ошибки или риски. Она предназначена только для тестирования."}, {"beta_version_notice_title", "Тестовая версия"}, + {"btc_avalanche_notice", "Эта транзакция использует адрес Avalanche BTC. Внимательно проверьте все детали, чтобы избежать ошибок или потери активов."}, {"calculat_modal_title", "Расчет"}, {"catalyst_transactions_notice", "Убедитесь, что адрес совпадает. Тщательно проверьте."}, {"catalyst_voting_registration", "Регистрация для голосования"}, @@ -5088,6 +5070,7 @@ const static lv_i18n_phrase_t ru_singulars[] = { {"receive_ada_more_t_title2", "Ключевые понятия в адресах ADA Cardano"}, {"receive_ada_show_address_detail", "Показать адрес целиком"}, {"receive_ada_stake_address", "Адрес для награды"}, + {"receive_avax_receive_main_title", "Получить AVAX"}, {"receive_btc_address_type", "Тип адреса"}, {"receive_btc_alert_desc", "Этот адрес предназначен только для Bitcoin, другие цифровые активы, отправленные на этот адрес, будут потеряны."}, {"receive_btc_extended_public_key", "Расширенный Открытый ключ"}, @@ -5420,12 +5403,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; @@ -5548,6 +5528,7 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"auto_shutdown_20", "自动关闭"}, {"beta_version_notice_desc", "当前的固件是一个测试版本,可能包含未知的错误或风险.仅供测试目的使用"}, {"beta_version_notice_title", "测试版本"}, + {"btc_avalanche_notice", "此交易使用Avalanche BTC地址。请仔细验证所有详细信息,以避免错误或资产损失。"}, {"calculat_modal_title", "计算中..."}, {"catalyst_transactions_notice", "请确保地址匹配。仔细核对。"}, {"catalyst_voting_registration", "确认投票注册"}, @@ -5993,6 +5974,7 @@ const static lv_i18n_phrase_t zh_cn_singulars[] = { {"receive_ada_more_t_title2", "Cardano 地址中的关键概念"}, {"receive_ada_show_address_detail", "显示地址细节"}, {"receive_ada_stake_address", "奖励地址"}, + {"receive_avax_receive_main_title", "接收 AVAX"}, {"receive_btc_address_type", "地址类型"}, {"receive_btc_alert_desc", "此地址仅用于 BTC 交易.将其他类型的数字资产发送到此地址将会导致资产丢失."}, {"receive_btc_extended_public_key", "扩展公钥"}, @@ -6372,8 +6354,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*/ @@ -6386,13 +6368,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; } @@ -6405,10 +6387,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; } } @@ -6423,23 +6405,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; } @@ -6455,31 +6437,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; } @@ -6494,6 +6476,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; } diff --git a/test/test_cmd.c b/test/test_cmd.c index c42079692..202a83fa2 100644 --- a/test/test_cmd.c +++ b/test/test_cmd.c @@ -806,7 +806,6 @@ static void ReadAddrFunc(int argc, char *argv[]) static void GetCurrentTimeFunc(int argc, char *argv[]) { - printf("current time : %s\n", GetCurrentTime()); } static void SetCurrentTimeFunc(int argc, char *argv[]) diff --git a/ui_simulator/simulator_model.c b/ui_simulator/simulator_model.c index 55cb92180..baebe08a7 100644 --- a/ui_simulator/simulator_model.c +++ b/ui_simulator/simulator_model.c @@ -5,6 +5,7 @@ #include "cjson/cJSON.h" #include "stdint.h" #include "gui_resolve_ur.h" +#include #ifndef BTC_ONLY #include "eapdu_services/service_resolve_ur.h" @@ -20,7 +21,17 @@ bool g_reboot = false; bool g_otpProtect = false; // Comment out this macro if you need to retrieve data from the file -#define GET_QR_DATA_FROM_SCREEN +// #define GET_QR_DATA_FROM_SCREEN + +void StampTimeToUtcTime(int64_t timeStamp, char *utcTime, int maxLen) +{ + struct tm *utc_time = gmtime(&timeStamp); + strftime(utcTime, maxLen, "%Y-%m-%d %H:%M:%S UTC", utc_time); +} + +void StopQrDecode(void) +{ +} void ClearUSBRequestId(void) { @@ -49,8 +60,7 @@ void NftLockDecodeTouchQuit() int32_t GetUpdatePubKey(uint8_t *pubKey) { sprintf(pubKey, "%02x", 0x4); - for (int i = 1; i < 65; i++) - { + for (int i = 1; i < 65; i++) { sprintf(&pubKey[i], "%02x", i); } } @@ -58,18 +68,13 @@ int32_t GetUpdatePubKey(uint8_t *pubKey) void TrngGet(void *buf, uint32_t len) { uint32_t buf4[4]; - for (uint32_t i = 0; i < len; i += 16) - { - for (int i = 0; i < 4; i++) - { + for (uint32_t i = 0; i < len; i += 16) { + for (int i = 0; i < 4; i++) { buf4[i] = 0x1 * i; } - if (len - i >= 16) - { + if (len - i >= 16) { memcpy((uint8_t *)buf + i, buf4, 16); - } - else - { + } else { memcpy((uint8_t *)buf + i, buf4, len - i); } } @@ -78,8 +83,7 @@ void TrngGet(void *buf, uint32_t len) void SE_GetTRng(void *buf, uint32_t len) { uint8_t *data = buf; - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { uint32_t randNum = rand(); data[i] = randNum & 0xFF; } @@ -88,8 +92,7 @@ void SE_GetTRng(void *buf, uint32_t len) int32_t SE_GetDS28S60Rng(uint8_t *rngArray, uint32_t num) { uint8_t *data = rngArray; - for (int i = 0; i < num; i++) - { + for (int i = 0; i < num; i++) { data[i] = num - i; } @@ -99,8 +102,7 @@ int32_t SE_GetDS28S60Rng(uint8_t *rngArray, uint32_t num) int32_t SE_GetAtecc608bRng(uint8_t *rngArray, uint32_t num) { uint8_t *data = rngArray; - for (int i = 0; i < num; i++) - { + for (int i = 0; i < num; i++) { data[i] = 2 * i; } @@ -155,8 +157,7 @@ bool FatfsFileExist(const char *path) lv_fs_file_t fp; lv_fs_res_t res = LV_FS_RES_OK; res = lv_fs_open(&fp, path, LV_FS_MODE_RD); - if (res == LV_FS_RES_OK) - { + if (res == LV_FS_RES_OK) { lv_fs_close(&fp); return true; } @@ -308,21 +309,18 @@ int FatfsFileWrite(const char *path, const uint8_t *data, uint32_t len) lv_fs_file_t fd; lv_fs_res_t ret = LV_FS_RES_OK; - if (path == NULL) - { + if (path == NULL) { return -1; } ret = lv_fs_open(&fd, path, LV_FS_MODE_WR); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_open failed %s ret = %d line = %d\n", path, ret, __LINE__); return -1; } ret = lv_fs_write(&fd, data, len, &readBytes); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_write failed %s ret = %d line = %d\n", path, ret, __LINE__); return -1; } @@ -433,7 +431,7 @@ int32_t AsyncExecuteWithPtr(void *func, const void *inData) static uint8_t buffer[100 * 1024]; -static char *qrcode[100]; +static char *qrcode[3000]; static uint32_t qrcode_size; char *FatfsFileRead(const char *path) @@ -447,15 +445,13 @@ char *FatfsFileRead(const char *path) printf("truePath: %s\n", truePath); ret = lv_fs_open(&fd, truePath, LV_FS_MODE_RD); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_open failed %s ret = %d line = %d\n", path, ret, __LINE__); return NULL; } ret = lv_fs_read(&fd, buffer, 1024 * 100, &readBytes); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_read failed %s ret = %d line = %d\n", path, ret, __LINE__); return NULL; } @@ -475,15 +471,13 @@ uint8_t *FatfsFileReadBytes(const char *path, uint32_t *readBytes) printf("truePath: %s\n", truePath); ret = lv_fs_open(&fd, truePath, LV_FS_MODE_RD); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_open failed %s ret = %d line = %d\n", path, ret, __LINE__); return NULL; } ret = lv_fs_read(&fd, buffer, 1024 * 100, readBytes); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_read failed %s ret = %d line = %d\n", path, ret, __LINE__); return NULL; } @@ -502,8 +496,7 @@ int32_t prepare_qrcode() lv_fs_file_t fd; lv_fs_res_t ret = LV_FS_RES_OK; ret = lv_fs_open(&fd, path, LV_FS_MODE_RD); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_open failed %s ret = %d line = %d\n", path, ret, __LINE__); return -1; } @@ -511,8 +504,7 @@ int32_t prepare_qrcode() int32_t readBytes = 0; ret = lv_fs_read(&fd, buffer, 100 * 1024, &readBytes); - if (ret != LV_FS_RES_OK) - { + if (ret != LV_FS_RES_OK) { printf("lv_fs_read failed %s ret = %d line = %d\n", path, ret, __LINE__); return -1; } @@ -521,12 +513,9 @@ int32_t prepare_qrcode() int lastIndex = 0; int lastQRIndex = 0; - for (size_t i = 0; i < readBytes; i++) - { - if (buffer[i] == '\n') - { - if (qrcode[lastQRIndex] != NULL) - { + for (size_t i = 0; i < readBytes; i++) { + if (buffer[i] == '\n') { + if (qrcode[lastQRIndex] != NULL) { free(qrcode[lastQRIndex]); } qrcode[lastQRIndex] = malloc(1024); @@ -536,11 +525,9 @@ int32_t prepare_qrcode() lastIndex = i + 1; lastQRIndex++; } - if (i == readBytes - 1) - { + if (i == readBytes - 1) { // printf("last char: %c\r\n", buffer[i]); - if (qrcode[lastQRIndex] != NULL) - { + if (qrcode[lastQRIndex] != NULL) { free(qrcode[lastQRIndex]); } qrcode[lastQRIndex] = malloc(1024); @@ -570,11 +557,9 @@ static void reset_qr_state() static bool on_qr_detected(const char *qrString) { printf("qrString: %s\r\n", qrString); - if (firstQrFlag) - { + if (firstQrFlag) { QRProtocol t = infer_qrcode_type(qrString); - switch (t) - { + switch (t) { case QRCodeTypeText: urResult = parse_qrcode_text(qrString); break; @@ -582,32 +567,24 @@ static bool on_qr_detected(const char *qrString) urResult = parse_ur(qrString); break; } - if (urResult->error_code == 0) - { - if (urResult->is_multi_part == 0) - { + if (urResult->error_code == 0) { + if (urResult->is_multi_part == 0) { // single qr code firstQrFlag = true; viewType.viewType = urResult->t; viewType.urType = urResult->ur_type; handleURResult(urResult, NULL, viewType, false); return true; - } - else - { + } else { // first qr code firstQrFlag = false; decoder = urResult->decoder; } } - } - else - { + } else { struct URParseMultiResult *MultiurResult = receive(qrString, decoder); - if (MultiurResult->error_code == 0) - { - if (MultiurResult->is_complete) - { + if (MultiurResult->error_code == 0) { + if (MultiurResult->is_complete) { firstQrFlag = true; viewType.viewType = MultiurResult->t; viewType.urType = MultiurResult->ur_type; @@ -615,15 +592,12 @@ static bool on_qr_detected(const char *qrString) handleURResult(NULL, MultiurResult, viewType, true); return true; } - } - else - { + } else { printf("error code: %d\r\n", MultiurResult->error_code); printf("error message: %s\r\n", MultiurResult->error_message); return true; } - if (!(MultiurResult->is_complete)) - { + if (!(MultiurResult->is_complete)) { free_ur_parse_multi_result(MultiurResult); } } @@ -726,6 +700,7 @@ int32_t read_qrcode() } #endif -bool GetEnsName(const char *addr, char *name) { +bool GetEnsName(const char *addr, char *name) +{ return false; } \ No newline at end of file diff --git a/ui_simulator/simulator_model.h b/ui_simulator/simulator_model.h index 2c5dc029d..2941d5ecc 100644 --- a/ui_simulator/simulator_model.h +++ b/ui_simulator/simulator_model.h @@ -220,7 +220,14 @@ extern bool g_reboot; GuiGetTonProofGUIData, \ NULL, \ FreeArMemory, \ - } + }, \ + { \ + REMAPVIEW_AVAX, \ + PC_SIMULATOR_PATH "/page_avax.json", \ + GuiGetAvaxGUIData, \ + NULL, \ + FreeAvaxMemory, \ + }, #endif #endif \ No newline at end of file From e4a2068277264caef5cb412441bc9cd4e9558a8a Mon Sep 17 00:00:00 2001 From: ww3512687 <15809188520@163.com> Date: Fri, 10 Jan 2025 16:02:22 +0800 Subject: [PATCH 2/3] delete unused code --- rust/apps/ethereum/src/address.rs | 47 ------------------------------- 1 file changed, 47 deletions(-) diff --git a/rust/apps/ethereum/src/address.rs b/rust/apps/ethereum/src/address.rs index 3d93aa212..aac77f93c 100644 --- a/rust/apps/ethereum/src/address.rs +++ b/rust/apps/ethereum/src/address.rs @@ -78,51 +78,4 @@ mod tests { let result = derive_address(hd_path, root_x_pub, root_path).unwrap(); assert_eq!("0x31eA4a0976ceE79AF136B1Cfa914e20E87546156", result); } - - fn get_avax_address(public_key: &PublicKey) -> String { - // 初始化 secp256k1 - // let secp = Secp256k1::new(); - - // 从私钥生成公钥 - // let secret_key = SecretKey::from_slice(private_key).unwrap(); - // let public_key = PublicKey::from_secret_key(&secp, &secret_key); - // println!("public_key11 = {:?}", public_key); - - // 序列化公钥并去掉第一个字节 - // let pub_key_bytes = public_key.serialize_uncompressed(); - // let pub_key_without_prefix = &pub_key_bytes[1..]; - - // 计算 Keccak-256 哈希 - // let mut keccak = Keccak::v256(); - // let mut hash = [0u8; 32]; - // keccak.update(pub_key_without_prefix); - // keccak.finalize(&mut hash); - let hash: [u8; 32] = keccak256(&public_key.serialize_uncompressed()[1..]); - println!("hash = {}", hex::encode(hash)); - - // 取最后20字节作为地址 - let address = &hash[12..]; - - let address = [ - 63, 229, 19, 56, 153, 45, 145, 59, 106, 153, 150, 147, 215, 195, 69, 100, 108, 163, - 187, 76, - ]; - - // 转换为16进制并添加0x前缀 - format!("0x{}", hex::encode(&address)) - } - - #[test] - fn test_avax_address() { - let pubkey = PublicKey::from_str( - "02f01fe98afe9db6a160ec7fd57d4de1dcf9848c97307c4e4babc29ee34074a606", - ) - .unwrap(); - println!("{}", pubkey); - let address = get_avax_address(&pubkey); - println!("address = {}", address); - let result = generate_address(pubkey).unwrap(); - println!("{}", result); - assert_eq!(2, 1); - } } From 761d623e0f4674c81b3a5d195a4af46a39502ec7 Mon Sep 17 00:00:00 2001 From: ww3512687 <15809188520@163.com> Date: Fri, 10 Jan 2025 16:13:57 +0800 Subject: [PATCH 3/3] delete unused code --- rust/apps/ethereum/src/lib.rs | 50 ----------------------------------- 1 file changed, 50 deletions(-) diff --git a/rust/apps/ethereum/src/lib.rs b/rust/apps/ethereum/src/lib.rs index a1003c50d..7080f5424 100644 --- a/rust/apps/ethereum/src/lib.rs +++ b/rust/apps/ethereum/src/lib.rs @@ -238,56 +238,6 @@ mod tests { assert_eq!(result.input, "3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000"); } - #[test] - fn test_parse_native_avax_tx() { - let sign_data = hex::decode("f8b182a86902841dcd6500843b9aca0082a02a945425890298aed601595a70ab815c96711a31bc6580b844a9059cbb000000000000000000000000dba1d159ccdf86fb35e55c0b29a5a41428153ae700000000000000000000000000000000000000000000000000000000000186a0c080a07ce11f564e85f5e35d079856dc0f421e544889ece981de823daa50cdb4d1b0a3a07c137e1026bc3cc5137e081d64ef005d4547a9f940645b900f1d5365268d7c74").unwrap(); - let path = "m/44'/60'/0'/0/0".to_string(); - //to: 3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad - //data: 3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000 - let seed = hex::decode("a5004bb4331238ebd23b3176bf121b773d8ada011b68351f5f59ddd47152a0a95fdef5cebd2da9e243d4e18ea02530bb6068077176bab81964e3ffd366032573").unwrap(); - let pubkey = get_public_key_by_seed(&seed, &path).unwrap(); - let result = parse_fee_market_tx(sign_data, pubkey); - // println!("{:?}", result.un wrap()); - assert!(false); - // assert_eq!(31, result.nonce); - // assert_eq!(1, result.chain_id); - // assert_eq!("0x9858EfFD232B4033E47d90003D41EC34EcaEda94", result.from); - // assert_eq!("0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", result.to); - // assert_eq!("0.01", result.value); - // assert_eq!(None, result.gas_price); - // assert_eq!("15.669800712 Gwei", result.max_fee_per_gas.unwrap()); - // assert_eq!("0.1 Gwei", result.max_priority_fee_per_gas.unwrap()); - // assert_eq!("0.002483224", result.max_fee.unwrap()); - // assert_eq!("0.000015847", result.max_priority.unwrap()); - // assert_eq!("158472", result.gas_limit); - // assert_eq!("0.002483224", result.max_txn_fee); - // assert_eq!(result.input, "3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000"); - } - - #[test] - fn test_parse_avax_tx() { - let sign_data = hex::decode("f90290820eae850702198d00831e8480948186359af5f57fbb40c6b14a588d2a59c0c2988080b9022457ecfd280000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000f8000000000000000400000001000000000001153a00000000000000000000000057d4eaf1091577a6b7d121202afbd2808134f1170000000000000000000000006b25532e1060ce10cc3b0a99e5683b91bfde6982000000000000000000000000000000000000000000000000000000000000000000000000487039debedbf32d260137b0a6f66b90962bec777250910d253781de326a716d0000000000000000000000006b0ecb6102b99e96e04441604e9812d7fe6be99c0000000000000000000000000000000000000000000000000000000387f3be4000000000000000000000000099a0e1a8d7b123678d7aa07bd5845271f68a3683000000000000000000000000000000000000000000000000000000000000000000000000000000822039d546fff3d9a766a9f789ebadd4b63c10a5bd0046672b21ca997c6f09eb22023fe4acedddfb56647a40615f3692c8c9bb222b1b14fcdc3363630dee90b7421ba783a0d2dc6c8e1e8aade40777d231bd8c1eb55145fffa512cc02e5e3ac8afff5eb97278cbac2e9b3c8bf460f25a0819596413c39ed2f95d06c58599a7fdd3061c000000000000000000000000000000000000000000000000000000000000830150f8a0ec5e6e186a6c3c83116cb2df2fb80b36598bfb4e05d6464dc1e2bdcda1ad5c4ba02fb72a377c3be3c70e4b1692f0494f7b667e9154fda71c99d1bb16d574b2da28").unwrap(); - let path = "m/44'/60'/0'/0/0".to_string(); - //to: 3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad - //data: 3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000 - let seed = hex::decode("a5004bb4331238ebd23b3176bf121b773d8ada011b68351f5f59ddd47152a0a95fdef5cebd2da9e243d4e18ea02530bb6068077176bab81964e3ffd366032573").unwrap(); - let pubkey = get_public_key_by_seed(&seed, &path).unwrap(); - let result = parse_fee_market_tx(sign_data, pubkey).unwrap(); - assert_eq!(31, result.nonce); - assert_eq!(1, result.chain_id); - assert_eq!("0x9858EfFD232B4033E47d90003D41EC34EcaEda94", result.from); - assert_eq!("0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", result.to); - assert_eq!("0.01", result.value); - assert_eq!(None, result.gas_price); - assert_eq!("15.669800712 Gwei", result.max_fee_per_gas.unwrap()); - assert_eq!("0.1 Gwei", result.max_priority_fee_per_gas.unwrap()); - assert_eq!("0.002483224", result.max_fee.unwrap()); - assert_eq!("0.000015847", result.max_priority.unwrap()); - assert_eq!("158472", result.gas_limit); - assert_eq!("0.002483224", result.max_txn_fee); - assert_eq!(result.input, "3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064996e5f00000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000f84605ccc515414000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000"); - } - #[test] fn test_parse_typed_data() { let sign_data = "7b227479706573223a7b22454950373132446f6d61696e223a5b7b226e616d65223a226e616d65222c2274797065223a22737472696e67227d2c7b226e616d65223a2276657273696f6e222c2274797065223a22737472696e67227d2c7b226e616d65223a22636861696e4964222c2274797065223a2275696e74323536227d2c7b226e616d65223a22766572696679696e67436f6e7472616374222c2274797065223a2261646472657373227d5d2c224f72646572436f6d706f6e656e7473223a5b7b226e616d65223a226f666665726572222c2274797065223a2261646472657373227d2c7b226e616d65223a227a6f6e65222c2274797065223a2261646472657373227d2c7b226e616d65223a226f66666572222c2274797065223a224f666665724974656d5b5d227d2c7b226e616d65223a22737461727454696d65222c2274797065223a2275696e74323536227d2c7b226e616d65223a22656e6454696d65222c2274797065223a2275696e74323536227d2c7b226e616d65223a227a6f6e6548617368222c2274797065223a2262797465733332227d2c7b226e616d65223a2273616c74222c2274797065223a2275696e74323536227d2c7b226e616d65223a22636f6e647569744b6579222c2274797065223a2262797465733332227d2c7b226e616d65223a22636f756e746572222c2274797065223a2275696e74323536227d5d2c224f666665724974656d223a5b7b226e616d65223a22746f6b656e222c2274797065223a2261646472657373227d5d2c22436f6e73696465726174696f6e4974656d223a5b7b226e616d65223a22746f6b656e222c2274797065223a2261646472657373227d2c7b226e616d65223a226964656e7469666965724f724372697465726961222c2274797065223a2275696e74323536227d2c7b226e616d65223a227374617274416d6f756e74222c2274797065223a2275696e74323536227d2c7b226e616d65223a22656e64416d6f756e74222c2274797065223a2275696e74323536227d2c7b226e616d65223a22726563697069656e74222c2274797065223a2261646472657373227d5d7d2c227072696d61727954797065223a224f72646572436f6d706f6e656e7473222c22646f6d61696e223a7b226e616d65223a22536561706f7274222c2276657273696f6e223a22312e31222c22636861696e4964223a2231222c22766572696679696e67436f6e7472616374223a22307830303030303030303030366333383532636245663365303845386446323839313639456445353831227d2c226d657373616765223a7b226f666665726572223a22307866333946643665353161616438384636463463653661423838323732373963666646623932323636222c226f66666572223a5b7b22746f6b656e223a22307841363034303630383930393233466634303065386336663532393034363141383341454441436563227d5d2c22737461727454696d65223a2231363538363435353931222c22656e6454696d65223a2231363539323530333836222c227a6f6e65223a22307830303443303035303030303061443130344437444264303065336165304135433030353630433030222c227a6f6e6548617368223a22307830303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c2273616c74223a223136313738323038383937313336363138222c22636f6e647569744b6579223a22307830303030303037623032323330303931613765643031323330303732663730303661303034643630613864346537316435393962383130343235306630303030222c22746f74616c4f726967696e616c436f6e73696465726174696f6e4974656d73223a2232222c22636f756e746572223a2230227d7d";