Merge branch 'refs/heads/main' into CW-679-Add-Ledger-Litecoin-Support
# Conflicts: # cw_bitcoin/lib/litecoin_wallet.dart # cw_bitcoin/lib/litecoin_wallet_service.dart
4
.github/workflows/cache_dependencies.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v1
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: "11.x"
|
java-version: "17.x"
|
||||||
- name: Configure placeholder git details
|
- name: Configure placeholder git details
|
||||||
run: |
|
run: |
|
||||||
git config --global user.email "CI@cakewallet.com"
|
git config --global user.email "CI@cakewallet.com"
|
||||||
|
@ -60,7 +60,7 @@ jobs:
|
||||||
path: |
|
path: |
|
||||||
/opt/android/cake_wallet/cw_haven/android/.cxx
|
/opt/android/cake_wallet/cw_haven/android/.cxx
|
||||||
/opt/android/cake_wallet/scripts/monero_c/release
|
/opt/android/cake_wallet/scripts/monero_c/release
|
||||||
key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh') }}
|
key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
|
||||||
|
|
||||||
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
||||||
name: Generate Externals
|
name: Generate Externals
|
||||||
|
|
|
@ -53,7 +53,9 @@ jobs:
|
||||||
channel: stable
|
channel: stable
|
||||||
|
|
||||||
- name: Install package dependencies
|
- name: Install package dependencies
|
||||||
run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang
|
||||||
|
|
||||||
- name: Execute Build and Setup Commands
|
- name: Execute Build and Setup Commands
|
||||||
run: |
|
run: |
|
||||||
|
@ -76,7 +78,7 @@ jobs:
|
||||||
path: |
|
path: |
|
||||||
/opt/android/cake_wallet/cw_haven/android/.cxx
|
/opt/android/cake_wallet/cw_haven/android/.cxx
|
||||||
/opt/android/cake_wallet/scripts/monero_c/release
|
/opt/android/cake_wallet/scripts/monero_c/release
|
||||||
key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh') }}
|
key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
|
||||||
|
|
||||||
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
||||||
name: Generate Externals
|
name: Generate Externals
|
187
.github/workflows/pr_test_build_linux.yml
vendored
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
name: PR Test Build linux
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
branch:
|
||||||
|
description: "Branch name to build"
|
||||||
|
required: true
|
||||||
|
default: "main"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
PR_test_build:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
STORE_PASS: test@cake_wallet
|
||||||
|
KEY_PASS: test@cake_wallet
|
||||||
|
PR_NUMBER: ${{ github.event.number }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: is pr
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: is not pr
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENVg
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: "17.x"
|
||||||
|
- name: Configure placeholder git details
|
||||||
|
run: |
|
||||||
|
git config --global user.email "CI@cakewallet.com"
|
||||||
|
git config --global user.name "Cake Github Actions"
|
||||||
|
- name: Flutter action
|
||||||
|
uses: subosito/flutter-action@v1
|
||||||
|
with:
|
||||||
|
flutter-version: "3.19.6"
|
||||||
|
channel: stable
|
||||||
|
|
||||||
|
- name: Install package dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt-get install -y curl unzip automake build-essential file pkg-config git python-is-python3 libtool libtinfo5 cmake clang
|
||||||
|
|
||||||
|
- name: Install desktop dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y ninja-build libgtk-3-dev gperf
|
||||||
|
- name: Execute Build and Setup Commands
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /opt/android
|
||||||
|
sudo chown $USER /opt/android
|
||||||
|
cd /opt/android
|
||||||
|
-y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
cargo install cargo-ndk
|
||||||
|
git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }}
|
||||||
|
cd scripts && ./gen_android_manifest.sh && cd ..
|
||||||
|
cd cake_wallet/scripts/android/
|
||||||
|
source ./app_env.sh cakewallet
|
||||||
|
./app_config.sh
|
||||||
|
cd ../../..
|
||||||
|
cd cake_wallet/scripts/linux/
|
||||||
|
source ./app_env.sh cakewallet
|
||||||
|
./app_config.sh
|
||||||
|
cd ../../..
|
||||||
|
|
||||||
|
- name: Cache Externals
|
||||||
|
id: cache-externals
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
/opt/android/cake_wallet/cw_haven/android/.cxx
|
||||||
|
/opt/android/cake_wallet/scripts/monero_c/release
|
||||||
|
key: linux_${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
|
||||||
|
|
||||||
|
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate Externals
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet/scripts/linux/
|
||||||
|
source ./app_env.sh cakewallet
|
||||||
|
./build_monero_all.sh
|
||||||
|
|
||||||
|
- name: Install Flutter dependencies
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet
|
||||||
|
flutter pub get
|
||||||
|
|
||||||
|
- name: Generate localization
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet
|
||||||
|
flutter packages pub run tool/generate_localization.dart
|
||||||
|
|
||||||
|
- name: Build generated code
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet
|
||||||
|
./model_generator.sh
|
||||||
|
|
||||||
|
- name: Add secrets
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet
|
||||||
|
touch lib/.secrets.g.dart
|
||||||
|
touch cw_evm/lib/.secrets.g.dart
|
||||||
|
touch cw_solana/lib/.secrets.g.dart
|
||||||
|
touch cw_core/lib/.secrets.g.dart
|
||||||
|
touch cw_nano/lib/.secrets.g.dart
|
||||||
|
touch cw_tron/lib/.secrets.g.dart
|
||||||
|
echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
|
||||||
|
echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
|
||||||
|
echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
|
||||||
|
echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
|
||||||
|
echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart
|
||||||
|
echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const quantexExchangeMarkup = '${{ secrets.QUANTEX_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
||||||
|
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
||||||
|
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||||
|
echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||||
|
|
||||||
|
- name: Rename app
|
||||||
|
run: |
|
||||||
|
echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet
|
||||||
|
flutter build linux --release
|
||||||
|
|
||||||
|
- name: Prepare release zip file
|
||||||
|
run: |
|
||||||
|
cd /opt/android/cake_wallet/build/linux/x64/release
|
||||||
|
zip -r ${{env.BRANCH_NAME}}.zip bundle
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: kittaakos/upload-artifact-as-is@v0
|
||||||
|
with:
|
||||||
|
path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip
|
||||||
|
|
||||||
|
# Just as an artifact would be enough
|
||||||
|
# - name: Send Test APK
|
||||||
|
# continue-on-error: true
|
||||||
|
# uses: adrey/slack-file-upload-action@1.0.5
|
||||||
|
# with:
|
||||||
|
# token: ${{ secrets.SLACK_APP_TOKEN }}
|
||||||
|
# path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip
|
||||||
|
# channel: ${{ secrets.SLACK_APK_CHANNEL }}
|
||||||
|
# title: "${{ env.BRANCH_NAME }}_linux.zip"
|
||||||
|
# filename: ${{ env.BRANCH_NAME }}_linux.zip
|
||||||
|
# initial_comment: ${{ github.event.head_commit.message }}
|
2
.gitignore
vendored
|
@ -160,6 +160,8 @@ macos/Runner/Release.entitlements
|
||||||
macos/Runner/Runner.entitlements
|
macos/Runner/Runner.entitlements
|
||||||
lib/core/secure_storage.dart
|
lib/core/secure_storage.dart
|
||||||
|
|
||||||
|
lib/core/secure_storage.dart
|
||||||
|
|
||||||
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
|
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
|
||||||
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
|
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
|
||||||
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
|
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
|
||||||
|
|
|
@ -18,6 +18,12 @@ migration:
|
||||||
- platform: windows
|
- platform: windows
|
||||||
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
||||||
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
||||||
|
- platform: macos
|
||||||
|
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
||||||
|
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
||||||
|
- platform: linux
|
||||||
|
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
||||||
|
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
<img height="100" src=".github/assets/Logo_CakeWallet.png">
|
![logo](.github/assets/Logo_CakeWallet.png)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -91,5 +91,4 @@ dependencies {
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
implementation 'com.unstoppabledomains:resolution:5.0.0'
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,10 @@ import android.net.Uri;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import com.unstoppabledomains.resolution.DomainResolution;
|
|
||||||
import com.unstoppabledomains.resolution.Resolution;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
public class MainActivity extends FlutterFragmentActivity {
|
public class MainActivity extends FlutterFragmentActivity {
|
||||||
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
||||||
final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24;
|
|
||||||
boolean isAppSecure = false;
|
boolean isAppSecure = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,14 +49,6 @@ public class MainActivity extends FlutterFragmentActivity {
|
||||||
random.nextBytes(bytes);
|
random.nextBytes(bytes);
|
||||||
handler.post(() -> result.success(bytes));
|
handler.post(() -> result.success(bytes));
|
||||||
break;
|
break;
|
||||||
case "getUnstoppableDomainAddress":
|
|
||||||
int version = Build.VERSION.SDK_INT;
|
|
||||||
if (version >= UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK) {
|
|
||||||
getUnstoppableDomainAddress(call, result);
|
|
||||||
} else {
|
|
||||||
handler.post(() -> result.success(""));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "setIsAppSecure":
|
case "setIsAppSecure":
|
||||||
isAppSecure = call.argument("isAppSecure");
|
isAppSecure = call.argument("isAppSecure");
|
||||||
if (isAppSecure) {
|
if (isAppSecure) {
|
||||||
|
@ -85,23 +73,6 @@ public class MainActivity extends FlutterFragmentActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getUnstoppableDomainAddress(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
|
||||||
DomainResolution resolution = new Resolution();
|
|
||||||
Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
String domain = call.argument("domain");
|
|
||||||
String ticker = call.argument("ticker");
|
|
||||||
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
try {
|
|
||||||
String address = resolution.getAddress(domain, ticker);
|
|
||||||
handler.post(() -> result.success(address));
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Expected Address, but got " + e.getMessage());
|
|
||||||
handler.post(() -> result.success(""));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disableBatteryOptimization() {
|
private void disableBatteryOptimization() {
|
||||||
String packageName = getPackageName();
|
String packageName = getPackageName();
|
||||||
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
|
|
|
@ -19,14 +19,10 @@ import android.net.Uri;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import com.unstoppabledomains.resolution.DomainResolution;
|
|
||||||
import com.unstoppabledomains.resolution.Resolution;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
public class MainActivity extends FlutterFragmentActivity {
|
public class MainActivity extends FlutterFragmentActivity {
|
||||||
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
||||||
final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
|
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
|
||||||
|
@ -51,14 +47,6 @@ public class MainActivity extends FlutterFragmentActivity {
|
||||||
random.nextBytes(bytes);
|
random.nextBytes(bytes);
|
||||||
handler.post(() -> result.success(bytes));
|
handler.post(() -> result.success(bytes));
|
||||||
break;
|
break;
|
||||||
case "getUnstoppableDomainAddress":
|
|
||||||
int version = Build.VERSION.SDK_INT;
|
|
||||||
if (version >= UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK) {
|
|
||||||
getUnstoppableDomainAddress(call, result);
|
|
||||||
} else {
|
|
||||||
handler.post(() -> result.success(""));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "disableBatteryOptimization":
|
case "disableBatteryOptimization":
|
||||||
disableBatteryOptimization();
|
disableBatteryOptimization();
|
||||||
handler.post(() -> result.success(null));
|
handler.post(() -> result.success(null));
|
||||||
|
@ -75,23 +63,6 @@ public class MainActivity extends FlutterFragmentActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getUnstoppableDomainAddress(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
|
||||||
DomainResolution resolution = new Resolution();
|
|
||||||
Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
String domain = call.argument("domain");
|
|
||||||
String ticker = call.argument("ticker");
|
|
||||||
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
try {
|
|
||||||
String address = resolution.getAddress(domain, ticker);
|
|
||||||
handler.post(() -> result.success(address));
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Expected Address, but got " + e.getMessage());
|
|
||||||
handler.post(() -> result.success(""));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disableBatteryOptimization() {
|
private void disableBatteryOptimization() {
|
||||||
String packageName = getPackageName();
|
String packageName = getPackageName();
|
||||||
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
|
|
|
@ -19,14 +19,10 @@ import android.net.Uri;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import com.unstoppabledomains.resolution.DomainResolution;
|
|
||||||
import com.unstoppabledomains.resolution.Resolution;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
public class MainActivity extends FlutterFragmentActivity {
|
public class MainActivity extends FlutterFragmentActivity {
|
||||||
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
||||||
final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24;
|
|
||||||
boolean isAppSecure = false;
|
boolean isAppSecure = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,14 +48,6 @@ public class MainActivity extends FlutterFragmentActivity {
|
||||||
random.nextBytes(bytes);
|
random.nextBytes(bytes);
|
||||||
handler.post(() -> result.success(bytes));
|
handler.post(() -> result.success(bytes));
|
||||||
break;
|
break;
|
||||||
case "getUnstoppableDomainAddress":
|
|
||||||
int version = Build.VERSION.SDK_INT;
|
|
||||||
if (version >= UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK) {
|
|
||||||
getUnstoppableDomainAddress(call, result);
|
|
||||||
} else {
|
|
||||||
handler.post(() -> result.success(""));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "setIsAppSecure":
|
case "setIsAppSecure":
|
||||||
isAppSecure = call.argument("isAppSecure");
|
isAppSecure = call.argument("isAppSecure");
|
||||||
if (isAppSecure) {
|
if (isAppSecure) {
|
||||||
|
@ -84,23 +72,6 @@ public class MainActivity extends FlutterFragmentActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getUnstoppableDomainAddress(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
|
||||||
DomainResolution resolution = new Resolution();
|
|
||||||
Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
String domain = call.argument("domain");
|
|
||||||
String ticker = call.argument("ticker");
|
|
||||||
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
try {
|
|
||||||
String address = resolution.getAddress(domain, ticker);
|
|
||||||
handler.post(() -> result.success(address));
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Expected Address, but got " + e.getMessage());
|
|
||||||
handler.post(() -> result.success(""));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disableBatteryOptimization() {
|
private void disableBatteryOptimization() {
|
||||||
String packageName = getPackageName();
|
String packageName = getPackageName();
|
||||||
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
|
|
|
@ -2,7 +2,7 @@ buildscript {
|
||||||
ext.kotlin_version = '1.8.21'
|
ext.kotlin_version = '1.8.21'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -15,7 +15,7 @@ buildscript {
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 28 KiB |
176
build-guide-linux.md
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
# Building CakeWallet for Linux
|
||||||
|
|
||||||
|
## Requirements and Setup
|
||||||
|
|
||||||
|
The following are the system requirements to build CakeWallet for your Linux device.
|
||||||
|
|
||||||
|
```
|
||||||
|
Ubuntu >= 16.04
|
||||||
|
Flutter 3.10.x
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building CakeWallet on Linux
|
||||||
|
|
||||||
|
These steps will help you configure and execute a build of CakeWallet from its source code.
|
||||||
|
|
||||||
|
### 1. Installing Package Dependencies
|
||||||
|
|
||||||
|
CakeWallet requires some packages to be install on your build system. You may easily install them on your build system with the following command:
|
||||||
|
|
||||||
|
`$ sudo apt install build-essential cmake pkg-config git curl autoconf libtool`
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> ### Check gcc version
|
||||||
|
>
|
||||||
|
> It is needed to use gcc 10 or 9 to successfully link dependencies with flutter.\
|
||||||
|
> To check what gcc version you are using:
|
||||||
|
>
|
||||||
|
> ```bash
|
||||||
|
> $ gcc --version
|
||||||
|
> $ g++ --version
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> If you are using gcc version newer than 10, then you need to downgrade to version 10.4.0:
|
||||||
|
>
|
||||||
|
> ```bash
|
||||||
|
> $ sudo apt install gcc-10 g++-10
|
||||||
|
> $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10
|
||||||
|
> $ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10
|
||||||
|
> ```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> Alternatively, you can use the [nix-shell](https://nixos.org/) with the `gcc10.nix` file\
|
||||||
|
> present on `scripts/linux` like so:
|
||||||
|
> ```bash
|
||||||
|
> $ nix-shell gcc10.nix
|
||||||
|
> ```
|
||||||
|
> This will get you in a nix environment with all the required dependencies that you can use to build the software from,\
|
||||||
|
> and it works in any linux distro.
|
||||||
|
|
||||||
|
### 2. Installing Flutter
|
||||||
|
|
||||||
|
Need to install flutter. For this please check section [How to install flutter on Linux](https://docs.flutter.dev/get-started/install/linux).
|
||||||
|
|
||||||
|
### 3. Verify Installations
|
||||||
|
|
||||||
|
Verify that the Flutter have been correctly installed on your system with the following command:
|
||||||
|
|
||||||
|
`$ flutter doctor`
|
||||||
|
|
||||||
|
The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
|
||||||
|
|
||||||
|
```
|
||||||
|
Doctor summary (to see all details, run flutter doctor -v):
|
||||||
|
[✓] Flutter (Channel stable, 3.10.x, on Linux, locale en_US.UTF-8)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Acquiring the CakeWallet Source Code
|
||||||
|
|
||||||
|
Download CakeWallet source code
|
||||||
|
|
||||||
|
`$ git clone https://github.com/cake-tech/cake_wallet.git --branch linux/password-direct-input`
|
||||||
|
|
||||||
|
Proceed into the source code before proceeding with the next steps:
|
||||||
|
|
||||||
|
`$ cd cake_wallet/scripts/linux/`
|
||||||
|
|
||||||
|
To configure some project properties run:
|
||||||
|
|
||||||
|
`$ ./cakewallet.sh`
|
||||||
|
|
||||||
|
Build the Monero libraries and their dependencies:
|
||||||
|
|
||||||
|
`$ ./build_all.sh`
|
||||||
|
|
||||||
|
Now the dependencies need to be copied into the CakeWallet project with this command:
|
||||||
|
|
||||||
|
`$ ./setup.sh`
|
||||||
|
|
||||||
|
It is now time to change back to the base directory of the CakeWallet source code:
|
||||||
|
|
||||||
|
`$ cd ../../`
|
||||||
|
|
||||||
|
Install Flutter package dependencies with this command:
|
||||||
|
|
||||||
|
`$ flutter pub get`
|
||||||
|
|
||||||
|
> #### If you will get an error like:
|
||||||
|
>
|
||||||
|
> ```
|
||||||
|
> The plugin `cw_shared_external` requires your app to be migrated to the Android embedding v2. Follow the steps on the migration doc above and re-run
|
||||||
|
> this command.
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> Then need to config Android project settings. For this open `scripts/android` (`$ cd scripts/android`) directory and run followed commands:
|
||||||
|
>
|
||||||
|
> ```
|
||||||
|
> $ source ./app_env.sh cakewallet
|
||||||
|
> $ ./app_config.sh
|
||||||
|
> $ cd ../..
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> Then re-configure Linux project again. For this open `scripts/linux` (`$cd scripts/linux`) directory and run:
|
||||||
|
> `$ ./cakewallet.sh`
|
||||||
|
> and back to project root directory:
|
||||||
|
> `$ cd ../..`
|
||||||
|
> and fetch dependecies again
|
||||||
|
> `$ flutter pub get`
|
||||||
|
|
||||||
|
Your CakeWallet binary will be built with some specific keys for iterate with 3rd party services. You may generate these secret keys placeholders with the following command:
|
||||||
|
|
||||||
|
`$ flutter packages pub run tool/generate_new_secrets.dart`
|
||||||
|
|
||||||
|
We will generate mobx models for the project.
|
||||||
|
|
||||||
|
`$ ./model_generator.sh`
|
||||||
|
|
||||||
|
Then we need to generate localization files.
|
||||||
|
|
||||||
|
`$ flutter packages pub run tool/generate_localization.dart`
|
||||||
|
|
||||||
|
### 5. Build!
|
||||||
|
|
||||||
|
`$ flutter build linux --release`
|
||||||
|
|
||||||
|
Path to executable file will be:
|
||||||
|
|
||||||
|
`build/linux/x64/release/bundle/cake_wallet`
|
||||||
|
|
||||||
|
> ### Troubleshooting
|
||||||
|
>
|
||||||
|
> If you got an error while building the application with `$ flutter build linux --release` command, add `-v` argument to the command (`$ flutter build linux -v --release`) to get details.\
|
||||||
|
> If you got in flutter build logs: undefined reference to `hid_free_enumeration`, or another error with undefined reference to `hid_*`, then rebuild monero lib without hidapi lib. Check does exists `libhidapi-dev` in your scope and remove it from your scope for build without it.
|
||||||
|
|
||||||
|
# Flatpak
|
||||||
|
|
||||||
|
For package the built application into flatpak you need fistly to install `flatpak` and `flatpak-builder`:
|
||||||
|
|
||||||
|
`$ sudo apt install flatpak flatpak-builder`
|
||||||
|
|
||||||
|
Then need to [add flathub](https://flatpak.org/setup/Ubuntu) (or just `$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo`). Then need to install freedesktop runtime and sdk:
|
||||||
|
|
||||||
|
`$ flatpak install flathub org.freedesktop.Platform//22.08 org.freedesktop.Sdk//22.08`
|
||||||
|
|
||||||
|
To build with using of `flatpak-build` directory run next:
|
||||||
|
|
||||||
|
`$ flatpak-builder --force-clean flatpak-build com.cakewallet.CakeWallet.yml`
|
||||||
|
|
||||||
|
And then export bundle:
|
||||||
|
|
||||||
|
`$ flatpak build-export export flatpak-build`
|
||||||
|
|
||||||
|
`$ flatpak build-bundle export cake_wallet.flatpak com.cakewallet.CakeWallet`
|
||||||
|
|
||||||
|
Result file: `cake_wallet.flatpak` should be generated in current directory.
|
||||||
|
|
||||||
|
For install generated flatpak file use:
|
||||||
|
|
||||||
|
`$ flatpak --user install cake_wallet.flatpak`
|
||||||
|
|
||||||
|
For run the installed application run:
|
||||||
|
|
||||||
|
`$ flatpak run com.cakewallet.CakeWallet`
|
||||||
|
|
||||||
|
Copyright (c) 2023 Cake Technologies LLC.
|
35
com.cakewallet.CakeWallet.yml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
app-id: com.cakewallet.CakeWallet
|
||||||
|
runtime: org.freedesktop.Platform
|
||||||
|
runtime-version: '22.08'
|
||||||
|
sdk: org.freedesktop.Sdk
|
||||||
|
command: cake_wallet
|
||||||
|
separate-locales: false
|
||||||
|
finish-args:
|
||||||
|
- --share=ipc
|
||||||
|
- --socket=fallback-x11
|
||||||
|
- --socket=wayland
|
||||||
|
- --device=dri
|
||||||
|
- --socket=pulseaudio
|
||||||
|
- --share=network
|
||||||
|
- --filesystem=home
|
||||||
|
modules:
|
||||||
|
- name: cake_wallet
|
||||||
|
buildsystem: simple
|
||||||
|
only-arches:
|
||||||
|
- x86_64
|
||||||
|
build-commands:
|
||||||
|
- "cp -R bundle /app/cake_wallet"
|
||||||
|
- "chmod +x /app/cake_wallet/cake_wallet"
|
||||||
|
- "mkdir -p /app/bin"
|
||||||
|
- "ln -s /app/cake_wallet/cake_wallet /app/bin/cake_wallet"
|
||||||
|
- "mkdir -p /app/share/icons/hicolor/scalable/apps"
|
||||||
|
- "cp cakewallet_icon_180.png /app/share/icons/hicolor/scalable/apps/com.cakewallet.CakeWallet.png"
|
||||||
|
- "mkdir -p /app/share/applications"
|
||||||
|
- "cp com.cakewallet.CakeWallet.desktop /app/share/applications"
|
||||||
|
sources:
|
||||||
|
- type: dir
|
||||||
|
path: build/linux/x64/release
|
||||||
|
- type: file
|
||||||
|
path: assets/images/cakewallet_icon_180.png
|
||||||
|
- type: file
|
||||||
|
path: linux/com.cakewallet.CakeWallet.desktop
|
|
@ -3,12 +3,13 @@
|
||||||
IOS="ios"
|
IOS="ios"
|
||||||
ANDROID="android"
|
ANDROID="android"
|
||||||
MACOS="macos"
|
MACOS="macos"
|
||||||
|
LINUX="linux"
|
||||||
|
|
||||||
PLATFORMS=($IOS $ANDROID $MACOS)
|
PLATFORMS=($IOS $ANDROID $MACOS $LINUX)
|
||||||
PLATFORM=$1
|
PLATFORM=$1
|
||||||
|
|
||||||
if ! [[ " ${PLATFORMS[*]} " =~ " ${PLATFORM} " ]]; then
|
if ! [[ " ${PLATFORMS[*]} " =~ " ${PLATFORM} " ]]; then
|
||||||
echo "specify platform: ./configure_cake_wallet.sh ios|android|macos"
|
echo "specify platform: ./configure_cake_wallet.sh ios|android|macos|linux"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -27,9 +28,14 @@ if [ "$PLATFORM" == "$ANDROID" ]; then
|
||||||
cd scripts/android
|
cd scripts/android
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$PLATFORM" == "$LINUX" ]; then
|
||||||
|
echo "Configuring for linux"
|
||||||
|
cd scripts/linux
|
||||||
|
fi
|
||||||
|
|
||||||
source ./app_env.sh cakewallet
|
source ./app_env.sh cakewallet
|
||||||
./app_config.sh
|
./app_config.sh
|
||||||
cd ../.. && flutter pub get
|
cd ../.. && flutter pub get
|
||||||
#flutter packages pub run tool/generate_localization.dart
|
flutter packages pub run tool/generate_localization.dart
|
||||||
./model_generator.sh
|
./model_generator.sh
|
||||||
#cd macos && pod install
|
#cd macos && pod install
|
||||||
|
|
|
@ -5,9 +5,10 @@ import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
|
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
||||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
|
||||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
||||||
import 'package:cw_bitcoin/psbt_transaction_builder.dart';
|
import 'package:cw_bitcoin/psbt_transaction_builder.dart';
|
||||||
|
@ -30,6 +31,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
Uint8List? seedBytes,
|
Uint8List? seedBytes,
|
||||||
String? mnemonic,
|
String? mnemonic,
|
||||||
String? xpub,
|
String? xpub,
|
||||||
|
@ -58,6 +60,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
currency:
|
currency:
|
||||||
networkParam == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc,
|
networkParam == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc,
|
||||||
alwaysScan: alwaysScan,
|
alwaysScan: alwaysScan,
|
||||||
|
@ -90,6 +93,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
String? passphrase,
|
String? passphrase,
|
||||||
String? addressPageType,
|
String? addressPageType,
|
||||||
BasedUtxoNetwork? network,
|
BasedUtxoNetwork? network,
|
||||||
|
@ -124,6 +128,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialSilentAddresses: initialSilentAddresses,
|
initialSilentAddresses: initialSilentAddresses,
|
||||||
initialSilentAddressIndex: initialSilentAddressIndex,
|
initialSilentAddressIndex: initialSilentAddressIndex,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||||
|
@ -137,6 +142,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required String password,
|
required String password,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
required bool alwaysScan,
|
required bool alwaysScan,
|
||||||
}) async {
|
}) async {
|
||||||
final network = walletInfo.network != null
|
final network = walletInfo.network != null
|
||||||
|
@ -148,7 +154,13 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
ElectrumWalletSnapshot? snp = null;
|
ElectrumWalletSnapshot? snp = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, network);
|
snp = await ElectrumWalletSnapshot.load(
|
||||||
|
encryptionFileUtils,
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
network,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!hasKeysFile) rethrow;
|
if (!hasKeysFile) rethrow;
|
||||||
}
|
}
|
||||||
|
@ -156,10 +168,18 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
final WalletKeysData keysData;
|
final WalletKeysData keysData;
|
||||||
// Migrate wallet from the old scheme to then new .keys file scheme
|
// Migrate wallet from the old scheme to then new .keys file scheme
|
||||||
if (!hasKeysFile) {
|
if (!hasKeysFile) {
|
||||||
keysData =
|
keysData = WalletKeysData(
|
||||||
WalletKeysData(mnemonic: snp!.mnemonic, xPub: snp.xpub, passphrase: snp.passphrase);
|
mnemonic: snp!.mnemonic,
|
||||||
|
xPub: snp.xpub,
|
||||||
|
passphrase: snp.passphrase,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
walletInfo.derivationInfo ??= DerivationInfo();
|
walletInfo.derivationInfo ??= DerivationInfo();
|
||||||
|
@ -198,6 +218,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialSilentAddresses: snp?.silentAddresses,
|
initialSilentAddresses: snp?.silentAddresses,
|
||||||
initialSilentAddressIndex: snp?.silentAddressIndex ?? 0,
|
initialSilentAddressIndex: snp?.silentAddressIndex ?? 0,
|
||||||
initialBalance: snp?.balance,
|
initialBalance: snp?.balance,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
initialRegularAddressIndex: snp?.regularAddressIndex,
|
initialRegularAddressIndex: snp?.regularAddressIndex,
|
||||||
initialChangeAddressIndex: snp?.changeAddressIndex,
|
initialChangeAddressIndex: snp?.changeAddressIndex,
|
||||||
|
|
|
@ -6,11 +6,13 @@ class BitcoinNewWalletCredentials extends WalletCredentials {
|
||||||
BitcoinNewWalletCredentials(
|
BitcoinNewWalletCredentials(
|
||||||
{required String name,
|
{required String name,
|
||||||
WalletInfo? walletInfo,
|
WalletInfo? walletInfo,
|
||||||
|
String? password,
|
||||||
DerivationType? derivationType,
|
DerivationType? derivationType,
|
||||||
String? derivationPath})
|
String? derivationPath})
|
||||||
: super(
|
: super(
|
||||||
name: name,
|
name: name,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
password: password,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
|
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
|
@ -19,11 +20,12 @@ class BitcoinWalletService extends WalletService<
|
||||||
BitcoinRestoreWalletFromSeedCredentials,
|
BitcoinRestoreWalletFromSeedCredentials,
|
||||||
BitcoinRestoreWalletFromWIFCredentials,
|
BitcoinRestoreWalletFromWIFCredentials,
|
||||||
BitcoinRestoreWalletFromHardware> {
|
BitcoinRestoreWalletFromHardware> {
|
||||||
BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan);
|
BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
||||||
final bool alwaysScan;
|
final bool alwaysScan;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletType getType() => WalletType.bitcoin;
|
WalletType getType() => WalletType.bitcoin;
|
||||||
|
@ -40,6 +42,7 @@ class BitcoinWalletService extends WalletService<
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
network: network,
|
network: network,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
|
@ -63,6 +66,7 @@ class BitcoinWalletService extends WalletService<
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
alwaysScan: alwaysScan,
|
alwaysScan: alwaysScan,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
saveBackup(name);
|
saveBackup(name);
|
||||||
|
@ -75,6 +79,7 @@ class BitcoinWalletService extends WalletService<
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
alwaysScan: alwaysScan,
|
alwaysScan: alwaysScan,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -99,6 +104,7 @@ class BitcoinWalletService extends WalletService<
|
||||||
walletInfo: currentWalletInfo,
|
walletInfo: currentWalletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
alwaysScan: alwaysScan,
|
alwaysScan: alwaysScan,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
|
@ -125,6 +131,7 @@ class BitcoinWalletService extends WalletService<
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
networkParam: network,
|
networkParam: network,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -153,6 +160,7 @@ class BitcoinWalletService extends WalletService<
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
network: network,
|
network: network,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
|
|
||||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
@ -6,6 +7,8 @@ import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_core/utils/file.dart';
|
import 'package:cw_core/utils/file.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||||
|
|
||||||
part 'electrum_transaction_history.g.dart';
|
part 'electrum_transaction_history.g.dart';
|
||||||
|
|
||||||
|
@ -15,13 +18,15 @@ class ElectrumTransactionHistory = ElectrumTransactionHistoryBase with _$Electru
|
||||||
|
|
||||||
abstract class ElectrumTransactionHistoryBase
|
abstract class ElectrumTransactionHistoryBase
|
||||||
extends TransactionHistoryBase<ElectrumTransactionInfo> with Store {
|
extends TransactionHistoryBase<ElectrumTransactionInfo> with Store {
|
||||||
ElectrumTransactionHistoryBase({required this.walletInfo, required String password})
|
ElectrumTransactionHistoryBase(
|
||||||
|
{required this.walletInfo, required String password, required this.encryptionFileUtils})
|
||||||
: _password = password,
|
: _password = password,
|
||||||
_height = 0 {
|
_height = 0 {
|
||||||
transactions = ObservableMap<String, ElectrumTransactionInfo>();
|
transactions = ObservableMap<String, ElectrumTransactionInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
final WalletInfo walletInfo;
|
final WalletInfo walletInfo;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
String _password;
|
String _password;
|
||||||
int _height;
|
int _height;
|
||||||
|
|
||||||
|
@ -44,7 +49,7 @@ abstract class ElectrumTransactionHistoryBase
|
||||||
txjson[tx.key] = tx.value.toJson();
|
txjson[tx.key] = tx.value.toJson();
|
||||||
}
|
}
|
||||||
final data = json.encode({'height': _height, 'transactions': txjson});
|
final data = json.encode({'height': _height, 'transactions': txjson});
|
||||||
await writeData(path: path, password: _password, data: data);
|
await encryptionFileUtils.write(path: path, password: _password, data: data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error while save bitcoin transaction history: ${e.toString()}');
|
print('Error while save bitcoin transaction history: ${e.toString()}');
|
||||||
}
|
}
|
||||||
|
@ -58,7 +63,7 @@ abstract class ElectrumTransactionHistoryBase
|
||||||
Future<Map<String, dynamic>> _read() async {
|
Future<Map<String, dynamic>> _read() async {
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
final path = '$dirPath/$transactionsHistoryFileName';
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
final content = await read(path: path, password: _password);
|
final content = await encryptionFileUtils.read(path: path, password: _password);
|
||||||
return json.decode(content) as Map<String, dynamic>;
|
return json.decode(content) as Map<String, dynamic>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'dart:isolate';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:cw_bitcoin/address_from_output.dart';
|
import 'package:cw_bitcoin/address_from_output.dart';
|
||||||
|
@ -33,7 +34,6 @@ import 'package:cw_core/sync_status.dart';
|
||||||
import 'package:cw_core/transaction_direction.dart';
|
import 'package:cw_core/transaction_direction.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cw_core/utils/file.dart';
|
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_keys_file.dart';
|
import 'package:cw_core/wallet_keys_file.dart';
|
||||||
|
@ -59,6 +59,7 @@ abstract class ElectrumWalletBase
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required this.network,
|
required this.network,
|
||||||
|
required this.encryptionFileUtils,
|
||||||
String? xpub,
|
String? xpub,
|
||||||
String? mnemonic,
|
String? mnemonic,
|
||||||
Uint8List? seedBytes,
|
Uint8List? seedBytes,
|
||||||
|
@ -93,7 +94,11 @@ abstract class ElectrumWalletBase
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.electrumClient = electrumClient ?? ElectrumClient();
|
this.electrumClient = electrumClient ?? ElectrumClient();
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = ElectrumTransactionHistory(walletInfo: walletInfo, password: password);
|
transactionHistory = ElectrumTransactionHistory(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
password: password,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
|
);
|
||||||
|
|
||||||
reaction((_) => syncStatus, _syncStatusReaction);
|
reaction((_) => syncStatus, _syncStatusReaction);
|
||||||
}
|
}
|
||||||
|
@ -138,6 +143,8 @@ abstract class ElectrumWalletBase
|
||||||
final String? _mnemonic;
|
final String? _mnemonic;
|
||||||
|
|
||||||
Bip32Slip10Secp256k1 get hd => accountHD.childKey(Bip32KeyIndex(0));
|
Bip32Slip10Secp256k1 get hd => accountHD.childKey(Bip32KeyIndex(0));
|
||||||
|
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
final String? passphrase;
|
final String? passphrase;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -178,6 +185,9 @@ abstract class ElectrumWalletBase
|
||||||
WalletKeysData get walletKeysData =>
|
WalletKeysData get walletKeysData =>
|
||||||
WalletKeysData(mnemonic: _mnemonic, xPub: xpub, passphrase: passphrase);
|
WalletKeysData(mnemonic: _mnemonic, xPub: xpub, passphrase: passphrase);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
|
|
||||||
BasedUtxoNetwork network;
|
BasedUtxoNetwork network;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1143,12 +1153,12 @@ abstract class ElectrumWalletBase
|
||||||
@override
|
@override
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
||||||
await saveKeysFile(_password);
|
await saveKeysFile(_password, encryptionFileUtils);
|
||||||
saveKeysFile(_password, true);
|
saveKeysFile(_password, encryptionFileUtils, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final path = await makePath();
|
final path = await makePath();
|
||||||
await write(path: path, password: _password, data: toJSON());
|
await encryptionFileUtils.write(path: path, password: _password, data: toJSON());
|
||||||
await transactionHistory.save();
|
await transactionHistory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
@ -51,9 +52,9 @@ class ElectrumWalletSnapshot {
|
||||||
String? derivationPath;
|
String? derivationPath;
|
||||||
|
|
||||||
static Future<ElectrumWalletSnapshot> load(
|
static Future<ElectrumWalletSnapshot> load(
|
||||||
String name, WalletType type, String password, BasedUtxoNetwork network) async {
|
EncryptionFileUtils encryptionFileUtils, String name, WalletType type, String password, BasedUtxoNetwork network) async {
|
||||||
final path = await pathForWallet(name: name, type: type);
|
final path = await pathForWallet(name: name, type: type);
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||||
final data = json.decode(jsonSource) as Map;
|
final data = json.decode(jsonSource) as Map;
|
||||||
final addressesTmp = data['addresses'] as List? ?? <Object>[];
|
final addressesTmp = data['addresses'] as List? ?? <Object>[];
|
||||||
final mnemonic = data['mnemonic'] as String?;
|
final mnemonic = data['mnemonic'] as String?;
|
||||||
|
|
|
@ -6,13 +6,14 @@ import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
||||||
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
|
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_keys_file.dart';
|
import 'package:cw_core/wallet_keys_file.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
@ -30,6 +31,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
Uint8List? seedBytes,
|
Uint8List? seedBytes,
|
||||||
String? mnemonic,
|
String? mnemonic,
|
||||||
String? xpub,
|
String? xpub,
|
||||||
|
@ -48,6 +50,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
currency: CryptoCurrency.ltc) {
|
currency: CryptoCurrency.ltc) {
|
||||||
walletAddresses = LitecoinWalletAddresses(
|
walletAddresses = LitecoinWalletAddresses(
|
||||||
walletInfo,
|
walletInfo,
|
||||||
|
@ -68,6 +71,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
String? passphrase,
|
String? passphrase,
|
||||||
String? addressPageType,
|
String? addressPageType,
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
|
@ -95,6 +99,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
unspentCoinsInfo: unspentCoinsInfo,
|
unspentCoinsInfo: unspentCoinsInfo,
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||||
|
@ -102,19 +107,24 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<LitecoinWallet> open({
|
static Future<LitecoinWallet> open(
|
||||||
required String name,
|
{required String name,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required String password,
|
required String password,
|
||||||
}) async {
|
required EncryptionFileUtils encryptionFileUtils}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
|
|
||||||
ElectrumWalletSnapshot? snp = null;
|
ElectrumWalletSnapshot? snp = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
snp = await ElectrumWalletSnapshot.load(
|
snp = await ElectrumWalletSnapshot.load(
|
||||||
name, walletInfo.type, password, LitecoinNetwork.mainnet);
|
encryptionFileUtils,
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
LitecoinNetwork.mainnet,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!hasKeysFile) rethrow;
|
if (!hasKeysFile) rethrow;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +135,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
keysData =
|
keysData =
|
||||||
WalletKeysData(mnemonic: snp!.mnemonic, xPub: snp.xpub, passphrase: snp.passphrase);
|
WalletKeysData(mnemonic: snp!.mnemonic, xPub: snp.xpub, passphrase: snp.passphrase);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LitecoinWallet(
|
return LitecoinWallet(
|
||||||
|
@ -137,6 +152,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialAddresses: snp?.addresses,
|
initialAddresses: snp?.addresses,
|
||||||
initialBalance: snp?.balance,
|
initialBalance: snp?.balance,
|
||||||
seedBytes: keysData.mnemonic != null ? await mnemonicToSeedBytes(keysData.mnemonic!) : null,
|
seedBytes: keysData.mnemonic != null ? await mnemonicToSeedBytes(keysData.mnemonic!) : null,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
initialRegularAddressIndex: snp?.regularAddressIndex,
|
initialRegularAddressIndex: snp?.regularAddressIndex,
|
||||||
initialChangeAddressIndex: snp?.changeAddressIndex,
|
initialChangeAddressIndex: snp?.changeAddressIndex,
|
||||||
addressPageType: snp?.addressPageType,
|
addressPageType: snp?.addressPageType,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
|
@ -17,11 +18,13 @@ import 'package:bip39/bip39.dart' as bip39;
|
||||||
class LitecoinWalletService extends WalletService<
|
class LitecoinWalletService extends WalletService<
|
||||||
BitcoinNewWalletCredentials,
|
BitcoinNewWalletCredentials,
|
||||||
BitcoinRestoreWalletFromSeedCredentials,
|
BitcoinRestoreWalletFromSeedCredentials,
|
||||||
BitcoinRestoreWalletFromWIFCredentials,BitcoinRestoreWalletFromHardware> {
|
BitcoinRestoreWalletFromWIFCredentials,
|
||||||
LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource);
|
BitcoinRestoreWalletFromHardware> {
|
||||||
|
LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletType getType() => WalletType.litecoin;
|
WalletType getType() => WalletType.litecoin;
|
||||||
|
@ -29,12 +32,13 @@ class LitecoinWalletService extends WalletService<
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
|
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
|
||||||
final wallet = await LitecoinWalletBase.create(
|
final wallet = await LitecoinWalletBase.create(
|
||||||
mnemonic: await generateElectrumMnemonic(),
|
mnemonic: await generateElectrumMnemonic(),
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
passphrase: credentials.passphrase,
|
passphrase: credentials.passphrase,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
|
@ -47,21 +51,29 @@ class LitecoinWalletService extends WalletService<
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> openWallet(String name, String password) async {
|
Future<LitecoinWallet> openWallet(String name, String password) async {
|
||||||
final walletInfo = walletInfoSource.values.firstWhereOrNull(
|
final walletInfo = walletInfoSource.values
|
||||||
(info) => info.id == WalletBase.idFor(name, getType()))!;
|
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final wallet = await LitecoinWalletBase.open(
|
final wallet = await LitecoinWalletBase.open(
|
||||||
password: password, name: name, walletInfo: walletInfo,
|
password: password,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
name: name,
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
saveBackup(name);
|
saveBackup(name);
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
await restoreWalletFilesFromBackup(name);
|
await restoreWalletFilesFromBackup(name);
|
||||||
final wallet = await LitecoinWalletBase.open(
|
final wallet = await LitecoinWalletBase.open(
|
||||||
password: password, name: name, walletInfo: walletInfo,
|
password: password,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
name: name,
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
@ -69,22 +81,23 @@ class LitecoinWalletService extends WalletService<
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> remove(String wallet) async {
|
Future<void> remove(String wallet) async {
|
||||||
File(await pathForWalletDir(name: wallet, type: getType()))
|
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
|
||||||
.delete(recursive: true);
|
final walletInfo = walletInfoSource.values
|
||||||
final walletInfo = walletInfoSource.values.firstWhereOrNull(
|
.firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
|
||||||
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
|
|
||||||
await walletInfoSource.delete(walletInfo.key);
|
await walletInfoSource.delete(walletInfo.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> rename(String currentName, String password, String newName) async {
|
Future<void> rename(String currentName, String password, String newName) async {
|
||||||
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull(
|
final currentWalletInfo = walletInfoSource.values
|
||||||
(info) => info.id == WalletBase.idFor(currentName, getType()))!;
|
.firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
|
||||||
final currentWallet = await LitecoinWalletBase.open(
|
final currentWallet = await LitecoinWalletBase.open(
|
||||||
password: password,
|
password: password,
|
||||||
name: currentName,
|
name: currentName,
|
||||||
walletInfo: currentWalletInfo,
|
walletInfo: currentWalletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
@ -116,23 +129,25 @@ class LitecoinWalletService extends WalletService<
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> restoreFromKeys(
|
Future<LitecoinWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials,
|
||||||
BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async =>
|
{bool? isTestnet}) async =>
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> restoreFromSeed(
|
Future<LitecoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials,
|
||||||
BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async {
|
{bool? isTestnet}) async {
|
||||||
if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) {
|
if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) {
|
||||||
throw LitecoinMnemonicIsIncorrectException();
|
throw LitecoinMnemonicIsIncorrectException();
|
||||||
}
|
}
|
||||||
|
|
||||||
final wallet = await LitecoinWalletBase.create(
|
final wallet = await LitecoinWalletBase.create(
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
passphrase: credentials.passphrase,
|
passphrase: credentials.passphrase,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
|
|
|
@ -23,7 +23,7 @@ String generateP2SHAddress({
|
||||||
required int index,
|
required int index,
|
||||||
}) =>
|
}) =>
|
||||||
ECPublic.fromBip32(hd.childKey(Bip32KeyIndex(index)).publicKey)
|
ECPublic.fromBip32(hd.childKey(Bip32KeyIndex(index)).publicKey)
|
||||||
.toP2wshInP2sh()
|
.toP2wpkhInP2sh()
|
||||||
.toAddress(network);
|
.toAddress(network);
|
||||||
|
|
||||||
String generateP2WSHAddress({
|
String generateP2WSHAddress({
|
||||||
|
|
|
@ -164,6 +164,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.9.2"
|
version: "8.9.2"
|
||||||
|
cake_backup:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: main
|
||||||
|
resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38"
|
||||||
|
url: "https://github.com/cake-tech/cake_backup.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0+1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -236,6 +245,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.7.0"
|
version: "2.7.0"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.8"
|
||||||
cw_core:
|
cw_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -846,6 +863,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
import 'package:bitbox/bitbox.dart' as bitbox;
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||||
|
@ -28,6 +29,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required Uint8List seedBytes,
|
required Uint8List seedBytes,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
BitcoinAddressType? addressPageType,
|
BitcoinAddressType? addressPageType,
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
ElectrumBalance? initialBalance,
|
ElectrumBalance? initialBalance,
|
||||||
|
@ -42,7 +44,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
currency: CryptoCurrency.bch) {
|
currency: CryptoCurrency.bch,
|
||||||
|
encryptionFileUtils: encryptionFileUtils) {
|
||||||
walletAddresses = BitcoinCashWalletAddresses(
|
walletAddresses = BitcoinCashWalletAddresses(
|
||||||
walletInfo,
|
walletInfo,
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
|
@ -63,6 +66,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
String? addressPageType,
|
String? addressPageType,
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
ElectrumBalance? initialBalance,
|
ElectrumBalance? initialBalance,
|
||||||
|
@ -76,6 +80,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
seedBytes: await MnemonicBip39.toSeed(mnemonic),
|
seedBytes: await MnemonicBip39.toSeed(mnemonic),
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||||
addressPageType: P2pkhAddressType.p2pkh,
|
addressPageType: P2pkhAddressType.p2pkh,
|
||||||
|
@ -87,6 +92,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required String password,
|
required String password,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
}) async {
|
}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
|
|
||||||
|
@ -94,7 +100,12 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
snp = await ElectrumWalletSnapshot.load(
|
snp = await ElectrumWalletSnapshot.load(
|
||||||
name, walletInfo.type, password, BitcoinCashNetwork.mainnet);
|
encryptionFileUtils,
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
BitcoinCashNetwork.mainnet,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!hasKeysFile) rethrow;
|
if (!hasKeysFile) rethrow;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +116,12 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
keysData =
|
keysData =
|
||||||
WalletKeysData(mnemonic: snp!.mnemonic, xPub: snp.xpub, passphrase: snp.passphrase);
|
WalletKeysData(mnemonic: snp!.mnemonic, xPub: snp.xpub, passphrase: snp.passphrase);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BitcoinCashWallet(
|
return BitcoinCashWallet(
|
||||||
|
@ -135,6 +151,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
}).toList(),
|
}).toList(),
|
||||||
initialBalance: snp?.balance,
|
initialBalance: snp?.balance,
|
||||||
seedBytes: await MnemonicBip39.toSeed(keysData.mnemonic!),
|
seedBytes: await MnemonicBip39.toSeed(keysData.mnemonic!),
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
initialRegularAddressIndex: snp?.regularAddressIndex,
|
initialRegularAddressIndex: snp?.regularAddressIndex,
|
||||||
initialChangeAddressIndex: snp?.changeAddressIndex,
|
initialChangeAddressIndex: snp?.changeAddressIndex,
|
||||||
addressPageType: P2pkhAddressType.p2pkh,
|
addressPageType: P2pkhAddressType.p2pkh,
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'package:cw_core/wallet_credentials.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
|
||||||
class BitcoinCashNewWalletCredentials extends WalletCredentials {
|
class BitcoinCashNewWalletCredentials extends WalletCredentials {
|
||||||
BitcoinCashNewWalletCredentials({required String name, WalletInfo? walletInfo})
|
BitcoinCashNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password})
|
||||||
: super(name: name, walletInfo: walletInfo);
|
: super(name: name, walletInfo: walletInfo, password: password);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BitcoinCashRestoreWalletFromSeedCredentials extends WalletCredentials {
|
class BitcoinCashRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:bip39/bip39.dart';
|
import 'package:bip39/bip39.dart';
|
||||||
import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart';
|
import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
@ -16,10 +17,11 @@ class BitcoinCashWalletService extends WalletService<
|
||||||
BitcoinCashRestoreWalletFromSeedCredentials,
|
BitcoinCashRestoreWalletFromSeedCredentials,
|
||||||
BitcoinCashRestoreWalletFromWIFCredentials,
|
BitcoinCashRestoreWalletFromWIFCredentials,
|
||||||
BitcoinCashNewWalletCredentials> {
|
BitcoinCashNewWalletCredentials> {
|
||||||
BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource);
|
BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletType getType() => WalletType.bitcoinCash;
|
WalletType getType() => WalletType.bitcoinCash;
|
||||||
|
@ -34,10 +36,11 @@ class BitcoinCashWalletService extends WalletService<
|
||||||
|
|
||||||
final wallet = await BitcoinCashWalletBase.create(
|
final wallet = await BitcoinCashWalletBase.create(
|
||||||
mnemonic: await MnemonicBip39.generate(strength: strength),
|
mnemonic: await MnemonicBip39.generate(strength: strength),
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
|
@ -54,7 +57,9 @@ class BitcoinCashWalletService extends WalletService<
|
||||||
password: password,
|
password: password,
|
||||||
name: name,
|
name: name,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
saveBackup(name);
|
saveBackup(name);
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -64,7 +69,9 @@ class BitcoinCashWalletService extends WalletService<
|
||||||
password: password,
|
password: password,
|
||||||
name: name,
|
name: name,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +93,8 @@ class BitcoinCashWalletService extends WalletService<
|
||||||
password: password,
|
password: password,
|
||||||
name: currentName,
|
name: currentName,
|
||||||
walletInfo: currentWalletInfo,
|
walletInfo: currentWalletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
@ -121,7 +129,8 @@ class BitcoinCashWalletService extends WalletService<
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
|
|
42
cw_core/lib/encryption_file_utils.dart
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:cw_core/utils/file.dart' as file;
|
||||||
|
import 'package:cake_backup/backup.dart' as cwb;
|
||||||
|
|
||||||
|
EncryptionFileUtils encryptionFileUtilsFor(bool direct)
|
||||||
|
=> direct
|
||||||
|
? XChaCha20EncryptionFileUtils()
|
||||||
|
: Salsa20EncryhptionFileUtils();
|
||||||
|
|
||||||
|
abstract class EncryptionFileUtils {
|
||||||
|
Future<void> write({required String path, required String password, required String data});
|
||||||
|
Future<String> read({required String path, required String password});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Salsa20EncryhptionFileUtils extends EncryptionFileUtils {
|
||||||
|
// Requires legacy complex key + iv as password
|
||||||
|
@override
|
||||||
|
Future<void> write({required String path, required String password, required String data}) async
|
||||||
|
=> await file.write(path: path, password: password, data: data);
|
||||||
|
|
||||||
|
// Requires legacy complex key + iv as password
|
||||||
|
@override
|
||||||
|
Future<String> read({required String path, required String password}) async
|
||||||
|
=> await file.read(path: path, password: password);
|
||||||
|
}
|
||||||
|
|
||||||
|
class XChaCha20EncryptionFileUtils extends EncryptionFileUtils {
|
||||||
|
@override
|
||||||
|
Future<void> write({required String path, required String password, required String data}) async {
|
||||||
|
final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits));
|
||||||
|
await File(path).writeAsBytes(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> read({required String path, required String password}) async {
|
||||||
|
final file = File(path);
|
||||||
|
final encrypted = await file.readAsBytes();
|
||||||
|
final bytes = await cwb.decrypt(password, encrypted);
|
||||||
|
return String.fromCharCodes(bytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,6 +84,8 @@ abstract class WalletBase<BalanceType extends Balance, HistoryType extends Trans
|
||||||
|
|
||||||
Future<void> changePassword(String password);
|
Future<void> changePassword(String password);
|
||||||
|
|
||||||
|
String get password;
|
||||||
|
|
||||||
Future<void>? updateBalance();
|
Future<void>? updateBalance();
|
||||||
|
|
||||||
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => null;
|
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => null;
|
||||||
|
|
|
@ -3,10 +3,10 @@ import 'dart:developer' as dev;
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cw_core/balance.dart';
|
import 'package:cw_core/balance.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
import 'package:cw_core/utils/file.dart';
|
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
|
@ -20,28 +20,32 @@ mixin WalletKeysFile<BalanceType extends Balance, HistoryType extends Transactio
|
||||||
|
|
||||||
Future<String> makeKeysFilePath() async => "${await makePath()}.keys";
|
Future<String> makeKeysFilePath() async => "${await makePath()}.keys";
|
||||||
|
|
||||||
Future<void> saveKeysFile(String password, [bool isBackup = false]) async {
|
Future<void> saveKeysFile(String password, EncryptionFileUtils encryptionFileUtils,
|
||||||
|
[bool isBackup = false]) async {
|
||||||
try {
|
try {
|
||||||
final rootPath = await makeKeysFilePath();
|
final rootPath = await makeKeysFilePath();
|
||||||
final path = "$rootPath${isBackup ? ".backup" : ""}";
|
final path = "$rootPath${isBackup ? ".backup" : ""}";
|
||||||
dev.log("Saving .keys file '$path'");
|
dev.log("Saving .keys file '$path'");
|
||||||
await write(path: path, password: password, data: walletKeysData.toJSON());
|
await encryptionFileUtils.write(
|
||||||
|
path: path, password: password, data: walletKeysData.toJSON());
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> createKeysFile(
|
static Future<void> createKeysFile(String name, WalletType type, String password,
|
||||||
String name, WalletType type, String password, WalletKeysData walletKeysData,
|
WalletKeysData walletKeysData, EncryptionFileUtils encryptionFileUtils,
|
||||||
[bool withBackup = true]) async {
|
[bool withBackup = true]) async {
|
||||||
try {
|
try {
|
||||||
final rootPath = await pathForWallet(name: name, type: type);
|
final rootPath = await pathForWallet(name: name, type: type);
|
||||||
final path = "$rootPath.keys";
|
final path = "$rootPath.keys";
|
||||||
|
|
||||||
dev.log("Saving .keys file '$path'");
|
dev.log("Saving .keys file '$path'");
|
||||||
await write(path: path, password: password, data: walletKeysData.toJSON());
|
await encryptionFileUtils.write(
|
||||||
|
path: path, password: password, data: walletKeysData.toJSON());
|
||||||
|
|
||||||
if (withBackup) {
|
if (withBackup) {
|
||||||
dev.log("Saving .keys.backup file '$path.backup'");
|
dev.log("Saving .keys.backup file '$path.backup'");
|
||||||
await write(path: "$path.backup", password: password, data: walletKeysData.toJSON());
|
await encryptionFileUtils.write(
|
||||||
|
path: "$path.backup", password: password, data: walletKeysData.toJSON());
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
@ -55,14 +59,19 @@ mixin WalletKeysFile<BalanceType extends Balance, HistoryType extends Transactio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<WalletKeysData> readKeysFile(String name, WalletType type, String password) async {
|
static Future<WalletKeysData> readKeysFile(
|
||||||
|
String name,
|
||||||
|
WalletType type,
|
||||||
|
String password,
|
||||||
|
EncryptionFileUtils encryptionFileUtils,
|
||||||
|
) async {
|
||||||
final path = await pathForWallet(name: name, type: type);
|
final path = await pathForWallet(name: name, type: type);
|
||||||
|
|
||||||
var readPath = "$path.keys";
|
var readPath = "$path.keys";
|
||||||
try {
|
try {
|
||||||
if (!File(readPath).existsSync()) throw Exception("No .keys file found for $name $type");
|
if (!File(readPath).existsSync()) throw Exception("No .keys file found for $name $type");
|
||||||
|
|
||||||
final jsonSource = await read(path: readPath, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: readPath, password: password);
|
||||||
final data = json.decode(jsonSource) as Map<String, dynamic>;
|
final data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
return WalletKeysData.fromJSON(data);
|
return WalletKeysData.fromJSON(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -72,12 +81,12 @@ mixin WalletKeysFile<BalanceType extends Balance, HistoryType extends Transactio
|
||||||
if (!File(readPath).existsSync())
|
if (!File(readPath).existsSync())
|
||||||
throw Exception("No .keys nor a .keys.backup file found for $name $type");
|
throw Exception("No .keys nor a .keys.backup file found for $name $type");
|
||||||
|
|
||||||
final jsonSource = await read(path: readPath, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: readPath, password: password);
|
||||||
final data = json.decode(jsonSource) as Map<String, dynamic>;
|
final data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
final keysData = WalletKeysData.fromJSON(data);
|
final keysData = WalletKeysData.fromJSON(data);
|
||||||
|
|
||||||
dev.log("Restoring .keys from .keys.backup");
|
dev.log("Restoring .keys from .keys.backup");
|
||||||
createKeysFile(name, type, password, keysData, false);
|
createKeysFile(name, type, password, keysData, encryptionFileUtils, false);
|
||||||
return keysData;
|
return keysData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.8.1"
|
version: "8.8.1"
|
||||||
|
cake_backup:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: main
|
||||||
|
resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38"
|
||||||
|
url: "https://github.com/cake-tech/cake_backup.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0+1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -169,6 +178,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
|
cryptography:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cryptography
|
||||||
|
sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.0"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.6"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -648,6 +673,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -19,6 +19,11 @@ dependencies:
|
||||||
flutter_mobx: ^2.0.6+1
|
flutter_mobx: ^2.0.6+1
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
encrypt: ^5.0.1
|
encrypt: ^5.0.1
|
||||||
|
cake_backup:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/cake_backup.git
|
||||||
|
ref: main
|
||||||
|
version: 1.0.0
|
||||||
socks5_proxy: ^1.0.4
|
socks5_proxy: ^1.0.4
|
||||||
unorm_dart: ^0.3.0
|
unorm_dart: ^0.3.0
|
||||||
# tor:
|
# tor:
|
||||||
|
|
|
@ -7,6 +7,7 @@ class EthereumTransactionHistory extends EVMChainTransactionHistory {
|
||||||
EthereumTransactionHistory({
|
EthereumTransactionHistory({
|
||||||
required super.walletInfo,
|
required super.walletInfo,
|
||||||
required super.password,
|
required super.password,
|
||||||
|
required super.encryptionFileUtils,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cw_core/cake_hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/erc20_token.dart';
|
import 'package:cw_core/erc20_token.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/transaction_direction.dart';
|
import 'package:cw_core/transaction_direction.dart';
|
||||||
|
@ -16,7 +17,6 @@ import 'package:cw_evm/evm_chain_transaction_info.dart';
|
||||||
import 'package:cw_evm/evm_chain_transaction_model.dart';
|
import 'package:cw_evm/evm_chain_transaction_model.dart';
|
||||||
import 'package:cw_evm/evm_chain_wallet.dart';
|
import 'package:cw_evm/evm_chain_wallet.dart';
|
||||||
import 'package:cw_evm/evm_erc20_balance.dart';
|
import 'package:cw_evm/evm_erc20_balance.dart';
|
||||||
import 'package:cw_evm/file.dart';
|
|
||||||
|
|
||||||
class EthereumWallet extends EVMChainWallet {
|
class EthereumWallet extends EVMChainWallet {
|
||||||
EthereumWallet({
|
EthereumWallet({
|
||||||
|
@ -26,6 +26,7 @@ class EthereumWallet extends EVMChainWallet {
|
||||||
super.mnemonic,
|
super.mnemonic,
|
||||||
super.initialBalance,
|
super.initialBalance,
|
||||||
super.privateKey,
|
super.privateKey,
|
||||||
|
required super.encryptionFileUtils,
|
||||||
}) : super(nativeCurrency: CryptoCurrency.eth);
|
}) : super(nativeCurrency: CryptoCurrency.eth);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -117,18 +118,24 @@ class EthereumWallet extends EVMChainWallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
EVMChainTransactionHistory setUpTransactionHistory(WalletInfo walletInfo, String password) {
|
EVMChainTransactionHistory setUpTransactionHistory(
|
||||||
return EthereumTransactionHistory(walletInfo: walletInfo, password: password);
|
WalletInfo walletInfo, String password, EncryptionFileUtils encryptionFileUtils) {
|
||||||
|
return EthereumTransactionHistory(
|
||||||
|
walletInfo: walletInfo, password: password, encryptionFileUtils: encryptionFileUtils);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<EthereumWallet> open(
|
static Future<EthereumWallet> open({
|
||||||
{required String name, required String password, required WalletInfo walletInfo}) async {
|
required String name,
|
||||||
|
required String password,
|
||||||
|
required WalletInfo walletInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
|
}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||||
|
|
||||||
Map<String, dynamic>? data;
|
Map<String, dynamic>? data;
|
||||||
try {
|
try {
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||||
|
|
||||||
data = json.decode(jsonSource) as Map<String, dynamic>;
|
data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -146,7 +153,12 @@ class EthereumWallet extends EVMChainWallet {
|
||||||
|
|
||||||
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EthereumWallet(
|
return EthereumWallet(
|
||||||
|
@ -156,6 +168,7 @@ class EthereumWallet extends EVMChainWallet {
|
||||||
privateKey: keysData.privateKey,
|
privateKey: keysData.privateKey,
|
||||||
initialBalance: balance,
|
initialBalance: balance,
|
||||||
client: EthereumClient(),
|
client: EthereumClient(),
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
@ -9,7 +10,7 @@ import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart';
|
||||||
import 'package:cw_evm/evm_chain_wallet_service.dart';
|
import 'package:cw_evm/evm_chain_wallet_service.dart';
|
||||||
|
|
||||||
class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
EthereumWalletService(super.walletInfoSource, {required this.client});
|
EthereumWalletService(super.walletInfoSource, super.isDirect, {required this.client});
|
||||||
|
|
||||||
late EthereumClient client;
|
late EthereumClient client;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -46,6 +48,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -59,6 +62,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
|
@ -71,7 +75,11 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
final currentWalletInfo = walletInfoSource.values
|
final currentWalletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||||
final currentWallet = await EthereumWallet.open(
|
final currentWallet = await EthereumWallet.open(
|
||||||
password: password, name: currentName, walletInfo: currentWalletInfo);
|
password: password,
|
||||||
|
name: currentName,
|
||||||
|
walletInfo: currentWalletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
@ -97,6 +105,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -114,6 +123,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
privateKey: credentials.privateKey,
|
privateKey: credentials.privateKey,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -135,6 +145,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_evm/evm_chain_transaction_info.dart';
|
import 'package:cw_evm/evm_chain_transaction_info.dart';
|
||||||
import 'package:cw_evm/file.dart';
|
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ abstract class EVMChainTransactionHistory = EVMChainTransactionHistoryBase
|
||||||
|
|
||||||
abstract class EVMChainTransactionHistoryBase
|
abstract class EVMChainTransactionHistoryBase
|
||||||
extends TransactionHistoryBase<EVMChainTransactionInfo> with Store {
|
extends TransactionHistoryBase<EVMChainTransactionInfo> with Store {
|
||||||
EVMChainTransactionHistoryBase({required this.walletInfo, required String password})
|
EVMChainTransactionHistoryBase(
|
||||||
|
{required this.walletInfo, required String password, required this.encryptionFileUtils})
|
||||||
: _password = password {
|
: _password = password {
|
||||||
transactions = ObservableMap<String, EVMChainTransactionInfo>();
|
transactions = ObservableMap<String, EVMChainTransactionInfo>();
|
||||||
}
|
}
|
||||||
|
@ -23,6 +24,7 @@ abstract class EVMChainTransactionHistoryBase
|
||||||
String _password;
|
String _password;
|
||||||
|
|
||||||
final WalletInfo walletInfo;
|
final WalletInfo walletInfo;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
|
|
||||||
//! Method to be overridden by all child classes
|
//! Method to be overridden by all child classes
|
||||||
|
|
||||||
|
@ -41,7 +43,7 @@ abstract class EVMChainTransactionHistoryBase
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
||||||
final data = json.encode({'transactions': transactions});
|
final data = json.encode({'transactions': transactions});
|
||||||
await writeData(path: path, password: _password, data: data);
|
await encryptionFileUtils.write(path: path, password: _password, data: data);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
log('Error while saving ${walletInfo.type.name} transaction history: ${e.toString()}');
|
log('Error while saving ${walletInfo.type.name} transaction history: ${e.toString()}');
|
||||||
log(s.toString());
|
log(s.toString());
|
||||||
|
@ -59,7 +61,7 @@ abstract class EVMChainTransactionHistoryBase
|
||||||
final transactionsHistoryFileNameForWallet = getTransactionHistoryFileName();
|
final transactionsHistoryFileNameForWallet = getTransactionHistoryFileName();
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
||||||
final content = await read(path: path, password: _password);
|
final content = await encryptionFileUtils.read(path: path, password: _password);
|
||||||
if (content.isEmpty) {
|
if (content.isEmpty) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:bip32/bip32.dart' as bip32;
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:cw_core/cake_hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/erc20_token.dart';
|
import 'package:cw_core/erc20_token.dart';
|
||||||
import 'package:cw_core/node.dart';
|
import 'package:cw_core/node.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
@ -27,7 +28,6 @@ import 'package:cw_evm/evm_chain_transaction_model.dart';
|
||||||
import 'package:cw_evm/evm_chain_transaction_priority.dart';
|
import 'package:cw_evm/evm_chain_transaction_priority.dart';
|
||||||
import 'package:cw_evm/evm_chain_wallet_addresses.dart';
|
import 'package:cw_evm/evm_chain_wallet_addresses.dart';
|
||||||
import 'package:cw_evm/evm_ledger_credentials.dart';
|
import 'package:cw_evm/evm_ledger_credentials.dart';
|
||||||
import 'package:cw_evm/file.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hex/hex.dart';
|
import 'package:hex/hex.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
@ -68,6 +68,7 @@ abstract class EVMChainWalletBase
|
||||||
String? privateKey,
|
String? privateKey,
|
||||||
required String password,
|
required String password,
|
||||||
EVMChainERC20Balance? initialBalance,
|
EVMChainERC20Balance? initialBalance,
|
||||||
|
required this.encryptionFileUtils,
|
||||||
}) : syncStatus = const NotConnectedSyncStatus(),
|
}) : syncStatus = const NotConnectedSyncStatus(),
|
||||||
_password = password,
|
_password = password,
|
||||||
_mnemonic = mnemonic,
|
_mnemonic = mnemonic,
|
||||||
|
@ -83,7 +84,7 @@ abstract class EVMChainWalletBase
|
||||||
),
|
),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = setUpTransactionHistory(walletInfo, password);
|
transactionHistory = setUpTransactionHistory(walletInfo, password, encryptionFileUtils);
|
||||||
|
|
||||||
if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) {
|
||||||
CakeHive.registerAdapter(Erc20TokenAdapter());
|
CakeHive.registerAdapter(Erc20TokenAdapter());
|
||||||
|
@ -95,6 +96,7 @@ abstract class EVMChainWalletBase
|
||||||
final String? _mnemonic;
|
final String? _mnemonic;
|
||||||
final String? _hexPrivateKey;
|
final String? _hexPrivateKey;
|
||||||
final String _password;
|
final String _password;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
|
|
||||||
late final Box<Erc20Token> erc20TokensBox;
|
late final Box<Erc20Token> erc20TokensBox;
|
||||||
|
|
||||||
|
@ -149,7 +151,11 @@ abstract class EVMChainWalletBase
|
||||||
|
|
||||||
Erc20Token createNewErc20TokenObject(Erc20Token token, String? iconPath);
|
Erc20Token createNewErc20TokenObject(Erc20Token token, String? iconPath);
|
||||||
|
|
||||||
EVMChainTransactionHistory setUpTransactionHistory(WalletInfo walletInfo, String password);
|
EVMChainTransactionHistory setUpTransactionHistory(
|
||||||
|
WalletInfo walletInfo,
|
||||||
|
String password,
|
||||||
|
EncryptionFileUtils encryptionFileUtils,
|
||||||
|
);
|
||||||
|
|
||||||
//! Common Methods across child classes
|
//! Common Methods across child classes
|
||||||
|
|
||||||
|
@ -510,13 +516,13 @@ abstract class EVMChainWalletBase
|
||||||
@override
|
@override
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
||||||
await saveKeysFile(_password);
|
await saveKeysFile(_password, encryptionFileUtils);
|
||||||
saveKeysFile(_password, true);
|
saveKeysFile(_password, encryptionFileUtils, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await walletAddresses.updateAddressesInBox();
|
await walletAddresses.updateAddressesInBox();
|
||||||
final path = await makePath();
|
final path = await makePath();
|
||||||
await write(path: path, password: _password, data: toJSON());
|
await encryptionFileUtils.write(path: path, password: _password, data: toJSON());
|
||||||
await transactionHistory.save();
|
await transactionHistory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,4 +696,7 @@ abstract class EVMChainWalletBase
|
||||||
bytesToHex(await _evmChainPrivateKey.signPersonalMessage(ascii.encode(message)));
|
bytesToHex(await _evmChainPrivateKey.signPersonalMessage(ascii.encode(message)));
|
||||||
|
|
||||||
Web3Client? getWeb3Client() => _client.getWeb3Client();
|
Web3Client? getWeb3Client() => _client.getWeb3Client();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:cw_core/wallet_credentials.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
|
||||||
class EVMChainNewWalletCredentials extends WalletCredentials {
|
class EVMChainNewWalletCredentials extends WalletCredentials {
|
||||||
EVMChainNewWalletCredentials({required String name, WalletInfo? walletInfo})
|
EVMChainNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password})
|
||||||
: super(name: name, walletInfo: walletInfo);
|
: super(name: name, walletInfo: walletInfo, password: password);
|
||||||
}
|
}
|
||||||
|
|
||||||
class EVMChainRestoreWalletFromSeedCredentials extends WalletCredentials {
|
class EVMChainRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||||
|
|
|
@ -15,9 +15,10 @@ abstract class EVMChainWalletService<T extends EVMChainWallet> extends WalletSer
|
||||||
EVMChainRestoreWalletFromSeedCredentials,
|
EVMChainRestoreWalletFromSeedCredentials,
|
||||||
EVMChainRestoreWalletFromPrivateKey,
|
EVMChainRestoreWalletFromPrivateKey,
|
||||||
EVMChainRestoreWalletFromHardware> {
|
EVMChainRestoreWalletFromHardware> {
|
||||||
EVMChainWalletService(this.walletInfoSource);
|
EVMChainWalletService(this.walletInfoSource, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletType getType();
|
WalletType getType();
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:cw_core/key.dart';
|
|
||||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
|
||||||
|
|
||||||
Future<void> write(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> writeData(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> read({required String path, required String password}) async {
|
|
||||||
final file = File(path);
|
|
||||||
|
|
||||||
if (!file.existsSync()) {
|
|
||||||
file.createSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
final encrypted = file.readAsStringSync();
|
|
||||||
|
|
||||||
return decode(password: password, data: encrypted);
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ dependencies:
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
collection: ^1.17.1
|
collection: ^1.17.1
|
||||||
shared_preferences: ^2.0.15
|
shared_preferences: ^2.0.15
|
||||||
|
mobx: ^2.0.7+4
|
||||||
cw_core:
|
cw_core:
|
||||||
path: ../cw_core
|
path: ../cw_core
|
||||||
ledger_flutter: ^1.0.1
|
ledger_flutter: ^1.0.1
|
||||||
|
|
|
@ -5,7 +5,7 @@ buildscript {
|
||||||
ext.kotlin_version = '1.7.10'
|
ext.kotlin_version = '1.7.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -17,7 +17,7 @@ buildscript {
|
||||||
rootProject.allprojects {
|
rootProject.allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,10 @@ class HavenWallet = HavenWalletBase with _$HavenWallet;
|
||||||
|
|
||||||
abstract class HavenWalletBase
|
abstract class HavenWalletBase
|
||||||
extends WalletBase<MoneroBalance, HavenTransactionHistory, HavenTransactionInfo> with Store {
|
extends WalletBase<MoneroBalance, HavenTransactionHistory, HavenTransactionInfo> with Store {
|
||||||
HavenWalletBase({required WalletInfo walletInfo})
|
HavenWalletBase({required WalletInfo walletInfo, String? password})
|
||||||
: balance = ObservableMap.of(getHavenBalance(accountIndex: 0)),
|
: balance = ObservableMap.of(getHavenBalance(accountIndex: 0)),
|
||||||
_isTransactionUpdating = false,
|
_isTransactionUpdating = false,
|
||||||
|
_password = password ?? '',
|
||||||
_hasSyncAfterStartup = false,
|
_hasSyncAfterStartup = false,
|
||||||
walletAddresses = HavenWalletAddresses(walletInfo),
|
walletAddresses = HavenWalletAddresses(walletInfo),
|
||||||
syncStatus = NotConnectedSyncStatus(),
|
syncStatus = NotConnectedSyncStatus(),
|
||||||
|
@ -56,6 +57,7 @@ abstract class HavenWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int _autoSaveInterval = 30;
|
static const int _autoSaveInterval = 30;
|
||||||
|
final String _password;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
HavenWalletAddresses walletAddresses;
|
HavenWalletAddresses walletAddresses;
|
||||||
|
@ -111,7 +113,7 @@ abstract class HavenWalletBase
|
||||||
_onAccountChangeReaction?.reaction.dispose();
|
_onAccountChangeReaction?.reaction.dispose();
|
||||||
_autoSaveTimer?.cancel();
|
_autoSaveTimer?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> connectToNode({required Node node}) async {
|
Future<void> connectToNode({required Node node}) async {
|
||||||
try {
|
try {
|
||||||
|
@ -414,4 +416,7 @@ abstract class HavenWalletBase
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.4.3"
|
version: "8.4.3"
|
||||||
|
cake_backup:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: main
|
||||||
|
resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38"
|
||||||
|
url: "https://github.com/cake-tech/cake_backup.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0+1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -169,6 +178,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.2"
|
||||||
|
cryptography:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cryptography
|
||||||
|
sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.0"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.6"
|
||||||
cw_core:
|
cw_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -639,6 +664,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -18,6 +18,9 @@ migration:
|
||||||
- platform: macos
|
- platform: macos
|
||||||
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
|
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
|
||||||
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
|
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
|
||||||
|
- platform: linux
|
||||||
|
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
|
||||||
|
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|
1
cw_monero/example/linux/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
flutter/ephemeral
|
138
cw_monero/example/linux/CMakeLists.txt
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
# Project-level configuration.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
|
# The name of the executable created for the application. Change this to change
|
||||||
|
# the on-disk name of your application.
|
||||||
|
set(BINARY_NAME "cw_monero_example")
|
||||||
|
# The unique GTK application identifier for this application. See:
|
||||||
|
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||||
|
set(APPLICATION_ID "com.cakewallet.cw_monero")
|
||||||
|
|
||||||
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
|
# versions of CMake.
|
||||||
|
cmake_policy(SET CMP0063 NEW)
|
||||||
|
|
||||||
|
# Load bundled libraries from the lib/ directory relative to the binary.
|
||||||
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||||
|
|
||||||
|
# Root filesystem for cross-building.
|
||||||
|
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
||||||
|
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
||||||
|
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Define build configuration options.
|
||||||
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||||
|
STRING "Flutter build mode" FORCE)
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||||
|
"Debug" "Profile" "Release")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Compilation settings that should be applied to most targets.
|
||||||
|
#
|
||||||
|
# Be cautious about adding new options here, as plugins use this function by
|
||||||
|
# default. In most cases, you should add new options to specific targets instead
|
||||||
|
# of modifying this function.
|
||||||
|
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||||
|
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||||
|
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||||
|
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Flutter library and tool build rules.
|
||||||
|
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||||
|
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||||
|
|
||||||
|
# System-level dependencies.
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
|
||||||
|
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||||
|
|
||||||
|
# Define the application target. To change its name, change BINARY_NAME above,
|
||||||
|
# not the value here, or `flutter run` will no longer work.
|
||||||
|
#
|
||||||
|
# Any new source files that you add to the application should be added here.
|
||||||
|
add_executable(${BINARY_NAME}
|
||||||
|
"main.cc"
|
||||||
|
"my_application.cc"
|
||||||
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply the standard set of build settings. This can be removed for applications
|
||||||
|
# that need different build settings.
|
||||||
|
apply_standard_settings(${BINARY_NAME})
|
||||||
|
|
||||||
|
# Add dependency libraries. Add any application-specific dependencies here.
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
|
||||||
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
|
||||||
|
# Only the install-generated bundle's copy of the executable will launch
|
||||||
|
# correctly, since the resources must in the right relative locations. To avoid
|
||||||
|
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||||
|
# the default top-level location.
|
||||||
|
set_target_properties(${BINARY_NAME}
|
||||||
|
PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
|
# them to the application.
|
||||||
|
include(flutter/generated_plugins.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
# === Installation ===
|
||||||
|
# By default, "installing" just makes a relocatable bundle in the build
|
||||||
|
# directory.
|
||||||
|
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Start with a clean build bundle directory every time.
|
||||||
|
install(CODE "
|
||||||
|
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||||
|
" COMPONENT Runtime)
|
||||||
|
|
||||||
|
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||||
|
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
|
||||||
|
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||||
|
install(FILES "${bundled_library}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
endforeach(bundled_library)
|
||||||
|
|
||||||
|
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||||
|
# from a previous install.
|
||||||
|
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||||
|
install(CODE "
|
||||||
|
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||||
|
" COMPONENT Runtime)
|
||||||
|
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
|
# Install the AOT library on non-Debug builds only.
|
||||||
|
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
|
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
endif()
|
88
cw_monero/example/linux/flutter/CMakeLists.txt
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
# This file controls Flutter-level build steps. It should not be edited.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||||
|
|
||||||
|
# Configuration provided via flutter tool.
|
||||||
|
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||||
|
|
||||||
|
# TODO: Move the rest of this into files in ephemeral. See
|
||||||
|
# https://github.com/flutter/flutter/issues/57146.
|
||||||
|
|
||||||
|
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||||
|
# which isn't available in 3.10.
|
||||||
|
function(list_prepend LIST_NAME PREFIX)
|
||||||
|
set(NEW_LIST "")
|
||||||
|
foreach(element ${${LIST_NAME}})
|
||||||
|
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||||
|
endforeach(element)
|
||||||
|
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# === Flutter Library ===
|
||||||
|
# System-level dependencies.
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||||
|
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||||
|
|
||||||
|
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||||
|
|
||||||
|
# Published to parent scope for install step.
|
||||||
|
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||||
|
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||||
|
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||||
|
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||||
|
"fl_basic_message_channel.h"
|
||||||
|
"fl_binary_codec.h"
|
||||||
|
"fl_binary_messenger.h"
|
||||||
|
"fl_dart_project.h"
|
||||||
|
"fl_engine.h"
|
||||||
|
"fl_json_message_codec.h"
|
||||||
|
"fl_json_method_codec.h"
|
||||||
|
"fl_message_codec.h"
|
||||||
|
"fl_method_call.h"
|
||||||
|
"fl_method_channel.h"
|
||||||
|
"fl_method_codec.h"
|
||||||
|
"fl_method_response.h"
|
||||||
|
"fl_plugin_registrar.h"
|
||||||
|
"fl_plugin_registry.h"
|
||||||
|
"fl_standard_message_codec.h"
|
||||||
|
"fl_standard_method_codec.h"
|
||||||
|
"fl_string_codec.h"
|
||||||
|
"fl_value.h"
|
||||||
|
"fl_view.h"
|
||||||
|
"flutter_linux.h"
|
||||||
|
)
|
||||||
|
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||||
|
add_library(flutter INTERFACE)
|
||||||
|
target_include_directories(flutter INTERFACE
|
||||||
|
"${EPHEMERAL_DIR}"
|
||||||
|
)
|
||||||
|
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||||
|
target_link_libraries(flutter INTERFACE
|
||||||
|
PkgConfig::GTK
|
||||||
|
PkgConfig::GLIB
|
||||||
|
PkgConfig::GIO
|
||||||
|
)
|
||||||
|
add_dependencies(flutter flutter_assemble)
|
||||||
|
|
||||||
|
# === Flutter tool backend ===
|
||||||
|
# _phony_ is a non-existent file to force this command to run every time,
|
||||||
|
# since currently there's no way to get a full input/output list from the
|
||||||
|
# flutter tool.
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env
|
||||||
|
${FLUTTER_TOOL_ENVIRONMENT}
|
||||||
|
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||||
|
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
add_custom_target(flutter_assemble DEPENDS
|
||||||
|
"${FLUTTER_LIBRARY}"
|
||||||
|
${FLUTTER_LIBRARY_HEADERS}
|
||||||
|
)
|
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <cw_monero/cw_monero_plugin.h>
|
||||||
|
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) cw_monero_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "CwMoneroPlugin");
|
||||||
|
cw_monero_plugin_register_with_registrar(cw_monero_registrar);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
#define GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
|
||||||
|
// Registers Flutter plugins.
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry);
|
||||||
|
|
||||||
|
#endif // GENERATED_PLUGIN_REGISTRANT_
|
24
cw_monero/example/linux/flutter/generated_plugins.cmake
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
cw_monero
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
|
endforeach(plugin)
|
||||||
|
|
||||||
|
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||||
|
endforeach(ffi_plugin)
|
6
cw_monero/example/linux/main.cc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include "my_application.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
g_autoptr(MyApplication) app = my_application_new();
|
||||||
|
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
|
}
|
104
cw_monero/example/linux/my_application.cc
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#include "my_application.h"
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
struct _MyApplication {
|
||||||
|
GtkApplication parent_instance;
|
||||||
|
char** dart_entrypoint_arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||||
|
|
||||||
|
// Implements GApplication::activate.
|
||||||
|
static void my_application_activate(GApplication* application) {
|
||||||
|
MyApplication* self = MY_APPLICATION(application);
|
||||||
|
GtkWindow* window =
|
||||||
|
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||||
|
|
||||||
|
// Use a header bar when running in GNOME as this is the common style used
|
||||||
|
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||||
|
// desktop).
|
||||||
|
// If running on X and not using GNOME then just use a traditional title bar
|
||||||
|
// in case the window manager does more exotic layout, e.g. tiling.
|
||||||
|
// If running on Wayland assume the header bar will work (may need changing
|
||||||
|
// if future cases occur).
|
||||||
|
gboolean use_header_bar = TRUE;
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
GdkScreen* screen = gtk_window_get_screen(window);
|
||||||
|
if (GDK_IS_X11_SCREEN(screen)) {
|
||||||
|
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||||
|
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||||
|
use_header_bar = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (use_header_bar) {
|
||||||
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
|
gtk_header_bar_set_title(header_bar, "cw_monero_example");
|
||||||
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
|
} else {
|
||||||
|
gtk_window_set_title(window, "cw_monero_example");
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
gtk_widget_show(GTK_WIDGET(window));
|
||||||
|
|
||||||
|
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||||
|
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||||
|
|
||||||
|
FlView* view = fl_view_new(project);
|
||||||
|
gtk_widget_show(GTK_WIDGET(view));
|
||||||
|
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||||
|
|
||||||
|
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||||
|
|
||||||
|
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GApplication::local_command_line.
|
||||||
|
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
||||||
|
MyApplication* self = MY_APPLICATION(application);
|
||||||
|
// Strip out the first argument as it is the binary name.
|
||||||
|
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||||
|
|
||||||
|
g_autoptr(GError) error = nullptr;
|
||||||
|
if (!g_application_register(application, nullptr, &error)) {
|
||||||
|
g_warning("Failed to register: %s", error->message);
|
||||||
|
*exit_status = 1;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_application_activate(application);
|
||||||
|
*exit_status = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GObject::dispose.
|
||||||
|
static void my_application_dispose(GObject* object) {
|
||||||
|
MyApplication* self = MY_APPLICATION(object);
|
||||||
|
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||||
|
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_application_class_init(MyApplicationClass* klass) {
|
||||||
|
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||||
|
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
|
||||||
|
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_application_init(MyApplication* self) {}
|
||||||
|
|
||||||
|
MyApplication* my_application_new() {
|
||||||
|
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||||
|
"application-id", APPLICATION_ID,
|
||||||
|
"flags", G_APPLICATION_NON_UNIQUE,
|
||||||
|
nullptr));
|
||||||
|
}
|
18
cw_monero/example/linux/my_application.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef FLUTTER_MY_APPLICATION_H_
|
||||||
|
#define FLUTTER_MY_APPLICATION_H_
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
|
||||||
|
GtkApplication)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* my_application_new:
|
||||||
|
*
|
||||||
|
* Creates a new Flutter-based application.
|
||||||
|
*
|
||||||
|
* Returns: a new #MyApplication.
|
||||||
|
*/
|
||||||
|
MyApplication* my_application_new();
|
||||||
|
|
||||||
|
#endif // FLUTTER_MY_APPLICATION_H_
|
|
@ -34,7 +34,6 @@ List<monero.SubaddressAccountRow> getAllAccount() {
|
||||||
// final size = monero.Wallet_numSubaddressAccounts(wptr!);
|
// final size = monero.Wallet_numSubaddressAccounts(wptr!);
|
||||||
refreshAccounts();
|
refreshAccounts();
|
||||||
int size = monero.SubaddressAccount_getAll_size(subaddressAccount!);
|
int size = monero.SubaddressAccount_getAll_size(subaddressAccount!);
|
||||||
print("size: $size");
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
monero.Wallet_addSubaddressAccount(wptr!);
|
monero.Wallet_addSubaddressAccount(wptr!);
|
||||||
return getAllAccount();
|
return getAllAccount();
|
||||||
|
|
|
@ -39,7 +39,7 @@ String getSeed() {
|
||||||
if (polyseed != "") {
|
if (polyseed != "") {
|
||||||
return polyseed;
|
return polyseed;
|
||||||
}
|
}
|
||||||
final legacy = monero.Wallet_seed(wptr!, seedOffset: '');
|
final legacy = getSeedLegacy("English");
|
||||||
return legacy;
|
return legacy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,9 @@ String getSeedLegacy(String? language) {
|
||||||
monero.Wallet_setSeedLanguage(wptr!, language: language ?? "English");
|
monero.Wallet_setSeedLanguage(wptr!, language: language ?? "English");
|
||||||
legacy = monero.Wallet_seed(wptr!, seedOffset: '');
|
legacy = monero.Wallet_seed(wptr!, seedOffset: '');
|
||||||
}
|
}
|
||||||
|
if (monero.Wallet_status(wptr!) != 0) {
|
||||||
|
return monero.Wallet_errorString(wptr!);
|
||||||
|
}
|
||||||
return legacy;
|
return legacy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart';
|
||||||
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
|
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
|
||||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart';
|
import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart';
|
||||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart';
|
import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart';
|
||||||
import 'package:cw_monero/api/transaction_history.dart';
|
|
||||||
import 'package:cw_monero/api/wallet.dart';
|
import 'package:cw_monero/api/wallet.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:cw_monero/api/transaction_history.dart';
|
||||||
import 'package:monero/monero.dart' as monero;
|
import 'package:monero/monero.dart' as monero;
|
||||||
|
|
||||||
class MoneroCException implements Exception {
|
class MoneroCException implements Exception {
|
||||||
|
@ -124,7 +123,16 @@ void restoreWalletFromKeysSync(
|
||||||
int nettype = 0,
|
int nettype = 0,
|
||||||
int restoreHeight = 0}) {
|
int restoreHeight = 0}) {
|
||||||
txhistory = null;
|
txhistory = null;
|
||||||
final newWptr = monero.WalletManager_createWalletFromKeys(
|
final newWptr = spendKey != ""
|
||||||
|
? monero.WalletManager_createDeterministicWalletFromSpendKey(
|
||||||
|
wmPtr,
|
||||||
|
path: path,
|
||||||
|
password: password,
|
||||||
|
language: language,
|
||||||
|
spendKeyString: spendKey,
|
||||||
|
newWallet: true, // TODO(mrcyjanek): safe to remove
|
||||||
|
restoreHeight: restoreHeight)
|
||||||
|
: monero.WalletManager_createWalletFromKeys(
|
||||||
wmPtr,
|
wmPtr,
|
||||||
path: path,
|
path: path,
|
||||||
password: password,
|
password: password,
|
||||||
|
|
|
@ -3,6 +3,8 @@ import 'dart:ffi';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
|
|
||||||
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/account.dart';
|
import 'package:cw_core/account.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/monero_amount_format.dart';
|
import 'package:cw_core/monero_amount_format.dart';
|
||||||
|
@ -50,7 +52,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
MoneroTransactionHistory, MoneroTransactionInfo> with Store {
|
MoneroTransactionHistory, MoneroTransactionInfo> with Store {
|
||||||
MoneroWalletBase(
|
MoneroWalletBase(
|
||||||
{required WalletInfo walletInfo,
|
{required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo})
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
|
required String password})
|
||||||
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
|
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
|
||||||
CryptoCurrency.xmr: MoneroBalance(
|
CryptoCurrency.xmr: MoneroBalance(
|
||||||
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
|
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
|
||||||
|
@ -59,6 +62,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
_isTransactionUpdating = false,
|
_isTransactionUpdating = false,
|
||||||
_hasSyncAfterStartup = false,
|
_hasSyncAfterStartup = false,
|
||||||
isEnabledAutoGenerateSubaddress = false,
|
isEnabledAutoGenerateSubaddress = false,
|
||||||
|
_password = password,
|
||||||
syncStatus = NotConnectedSyncStatus(),
|
syncStatus = NotConnectedSyncStatus(),
|
||||||
unspentCoins = [],
|
unspentCoins = [],
|
||||||
this.unspentCoinsInfo = unspentCoinsInfo,
|
this.unspentCoinsInfo = unspentCoinsInfo,
|
||||||
|
@ -111,6 +115,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
String get seed => monero_wallet.getSeed();
|
String get seed => monero_wallet.getSeed();
|
||||||
String seedLegacy(String? language) => monero_wallet.getSeedLegacy(language);
|
String seedLegacy(String? language) => monero_wallet.getSeedLegacy(language);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MoneroWalletKeys get keys => MoneroWalletKeys(
|
MoneroWalletKeys get keys => MoneroWalletKeys(
|
||||||
privateSpendKey: monero_wallet.getSecretSpendKey(),
|
privateSpendKey: monero_wallet.getSecretSpendKey(),
|
||||||
|
@ -127,6 +134,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
bool _hasSyncAfterStartup;
|
bool _hasSyncAfterStartup;
|
||||||
Timer? _autoSaveTimer;
|
Timer? _autoSaveTimer;
|
||||||
List<MoneroUnspent> unspentCoins;
|
List<MoneroUnspent> unspentCoins;
|
||||||
|
String _password;
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
await walletAddresses.init();
|
await walletAddresses.init();
|
||||||
|
|
|
@ -93,7 +93,9 @@ class MoneroWalletService extends WalletService<
|
||||||
await monero_wallet_manager.createWallet(
|
await monero_wallet_manager.createWallet(
|
||||||
path: path, password: credentials.password!, language: credentials.language);
|
path: path, password: credentials.password!, language: credentials.language);
|
||||||
final wallet = MoneroWallet(
|
final wallet = MoneroWallet(
|
||||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
walletInfo: credentials.walletInfo!,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: credentials.password!);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -126,10 +128,14 @@ class MoneroWalletService extends WalletService<
|
||||||
await repairOldAndroidWallet(name);
|
await repairOldAndroidWallet(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
await monero_wallet_manager.openWalletAsync({'path': path, 'password': password});
|
await monero_wallet_manager
|
||||||
final walletInfo = walletInfoSource.values
|
.openWalletAsync({'path': path, 'password': password});
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
final walletInfo = walletInfoSource.values.firstWhere(
|
||||||
wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
(info) => info.id == WalletBase.idFor(name, getType()));
|
||||||
|
final wallet = MoneroWallet(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: password);
|
||||||
final isValid = wallet.walletAddresses.validate();
|
final isValid = wallet.walletAddresses.validate();
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
|
@ -162,15 +168,22 @@ class MoneroWalletService extends WalletService<
|
||||||
final bool invalidSignature = e.toString().contains('invalid signature') ||
|
final bool invalidSignature = e.toString().contains('invalid signature') ||
|
||||||
(e is WalletOpeningException && e.message.contains('invalid signature'));
|
(e is WalletOpeningException && e.message.contains('invalid signature'));
|
||||||
|
|
||||||
|
final bool invalidPassword = e.toString().contains('invalid password') ||
|
||||||
|
(e is WalletOpeningException && e.message.contains('invalid password'));
|
||||||
|
|
||||||
if (!isBadAlloc &&
|
if (!isBadAlloc &&
|
||||||
!doesNotCorrespond &&
|
!doesNotCorrespond &&
|
||||||
!isMissingCacheFilesIOS &&
|
!isMissingCacheFilesIOS &&
|
||||||
!isMissingCacheFilesAndroid &&
|
!isMissingCacheFilesAndroid &&
|
||||||
!invalidSignature &&
|
!invalidSignature &&
|
||||||
|
!invalidPassword &&
|
||||||
wallet != null &&
|
wallet != null &&
|
||||||
wallet.onError != null) {
|
wallet.onError != null) {
|
||||||
wallet.onError!(FlutterErrorDetails(exception: e, stack: s));
|
wallet.onError!(FlutterErrorDetails(exception: e, stack: s));
|
||||||
}
|
}
|
||||||
|
if (invalidPassword) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
|
||||||
await restoreOrResetWalletFiles(name);
|
await restoreOrResetWalletFiles(name);
|
||||||
return openWallet(name, password);
|
return openWallet(name, password);
|
||||||
|
@ -206,11 +219,15 @@ class MoneroWalletService extends WalletService<
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> rename(String currentName, String password, String newName) async {
|
Future<void> rename(
|
||||||
final currentWalletInfo = walletInfoSource.values
|
String currentName, String password, String newName) async {
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
final currentWalletInfo = walletInfoSource.values.firstWhere(
|
||||||
final currentWallet =
|
(info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||||
MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
final currentWallet = MoneroWallet(
|
||||||
|
walletInfo: currentWalletInfo,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
|
|
||||||
|
@ -235,7 +252,9 @@ class MoneroWalletService extends WalletService<
|
||||||
viewKey: credentials.viewKey,
|
viewKey: credentials.viewKey,
|
||||||
spendKey: credentials.spendKey);
|
spendKey: credentials.spendKey);
|
||||||
final wallet = MoneroWallet(
|
final wallet = MoneroWallet(
|
||||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
walletInfo: credentials.walletInfo!,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: credentials.password!);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -268,7 +287,9 @@ class MoneroWalletService extends WalletService<
|
||||||
seed: credentials.mnemonic,
|
seed: credentials.mnemonic,
|
||||||
restoreHeight: credentials.height!);
|
restoreHeight: credentials.height!);
|
||||||
final wallet = MoneroWallet(
|
final wallet = MoneroWallet(
|
||||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
walletInfo: credentials.walletInfo!,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: credentials.password!);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -315,7 +336,11 @@ class MoneroWalletService extends WalletService<
|
||||||
restoreHeight: height,
|
restoreHeight: height,
|
||||||
spendKey: spendKey);
|
spendKey: spendKey);
|
||||||
|
|
||||||
final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
final wallet = MoneroWallet(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -364,7 +389,11 @@ class MoneroWalletService extends WalletService<
|
||||||
await monero_wallet_manager.openWalletAsync({'path': path, 'password': password});
|
await monero_wallet_manager.openWalletAsync({'path': path, 'password': password});
|
||||||
final walletInfo = walletInfoSource.values
|
final walletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
||||||
final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
final wallet = MoneroWallet(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
return wallet.seed;
|
return wallet.seed;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// if the file couldn't be opened or read
|
// if the file couldn't be opened or read
|
||||||
|
|
270
cw_monero/linux/CMakeLists.txt
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||||
|
# installed. You should not increase this version, as doing so will cause
|
||||||
|
# the plugin to fail to compile for some customers of the plugin.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
# Project-level configuration.
|
||||||
|
set(PROJECT_NAME "cw_monero")
|
||||||
|
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||||
|
|
||||||
|
# This value is used when generating builds using this plugin, so it must
|
||||||
|
# not be changed.
|
||||||
|
set(PLUGIN_NAME "cw_monero_plugin")
|
||||||
|
|
||||||
|
# Define the plugin library target. Its name must not be changed (see comment
|
||||||
|
# on PLUGIN_NAME above).
|
||||||
|
#
|
||||||
|
# Any new source files that you add to the plugin should be added here.
|
||||||
|
add_library(${PLUGIN_NAME} SHARED
|
||||||
|
"cw_monero_plugin.cc"
|
||||||
|
"../ios/Classes/monero_api.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply a standard set of build settings that are configured in the
|
||||||
|
# application-level CMakeLists.txt. This can be removed for plugins that want
|
||||||
|
# full control over build settings.
|
||||||
|
apply_standard_settings(${PLUGIN_NAME})
|
||||||
|
|
||||||
|
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
||||||
|
# between plugins. This should not be removed; any symbols that should be
|
||||||
|
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
||||||
|
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||||
|
CXX_VISIBILITY_PRESET hidden)
|
||||||
|
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||||
|
|
||||||
|
# Source include directories and library dependencies. Add any plugin-specific
|
||||||
|
# dependencies here.
|
||||||
|
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
|
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
|
||||||
|
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
target_link_libraries(${PLUGIN_NAME} PUBLIC cw_monero)
|
||||||
|
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||||
|
# This list could contain prebuilt libraries, or libraries created by an
|
||||||
|
# external build triggered from this build file.
|
||||||
|
set(cw_monero_bundled_libraries
|
||||||
|
""
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library( cw_monero
|
||||||
|
STATIC
|
||||||
|
../ios/Classes/monero_api.cpp)
|
||||||
|
|
||||||
|
set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../cw_shared_external/ios/External/linux)
|
||||||
|
|
||||||
|
############
|
||||||
|
# libsodium
|
||||||
|
############
|
||||||
|
|
||||||
|
add_library(sodium STATIC IMPORTED)
|
||||||
|
set_target_properties(sodium PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libsodium.a)
|
||||||
|
|
||||||
|
############
|
||||||
|
# OpenSSL
|
||||||
|
############
|
||||||
|
|
||||||
|
add_library(crypto STATIC IMPORTED)
|
||||||
|
set_target_properties(crypto PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libcrypto.a)
|
||||||
|
|
||||||
|
add_library(ssl STATIC IMPORTED)
|
||||||
|
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libssl.a)
|
||||||
|
|
||||||
|
############
|
||||||
|
# Boost
|
||||||
|
############
|
||||||
|
|
||||||
|
add_library(boost_chrono STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_chrono.a)
|
||||||
|
|
||||||
|
add_library(boost_date_time STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_date_time.a)
|
||||||
|
|
||||||
|
add_library(boost_filesystem STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_filesystem.a)
|
||||||
|
|
||||||
|
add_library(boost_program_options STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_program_options.a)
|
||||||
|
|
||||||
|
add_library(boost_regex STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_regex.a)
|
||||||
|
|
||||||
|
add_library(boost_serialization STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_serialization.a)
|
||||||
|
|
||||||
|
add_library(boost_system STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_system.a)
|
||||||
|
|
||||||
|
add_library(boost_thread STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_thread.a)
|
||||||
|
|
||||||
|
add_library(boost_wserialization STATIC IMPORTED)
|
||||||
|
set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libboost_wserialization.a)
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Monero
|
||||||
|
#############
|
||||||
|
|
||||||
|
|
||||||
|
add_library(wallet STATIC IMPORTED)
|
||||||
|
set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libwallet.a)
|
||||||
|
|
||||||
|
add_library(wallet_api STATIC IMPORTED)
|
||||||
|
set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libwallet_api.a)
|
||||||
|
|
||||||
|
add_library(cryptonote_core STATIC IMPORTED)
|
||||||
|
set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libcryptonote_core.a)
|
||||||
|
|
||||||
|
add_library(cryptonote_basic STATIC IMPORTED)
|
||||||
|
set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libcryptonote_basic.a)
|
||||||
|
|
||||||
|
add_library(cryptonote_format_utils_basic STATIC IMPORTED)
|
||||||
|
set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libcryptonote_format_utils_basic.a)
|
||||||
|
|
||||||
|
add_library(mnemonics STATIC IMPORTED)
|
||||||
|
set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libmnemonics.a)
|
||||||
|
|
||||||
|
add_library(common STATIC IMPORTED)
|
||||||
|
set_target_properties(common PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libcommon.a)
|
||||||
|
|
||||||
|
add_library(cncrypto STATIC IMPORTED)
|
||||||
|
set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libcncrypto.a)
|
||||||
|
|
||||||
|
add_library(ringct STATIC IMPORTED)
|
||||||
|
set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libringct.a)
|
||||||
|
|
||||||
|
add_library(ringct_basic STATIC IMPORTED)
|
||||||
|
set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libringct_basic.a)
|
||||||
|
|
||||||
|
add_library(blockchain_db STATIC IMPORTED)
|
||||||
|
set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libblockchain_db.a)
|
||||||
|
|
||||||
|
add_library(lmdb STATIC IMPORTED)
|
||||||
|
set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/liblmdb.a)
|
||||||
|
|
||||||
|
add_library(easylogging STATIC IMPORTED)
|
||||||
|
set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libeasylogging.a)
|
||||||
|
|
||||||
|
add_library(epee STATIC IMPORTED)
|
||||||
|
set_target_properties(epee PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libepee.a)
|
||||||
|
|
||||||
|
add_library(blocks STATIC IMPORTED)
|
||||||
|
set_target_properties(blocks PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libblocks.a)
|
||||||
|
|
||||||
|
add_library(checkpoints STATIC IMPORTED)
|
||||||
|
set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libcheckpoints.a)
|
||||||
|
|
||||||
|
add_library(device STATIC IMPORTED)
|
||||||
|
set_target_properties(device PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libdevice.a)
|
||||||
|
|
||||||
|
add_library(device_trezor STATIC IMPORTED)
|
||||||
|
set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libdevice_trezor.a)
|
||||||
|
|
||||||
|
add_library(multisig STATIC IMPORTED)
|
||||||
|
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libmultisig.a)
|
||||||
|
|
||||||
|
add_library(version STATIC IMPORTED)
|
||||||
|
set_target_properties(version PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libversion.a)
|
||||||
|
|
||||||
|
add_library(net STATIC IMPORTED)
|
||||||
|
set_target_properties(net PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libnet.a)
|
||||||
|
|
||||||
|
add_library(hardforks STATIC IMPORTED)
|
||||||
|
set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libhardforks.a)
|
||||||
|
|
||||||
|
add_library(randomx STATIC IMPORTED)
|
||||||
|
set_target_properties(randomx PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/librandomx.a)
|
||||||
|
|
||||||
|
add_library(rpc_base STATIC IMPORTED)
|
||||||
|
set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/librpc_base.a)
|
||||||
|
|
||||||
|
add_library(wallet-crypto STATIC IMPORTED)
|
||||||
|
set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/monero/libwallet-crypto.a)
|
||||||
|
|
||||||
|
add_library(unbound STATIC IMPORTED)
|
||||||
|
set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/lib/libunbound.a)
|
||||||
|
|
||||||
|
include_directories( ${EXTERNAL_LIBS_DIR}/include )
|
||||||
|
|
||||||
|
target_link_libraries( cw_monero
|
||||||
|
|
||||||
|
wallet_api
|
||||||
|
wallet
|
||||||
|
cryptonote_core
|
||||||
|
cryptonote_basic
|
||||||
|
cryptonote_format_utils_basic
|
||||||
|
mnemonics
|
||||||
|
ringct
|
||||||
|
ringct_basic
|
||||||
|
net
|
||||||
|
common
|
||||||
|
cncrypto
|
||||||
|
blockchain_db
|
||||||
|
lmdb
|
||||||
|
easylogging
|
||||||
|
unbound
|
||||||
|
epee
|
||||||
|
blocks
|
||||||
|
checkpoints
|
||||||
|
device
|
||||||
|
device_trezor
|
||||||
|
multisig
|
||||||
|
version
|
||||||
|
randomx
|
||||||
|
hardforks
|
||||||
|
rpc_base
|
||||||
|
wallet-crypto
|
||||||
|
|
||||||
|
boost_chrono
|
||||||
|
boost_date_time
|
||||||
|
boost_filesystem
|
||||||
|
boost_program_options
|
||||||
|
boost_regex
|
||||||
|
boost_serialization
|
||||||
|
boost_system
|
||||||
|
boost_thread
|
||||||
|
boost_wserialization
|
||||||
|
|
||||||
|
ssl
|
||||||
|
crypto
|
||||||
|
|
||||||
|
sodium
|
||||||
|
)
|
70
cw_monero/linux/cw_monero_plugin.cc
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "include/cw_monero/cw_monero_plugin.h"
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#define CW_MONERO_PLUGIN(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj), cw_monero_plugin_get_type(), \
|
||||||
|
CwMoneroPlugin))
|
||||||
|
|
||||||
|
struct _CwMoneroPlugin {
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(CwMoneroPlugin, cw_monero_plugin, g_object_get_type())
|
||||||
|
|
||||||
|
// Called when a method call is received from Flutter.
|
||||||
|
static void cw_monero_plugin_handle_method_call(
|
||||||
|
CwMoneroPlugin* self,
|
||||||
|
FlMethodCall* method_call) {
|
||||||
|
g_autoptr(FlMethodResponse) response = nullptr;
|
||||||
|
|
||||||
|
const gchar* method = fl_method_call_get_name(method_call);
|
||||||
|
|
||||||
|
if (strcmp(method, "getPlatformVersion") == 0) {
|
||||||
|
struct utsname uname_data = {};
|
||||||
|
uname(&uname_data);
|
||||||
|
g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
|
||||||
|
g_autoptr(FlValue) result = fl_value_new_string(version);
|
||||||
|
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
|
||||||
|
} else {
|
||||||
|
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
|
||||||
|
}
|
||||||
|
|
||||||
|
fl_method_call_respond(method_call, response, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cw_monero_plugin_dispose(GObject* object) {
|
||||||
|
G_OBJECT_CLASS(cw_monero_plugin_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cw_monero_plugin_class_init(CwMoneroPluginClass* klass) {
|
||||||
|
G_OBJECT_CLASS(klass)->dispose = cw_monero_plugin_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cw_monero_plugin_init(CwMoneroPlugin* self) {}
|
||||||
|
|
||||||
|
static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
|
||||||
|
gpointer user_data) {
|
||||||
|
CwMoneroPlugin* plugin = CW_MONERO_PLUGIN(user_data);
|
||||||
|
cw_monero_plugin_handle_method_call(plugin, method_call);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw_monero_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
|
||||||
|
CwMoneroPlugin* plugin = CW_MONERO_PLUGIN(
|
||||||
|
g_object_new(cw_monero_plugin_get_type(), nullptr));
|
||||||
|
|
||||||
|
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
|
||||||
|
g_autoptr(FlMethodChannel) channel =
|
||||||
|
fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
|
||||||
|
"cw_monero",
|
||||||
|
FL_METHOD_CODEC(codec));
|
||||||
|
fl_method_channel_set_method_call_handler(channel, method_call_cb,
|
||||||
|
g_object_ref(plugin),
|
||||||
|
g_object_unref);
|
||||||
|
|
||||||
|
g_object_unref(plugin);
|
||||||
|
}
|
11
cw_monero/linux/flutter/generated_plugin_registrant.cc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
}
|
15
cw_monero/linux/flutter/generated_plugin_registrant.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
#define GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
|
||||||
|
// Registers Flutter plugins.
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry);
|
||||||
|
|
||||||
|
#endif // GENERATED_PLUGIN_REGISTRANT_
|
23
cw_monero/linux/flutter/generated_plugins.cmake
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
|
endforeach(plugin)
|
||||||
|
|
||||||
|
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||||
|
endforeach(ffi_plugin)
|
26
cw_monero/linux/include/cw_monero/cw_monero_plugin.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef FLUTTER_PLUGIN_CW_MONERO_PLUGIN_H_
|
||||||
|
#define FLUTTER_PLUGIN_CW_MONERO_PLUGIN_H_
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifdef FLUTTER_PLUGIN_IMPL
|
||||||
|
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define FLUTTER_PLUGIN_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _CwMoneroPlugin CwMoneroPlugin;
|
||||||
|
typedef struct {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
} CwMoneroPluginClass;
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT GType cw_monero_plugin_get_type();
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT void cw_monero_plugin_register_with_registrar(
|
||||||
|
FlPluginRegistrar* registrar);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif // FLUTTER_PLUGIN_CW_MONERO_PLUGIN_H_
|
|
@ -113,6 +113,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.9.2"
|
version: "8.9.2"
|
||||||
|
cake_backup:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: main
|
||||||
|
resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38"
|
||||||
|
url: "https://github.com/cake-tech/cake_backup.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0+1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -169,6 +178,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
|
cryptography:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cryptography
|
||||||
|
sha256: d146b76d33d94548cf035233fbc2f4338c1242fa119013bead807d033fc4ae05
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.0"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.8"
|
||||||
cw_core:
|
cw_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -342,10 +367,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.1"
|
version: "0.6.7"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -696,6 +721,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:cw_core/key.dart';
|
|
||||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
|
||||||
|
|
||||||
Future<void> write(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> writeData(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> read({required String path, required String password}) async {
|
|
||||||
final file = File(path);
|
|
||||||
|
|
||||||
if (!file.existsSync()) {
|
|
||||||
file.createSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
final encrypted = file.readAsStringSync();
|
|
||||||
|
|
||||||
return decode(password: password, data: encrypted);
|
|
||||||
}
|
|
|
@ -2,24 +2,29 @@ import 'dart:convert';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_nano/file.dart';
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_nano/nano_transaction_info.dart';
|
import 'package:cw_nano/nano_transaction_info.dart';
|
||||||
|
|
||||||
part 'nano_transaction_history.g.dart';
|
part 'nano_transaction_history.g.dart';
|
||||||
|
|
||||||
const transactionsHistoryFileName = 'transactions.json';
|
const transactionsHistoryFileName = 'transactions.json';
|
||||||
|
|
||||||
class NanoTransactionHistory = NanoTransactionHistoryBase with _$NanoTransactionHistory;
|
class NanoTransactionHistory = NanoTransactionHistoryBase with _$NanoTransactionHistory;
|
||||||
|
|
||||||
abstract class NanoTransactionHistoryBase
|
abstract class NanoTransactionHistoryBase extends TransactionHistoryBase<NanoTransactionInfo>
|
||||||
extends TransactionHistoryBase<NanoTransactionInfo> with Store {
|
with Store {
|
||||||
NanoTransactionHistoryBase({required this.walletInfo, required String password})
|
NanoTransactionHistoryBase({
|
||||||
: _password = password {
|
required this.walletInfo,
|
||||||
|
required String password,
|
||||||
|
required this.encryptionFileUtils,
|
||||||
|
}) : _password = password {
|
||||||
transactions = ObservableMap<String, NanoTransactionInfo>();
|
transactions = ObservableMap<String, NanoTransactionInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
final WalletInfo walletInfo;
|
final WalletInfo walletInfo;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
String _password;
|
String _password;
|
||||||
|
|
||||||
Future<void> init() async => await _load();
|
Future<void> init() async => await _load();
|
||||||
|
@ -30,7 +35,7 @@ abstract class NanoTransactionHistoryBase
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
final path = '$dirPath/$transactionsHistoryFileName';
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
final data = json.encode({'transactions': transactions});
|
final data = json.encode({'transactions': transactions});
|
||||||
await writeData(path: path, password: _password, data: data);
|
await encryptionFileUtils.write(path: path, password: _password, data: data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error while save nano transaction history: ${e.toString()}');
|
print('Error while save nano transaction history: ${e.toString()}');
|
||||||
}
|
}
|
||||||
|
@ -46,7 +51,10 @@ abstract class NanoTransactionHistoryBase
|
||||||
Future<Map<String, dynamic>> _read() async {
|
Future<Map<String, dynamic>> _read() async {
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
final path = '$dirPath/$transactionsHistoryFileName';
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
final content = await read(path: path, password: _password);
|
final content = await encryptionFileUtils.read(path: path, password: _password);
|
||||||
|
if (content.isEmpty) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return json.decode(content) as Map<String, dynamic>;
|
return json.decode(content) as Map<String, dynamic>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'dart:io';
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:cw_core/cake_hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/n2_node.dart';
|
import 'package:cw_core/n2_node.dart';
|
||||||
import 'package:cw_core/nano_account.dart';
|
import 'package:cw_core/nano_account.dart';
|
||||||
import 'package:cw_core/nano_account_info_response.dart';
|
import 'package:cw_core/nano_account_info_response.dart';
|
||||||
|
@ -17,7 +18,6 @@ import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_keys_file.dart';
|
import 'package:cw_core/wallet_keys_file.dart';
|
||||||
import 'package:cw_nano/file.dart';
|
|
||||||
import 'package:cw_nano/nano_balance.dart';
|
import 'package:cw_nano/nano_balance.dart';
|
||||||
import 'package:cw_nano/nano_client.dart';
|
import 'package:cw_nano/nano_client.dart';
|
||||||
import 'package:cw_nano/nano_transaction_credentials.dart';
|
import 'package:cw_nano/nano_transaction_credentials.dart';
|
||||||
|
@ -42,11 +42,13 @@ abstract class NanoWalletBase
|
||||||
required String mnemonic,
|
required String mnemonic,
|
||||||
required String password,
|
required String password,
|
||||||
NanoBalance? initialBalance,
|
NanoBalance? initialBalance,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
}) : syncStatus = NotConnectedSyncStatus(),
|
}) : syncStatus = NotConnectedSyncStatus(),
|
||||||
_password = password,
|
_password = password,
|
||||||
_mnemonic = mnemonic,
|
_mnemonic = mnemonic,
|
||||||
_derivationType = walletInfo.derivationInfo!.derivationType!,
|
_derivationType = walletInfo.derivationInfo!.derivationType!,
|
||||||
_isTransactionUpdating = false,
|
_isTransactionUpdating = false,
|
||||||
|
_encryptionFileUtils = encryptionFileUtils,
|
||||||
_client = NanoClient(),
|
_client = NanoClient(),
|
||||||
walletAddresses = NanoWalletAddresses(walletInfo),
|
walletAddresses = NanoWalletAddresses(walletInfo),
|
||||||
balance = ObservableMap<CryptoCurrency, NanoBalance>.of({
|
balance = ObservableMap<CryptoCurrency, NanoBalance>.of({
|
||||||
|
@ -55,7 +57,11 @@ abstract class NanoWalletBase
|
||||||
}),
|
}),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = NanoTransactionHistory(walletInfo: walletInfo, password: password);
|
transactionHistory = NanoTransactionHistory(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
password: password,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
|
);
|
||||||
if (!CakeHive.isAdapterRegistered(NanoAccount.typeId)) {
|
if (!CakeHive.isAdapterRegistered(NanoAccount.typeId)) {
|
||||||
CakeHive.registerAdapter(NanoAccountAdapter());
|
CakeHive.registerAdapter(NanoAccountAdapter());
|
||||||
}
|
}
|
||||||
|
@ -65,6 +71,8 @@ abstract class NanoWalletBase
|
||||||
final String _password;
|
final String _password;
|
||||||
DerivationType _derivationType;
|
DerivationType _derivationType;
|
||||||
|
|
||||||
|
final EncryptionFileUtils _encryptionFileUtils;
|
||||||
|
|
||||||
String? _privateKey;
|
String? _privateKey;
|
||||||
String? _publicAddress;
|
String? _publicAddress;
|
||||||
String? _hexSeed;
|
String? _hexSeed;
|
||||||
|
@ -89,6 +97,9 @@ abstract class NanoWalletBase
|
||||||
@observable
|
@observable
|
||||||
late ObservableMap<CryptoCurrency, NanoBalance> balance;
|
late ObservableMap<CryptoCurrency, NanoBalance> balance;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
|
|
||||||
static const int POLL_INTERVAL_SECONDS = 10;
|
static const int POLL_INTERVAL_SECONDS = 10;
|
||||||
|
|
||||||
// initialize the different forms of private / public key we'll need:
|
// initialize the different forms of private / public key we'll need:
|
||||||
|
@ -308,13 +319,13 @@ abstract class NanoWalletBase
|
||||||
@override
|
@override
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
||||||
await saveKeysFile(_password);
|
await saveKeysFile(_password, _encryptionFileUtils);
|
||||||
saveKeysFile(_password, true);
|
saveKeysFile(_password, _encryptionFileUtils, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await walletAddresses.updateAddressesInBox();
|
await walletAddresses.updateAddressesInBox();
|
||||||
final path = await makePath();
|
final path = await makePath();
|
||||||
await write(path: path, password: _password, data: toJSON());
|
await _encryptionFileUtils.write(path: path, password: _password, data: toJSON());
|
||||||
await transactionHistory.save();
|
await transactionHistory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,13 +384,14 @@ abstract class NanoWalletBase
|
||||||
required String name,
|
required String name,
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
}) async {
|
}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||||
|
|
||||||
Map<String, dynamic>? data = null;
|
Map<String, dynamic>? data = null;
|
||||||
try {
|
try {
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||||
|
|
||||||
data = json.decode(jsonSource) as Map<String, dynamic>;
|
data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -400,7 +412,12 @@ abstract class NanoWalletBase
|
||||||
keysData = WalletKeysData(
|
keysData = WalletKeysData(
|
||||||
mnemonic: isHexSeed ? null : mnemonic, altMnemonic: isHexSeed ? mnemonic : null);
|
mnemonic: isHexSeed ? null : mnemonic, altMnemonic: isHexSeed ? mnemonic : null);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivationType derivationType = DerivationType.nano;
|
DerivationType derivationType = DerivationType.nano;
|
||||||
|
@ -416,6 +433,7 @@ abstract class NanoWalletBase
|
||||||
password: password,
|
password: password,
|
||||||
mnemonic: keysData.mnemonic!,
|
mnemonic: keysData.mnemonic!,
|
||||||
initialBalance: balance,
|
initialBalance: balance,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
);
|
);
|
||||||
// init() should always be run after this!
|
// init() should always be run after this!
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
|
@ -15,9 +16,10 @@ import 'package:nanoutil/nanoutil.dart';
|
||||||
|
|
||||||
class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
NanoRestoreWalletFromSeedCredentials, NanoRestoreWalletFromKeysCredentials, NanoNewWalletCredentials> {
|
NanoRestoreWalletFromSeedCredentials, NanoRestoreWalletFromKeysCredentials, NanoNewWalletCredentials> {
|
||||||
NanoWalletService(this.walletInfoSource);
|
NanoWalletService(this.walletInfoSource, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
static bool walletFilesExist(String path) =>
|
static bool walletFilesExist(String path) =>
|
||||||
!File(path).existsSync() && !File('$path.keys').existsSync();
|
!File(path).existsSync() && !File('$path.keys').existsSync();
|
||||||
|
@ -38,6 +40,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -65,8 +68,12 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
|
|
||||||
String randomWords =
|
String randomWords =
|
||||||
(List<String>.from(nm.NanoMnemomics.WORDLIST)..shuffle()).take(24).join(' ');
|
(List<String>.from(nm.NanoMnemomics.WORDLIST)..shuffle()).take(24).join(' ');
|
||||||
final currentWallet =
|
final currentWallet = NanoWallet(
|
||||||
NanoWallet(walletInfo: currentWalletInfo, password: password, mnemonic: randomWords);
|
walletInfo: currentWalletInfo,
|
||||||
|
password: password,
|
||||||
|
mnemonic: randomWords,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
@ -103,6 +110,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: mnemonic ?? credentials.seedKey,
|
mnemonic: mnemonic ?? credentials.seedKey,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
|
@ -139,6 +147,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -160,6 +169,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -172,6 +182,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
|
@ -137,6 +137,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.9.2"
|
version: "8.9.2"
|
||||||
|
cake_backup:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: main
|
||||||
|
resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38"
|
||||||
|
url: "https://github.com/cake-tech/cake_backup.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0+1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -193,6 +202,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
|
cryptography:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cryptography
|
||||||
|
sha256: d146b76d33d94548cf035233fbc2f4338c1242fa119013bead807d033fc4ae05
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.0"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.8"
|
||||||
cw_core:
|
cw_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -797,6 +822,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -8,6 +8,7 @@ class PolygonTransactionHistory extends EVMChainTransactionHistory {
|
||||||
PolygonTransactionHistory({
|
PolygonTransactionHistory({
|
||||||
required super.walletInfo,
|
required super.walletInfo,
|
||||||
required super.password,
|
required super.password,
|
||||||
|
required super.encryptionFileUtils,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cw_core/cake_hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/erc20_token.dart';
|
import 'package:cw_core/erc20_token.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/transaction_direction.dart';
|
import 'package:cw_core/transaction_direction.dart';
|
||||||
|
@ -12,7 +13,6 @@ import 'package:cw_evm/evm_chain_transaction_info.dart';
|
||||||
import 'package:cw_evm/evm_chain_transaction_model.dart';
|
import 'package:cw_evm/evm_chain_transaction_model.dart';
|
||||||
import 'package:cw_evm/evm_chain_wallet.dart';
|
import 'package:cw_evm/evm_chain_wallet.dart';
|
||||||
import 'package:cw_evm/evm_erc20_balance.dart';
|
import 'package:cw_evm/evm_erc20_balance.dart';
|
||||||
import 'package:cw_evm/file.dart';
|
|
||||||
import 'package:cw_polygon/default_polygon_erc20_tokens.dart';
|
import 'package:cw_polygon/default_polygon_erc20_tokens.dart';
|
||||||
import 'package:cw_polygon/polygon_client.dart';
|
import 'package:cw_polygon/polygon_client.dart';
|
||||||
import 'package:cw_polygon/polygon_transaction_history.dart';
|
import 'package:cw_polygon/polygon_transaction_history.dart';
|
||||||
|
@ -26,6 +26,7 @@ class PolygonWallet extends EVMChainWallet {
|
||||||
super.initialBalance,
|
super.initialBalance,
|
||||||
super.privateKey,
|
super.privateKey,
|
||||||
required super.client,
|
required super.client,
|
||||||
|
required super.encryptionFileUtils,
|
||||||
}) : super(nativeCurrency: CryptoCurrency.maticpoly);
|
}) : super(nativeCurrency: CryptoCurrency.maticpoly);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -92,18 +93,27 @@ class PolygonWallet extends EVMChainWallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
EVMChainTransactionHistory setUpTransactionHistory(WalletInfo walletInfo, String password) {
|
EVMChainTransactionHistory setUpTransactionHistory(
|
||||||
return PolygonTransactionHistory(walletInfo: walletInfo, password: password);
|
WalletInfo walletInfo, String password, EncryptionFileUtils encryptionFileUtils) {
|
||||||
|
return PolygonTransactionHistory(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
password: password,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<PolygonWallet> open(
|
static Future<PolygonWallet> open({
|
||||||
{required String name, required String password, required WalletInfo walletInfo}) async {
|
required String name,
|
||||||
|
required String password,
|
||||||
|
required WalletInfo walletInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
|
}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||||
|
|
||||||
Map<String, dynamic>? data;
|
Map<String, dynamic>? data;
|
||||||
try {
|
try {
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||||
|
|
||||||
data = json.decode(jsonSource) as Map<String, dynamic>;
|
data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -121,7 +131,12 @@ class PolygonWallet extends EVMChainWallet {
|
||||||
|
|
||||||
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PolygonWallet(
|
return PolygonWallet(
|
||||||
|
@ -131,6 +146,7 @@ class PolygonWallet extends EVMChainWallet {
|
||||||
privateKey: keysData.privateKey,
|
privateKey: keysData.privateKey,
|
||||||
initialBalance: balance,
|
initialBalance: balance,
|
||||||
client: PolygonClient(),
|
client: PolygonClient(),
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
@ -10,7 +11,7 @@ import 'package:cw_polygon/polygon_wallet.dart';
|
||||||
|
|
||||||
class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
PolygonWalletService(
|
PolygonWalletService(
|
||||||
super.walletInfoSource, {
|
super.walletInfoSource, super.isDirect, {
|
||||||
required this.client,
|
required this.client,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -48,6 +50,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -61,6 +64,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -77,6 +81,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
privateKey: credentials.privateKey,
|
privateKey: credentials.privateKey,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -99,6 +104,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -120,6 +126,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
client: client,
|
client: client,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -134,7 +141,11 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
|
||||||
final currentWalletInfo = walletInfoSource.values
|
final currentWalletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||||
final currentWallet = await PolygonWallet.open(
|
final currentWallet = await PolygonWallet.open(
|
||||||
password: password, name: currentName, walletInfo: currentWalletInfo);
|
password: password,
|
||||||
|
name: currentName,
|
||||||
|
walletInfo: currentWalletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
|
|
@ -5,7 +5,7 @@ buildscript {
|
||||||
ext.kotlin_version = '1.7.10'
|
ext.kotlin_version = '1.7.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -17,7 +17,7 @@ buildscript {
|
||||||
rootProject.allprojects {
|
rootProject.allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:cw_core/key.dart';
|
|
||||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
|
||||||
|
|
||||||
Future<void> write(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> writeData(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> read({required String path, required String password}) async {
|
|
||||||
final file = File(path);
|
|
||||||
|
|
||||||
if (!file.existsSync()) {
|
|
||||||
file.createSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
final encrypted = file.readAsStringSync();
|
|
||||||
|
|
||||||
return decode(password: password, data: encrypted);
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_solana/file.dart';
|
|
||||||
import 'package:cw_solana/solana_transaction_info.dart';
|
import 'package:cw_solana/solana_transaction_info.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
@ -15,12 +15,14 @@ class SolanaTransactionHistory = SolanaTransactionHistoryBase with _$SolanaTrans
|
||||||
|
|
||||||
abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase<SolanaTransactionInfo>
|
abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase<SolanaTransactionInfo>
|
||||||
with Store {
|
with Store {
|
||||||
SolanaTransactionHistoryBase({required this.walletInfo, required String password})
|
SolanaTransactionHistoryBase(
|
||||||
|
{required this.walletInfo, required String password, required this.encryptionFileUtils})
|
||||||
: _password = password {
|
: _password = password {
|
||||||
transactions = ObservableMap<String, SolanaTransactionInfo>();
|
transactions = ObservableMap<String, SolanaTransactionInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
final WalletInfo walletInfo;
|
final WalletInfo walletInfo;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
String _password;
|
String _password;
|
||||||
|
|
||||||
Future<void> init() async => await _load();
|
Future<void> init() async => await _load();
|
||||||
|
@ -32,7 +34,7 @@ abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase<Solan
|
||||||
final path = '$dirPath/$transactionsHistoryFileName';
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson()));
|
final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson()));
|
||||||
final data = json.encode({'transactions': transactionMaps});
|
final data = json.encode({'transactions': transactionMaps});
|
||||||
await writeData(path: path, password: _password, data: data);
|
await encryptionFileUtils.write(path: path, password: _password, data: data);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
print('Error while saving solana transaction history: ${e.toString()}');
|
print('Error while saving solana transaction history: ${e.toString()}');
|
||||||
print(s);
|
print(s);
|
||||||
|
@ -49,7 +51,7 @@ abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase<Solan
|
||||||
Future<Map<String, dynamic>> _read() async {
|
Future<Map<String, dynamic>> _read() async {
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
final path = '$dirPath/$transactionsHistoryFileName';
|
final path = '$dirPath/$transactionsHistoryFileName';
|
||||||
final content = await read(path: path, password: _password);
|
final content = await encryptionFileUtils.read(path: path, password: _password);
|
||||||
if (content.isEmpty) {
|
if (content.isEmpty) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:cw_core/cake_hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/node.dart';
|
import 'package:cw_core/node.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/pending_transaction.dart';
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
|
@ -15,7 +16,6 @@ import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_keys_file.dart';
|
import 'package:cw_core/wallet_keys_file.dart';
|
||||||
import 'package:cw_solana/default_spl_tokens.dart';
|
import 'package:cw_solana/default_spl_tokens.dart';
|
||||||
import 'package:cw_solana/file.dart';
|
|
||||||
import 'package:cw_solana/solana_balance.dart';
|
import 'package:cw_solana/solana_balance.dart';
|
||||||
import 'package:cw_solana/solana_client.dart';
|
import 'package:cw_solana/solana_client.dart';
|
||||||
import 'package:cw_solana/solana_exceptions.dart';
|
import 'package:cw_solana/solana_exceptions.dart';
|
||||||
|
@ -46,6 +46,7 @@ abstract class SolanaWalletBase
|
||||||
String? privateKey,
|
String? privateKey,
|
||||||
required String password,
|
required String password,
|
||||||
SolanaBalance? initialBalance,
|
SolanaBalance? initialBalance,
|
||||||
|
required this.encryptionFileUtils,
|
||||||
}) : syncStatus = const NotConnectedSyncStatus(),
|
}) : syncStatus = const NotConnectedSyncStatus(),
|
||||||
_password = password,
|
_password = password,
|
||||||
_mnemonic = mnemonic,
|
_mnemonic = mnemonic,
|
||||||
|
@ -56,7 +57,11 @@ abstract class SolanaWalletBase
|
||||||
{CryptoCurrency.sol: initialBalance ?? SolanaBalance(BigInt.zero.toDouble())}),
|
{CryptoCurrency.sol: initialBalance ?? SolanaBalance(BigInt.zero.toDouble())}),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = SolanaTransactionHistory(walletInfo: walletInfo, password: password);
|
transactionHistory = SolanaTransactionHistory(
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
password: password,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
|
);
|
||||||
|
|
||||||
if (!CakeHive.isAdapterRegistered(SPLToken.typeId)) {
|
if (!CakeHive.isAdapterRegistered(SPLToken.typeId)) {
|
||||||
CakeHive.registerAdapter(SPLTokenAdapter());
|
CakeHive.registerAdapter(SPLTokenAdapter());
|
||||||
|
@ -68,6 +73,7 @@ abstract class SolanaWalletBase
|
||||||
final String _password;
|
final String _password;
|
||||||
final String? _mnemonic;
|
final String? _mnemonic;
|
||||||
final String? _hexPrivateKey;
|
final String? _hexPrivateKey;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
|
|
||||||
// The Solana WalletPair
|
// The Solana WalletPair
|
||||||
Ed25519HDKeyPair? _walletKeyPair;
|
Ed25519HDKeyPair? _walletKeyPair;
|
||||||
|
@ -77,7 +83,7 @@ abstract class SolanaWalletBase
|
||||||
// To access the privateKey bytes.
|
// To access the privateKey bytes.
|
||||||
Ed25519HDKeyPairData? _keyPairData;
|
Ed25519HDKeyPairData? _keyPairData;
|
||||||
|
|
||||||
late SolanaWalletClient _client;
|
late final SolanaWalletClient _client;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
double? estimatedFee;
|
double? estimatedFee;
|
||||||
|
@ -97,7 +103,7 @@ abstract class SolanaWalletBase
|
||||||
@observable
|
@observable
|
||||||
late ObservableMap<CryptoCurrency, SolanaBalance> balance;
|
late ObservableMap<CryptoCurrency, SolanaBalance> balance;
|
||||||
|
|
||||||
Completer<SharedPreferences> _sharedPrefs = Completer();
|
final Completer<SharedPreferences> _sharedPrefs = Completer();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Ed25519HDKeyPairData get keys {
|
Ed25519HDKeyPairData get keys {
|
||||||
|
@ -343,13 +349,13 @@ abstract class SolanaWalletBase
|
||||||
@override
|
@override
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
||||||
await saveKeysFile(_password);
|
await saveKeysFile(_password, encryptionFileUtils);
|
||||||
saveKeysFile(_password, true);
|
saveKeysFile(_password, encryptionFileUtils, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await walletAddresses.updateAddressesInBox();
|
await walletAddresses.updateAddressesInBox();
|
||||||
final path = await makePath();
|
final path = await makePath();
|
||||||
await write(path: path, password: _password, data: toJSON());
|
await encryptionFileUtils.write(path: path, password: _password, data: toJSON());
|
||||||
await transactionHistory.save();
|
await transactionHistory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,13 +388,14 @@ abstract class SolanaWalletBase
|
||||||
required String name,
|
required String name,
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
}) async {
|
}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||||
|
|
||||||
Map<String, dynamic>? data;
|
Map<String, dynamic>? data;
|
||||||
try {
|
try {
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||||
|
|
||||||
data = json.decode(jsonSource) as Map<String, dynamic>;
|
data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -405,7 +412,12 @@ abstract class SolanaWalletBase
|
||||||
|
|
||||||
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SolanaWallet(
|
return SolanaWallet(
|
||||||
|
@ -414,6 +426,7 @@ abstract class SolanaWalletBase
|
||||||
mnemonic: keysData.mnemonic,
|
mnemonic: keysData.mnemonic,
|
||||||
privateKey: keysData.privateKey,
|
privateKey: keysData.privateKey,
|
||||||
initialBalance: balance,
|
initialBalance: balance,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,4 +585,7 @@ abstract class SolanaWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
SolanaClient? get solanaClient => _client.getSolanaClient;
|
SolanaClient? get solanaClient => _client.getSolanaClient;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'package:cw_core/wallet_credentials.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
|
||||||
class SolanaNewWalletCredentials extends WalletCredentials {
|
class SolanaNewWalletCredentials extends WalletCredentials {
|
||||||
SolanaNewWalletCredentials({required String name, WalletInfo? walletInfo})
|
SolanaNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password})
|
||||||
: super(name: name, walletInfo: walletInfo);
|
: super(name: name, walletInfo: walletInfo, password: password);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SolanaRestoreWalletFromSeedCredentials extends WalletCredentials {
|
class SolanaRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/balance.dart';
|
import 'package:cw_core/balance.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
@ -17,9 +18,10 @@ import 'package:hive/hive.dart';
|
||||||
|
|
||||||
class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
SolanaRestoreWalletFromSeedCredentials, SolanaRestoreWalletFromPrivateKey, SolanaNewWalletCredentials> {
|
SolanaRestoreWalletFromSeedCredentials, SolanaRestoreWalletFromPrivateKey, SolanaNewWalletCredentials> {
|
||||||
SolanaWalletService(this.walletInfoSource);
|
SolanaWalletService(this.walletInfoSource, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SolanaWallet> create(SolanaNewWalletCredentials credentials, {bool? isTestnet}) async {
|
Future<SolanaWallet> create(SolanaNewWalletCredentials credentials, {bool? isTestnet}) async {
|
||||||
|
@ -31,6 +33,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -56,6 +59,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -69,6 +73,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -92,6 +97,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
privateKey: credentials.privateKey,
|
privateKey: credentials.privateKey,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -112,6 +118,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -126,7 +133,11 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
final currentWalletInfo = walletInfoSource.values
|
final currentWalletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||||
final currentWallet = await SolanaWalletBase.open(
|
final currentWallet = await SolanaWalletBase.open(
|
||||||
password: password, name: currentName, walletInfo: currentWalletInfo);
|
password: password,
|
||||||
|
name: currentName,
|
||||||
|
walletInfo: currentWalletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:cw_core/key.dart';
|
|
||||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
|
||||||
|
|
||||||
Future<void> write(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> writeData(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String data}) async {
|
|
||||||
final keys = extractKeys(password);
|
|
||||||
final key = encrypt.Key.fromBase64(keys.first);
|
|
||||||
final iv = encrypt.IV.fromBase64(keys.last);
|
|
||||||
final encrypted = await encode(key: key, iv: iv, data: data);
|
|
||||||
final f = File(path);
|
|
||||||
f.writeAsStringSync(encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> read({required String path, required String password}) async {
|
|
||||||
final file = File(path);
|
|
||||||
|
|
||||||
if (!file.existsSync()) {
|
|
||||||
file.createSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
final encrypted = file.readAsStringSync();
|
|
||||||
|
|
||||||
return decode(password: password, data: encrypted);
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ import 'dart:core';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_evm/file.dart';
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_tron/tron_transaction_info.dart';
|
import 'package:cw_tron/tron_transaction_info.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
@ -14,7 +14,8 @@ class TronTransactionHistory = TronTransactionHistoryBase with _$TronTransaction
|
||||||
|
|
||||||
abstract class TronTransactionHistoryBase extends TransactionHistoryBase<TronTransactionInfo>
|
abstract class TronTransactionHistoryBase extends TransactionHistoryBase<TronTransactionInfo>
|
||||||
with Store {
|
with Store {
|
||||||
TronTransactionHistoryBase({required this.walletInfo, required String password})
|
TronTransactionHistoryBase(
|
||||||
|
{required this.walletInfo, required String password, required this.encryptionFileUtils})
|
||||||
: _password = password {
|
: _password = password {
|
||||||
transactions = ObservableMap<String, TronTransactionInfo>();
|
transactions = ObservableMap<String, TronTransactionInfo>();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,7 @@ abstract class TronTransactionHistoryBase extends TransactionHistoryBase<TronTra
|
||||||
String _password;
|
String _password;
|
||||||
|
|
||||||
final WalletInfo walletInfo;
|
final WalletInfo walletInfo;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
|
|
||||||
Future<void> init() async => await _load();
|
Future<void> init() async => await _load();
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ abstract class TronTransactionHistoryBase extends TransactionHistoryBase<TronTra
|
||||||
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
||||||
final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson()));
|
final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson()));
|
||||||
final data = json.encode({'transactions': transactionMaps});
|
final data = json.encode({'transactions': transactionMaps});
|
||||||
await writeData(path: path, password: _password, data: data);
|
await encryptionFileUtils.write(path: path, password: _password, data: data);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
log('Error while saving ${walletInfo.type.name} transaction history: ${e.toString()}');
|
log('Error while saving ${walletInfo.type.name} transaction history: ${e.toString()}');
|
||||||
log(s.toString());
|
log(s.toString());
|
||||||
|
@ -51,7 +53,7 @@ abstract class TronTransactionHistoryBase extends TransactionHistoryBase<TronTra
|
||||||
String transactionsHistoryFileNameForWallet = 'tron_transactions.json';
|
String transactionsHistoryFileNameForWallet = 'tron_transactions.json';
|
||||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||||
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
String path = '$dirPath/$transactionsHistoryFileNameForWallet';
|
||||||
final content = await read(path: path, password: _password);
|
final content = await encryptionFileUtils.read(path: path, password: _password);
|
||||||
if (content.isEmpty) {
|
if (content.isEmpty) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cw_core/cake_hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/node.dart';
|
import 'package:cw_core/node.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/pending_transaction.dart';
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
|
@ -19,7 +20,6 @@ import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_keys_file.dart';
|
import 'package:cw_core/wallet_keys_file.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:cw_tron/default_tron_tokens.dart';
|
import 'package:cw_tron/default_tron_tokens.dart';
|
||||||
import 'package:cw_tron/file.dart';
|
|
||||||
import 'package:cw_tron/tron_abi.dart';
|
import 'package:cw_tron/tron_abi.dart';
|
||||||
import 'package:cw_tron/tron_balance.dart';
|
import 'package:cw_tron/tron_balance.dart';
|
||||||
import 'package:cw_tron/tron_client.dart';
|
import 'package:cw_tron/tron_client.dart';
|
||||||
|
@ -46,6 +46,7 @@ abstract class TronWalletBase
|
||||||
String? privateKey,
|
String? privateKey,
|
||||||
required String password,
|
required String password,
|
||||||
TronBalance? initialBalance,
|
TronBalance? initialBalance,
|
||||||
|
required this.encryptionFileUtils,
|
||||||
}) : syncStatus = const NotConnectedSyncStatus(),
|
}) : syncStatus = const NotConnectedSyncStatus(),
|
||||||
_password = password,
|
_password = password,
|
||||||
_mnemonic = mnemonic,
|
_mnemonic = mnemonic,
|
||||||
|
@ -57,7 +58,8 @@ abstract class TronWalletBase
|
||||||
),
|
),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = TronTransactionHistory(walletInfo: walletInfo, password: password);
|
transactionHistory = TronTransactionHistory(
|
||||||
|
walletInfo: walletInfo, password: password, encryptionFileUtils: encryptionFileUtils);
|
||||||
|
|
||||||
if (!CakeHive.isAdapterRegistered(TronToken.typeId)) {
|
if (!CakeHive.isAdapterRegistered(TronToken.typeId)) {
|
||||||
CakeHive.registerAdapter(TronTokenAdapter());
|
CakeHive.registerAdapter(TronTokenAdapter());
|
||||||
|
@ -67,6 +69,7 @@ abstract class TronWalletBase
|
||||||
final String? _mnemonic;
|
final String? _mnemonic;
|
||||||
final String? _hexPrivateKey;
|
final String? _hexPrivateKey;
|
||||||
final String _password;
|
final String _password;
|
||||||
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
|
|
||||||
late final Box<TronToken> tronTokensBox;
|
late final Box<TronToken> tronTokensBox;
|
||||||
|
|
||||||
|
@ -125,13 +128,14 @@ abstract class TronWalletBase
|
||||||
required String name,
|
required String name,
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
|
required EncryptionFileUtils encryptionFileUtils,
|
||||||
}) async {
|
}) async {
|
||||||
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
|
||||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||||
|
|
||||||
Map<String, dynamic>? data;
|
Map<String, dynamic>? data;
|
||||||
try {
|
try {
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||||
|
|
||||||
data = json.decode(jsonSource) as Map<String, dynamic>;
|
data = json.decode(jsonSource) as Map<String, dynamic>;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -148,7 +152,12 @@ abstract class TronWalletBase
|
||||||
|
|
||||||
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(name, walletInfo.type, password);
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
|
name,
|
||||||
|
walletInfo.type,
|
||||||
|
password,
|
||||||
|
encryptionFileUtils,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TronWallet(
|
return TronWallet(
|
||||||
|
@ -157,6 +166,7 @@ abstract class TronWalletBase
|
||||||
mnemonic: keysData.mnemonic,
|
mnemonic: keysData.mnemonic,
|
||||||
privateKey: keysData.privateKey,
|
privateKey: keysData.privateKey,
|
||||||
initialBalance: balance,
|
initialBalance: balance,
|
||||||
|
encryptionFileUtils: encryptionFileUtils,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,13 +440,13 @@ abstract class TronWalletBase
|
||||||
@override
|
@override
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
if (!(await WalletKeysFile.hasKeysFile(walletInfo.name, walletInfo.type))) {
|
||||||
await saveKeysFile(_password);
|
await saveKeysFile(_password, encryptionFileUtils);
|
||||||
saveKeysFile(_password, true);
|
saveKeysFile(_password, encryptionFileUtils, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await walletAddresses.updateAddressesInBox();
|
await walletAddresses.updateAddressesInBox();
|
||||||
final path = await makePath();
|
final path = await makePath();
|
||||||
await write(path: path, password: _password, data: toJSON());
|
await encryptionFileUtils.write(path: path, password: _password, data: toJSON());
|
||||||
await transactionHistory.save();
|
await transactionHistory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,4 +594,7 @@ abstract class TronWalletBase
|
||||||
_transactionsUpdateTimer?.cancel();
|
_transactionsUpdateTimer?.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get password => _password;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'package:cw_core/wallet_credentials.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
|
||||||
class TronNewWalletCredentials extends WalletCredentials {
|
class TronNewWalletCredentials extends WalletCredentials {
|
||||||
TronNewWalletCredentials({required String name, WalletInfo? walletInfo})
|
TronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password})
|
||||||
: super(name: name, walletInfo: walletInfo);
|
: super(name: name, walletInfo: walletInfo, password: password);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TronRestoreWalletFromSeedCredentials extends WalletCredentials {
|
class TronRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:cw_core/balance.dart';
|
import 'package:cw_core/balance.dart';
|
||||||
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
|
@ -21,11 +22,12 @@ class TronWalletService extends WalletService<
|
||||||
TronRestoreWalletFromSeedCredentials,
|
TronRestoreWalletFromSeedCredentials,
|
||||||
TronRestoreWalletFromPrivateKey,
|
TronRestoreWalletFromPrivateKey,
|
||||||
TronNewWalletCredentials> {
|
TronNewWalletCredentials> {
|
||||||
TronWalletService(this.walletInfoSource, {required this.client});
|
TronWalletService(this.walletInfoSource, {required this.client, required this.isDirect});
|
||||||
|
|
||||||
late TronClient client;
|
late TronClient client;
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
|
final bool isDirect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletType getType() => WalletType.tron;
|
WalletType getType() => WalletType.tron;
|
||||||
|
@ -43,6 +45,7 @@ class TronWalletService extends WalletService<
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -62,6 +65,7 @@ class TronWalletService extends WalletService<
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -75,6 +79,7 @@ class TronWalletService extends WalletService<
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -92,6 +97,7 @@ class TronWalletService extends WalletService<
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
privateKey: credentials.privateKey,
|
privateKey: credentials.privateKey,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -114,6 +120,7 @@ class TronWalletService extends WalletService<
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
@ -128,7 +135,11 @@ class TronWalletService extends WalletService<
|
||||||
final currentWalletInfo = walletInfoSource.values
|
final currentWalletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||||
final currentWallet = await TronWalletBase.open(
|
final currentWallet = await TronWalletBase.open(
|
||||||
password: password, name: currentName, walletInfo: currentWalletInfo);
|
password: password,
|
||||||
|
name: currentName,
|
||||||
|
walletInfo: currentWalletInfo,
|
||||||
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
|
);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
await saveBackup(newName);
|
await saveBackup(newName);
|
||||||
|
|
|
@ -41,7 +41,7 @@ String getSeed() {
|
||||||
if (polyseed != "") {
|
if (polyseed != "") {
|
||||||
return polyseed;
|
return polyseed;
|
||||||
}
|
}
|
||||||
final legacy = wownero.Wallet_seed(wptr!, seedOffset: '');
|
final legacy = getSeedLegacy(null);
|
||||||
return legacy;
|
return legacy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,9 @@ String getSeedLegacy(String? language) {
|
||||||
wownero.Wallet_setSeedLanguage(wptr!, language: language ?? "English");
|
wownero.Wallet_setSeedLanguage(wptr!, language: language ?? "English");
|
||||||
legacy = wownero.Wallet_seed(wptr!, seedOffset: '');
|
legacy = wownero.Wallet_seed(wptr!, seedOffset: '');
|
||||||
}
|
}
|
||||||
|
if (wownero.Wallet_status(wptr!) != 0) {
|
||||||
|
return wownero.Wallet_errorString(wptr!);
|
||||||
|
}
|
||||||
return legacy;
|
return legacy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,16 @@ void restoreWalletFromKeysSync(
|
||||||
int nettype = 0,
|
int nettype = 0,
|
||||||
int restoreHeight = 0}) {
|
int restoreHeight = 0}) {
|
||||||
txhistory = null;
|
txhistory = null;
|
||||||
final newWptr = wownero.WalletManager_createWalletFromKeys(
|
final newWptr = spendKey != ""
|
||||||
|
? wownero.WalletManager_createDeterministicWalletFromSpendKey(
|
||||||
|
wmPtr,
|
||||||
|
path: path,
|
||||||
|
password: password,
|
||||||
|
language: language,
|
||||||
|
spendKeyString: spendKey,
|
||||||
|
newWallet: true, // TODO(mrcyjanek): safe to remove
|
||||||
|
restoreHeight: restoreHeight)
|
||||||
|
: wownero.WalletManager_createWalletFromKeys(
|
||||||
wmPtr,
|
wmPtr,
|
||||||
path: path,
|
path: path,
|
||||||
password: password,
|
password: password,
|
||||||
|
|
|
@ -50,7 +50,7 @@ abstract class WowneroWalletBase
|
||||||
extends WalletBase<WowneroBalance, WowneroTransactionHistory, WowneroTransactionInfo>
|
extends WalletBase<WowneroBalance, WowneroTransactionHistory, WowneroTransactionInfo>
|
||||||
with Store {
|
with Store {
|
||||||
WowneroWalletBase(
|
WowneroWalletBase(
|
||||||
{required WalletInfo walletInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo})
|
{required WalletInfo walletInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo, required String password})
|
||||||
: balance = ObservableMap<CryptoCurrency, WowneroBalance>.of({
|
: balance = ObservableMap<CryptoCurrency, WowneroBalance>.of({
|
||||||
CryptoCurrency.wow: WowneroBalance(
|
CryptoCurrency.wow: WowneroBalance(
|
||||||
fullBalance: wownero_wallet.getFullBalance(accountIndex: 0),
|
fullBalance: wownero_wallet.getFullBalance(accountIndex: 0),
|
||||||
|
@ -58,6 +58,7 @@ abstract class WowneroWalletBase
|
||||||
}),
|
}),
|
||||||
_isTransactionUpdating = false,
|
_isTransactionUpdating = false,
|
||||||
_hasSyncAfterStartup = false,
|
_hasSyncAfterStartup = false,
|
||||||
|
_password = password,
|
||||||
isEnabledAutoGenerateSubaddress = false,
|
isEnabledAutoGenerateSubaddress = false,
|
||||||
syncStatus = NotConnectedSyncStatus(),
|
syncStatus = NotConnectedSyncStatus(),
|
||||||
unspentCoins = [],
|
unspentCoins = [],
|
||||||
|
@ -109,6 +110,10 @@ abstract class WowneroWalletBase
|
||||||
|
|
||||||
String seedLegacy(String? language) => wownero_wallet.getSeedLegacy(language);
|
String seedLegacy(String? language) => wownero_wallet.getSeedLegacy(language);
|
||||||
|
|
||||||
|
String get password => _password;
|
||||||
|
|
||||||
|
String _password;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MoneroWalletKeys get keys => MoneroWalletKeys(
|
MoneroWalletKeys get keys => MoneroWalletKeys(
|
||||||
privateSpendKey: wownero_wallet.getSecretSpendKey(),
|
privateSpendKey: wownero_wallet.getSecretSpendKey(),
|
||||||
|
|
|
@ -93,7 +93,7 @@ class WowneroWalletService extends WalletService<
|
||||||
await wownero_wallet_manager.createWallet(
|
await wownero_wallet_manager.createWallet(
|
||||||
path: path, password: credentials.password!, language: credentials.language);
|
path: path, password: credentials.password!, language: credentials.language);
|
||||||
final wallet = WowneroWallet(
|
final wallet = WowneroWallet(
|
||||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -129,7 +129,7 @@ class WowneroWalletService extends WalletService<
|
||||||
await wownero_wallet_manager.openWalletAsync({'path': path, 'password': password});
|
await wownero_wallet_manager.openWalletAsync({'path': path, 'password': password});
|
||||||
final walletInfo = walletInfoSource.values
|
final walletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
||||||
wallet = WowneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
wallet = WowneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, password: password);
|
||||||
final isValid = wallet.walletAddresses.validate();
|
final isValid = wallet.walletAddresses.validate();
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
|
@ -210,7 +210,7 @@ class WowneroWalletService extends WalletService<
|
||||||
final currentWalletInfo = walletInfoSource.values
|
final currentWalletInfo = walletInfoSource.values
|
||||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||||
final currentWallet =
|
final currentWallet =
|
||||||
WowneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
WowneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource, password: password);
|
||||||
|
|
||||||
await currentWallet.renameWalletFiles(newName);
|
await currentWallet.renameWalletFiles(newName);
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ class WowneroWalletService extends WalletService<
|
||||||
viewKey: credentials.viewKey,
|
viewKey: credentials.viewKey,
|
||||||
spendKey: credentials.spendKey);
|
spendKey: credentials.spendKey);
|
||||||
final wallet = WowneroWallet(
|
final wallet = WowneroWallet(
|
||||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -268,7 +268,7 @@ class WowneroWalletService extends WalletService<
|
||||||
seed: credentials.mnemonic,
|
seed: credentials.mnemonic,
|
||||||
restoreHeight: credentials.height!);
|
restoreHeight: credentials.height!);
|
||||||
final wallet = WowneroWallet(
|
final wallet = WowneroWallet(
|
||||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -315,7 +315,7 @@ class WowneroWalletService extends WalletService<
|
||||||
restoreHeight: height,
|
restoreHeight: height,
|
||||||
spendKey: spendKey);
|
spendKey: spendKey);
|
||||||
|
|
||||||
final wallet = WowneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
final wallet = WowneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, password: password);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
|
|
@ -113,6 +113,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.4.3"
|
version: "8.4.3"
|
||||||
|
cake_backup:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: main
|
||||||
|
resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38"
|
||||||
|
url: "https://github.com/cake-tech/cake_backup.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0+1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -169,6 +178,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.2"
|
||||||
|
cryptography:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cryptography
|
||||||
|
sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.0"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.8"
|
||||||
cw_core:
|
cw_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -680,6 +705,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -36,7 +36,6 @@ target 'Runner' do
|
||||||
|
|
||||||
# Cake Wallet (Legacy)
|
# Cake Wallet (Legacy)
|
||||||
pod 'CryptoSwift'
|
pod 'CryptoSwift'
|
||||||
pod 'UnstoppableDomainsResolution', '~> 4.0.0'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
|
|
|
@ -8,6 +8,36 @@ PODS:
|
||||||
- Flutter
|
- Flutter
|
||||||
- ReachabilitySwift
|
- ReachabilitySwift
|
||||||
- CryptoSwift (1.8.2)
|
- CryptoSwift (1.8.2)
|
||||||
|
- cw_haven (0.0.1):
|
||||||
|
- cw_haven/Boost (= 0.0.1)
|
||||||
|
- cw_haven/Haven (= 0.0.1)
|
||||||
|
- cw_haven/OpenSSL (= 0.0.1)
|
||||||
|
- cw_haven/Sodium (= 0.0.1)
|
||||||
|
- cw_shared_external
|
||||||
|
- Flutter
|
||||||
|
- cw_haven/Boost (0.0.1):
|
||||||
|
- cw_shared_external
|
||||||
|
- Flutter
|
||||||
|
- cw_haven/Haven (0.0.1):
|
||||||
|
- cw_shared_external
|
||||||
|
- Flutter
|
||||||
|
- cw_haven/OpenSSL (0.0.1):
|
||||||
|
- cw_shared_external
|
||||||
|
- Flutter
|
||||||
|
- cw_haven/Sodium (0.0.1):
|
||||||
|
- cw_shared_external
|
||||||
|
- Flutter
|
||||||
|
- cw_shared_external (0.0.1):
|
||||||
|
- cw_shared_external/Boost (= 0.0.1)
|
||||||
|
- cw_shared_external/OpenSSL (= 0.0.1)
|
||||||
|
- cw_shared_external/Sodium (= 0.0.1)
|
||||||
|
- Flutter
|
||||||
|
- cw_shared_external/Boost (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- cw_shared_external/OpenSSL (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- cw_shared_external/Sodium (0.0.1):
|
||||||
|
- Flutter
|
||||||
- device_display_brightness (0.0.1):
|
- device_display_brightness (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
|
@ -115,6 +145,8 @@ DEPENDENCIES:
|
||||||
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
|
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- CryptoSwift
|
- CryptoSwift
|
||||||
|
- cw_haven (from `.symlinks/plugins/cw_haven/ios`)
|
||||||
|
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
|
||||||
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||||
|
@ -162,6 +194,10 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/barcode_scan2/ios"
|
:path: ".symlinks/plugins/barcode_scan2/ios"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
|
cw_haven:
|
||||||
|
:path: ".symlinks/plugins/cw_haven/ios"
|
||||||
|
cw_shared_external:
|
||||||
|
:path: ".symlinks/plugins/cw_shared_external/ios"
|
||||||
device_display_brightness:
|
device_display_brightness:
|
||||||
:path: ".symlinks/plugins/device_display_brightness/ios"
|
:path: ".symlinks/plugins/device_display_brightness/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
|
@ -216,6 +252,8 @@ SPEC CHECKSUMS:
|
||||||
BigInt: f668a80089607f521586bbe29513d708491ef2f7
|
BigInt: f668a80089607f521586bbe29513d708491ef2f7
|
||||||
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
|
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
|
||||||
CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea
|
CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea
|
||||||
|
cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
|
||||||
|
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
|
||||||
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
|
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
|
||||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||||
devicelocale: b22617f40038496deffba44747101255cee005b0
|
devicelocale: b22617f40038496deffba44747101255cee005b0
|
||||||
|
|
|
@ -483,7 +483,7 @@
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.0.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.fotolockr.cakewallet";
|
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
@ -629,7 +629,7 @@
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.0.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.fotolockr.cakewallet";
|
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
@ -667,7 +667,7 @@
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.0.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.fotolockr.cakewallet";
|
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Flutter
|
import Flutter
|
||||||
import UnstoppableDomainsResolution
|
|
||||||
import workmanager
|
import workmanager
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
lazy var resolution : Resolution? = {
|
|
||||||
return try? Resolution()
|
|
||||||
}()
|
|
||||||
|
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
|
@ -87,27 +82,7 @@ import workmanager
|
||||||
}
|
}
|
||||||
|
|
||||||
result(secRandom(count: count))
|
result(secRandom(count: count))
|
||||||
case "getUnstoppableDomainAddress":
|
|
||||||
guard let args = call.arguments as? Dictionary<String, String>,
|
|
||||||
let domain = args["domain"],
|
|
||||||
let ticker = args["ticker"],
|
|
||||||
let resolution = self?.resolution else {
|
|
||||||
result(nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resolution.addr(domain: domain, ticker: ticker) { addrResult in
|
|
||||||
var address : String = ""
|
|
||||||
|
|
||||||
switch addrResult {
|
|
||||||
case .success(let returnValue):
|
|
||||||
address = returnValue
|
|
||||||
case .failure(let error):
|
|
||||||
print("Expected Address, but got \(error)")
|
|
||||||
}
|
|
||||||
|
|
||||||
result(address)
|
|
||||||
}
|
|
||||||
case "setIsAppSecure":
|
case "setIsAppSecure":
|
||||||
guard let args = call.arguments as? Dictionary<String, Bool>,
|
guard let args = call.arguments as? Dictionary<String, Bool>,
|
||||||
let isAppSecure = args["isAppSecure"] else {
|
let isAppSecure = args["isAppSecure"] else {
|
||||||
|
|