From 5ed628fc1fce73836ff31c89c2430a2b3abc4ebd Mon Sep 17 00:00:00 2001 From: Kalvis Kuskis <44435644+kalvkusk@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:27:26 +0300 Subject: [PATCH] main -> release 1.0.8 (#290) * chore: update tauri gh action * Update README.md (#283) * chore: OTA * feat: add legacy account etc (#280) * remove unnecessary spaces from mnemonics * feat: total balances of all accounts * feat:show the ol_account::real_balance() of the accounts * feat: add legacy account * addresses are shown in uppercase * typo * rust lint error * Revert "feat:show the ol_account::real_balance() of the accounts" This reverts commit 912f2925ef912fb28296f114e6503eb525797819. * support legacy account transfer --------- Co-authored-by: Kalvis Kuskis <44435644+kalvkusk@users.noreply.github.com> * Docs update (#287) * get-started.md links Tauri links edited for the right ones * Update canary-releases.md Link for Canary release updated to the last up-to-date * Update start-carpe-mac.md Link for macOS Carpe updated * Update start-carpe-windows.md Updated Carpe's Windows version download link * Update usage.md - Remove mining mention - Change the way onboarding is presented * Update releasing.md Updated Tauri link * Update windows-dev-setup.md Git clone repo updated * Update README.md Removed mention of mining * Update README.md Edited introduction link for 0L Network * Fix refresh_upstream_peer_stats (#289) * fix refresh_upstream_peer_stats * lint error * update preferences.rs --------- Co-authored-by: 0o-de-lally <1364012+0o-de-lally@users.noreply.github.com> Co-authored-by: BBK Co-authored-by: Manied <75039940+leManied@users.noreply.github.com> --- README.md | 8 +- autoupdater/autoupdater_payload.json | 12 +- docs/canary-releases.md | 2 +- docs/devs/get-started.md | 6 +- docs/devs/releasing.md | 2 +- docs/devs/windows-dev-setup.md | 2 +- docs/start-carpe-mac.md | 2 +- docs/start-carpe-windows.md | 2 +- docs/usage.md | 10 +- src-tauri/Cargo.lock | 14 +- src-tauri/Cargo.toml | 10 +- src-tauri/src/commands/preferences.rs | 6 +- src-tauri/src/commands/tx.rs | 3 +- src-tauri/src/commands/wallets.rs | 124 ++++++++++++++++-- src-tauri/src/configs.rs | 7 + src/components/dev/DebugPaths.svelte | 18 +-- src/components/dev/DevMode.svelte | 4 +- src/components/txs/Transactions.svelte | 1 + .../wallet/AccountFromMnemForm.svelte | 16 ++- .../wallet/AccountFromMnemSubmit.svelte | 24 ++-- .../wallet/AccountFromPrivateKey.svelte | 12 +- src/components/wallet/AddWatchAccount.svelte | 6 +- src/components/wallet/Wallet.svelte | 23 ++-- src/lang/locales/ar.json | 1 + src/lang/locales/de.json | 1 + src/lang/locales/en.json | 1 + src/lang/locales/es.json | 1 + src/lang/locales/fr.json | 1 + src/lang/locales/it.json | 1 + src/lang/locales/pt.json | 1 + src/lang/locales/zh_cn.json | 1 + src/modules/accountActions.ts | 36 ++++- src/modules/accountTransactions.ts | 9 +- src/modules/accounts.ts | 2 +- src/modules/networks.ts | 9 +- src/modules/tick.ts | 5 +- 36 files changed, 272 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 5d230f0b..caf99e77 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,14 @@ Currently Windows and Mac are supported: -- [Download Windows 10+](https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.2/carpe_1.0.2_x64_en-US.msi) and read the [Windows instructions](docs/start-carpe-windows.md) +- [Download Windows 10+](https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.7/carpe_1.0.7_x64_en-US.msi) -- [Download MacOs 11+](https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.2/carpe_1.0.2_x64.dmg) and read the [Mac instructions](docs/start-carpe-mac.md) +- [Download MacOs 11+](https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.7/carpe_1.0.7_x64.dmg) -On Windows, currently, Microsoft Edge WebView2 must be installed manually first. -https://developer.microsoft.com/en-us/microsoft-edge/webview2/consumer # About -Carpe is a desktop "wallet" that connects to the 0L network and lets you create accounts, do some account management. It also is a light "miner" allowing you to mine coins! To learn more about 0L itself follow the link: [0L introduction](https://github.com/OLSF/libra#readme). +Carpe is a desktop "wallet" that connects to the 0L network and lets you create accounts, do some account management. To learn more about 0L itself, you can check out the official website of the project : [0L Network website](https://0l.network/). # Creating Accounts diff --git a/autoupdater/autoupdater_payload.json b/autoupdater/autoupdater_payload.json index 52275276..638c4735 100644 --- a/autoupdater/autoupdater_payload.json +++ b/autoupdater/autoupdater_payload.json @@ -1,15 +1,15 @@ { - "version": "1.0.6", - "notes": "Bugfixes", + "version": "1.0.7", + "notes": "Miner sunset", "pub_date": "2024-03-11T10:57:15.333Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVSb2t0YlhzSHBEbHFML2t4OFFGUG1RUFNWVkJYbXJISnJnQkg2Y0QxVmF4OHVjbUFuenpkMGJmMDdZVzYzN0tHbk5iY2RsMXhRUTRUQlBSNFVzcGhZdm9iSUpOb00xSWdrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzEwMTU4NzUyCWZpbGU6Y2FycGVfMS4wLjZfeDY0X2VuLVVTLm1zaS56aXAKbjFTMGxsKytJQVJ1UW91VFZTYnEvSTZwTDFFdzVLR3phNzk5MHBEVEpQaTl6bnRYMk12VXJLcEdxNHpjcEpOODBadGZ3TTl6T1RsUmZFOWl3UjRWQlE9PQo=", - "url": "https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.6/carpe_1.0.6_x64_en-US.msi.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVSb2t0YlhzSHBEbHIveDg4cERZS0RPbkN4bGNHYmZhaHdpZm5EREk0MExoOWYxejFwZnVtNHZZMUhEaE9kTXJPMnlkbE0wd1BRenRDUno4T2s3WmJvaDJCMjl1L0dWVlEwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzEyODQ4NTQ3CWZpbGU6Y2FycGVfMS4wLjdfeDY0X2VuLVVTLm1zaS56aXAKUVhIcHM0b0hPWmlZZi9vRmdqSmxmTWF2WUtqQnMzTWdVRyt2QmhIUkxWZ0hHeHVqalZSVmNEVnltcUFmS0swdlJBb3EvTVR2QVhzM3pLS2d3dVVHREE9PQo=", + "url": "https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.7/carpe_1.0.7_x64_en-US.msi.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVSb2t0YlhzSHBEbG9TM0gzY0RuUFI2SVVSM2xVUnFvb2JNcUx6Q3paK2Y0ZzVrZlNrN0ZSV3N5ckR4MnhWRnZjbUVpdWpOblQvME54eHZGc3JEY1hHQjI5TS9jWlZ4MGdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzEwMTYxODIyCWZpbGU6Y2FycGUuYXBwLnRhci5negpvSmo4QnZmMW92VFQwbFJWWHVHOFRNZG0wanJhZFlLSHNxZmVLendSYzNmRWlqV1JiRnpDQkhTbndyTjBYWHNPbjhVa0s3eFpXKzdLR2dnWkxFREFDdz09Cg==", - "url": "https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.6/carpe_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVSb2t0YlhzSHBEbHI0RXZ6L24vczhRaWNCOStEMmVkV3RNemNmcVBLSHlFMlM2STRKL0pycjUwbkZoTVVUd2hFVjk2YVhuVHJwNUtCVEtYNThnNWFMb25SOGxIU3hRNEFvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzEyODQ4NzM4CWZpbGU6Y2FycGUuYXBwLnRhci5negpYRVk4dnBmMVNPdXd6TnA5UnlzV1lzbHZJd210ZUdwRE4rbndyN3JtSkt4eGhFeDFtZU1RSHpQNUx0cnF3enJPMWZGQVJzekU2dkR6M3Ywd0JLRThCZz09Cg==", + "url": "https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.7/carpe_x64.app.tar.gz" } } } diff --git a/docs/canary-releases.md b/docs/canary-releases.md index 130471a1..371907eb 100644 --- a/docs/canary-releases.md +++ b/docs/canary-releases.md @@ -6,4 +6,4 @@ Canary version allows you to have both installations side-by-side without interf Canary versions will receive Over-The-Air updates just like the production version. -[Download Carpe Canary Here](https://github.com/0LNetworkCommunity/carpe/releases/tag/v1.0.0-16-canary) +[Download Carpe Canary Here](https://github.com/0LNetworkCommunity/carpe/releases/tag/v1.0.1-3-canary) diff --git a/docs/devs/get-started.md b/docs/devs/get-started.md index 93d5173e..65ea55bd 100644 --- a/docs/devs/get-started.md +++ b/docs/devs/get-started.md @@ -1,6 +1,6 @@ # Developing and Building Carpe with Tauri and Svelte -Carpe leverages the power of [Tauri](https://tauri.studio) for building secure, lightweight desktop applications and [Svelte](https://svelte.dev) for creating efficient, reactive web interfaces. The template for Carpe can be found at: https://github.com/jbarszczewski/tauri-svelte-template. +Carpe leverages the power of [Tauri](https://tauri.app/) for building secure, lightweight desktop applications and [Svelte](https://svelte.dev) for creating efficient, reactive web interfaces. The template for Carpe can be found at: https://github.com/jbarszczewski/tauri-svelte-template. ## Get Started @@ -16,7 +16,7 @@ Ensure you have the following prerequisites installed: Additionally, you'll need to set up your environment for Tauri development: -- Follow the Tauri setup guide: [Setting up your environment](https://tauri.studio/en/docs/getting-started/intro#setting-up-your-environment). +- Follow the Tauri setup guide: [Setting up your environment](https://tauri.app/v1/guides/). - For Windows users, a specific guide is available: [Windows development environment setup](./windows-dev-setup.md). ### Installation Steps @@ -55,6 +55,6 @@ This generates an optimized version of your application, including standalone ex ## Additional Resources -- [Tauri Studio](https://tauri.studio): Official Tauri project website with comprehensive documentation. +- [Tauri Studio](https://tauri.app/): Official Tauri project website with comprehensive documentation. - [Svelte](https://svelte.dev): Home of the Svelte framework, with guides, tutorials, and API documentation. - [Sveltestrap](https://sveltestrap.js.org): Bootstrap 4 components for Svelte, facilitating quick and responsive UI development. diff --git a/docs/devs/releasing.md b/docs/devs/releasing.md index 933aa8fd..826263e6 100644 --- a/docs/devs/releasing.md +++ b/docs/devs/releasing.md @@ -45,4 +45,4 @@ Before creating a new TAG, please confirm that Cargo.toml file is pointing to th If the app icon design will be changed, the high resolution file needs to be in `./app-icon.png`. Then simply run `yarn tauri icon`, and all the icon formats will be created. -https://tauri.studio/docs/guides/icons/ +[https://tauri.studio/docs/guides/icons/](https://tauri.app/v1/guides/features/icons/#__docusaurus_skipToContent_fallback) diff --git a/docs/devs/windows-dev-setup.md b/docs/devs/windows-dev-setup.md index e8d9d1cf..f767a222 100644 --- a/docs/devs/windows-dev-setup.md +++ b/docs/devs/windows-dev-setup.md @@ -84,7 +84,7 @@ The MS compiler toolchain requires various environment variables set correctly. Carpe can now be cloned from GitHub and built, in the shell opened in step 7, with the same commands as used for the Linux and MacOS builds: ``` -git clone [git@github.com:OLSF/carpe.git](https://github.com/OLSF/carpe.git) +git clone https://github.com/0LNetworkCommunity/carpe.git cd carpe cd cd src-tauri cargo build diff --git a/docs/start-carpe-mac.md b/docs/start-carpe-mac.md index 3d7b63d1..3b2c3f4a 100644 --- a/docs/start-carpe-mac.md +++ b/docs/start-carpe-mac.md @@ -5,7 +5,7 @@ You can find the installable Mac package in the releases folder: macOS version 10.15 or higher -https://github.com/OLSF/carpe/releases/download/v0.3.0/carpe-macos-10.15.dmg +[https://github.com/OLSF/carpe/releases/download/v0.3.0/carpe-macos-10.15.dmg](https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.7/carpe_1.0.7_x64.dmg) ## Allow App Permissions diff --git a/docs/start-carpe-windows.md b/docs/start-carpe-windows.md index f86c32d5..ccba2861 100644 --- a/docs/start-carpe-windows.md +++ b/docs/start-carpe-windows.md @@ -4,7 +4,7 @@ You can find the Windows 10 installer in the releases folder: -https://github.com/OLSF/carpe/releases/download/v0.3.0/carpe_0.3.0_x64.msi +[https://github.com/OLSF/carpe/releases/download/v0.3.0/carpe_0.3.0_x64.msi](https://github.com/0LNetworkCommunity/carpe/releases/download/v1.0.7/carpe_1.0.7_x64_en-US.msi) # Important: diff --git a/docs/usage.md b/docs/usage.md index 5e0560dc..490858b5 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -24,19 +24,13 @@ On MacOS you will be prompted for your OS login password (on Windows and Ubuntu ![screen01](./img/keyring.png) -## Get a friend to onboard +## Get onboard Until you can use the newly created account, you need some 0L user who "onboards" you. Please send the displayed "authkey" to this person. After the onboarding transaction has been done, the wallet will show some BALANCE for your account and no longer the text "Account not on chain". -If you don't yet have a friend on 0L, come to the [Discord Server](https://discord.gg/AzCp63pggW) and make a new friend that can send your onboarding transaction. - -## Mining - -After your account has been onboarded, new menus appear on top of the screen. Switch to "MINER" to earn coins. - -To start mining, just click on the red toggle button, so it turns into green color. +If you don't yet have a friend on 0L, come to the [Discord Server](https://discord.gg/AzCp63pggW) and send your 0L public adress in the onboarding channel. ## DANGER diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0f31a8da..a4cf53ba 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6146,7 +6146,7 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libra-cached-packages" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "bcs 0.1.4", "diem-types", @@ -6158,7 +6158,7 @@ dependencies = [ [[package]] name = "libra-framework" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "anyhow", "bcs 0.1.4", @@ -6179,7 +6179,7 @@ dependencies = [ [[package]] name = "libra-query" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "anyhow", "clap 4.3.10", @@ -6193,7 +6193,7 @@ dependencies = [ [[package]] name = "libra-tower" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "anyhow", "byteorder", @@ -6214,7 +6214,7 @@ dependencies = [ [[package]] name = "libra-txs" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "anyhow", "bcs 0.1.4", @@ -6240,7 +6240,7 @@ dependencies = [ [[package]] name = "libra-types" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "anyhow", "async-trait", @@ -6275,7 +6275,7 @@ dependencies = [ [[package]] name = "libra-wallet" version = "0.1.0" -source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=da8bcdb4#da8bcdb425c9568370a939c5ead644a7e846d635" +source = "git+https://github.com/0LNetworkCommunity/libra-framework.git?rev=7ce1536#7ce1536adae9a75c1a7a8a1a2ebcea9033b7b188" dependencies = [ "anyhow", "blst", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8917e358..a553a07e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,11 +19,11 @@ gmp-mpfr-sys = { version = "1.6", default-features = false } openssl-sys = "0.9.98" [dependencies] -libra-query = { git = "https://github.com/0LNetworkCommunity/libra-framework.git", rev = "da8bcdb4" } -libra-tower = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "da8bcdb4" } -libra-types = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "da8bcdb4" } -libra-txs = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "da8bcdb4" } -libra-wallet = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "da8bcdb4" } +libra-query = { git = "https://github.com/0LNetworkCommunity/libra-framework.git", rev = "7ce1536" } +libra-tower = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "7ce1536" } +libra-types = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "7ce1536" } +libra-txs = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "7ce1536" } +libra-wallet = { git = "https://github.com/0LNetworkCommunity/libra-framework", rev = "7ce1536" } # without these pinned versions, poem-openapi-types fail poem = { version = "=1.3.55", features = ["anyhow", "rustls"] } diff --git a/src-tauri/src/commands/preferences.rs b/src-tauri/src/commands/preferences.rs index 13a3b09b..8388964d 100644 --- a/src-tauri/src/commands/preferences.rs +++ b/src-tauri/src/commands/preferences.rs @@ -58,9 +58,9 @@ pub fn debug_preferences_path() -> Result { /// refreshes statistics and returns the synced peers pub async fn refresh_upstream_peer_stats() -> Result, CarpeError> { let mut app_cfg = get_cfg()?; - app_cfg.refresh_network_profile_and_save(None).await?; // uses app_cfg.chain_info_chain_id - let np = app_cfg.get_network_profile(None)?; - // dbg!(&np); + + let np = app_cfg.refresh_network_profile_and_save(None).await?; // uses app_cfg.chain_info_chain_id + app_cfg.network_playlist = vec![np.clone()]; app_cfg.save_file()?; let peers = match np.the_good_ones() { diff --git a/src-tauri/src/commands/tx.rs b/src-tauri/src/commands/tx.rs index 368fe187..cce919f7 100644 --- a/src-tauri/src/commands/tx.rs +++ b/src-tauri/src/commands/tx.rs @@ -17,6 +17,7 @@ pub async fn coin_transfer( _sender: AccountAddress, receiver: &str, amount: u64, + legacy: bool, ) -> Result<(), CarpeError> { // NOTE: unsure Serde was catching all cases check serialization let receiver_account = match AccountAddress::from_str(receiver) { @@ -30,7 +31,7 @@ pub async fn coin_transfer( let mut config = get_cfg()?; inject_private_key_to_cfg(&mut config)?; - let mut sender = Sender::from_app_cfg(&config, None).await?; + let mut sender = Sender::from_app_cfg(&config, None, legacy).await?; sender .transfer(receiver_account, amount as f64, false) .await?; diff --git a/src-tauri/src/commands/wallets.rs b/src-tauri/src/commands/wallets.rs index cd8ab01f..e8f5b61f 100644 --- a/src-tauri/src/commands/wallets.rs +++ b/src-tauri/src/commands/wallets.rs @@ -1,12 +1,12 @@ use crate::{ carpe_error::CarpeError, commands::query, - configs::{self, get_cfg, get_client}, + configs::{self, default_legacy_account_path, get_cfg, get_client}, configs_profile, key_manager::{self, get_private_key, inject_private_key_to_cfg}, }; -use anyhow::{anyhow, Context}; +use anyhow::{anyhow, Context, Error}; use libra_txs::{submit_transaction::Sender, txs_cli_user::SetSlowTx}; use libra_types::{ exports::{AccountAddress, AuthenticationKey, Ed25519PrivateKey, ValidCryptoMaterialStringExt}, @@ -16,6 +16,8 @@ use libra_types::{ }; use libra_wallet::account_keys::{self, KeyChain}; use serde::{Deserialize, Serialize}; +use std::fs::{self, File}; +use std::io::prelude::*; #[derive(serde::Deserialize, serde::Serialize, Debug)] pub struct NewKeygen { @@ -23,6 +25,21 @@ pub struct NewKeygen { mnem: String, } +#[derive(serde::Deserialize, serde::Serialize, Debug)] +pub struct LegacyAccounts { + pub accounts: Vec, +} + +#[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq)] +pub struct LegacyAccount { + pub authkey: AuthenticationKey, +} + +impl LegacyAccount { + pub fn new(authkey: AuthenticationKey) -> Self { + LegacyAccount { authkey } + } +} /// a subset of AppCfg::Profile, dropping the private key #[derive(Debug, Serialize, Deserialize)] pub struct CarpeProfile { @@ -74,18 +91,23 @@ pub fn is_init() -> Result { /// default way accounts get initialized in Carpe #[tauri::command(async)] // don't want this to be async. We want it to block before moving back to the wallets page (and then needing a refresh), it's a smoother UI. -pub async fn init_from_mnem(mnem: String) -> Result { +pub async fn init_from_mnem(mnem: String, is_legacy: bool) -> Result { let wallet = account_keys::get_keys_from_mnem(mnem.clone())?; - init_from_private_key(wallet.child_0_owner.pri_key.to_encoded_string()?).await + init_from_private_key(wallet.child_0_owner.pri_key.to_encoded_string()?, is_legacy).await } #[tauri::command(async)] -pub async fn init_from_private_key(pri_key_string: String) -> Result { +pub async fn init_from_private_key( + pri_key_string: String, + is_legacy: bool, +) -> Result { let pri = Ed25519PrivateKey::from_encoded_string(&pri_key_string) .map_err(|_| anyhow!("cannot parse encoded private key"))?; let acc_struct = account_keys::get_account_from_private(&pri); let authkey = acc_struct.auth_key; - + if is_legacy { + let _ = add_legacy_accounts(authkey); + } // IMPORTANT // let's check if this account has had a rotated authkey, // so the address we derive may not be the expected one. @@ -177,7 +199,15 @@ pub async fn get_originating_address( auth_key: AuthenticationKey, ) -> Result { let client = get_client()?; - Ok(client.lookup_originating_address(auth_key).await?) + let all = read_legacy_accounts().unwrap(); + let acc_list: Vec = all.accounts.iter().map(|a| a.authkey.to_string()).collect(); + if acc_list.contains(&auth_key.to_string()) { + let a = auth_key.to_string()[32..].to_owned(); + let b = String::from("00000000000000000000000000000000"); + Ok(AccountAddress::from_hex_literal(&format!("0x{}{}", b, a)).unwrap()) + } else { + Ok(client.lookup_originating_address(auth_key).await?) + } } /// Switch tx profiles, change 0L.toml to use selected account @@ -200,6 +230,7 @@ pub fn remove_accounts() -> Result { let mut cfg = configs::get_cfg()?; cfg.user_profiles = vec![]; cfg.save_file()?; + let _ = remove_legacy_accounts(); Ok("removed all accounts".to_owned()) } @@ -220,7 +251,7 @@ fn get_short(acc: AccountAddress) -> String { async fn test_init_mnem() { use libra_types::legacy_types::app_cfg::AppCfg; let alice = "talent sunset lizard pill fame nuclear spy noodle basket okay critic grow sleep legend hurry pitch blanket clerk impose rough degree sock insane purse".to_string(); - init_from_mnem(alice).await.unwrap(); + init_from_mnem(alice, false).await.unwrap(); let _cfg = AppCfg::load(None).unwrap(); } @@ -235,11 +266,11 @@ async fn test_fetch_originating() { } #[tauri::command(async)] -pub async fn set_slow_wallet() -> Result<(), CarpeError> { +pub async fn set_slow_wallet(legacy: bool) -> Result<(), CarpeError> { // NOTE: unsure Serde was catching all cases check serialization let mut config = get_cfg()?; inject_private_key_to_cfg(&mut config)?; - let mut sender = Sender::from_app_cfg(&config, None).await?; + let mut sender = Sender::from_app_cfg(&config, None, legacy).await?; let t = SetSlowTx {}; t.run(&mut sender).await?; @@ -256,9 +287,80 @@ pub fn get_private_key_from_os(address: AccountAddress) -> Result Result { +pub async fn add_watch_account( + address: AccountAddress, + is_legacy: bool, +) -> Result { let authkey: AuthenticationKey = query::get_auth_key(address).await?; + if is_legacy { + let _ = add_legacy_accounts(authkey); + } configs_profile::set_account_profile(address, authkey).await?; let core_profile = &Profile::new(authkey, address); Ok(core_profile.into()) } + +fn read_legacy_accounts() -> Result { + let db_path = default_legacy_account_path(); + if db_path.exists() { + let file = File::open(db_path)?; + Ok(serde_json::from_reader(file)?) + } else { + Ok(LegacyAccounts { accounts: vec![] }) + } +} + +fn add_legacy_accounts(authkey: AuthenticationKey) -> Result { + let mut all = read_legacy_accounts()?; + // push new account + let new_account = LegacyAccount { authkey }; + let acc_list: Vec = all.accounts.iter().map(|a| a.authkey.to_string()).collect(); + if !acc_list.contains(&new_account.authkey.to_string()) { + all.accounts.push(new_account); + let _ = update_legacy_accounts(&all); + Ok(all) + } else { + Err(CarpeError::misc("account already exists")) + } +} +fn update_legacy_accounts(accounts: &LegacyAccounts) -> Result<(), CarpeError> { + let db_path = default_legacy_account_path(); + let serialized = serde_json::to_vec(accounts) + .map_err(|e| CarpeError::config(&format!("json legacyAccounts should serialize, {:?}", &e)))?; + + File::create(db_path) + .map_err(|e| { + CarpeError::config(&format!( + "carpe legacyAccounts.json should be created!, {:?}", + &e + )) + })? + .write_all(&serialized) + .map_err(|e| { + CarpeError::config(&format!( + "carpe legacyAccounts.json should be written!, {:?}", + &e + )) + })?; + Ok(()) +} + +pub fn remove_legacy_accounts() -> Result { + let db_path = default_legacy_account_path(); + dbg!(&db_path); + if db_path.exists() { + match fs::remove_file(&db_path) { + Ok(_) => return Ok("removed all legacy accounts".to_owned()), + _ => { + return Err(CarpeError::misc(&format!( + "unable to delete account file found at {:?}", + &db_path + ))) + } + } + } + Err(CarpeError::misc(&format!( + "No legacy accounts to remove. No account file found at {:?}", + &db_path + ))) +} diff --git a/src-tauri/src/configs.rs b/src-tauri/src/configs.rs index 5d2b1db0..94ff58c2 100644 --- a/src-tauri/src/configs.rs +++ b/src-tauri/src/configs.rs @@ -20,6 +20,13 @@ static CONFIG_DIR: Lazy = Lazy::new(|| { os_path.config_dir().to_path_buf() }); +static LEGACY_ACCOUNTS_FILE: &str = "legacy_accounts.json"; + +// get the config path for LEGACY_ACCOUNTS_FILE +pub fn default_legacy_account_path() -> PathBuf { + CONFIG_DIR.join(LEGACY_ACCOUNTS_FILE) +} + /// get the config path for files // NOTE: update in V1 we are now using OS specific paths. // Lin: /home/alice/.config/carpe diff --git a/src/components/dev/DebugPaths.svelte b/src/components/dev/DebugPaths.svelte index b0070e81..073d8f00 100644 --- a/src/components/dev/DebugPaths.svelte +++ b/src/components/dev/DebugPaths.svelte @@ -1,15 +1,15 @@
@@ -23,8 +27,12 @@ bind:value={formDangerMnem} /> - - +
+ +
+
diff --git a/src/components/wallet/AccountFromMnemSubmit.svelte b/src/components/wallet/AccountFromMnemSubmit.svelte index 1bc46b2c..40f94997 100644 --- a/src/components/wallet/AccountFromMnemSubmit.svelte +++ b/src/components/wallet/AccountFromMnemSubmit.svelte @@ -6,26 +6,24 @@ export let formDangerMnem: string export let isNewAccount = true - + export let isLegacy = false; function openConfirmationModal() { UIkit.modal('#submit-confirmation-modal').show() } let isSubmitting = false - function initAccount(mnem_string: string) { + function initAccount(mnem_string: string, isLegacy) { if (mnem_string.length == 0) return - + mnem_string = mnem_string.trim().split(/\s+/).join(' ') isSubmitting = true - addAccount(InitType.Mnem, mnem_string.trim()) - .finally(() => { - isSubmitting = false - mnem_string = null - UIkit.modal('#submit-confirmation-modal').hide() - }) + addAccount(InitType.Mnem, mnem_string.trim(), isLegacy).finally(() => { + isSubmitting = false + mnem_string = null + UIkit.modal('#submit-confirmation-modal').hide() + }) } - onDestroy(() => formDangerMnem=null) - + onDestroy(() => (formDangerMnem = null)) {#if isNewAccount} @@ -56,7 +54,7 @@ class="uk-button uk-button-primary" type="button" disabled={isSubmitting} - on:click|preventDefault={initAccount(formDangerMnem)} + on:click|preventDefault={initAccount(formDangerMnem, isLegacy)} > {#if isSubmitting} {$_('wallet.account_from_mnem_submit.btn_submiting')} @@ -72,7 +70,7 @@ class="uk-button uk-button-primary" type="button" disabled={isSubmitting} - on:click|preventDefault={initAccount(formDangerMnem)} + on:click|preventDefault={initAccount(formDangerMnem, isLegacy)} > {#if isSubmitting} {$_('wallet.account_from_mnem_submit.btn_submiting')}... diff --git a/src/components/wallet/AccountFromPrivateKey.svelte b/src/components/wallet/AccountFromPrivateKey.svelte index 72916a44..074ec4b3 100644 --- a/src/components/wallet/AccountFromPrivateKey.svelte +++ b/src/components/wallet/AccountFromPrivateKey.svelte @@ -3,9 +3,12 @@ import { InitType, addAccount } from '../../modules/accountActions' let danger_temp_private_key: string - + let isLegacy = false + function toggle() { + isLegacy = !isLegacy + } const initAccount = (pri_key: string) => { - addAccount(InitType.PriKey, pri_key.trim()) + addAccount(InitType.PriKey, pri_key.trim(), isLegacy) } @@ -22,6 +25,11 @@ bind:value={danger_temp_private_key} /> +
+ +
diff --git a/src/components/wallet/AddWatchAccount.svelte b/src/components/wallet/AddWatchAccount.svelte index f5099c4b..c1d8af66 100644 --- a/src/components/wallet/AddWatchAccount.svelte +++ b/src/components/wallet/AddWatchAccount.svelte @@ -5,7 +5,9 @@ let address: string const initAccount = (address: string) => { - addWatchAccount(address.trim()) + address = address.trim() + let isLegacy = address.length === 32 || address.startsWith('0'.padStart(32, '0')) + addWatchAccount(address, isLegacy) } @@ -30,7 +32,7 @@ type="button" on:click|preventDefault={initAccount(address)} > - {$_('wallet.account_from_mnem_submit.btn_submit')} + {$_('wallet.account_from_mnem_submit.btn_submit')} diff --git a/src/components/wallet/Wallet.svelte b/src/components/wallet/Wallet.svelte index e21829e0..b66043b3 100644 --- a/src/components/wallet/Wallet.svelte +++ b/src/components/wallet/Wallet.svelte @@ -2,7 +2,8 @@ import { _ } from 'svelte-i18n' import UIkit from 'uikit' import Icons from 'uikit/dist/js/uikit-icons' - import { allAccounts, pendingAccounts } from '../../modules/accounts' + import { allAccounts, pendingAccounts, totalBalance } from '../../modules/accounts' + import { printCoins } from '../../modules/coinHelpers' // views import Newbie from './Newbie.svelte' @@ -12,26 +13,32 @@ import { connected } from '../../modules/networks' UIkit.use(Icons) -
-
- {#if !$allAccounts || ($allAccounts && $allAccounts.length == 0)} + {#if !$allAccounts || ($allAccounts && $allAccounts.length == 0)} +
- {:else if $allAccounts && $allAccounts.length > 0} +
+ {:else if $allAccounts && $allAccounts.length > 0} +

{$_('wallet.wallet')}

- +
+ {$_('wallet.account_list.balance')}: {printCoins($totalBalance.total)} + {$_('wallet.account_list.unlocked')}: {printCoins($totalBalance.unlocked)} +
{#if $connected && $pendingAccounts.length > 0} {/if} - {/if} -
+
+ {/if}
diff --git a/src/lang/locales/ar.json b/src/lang/locales/ar.json index 28660de9..76b52c01 100644 --- a/src/lang/locales/ar.json +++ b/src/lang/locales/ar.json @@ -35,6 +35,7 @@ "btn_restore_account": "Restore Account", "btn_add_watch_account": "Watch Account", "newbie_message": "Looks like you don't have any accounts", + "legacy_account_opt": "Legacy account, address length 32 characters", "reminder_create": { "card_title": "Onboarding", "message_headline": "You have generated keys for an account, but it does not yet exist on chain.", diff --git a/src/lang/locales/de.json b/src/lang/locales/de.json index 24525776..4fbdd970 100644 --- a/src/lang/locales/de.json +++ b/src/lang/locales/de.json @@ -35,6 +35,7 @@ "btn_restore_account": "Konto wiederherstellen", "btn_add_watch_account": "Konto beobachten", "newbie_message": "Sieht aus, als hättest du keine Konten", + "legacy_account_opt": "Ältere Adresse, 32-Zeichen-Adresse", "reminder_create": { "card_title": "Onboarding", "message_headline": "Du hast Keys für ein Konto erzeugt, aber es existiert noch nicht auf der Chain.", diff --git a/src/lang/locales/en.json b/src/lang/locales/en.json index 59512213..9130d937 100644 --- a/src/lang/locales/en.json +++ b/src/lang/locales/en.json @@ -35,6 +35,7 @@ "btn_restore_account": "Restore Account", "btn_add_watch_account": "Watch Account", "newbie_message": "Looks like you don't have any accounts", + "legacy_account_opt": "Legacy account, address length 32 characters", "reminder_create": { "card_title": "Onboarding", "message_headline": "You have generated keys for an account, but it does not yet exist on chain.", diff --git a/src/lang/locales/es.json b/src/lang/locales/es.json index 39610b25..b722e847 100644 --- a/src/lang/locales/es.json +++ b/src/lang/locales/es.json @@ -35,6 +35,7 @@ "btn_restore_account": "Restore Account", "btn_add_watch_account": "Watch Account", "newbie_message": "Looks like you don't have any accounts", + "legacy_account_opt": "Legacy account, address length 32 characters", "reminder_create": { "card_title": "Onboarding", "message_headline": "You have generated keys for an account, but it does not yet exist on chain.", diff --git a/src/lang/locales/fr.json b/src/lang/locales/fr.json index ddd70b90..9b54b4c0 100644 --- a/src/lang/locales/fr.json +++ b/src/lang/locales/fr.json @@ -35,6 +35,7 @@ "btn_restore_account": "Récupération de Compte", "btn_add_watch_account": "Watch Account", "newbie_message": "Compte de surveillance", + "legacy_account_opt": "Adresse héritée, adresse de 32 caractères", "reminder_create": { "card_title": "Onboarding", "message_headline": "Vous avez généré les clés de votre compte mais il n'existe pas encore sur la chaine.", diff --git a/src/lang/locales/it.json b/src/lang/locales/it.json index e235568d..56d48839 100644 --- a/src/lang/locales/it.json +++ b/src/lang/locales/it.json @@ -35,6 +35,7 @@ "btn_restore_account": "Restore Account", "btn_add_watch_account": "Watch Account", "newbie_message": "Looks like you don't have any accounts", + "legacy_account_opt": "Legacy account, address length 32 characters", "reminder_create": { "card_title": "Onboarding", "message_headline": "You have generated keys for an account, but it does not yet exist on chain.", diff --git a/src/lang/locales/pt.json b/src/lang/locales/pt.json index 30d609d3..a6cc6340 100644 --- a/src/lang/locales/pt.json +++ b/src/lang/locales/pt.json @@ -35,6 +35,7 @@ "btn_restore_account": "Restaurar Conta", "btn_add_watch_account": "Ver conta", "newbie_message": "Parece que você não tem nenhuma conta ainda", + "legacy_account_opt": "Endereço herdado, endereço de 32 caracteres", "reminder_create": { "card_title": "Integração", "message_headline": "Você gerou chaves para uma conta, mas ela não existe na rede ainda.", diff --git a/src/lang/locales/zh_cn.json b/src/lang/locales/zh_cn.json index 11fabe19..18f00d6d 100644 --- a/src/lang/locales/zh_cn.json +++ b/src/lang/locales/zh_cn.json @@ -35,6 +35,7 @@ "btn_restore_account": "恢复账号", "btn_add_watch_account": "观察账号", "newbie_message": "您似乎还没有创建账号。", + "legacy_account_opt": "遗留地址, 32字符的地址", "reminder_create": { "card_title": "激活", "message_headline": "您的账号已经创建成功,但是还没有激活。", diff --git a/src/modules/accountActions.ts b/src/modules/accountActions.ts index 5981ba46..411644c1 100644 --- a/src/modules/accountActions.ts +++ b/src/modules/accountActions.ts @@ -18,6 +18,7 @@ import { watchAccounts, pendingAccounts, isCarpeTickRunning, + totalBalance, } from './accounts' import type { CarpeProfile, SlowWalletBalance } from './accounts' import { navigate } from 'svelte-navigator' @@ -26,10 +27,24 @@ import { initNetwork } from './networks' allAccounts.subscribe((v) => { pendingAccounts.set(v.filter((x) => x && !x.on_chain)) + const allBalance: SlowWalletBalance = v.reduce( + (p, c): SlowWalletBalance => { + return { + total: p.total + c.balance.total, + unlocked: p.unlocked + c.balance.unlocked, + } + }, + { + total: 0, + unlocked: 0, + }, + ) + totalBalance.set(allBalance) }) export const getDefaultProfile = async () => { invoke('get_default_profile', {}) .then((res: CarpeProfile) => { + res.account = res.account.toLocaleUpperCase() signingAccount.set(res) }) .catch((e) => { @@ -44,6 +59,8 @@ export const getAccounts = async () => { const watchList = get(watchAccounts) result.map((item) => { item.watch_only = watchList.includes(item.account) + item.account = item.account.toLocaleUpperCase() + item.auth_key = item.auth_key.toLocaleUpperCase() }) allAccounts.set(result) }) @@ -62,6 +79,8 @@ export const refreshAccounts = async () => { const watchList = get(watchAccounts) result.map((item) => { item.watch_only = watchList.includes(item.account) + item.account = item.account.toLocaleUpperCase() + item.auth_key = item.auth_key.toLocaleUpperCase() }) allAccounts.set(result) @@ -71,11 +90,13 @@ export const refreshAccounts = async () => { const { account, on_chain, + watch_only, balance: { unlocked, total }, } = item return ( account === currentAccount.account && (on_chain !== currentAccount.on_chain || + watch_only !== currentAccount.watch_only || unlocked !== currentAccount.balance?.unlocked || total !== currentAccount.balance?.total) ) @@ -103,15 +124,19 @@ export enum InitType { PriKey, } -export const addAccount = async (init_type: InitType, secret: string) => { +export const addAccount = async ( + init_type: InitType, + secret: string, + isLegacy: boolean = false, +) => { let method_name = '' let arg_obj = {} if (init_type == InitType.Mnem) { method_name = 'init_from_mnem' - arg_obj = { mnem: secret.trim() } + arg_obj = { mnem: secret.trim(), isLegacy } } else if (init_type == InitType.PriKey) { method_name = 'init_from_private_key' - arg_obj = { priKeyString: secret.trim() } + arg_obj = { priKeyString: secret.trim(), isLegacy } } // submit return invoke(method_name, arg_obj) @@ -170,6 +195,7 @@ export const setAccount = async (account: string, notifySucess = true) => { invoke('switch_profile', { account }) .then((res: CarpeProfile) => { + res.account = res.account.toLocaleUpperCase() signingAccount.set(res) isInit.set(true) if (notifySucess) { @@ -377,7 +403,7 @@ export function getPrivateKey(address: string, callback = null) { }) } -export function addWatchAccount(address: string) { +export function addWatchAccount(address: string, isLegacy: boolean = true) { const accountList: CarpeProfile[] = get(allAccounts) // v5 address padding 0 if (address.length == 32) { @@ -393,6 +419,7 @@ export function addWatchAccount(address: string) { invoke('add_watch_account', { address, + isLegacy, }) .then(async (res: CarpeProfile) => { let list = get(watchAccounts) @@ -415,6 +442,7 @@ async function onAccountAdd(res: CarpeProfile) { responses.set(JSON.stringify(res)) // cannot switch profile with miner running if (!get(minerLoopEnabled)) { + res.account = res.account.toLocaleUpperCase() signingAccount.set(res) } await initNetwork() diff --git a/src/modules/accountTransactions.ts b/src/modules/accountTransactions.ts index c45a4be5..12d32b20 100644 --- a/src/modules/accountTransactions.ts +++ b/src/modules/accountTransactions.ts @@ -2,7 +2,8 @@ import { notify_success } from './carpeNotify' import { invoke } from '@tauri-apps/api/tauri' import { raise_error, type CarpeError } from './carpeError' import { responses } from './debug' - +import { signingAccount } from './accounts' +import { get } from 'svelte/store' export enum WalletType { Slow = 0, Community = 1, @@ -11,8 +12,10 @@ export enum WalletType { export const setWalletType = async (wtype: WalletType) => { // TODO: implement community if necessary if (wtype != WalletType.Slow) return - - invoke('set_slow_wallet') + const account = get(signingAccount) + invoke('set_slow_wallet', { + legacy: account.account.startsWith('0'.repeat(32)), + }) .then((res: string) => { notify_success(`The account is set to: SlowWallet`) responses.set(res) diff --git a/src/modules/accounts.ts b/src/modules/accounts.ts index 328c786d..a5b29668 100644 --- a/src/modules/accounts.ts +++ b/src/modules/accounts.ts @@ -39,7 +39,7 @@ export const canMigrate = writable(false) export const migrateSuccess = writable() export const migrateInProgress = writable() export const isCarpeTickRunning = writable(false) - +export const totalBalance = writable({ total: 0, unlocked: 0 }) const localeWatchAccounts = JSON.parse(localStorage.getItem('watchAccounts') || '[]') export const watchAccounts = writable(localeWatchAccounts) diff --git a/src/modules/networks.ts b/src/modules/networks.ts index 978dfb2f..6da8048f 100644 --- a/src/modules/networks.ts +++ b/src/modules/networks.ts @@ -158,10 +158,6 @@ export const incrementBackoff = () => { scanning_fullnodes_backoff.set(new_time.getSeconds()) } -let current_network_profile: NetworkPlaylist = defaultPlaylist() -network_profile.subscribe((value) => { - current_network_profile = value -}) let isTest = false nodeEnvIsTest.subscribe((value) => { isTest = value @@ -170,9 +166,8 @@ export const initNetwork = async () => { logger(Level.Info, 'initNetwork') if (!isTest) { await getNetwork() - if (current_network_profile.chain_id === NamedChain.TESTING) { - return await updateNetwork(playlistJsonUrl, false) - } + + return await updateNetwork(playlistJsonUrl, false) } return true } diff --git a/src/modules/tick.ts b/src/modules/tick.ts index b082d0c8..fa8aa00f 100644 --- a/src/modules/tick.ts +++ b/src/modules/tick.ts @@ -1,7 +1,7 @@ import { get } from 'svelte/store' import { getAccounts, refreshAccounts } from './accountActions' // import { getLocalHeight, getTowerChainView, maybeEmitBacklog } from './miner_invoke' -import { getMetadata } from './networks' +import { getMetadata, refreshUpstreamPeerStats } from './networks' import { isInit } from './accounts' import { Level, logger } from './carpeError' @@ -21,7 +21,8 @@ export const carpeTick = async () => { tick_in_progress = true // don't try to connect while we are booting up the app and looking for fullnodes - // things that need network connectivity e.g. miner happen here + + await refreshUpstreamPeerStats() getMetadata() .then(refreshAccounts) // tower things