Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keystone connect #1629

Merged
merged 7 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified images/walletList/walletListKeystone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions rust/apps/bitcoin/src/addresses/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ mod tests {

#[test]
fn test_btc_p2tr_no_script_address() {
let extended_pubkey = "xpub6Cq9mdT8xwFe9LYQnt9y1hJXTyo7KQJM8pRH6K95F1mbELzgm825m3hyAZ97vsUV8Xh7VRwu7bKuLZEmUV1ABqCRQqFzZHAsfaJXTYSY1cf";
let address =
get_address("M/86'/0'/0'/0/0".to_string(), &extended_pubkey.to_string()).unwrap();
assert_eq!(
address,
"bc1pf7al7fmsrfxftwp0durgv3zv9ezqzrqdhk34gjcuqasw6fnlxu7sw8xvjs"
);
}

#[test]
fn test_btc_p2tr_no_script_address_testnet() {
let extended_pubkey = "tpubDDfvzhdVV4unsoKt5aE6dcsNsfeWbTgmLZPi8LQDYU2xixrYemMfWJ3BaVneH3u7DBQePdTwhpybaKRU95pi6PMUtLPBJLVQRpzEnjfjZzX";
let address =
get_address("M/86'/1'/0'/0/0".to_string(), &extended_pubkey.to_string()).unwrap();
Expand Down
425 changes: 425 additions & 0 deletions rust/apps/wallets/src/keystone_connect.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions rust/apps/wallets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mod utils;
pub mod xbull;
pub mod xrp_toolkit;
pub mod zcash;
pub mod keystone_connect;
//TODO: get these value from device
pub const DEVICE_TYPE: &str = "Keystone 3 Pro";

Expand Down
64 changes: 64 additions & 0 deletions rust/rust_c/src/wallet/multi_coins_wallet/keystone_connect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::common::ffi::CSliceFFI;
use crate::common::structs::ExtendedPublicKey;
use crate::common::types::{Ptr, PtrBytes, PtrString};
use crate::common::ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT};
use crate::common::utils::{recover_c_array, recover_c_char};
use crate::extract_array;
use alloc::{format, string::ToString};
use ur_registry::{
error::URError, extend::crypto_multi_accounts::CryptoMultiAccounts, traits::RegistryItem,
};

use super::utils::normalize_xpub;

#[no_mangle]
pub extern "C" fn get_keystone_connect_wallet_ur(
master_fingerprint: PtrBytes,
master_fingerprint_length: u32,
serial_number: PtrString,
public_keys: Ptr<CSliceFFI<ExtendedPublicKey>>,
device_type: PtrString,
device_version: PtrString,
) -> Ptr<UREncodeResult> {
if master_fingerprint_length != 4 {
return UREncodeResult::from(URError::UrEncodeError(format!(
"master fingerprint length must be 4, current is {}",
master_fingerprint_length
)))
.c_ptr();
}
let mfp = extract_array!(master_fingerprint, u8, master_fingerprint_length);
let mfp = match <[u8; 4]>::try_from(mfp) {
Ok(mfp) => mfp,
Err(e) => return UREncodeResult::from(URError::UrEncodeError(e.to_string())).c_ptr(),
};
unsafe {
let keys = recover_c_array(public_keys);
let serial_number = recover_c_char(serial_number);
let device_version = recover_c_char(device_version);
let device_type = recover_c_char(device_type);
match normalize_xpub(keys) {
Ok(_keys) => {
match app_wallets::keystone_connect::generate_crypto_multi_accounts(
mfp,
&serial_number,
_keys,
&device_type,
&device_version,
) {
Ok(data) => match data.try_into() {
Ok(_v) => UREncodeResult::encode(
_v,
CryptoMultiAccounts::get_registry_type().get_type(),
FRAGMENT_MAX_LENGTH_DEFAULT,
)
.c_ptr(),
Err(_e) => UREncodeResult::from(_e).c_ptr(),
},
Err(_e) => UREncodeResult::from(_e).c_ptr(),
}
}
Err(_e) => UREncodeResult::from(_e).c_ptr(),
}
}
}
1 change: 1 addition & 0 deletions rust/rust_c/src/wallet/multi_coins_wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod tonkeeper;
mod utils;
pub mod xbull;
pub mod xrp_toolkit;
pub mod keystone_connect;

pub mod core_wallet;
pub mod thor_wallet;
Expand Down
3 changes: 3 additions & 0 deletions rust/rust_c/src/zcash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ mod tests {

#[test]
fn test_aes256_cbc_decrypt() {
//8dd387c3b2656d9f24ace7c3daf6fc26a1c161098460f8dddd37545fc951f9cd7da6c75c71ae52f32ceb8827eca2169ef4a643d2ccb9f01389d281a85850e2ddd100630ab1ca51310c3e6ccdd3029d0c48db18cdc971dba8f0daff9ad281b56221ffefc7d32333ea310a1f74f99dea444f8a089002cf1f0cd6a4ddf608a7b5388dc09f9417612657b9bf335a466f951547f9707dd129b3c24c900a26010f51c543eba10e9aabef7062845dc6969206b25577a352cb4d984db67c54c7615fe60769726bffa59fd8bd0b66fe29ee3c358af13cf0796c2c062bc79b73271eb0366f0536e425f8e42307ead4c695804fd3281aca5577d9a621e3a8047b14128c280c45343b5bbb783a065d94764e90ad6820fe81a200637401c256b1fb8f58a9d412d303b89c647411662907cdc55ed93adb
//73e6ca87d5cd5622cdc747367905efe7
//68487dc295052aa79c530e283ce698b8c6bb1b42ff0944252e1910dbecdc5425
let data = convert_c_char("639194f4bf964e15d8ea9c9bd9d96918".to_string());
let password = convert_c_char("password".to_string());
let mut seed = hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/ui/gui_assets/images_hash.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2704e955edd599bb96594a78763d6a42
2d0b63d974652e3681292274a77162db
96 changes: 48 additions & 48 deletions src/ui/gui_assets/walletList/walletListKeystone.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/ui/gui_components/gui_status_bar.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const static CoinWalletInfo_t g_coinWalletBtn[] = {

const static WalletInfo_t g_walletBtn[] = {
#ifndef BTC_ONLY
{WALLET_LIST_KEYSTONE, "Keystone", &walletKeystone},
{WALLET_LIST_KEYSTONE, "Keystone Nexus", &walletKeystone},
{WALLET_LIST_METAMASK, "MetaMask", &walletMetamask},
{WALLET_LIST_OKX, "OKX Wallet", &walletOkx},
{WALLET_LIST_ETERNL, "Eternl Wallet", &walletEternl},
Expand Down
42 changes: 42 additions & 0 deletions src/ui/gui_wallet/multi/web3/gui_wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,48 @@ UREncodeResult *GuiGetKeystoneWalletData(void)
return g_urEncode;
}

UREncodeResult *GuiGetKeystoneConnectWalletData(void)
{
uint8_t mfp[4] = {0};
GetMasterFingerPrint(mfp);
PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey));
// btc 4
// + eth 1
// + trx 1
ExtendedPublicKey keys[6];
public_keys->data = keys;
public_keys->size = 6;

// eth standard
keys[0].path = "m/44'/60'/0'";
keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_ETH_BIP44_STANDARD);


keys[1].path = "m/44'/0'/0'";
keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY);

keys[2].path = "m/49'/0'/0'";
keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC);

keys[3].path = "m/84'/0'/0'";
keys[3].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT);

keys[4].path = "m/86'/0'/0'";
keys[4].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_TAPROOT);

keys[5].path = GetXPubPath(XPUB_TYPE_TRX);
keys[5].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_TRX);

char serialNumber[256];
GetSerialNumber(serialNumber);
char firmwareVersion[12];
GetSoftWareVersionNumber(firmwareVersion);
g_urEncode = get_keystone_connect_wallet_ur(mfp, sizeof(mfp), serialNumber, public_keys, "Keystone 3 Pro", firmwareVersion);
CHECK_CHAIN_PRINT(g_urEncode);
SRAM_FREE(public_keys);
return g_urEncode;
}

UREncodeResult *GuiGetBitgetWalletData(void)
{
uint8_t mfp[4] = {0};
Expand Down
1 change: 1 addition & 0 deletions src/ui/gui_wallet/multi/web3/gui_wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ UREncodeResult *GuiGetImTokenData(void);
UREncodeResult *GuiGetCoreWalletData(void);
UREncodeResult *GuiGetKeystoneWalletData(void);
UREncodeResult *GuiGetThorWalletBtcData(void);
UREncodeResult *GuiGetKeystoneConnectWalletData(void);
#endif
22 changes: 11 additions & 11 deletions src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ static const lv_img_dsc_t *g_backpackWalletCoinArray[2] = {
};

static const lv_img_dsc_t *g_keystoneWalletCoinArray[] = {
&coinBtc, &coinEth, &coinBnb, &coinBch,
&coinDash, &coinLtc, &coinTrx, &coinXrp,
&coinBtc, &coinEth,&coinTrx
};

static const lv_img_dsc_t *g_blueWalletCoinArray[4] = {
Expand Down Expand Up @@ -324,9 +323,10 @@ static void GuiInitWalletListArray()
case WALLET_LIST_WANDER:
enable = !isTempAccount;
break;
case WALLET_LIST_KEYSTONE:
enable = isRussian;
break;
// open keystone for test
// case WALLET_LIST_KEYSTONE:
// enable = isRussian;
// break;
default:
break;
}
Expand Down Expand Up @@ -849,11 +849,11 @@ static void AddKeystoneWalletCoins(void)
lv_img_set_pivot(img, 0, 0);
lv_obj_align(img, LV_ALIGN_TOP_LEFT, 32 * i, 0);
}
lv_obj_t *img = GuiCreateImg(g_coinCont, &imgMore);
lv_img_set_zoom(img, 150);
lv_img_set_pivot(img, 0, 0);
lv_obj_set_style_img_opa(img, LV_OPA_30, LV_PART_MAIN);
lv_obj_align(img, LV_ALIGN_TOP_LEFT, 132, 2);
// lv_obj_t *img = GuiCreateImg(g_coinCont, &imgMore);
// lv_img_set_zoom(img, 150);
// lv_img_set_pivot(img, 0, 0);
// lv_obj_set_style_img_opa(img, LV_OPA_30, LV_PART_MAIN);
// lv_obj_align(img, LV_ALIGN_TOP_LEFT, 132, 2);
}

static void AddBlueWalletCoins(void)
Expand Down Expand Up @@ -1352,7 +1352,7 @@ void GuiConnectWalletSetQrdata(WALLET_LIST_INDEX_ENUM index)
break;
case WALLET_LIST_KEYSTONE:
// todo add keystone ur logic
func = GuiGetKeystoneWalletData;
func = GuiGetKeystoneConnectWalletData;
AddKeystoneWalletCoins();
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion src/ui/lv_i18n/data.csv
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ Wallet Profile,24,wallet_profile_mid_btn,Wallet Profile,Профиль коше
,20,ar_address_check_desc,"Different wallets may generate AR addresses differently, resulting in different addresses from the same phrase. This is normal. After connecting to the software wallet, please compare the address to ensure it matches the hardware wallet.","Разные кошельки могут генерировать AR-адреса по-разному, что приводит к различным адресам от одной и той же фразы. Это нормально. После подключения к программному кошельку, пожалуйста, сравните адрес, чтобы убедиться, что он совпадает с адресом аппаратного кошелька.","서로 다른 지갑은 AR 주소를 다르게 생성할 수 있으며, 결과적으로 동일한 구문에서도 다른 주소가 생성될 수 있습니다. 이는 정상적인 현상입니다. 소프트웨어 지갑에 연결한 후 주소가 하드웨어 지갑과 일치하는지 확인해주시기 바랍니다","不同的钱包可能以不同的方式生成AR地址, 从而导致相同的短语产生不同的地址。这是正常的。连接到软件钱包后, 请比较地址以确保与硬件钱包匹配。","Diferentes monederos pueden generar direcciones AR de manera diferente, resultando en direcciones diferentes a partir de la misma frase. Esto es normal. Después de conectarse al monedero de software, por favor compare la dirección para asegurarse de que coincide con el monedero de hardware.","Unterschiedliche Wallets können AR-Adressen unterschiedlich generieren, was zu unterschiedlichen Adressen aus demselben Satz führt. Dies ist normal. Nach dem Verbinden mit der Software-Wallet vergleichen Sie bitte die Adresse, um sicherzustellen, dass sie mit der Hardware Wallet übereinstimmt",異なるウォレットは、同じフレーズから異なるアドレスを生成する場合があります。これは正常な動作です。ソフトウェアウォレットに接続後、アドレスがハードウェアウォレットと一致するかどうか確認してください。
,20,solana_parse_tx_notice,The accounts in Instructions will be affected by this transaction. Please review carefully.,"Счета, указанные в Инструкциях, будут затронуты этой операцией. Пожалуйста, внимательно проверьте.",지침서에 명시된 계좌들은 이 거래의 영향을 받게 됩니다. 주의 깊게 검토해 주시기 바랍니다.,说明中的账户将受到此交易的影响。请仔细检查。,"Las cuentas indicadas en las Instrucciones se verán afectadas por esta transacción. Por favor, revíselas detenidamente.",Laut Anweisung betroffene Konten werden von dieser Transaktion beeinflusst. Bitte sorgfältig prüfen.,指示書の口座がこの取引の影響を受けます。慎重に確認してください。
,20,solana_alt_notice,The Address Lookup Table URL provides a reference to view detailed account information related to this transaction. Please note that the URL may expire or change over time,"Ссылка на таблицу адресов предоставляет информацию по счетам, связанным с этой операцией. Имейте в виду, что ссылка может измениться или устареть со временем.","주소록 테이블 URL은 이 거래와 관련된 계좌 정보를 제공합니다. 단, URL이 만료되거나 변경될 수 있음을 유의하시기 바랍니다.",地址查找表的网址提供了与此交易相关账户信息的参考。请注意该网址可能会过期。,La URL de la Tabla de Consulta de Direcciones proporciona una referencia para ver la información detallada de las cuentas relacionadas con esta transacción. Tenga en cuenta que la URL puede expirar o cambiar con el tiempo.,"Die URL der Adresstabelle bietet eine Referenz, um detaillierte Kontoinformationen zu dieser Transaktion einzusehen. Bitte beachten Sie, dass die URL ablaufen oder sich ändern kann.",アドレス参照表のURLでは、この取引に関連する詳細な口座情報を確認できます。URLは期限切れや変更の可能性があることにご留意ください。
,20,connect_keystone_title,Keystone,Keystone,Keystone,Keystone,Keystone,Keystone,Keystone
,20,connect_keystone_title,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus,Keystone Nexus
,20,connect_keystone_link,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone,https://keyst.one/t/3rd/keystone
,20,hardware_call_approve_notice,"Please note, if the path not saved on the device will require a password to be recalculated.","Обратите внимание, что если путь не сохранен на устройстве, потребуется пересчитать пароль.",주의사항: 경로가 기기에 저장되어 있지 않으면 비밀번호를 다시 계산해야 합니다.,"请注意,如果路径未保存在设备上,将需要重新计算密码。","Tenga en cuenta que, si la ruta no se guarda en el dispositivo, se requerirá recalcular la contraseña.","Bitte beachten Sie, dass wenn der Pfad nicht auf dem Gerät gespeichert ist, ein Passwort neu berechnet werden muss.",注意事項: デバイスにパスが保存されていない場合、パスワードを再計算する必要があります。
,20,invaild_account_path,Invalid Account Path,Недействительный путь учетной записи,잘못된 계정 경로,无效的账户路径,Ruta de cuenta no válida,Ungültiger Kontopfad,無効なアカウントパス
Expand Down
Loading
Loading