Merge branch 'main' into ui-enhancements

This commit is contained in:
tuxsudo 2025-01-22 23:20:21 -05:00 committed by GitHub
commit ce0d7da97a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
101 changed files with 1452 additions and 653 deletions
.github/workflows
assets/images
build-guide-linux.mdbuild-guide-win.md
cw_core/lib
cw_monero/lib
integration_test
integration_test_runner.sh
lib
linux
model_generator.shpubspec_base.yaml
res/values
scripts

View file

@ -1,84 +0,0 @@
name: Cache Dependencies
on:
workflow_dispatch:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-20.04
steps:
- name: Free Disk Space (Ubuntu)
uses: insightsengineering/disk-space-reclaimer@v1
with:
tools-cache: true
android: false
dotnet: true
haskell: true
large-packages: true
swap-storage: true
docker-images: true
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: "temurin"
java-version: "17"
- 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.24.4"
channel: stable
- name: Install package dependencies
run: 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
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 main
cd cake_wallet/scripts/android/
./install_ndk.sh
source ./app_env.sh cakewallet
chmod +x pubspec_gen.sh
./app_config.sh
- 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: ${{ 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/android/
source ./app_env.sh cakewallet
./build_monero_all.sh
- name: Cache Keystore
id: cache-keystore
uses: actions/cache@v3
with:
path: /opt/android/cake_wallet/android/app
key: keystore
- if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
name: Generate KeyStore
run: |
cd /opt/android/cake_wallet/android/app
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS

View file

@ -1,169 +1,93 @@
name: PR Test Build name: Cake Wallet Android
on: on: [push]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
branch:
description: "Branch name to build"
required: true
default: "main"
defaults:
run:
shell: bash
jobs: jobs:
PR_test_build: PR_test_build:
runs-on: ubuntu-20.04 runs-on: linux-amd64
container:
image: ghcr.io/cake-tech/cake_wallet:main-linux
env:
STORE_PASS: test@cake_wallet
KEY_PASS: test@cake_wallet
MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
ANDROID_AVD_HOME: /root/.android/avd
volumes:
- /opt/cw_cache_android/root/.cache:/root/.cache
- /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
- /opt/cw_cache_android/root/.ccache:/root/.ccache
- /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
- /opt/cw_cache_android/root/.gradle/:/root/.gradle
- /opt/cw_cache_android/root/.android/:/root/.android
- /opt/cw_cache_android/root/go/pkg:/root/go/pkg
- /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
- /dev/kvm:/dev/kvm
strategy: strategy:
matrix: matrix:
api-level: [29] api-level: [29]
env:
STORE_PASS: test@cake_wallet
KEY_PASS: test@cake_wallet
PR_NUMBER: ${{ github.event.number }}
steps: steps:
- name: is pr - name: Fix github actions messing up $HOME...
if: github.event_name == 'pull_request' run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV'
run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV - uses: actions/checkout@v4
- name: configure git
- name: is not pr
if: github.event_name != 'pull_request'
run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENV
- name: Free Disk Space (Ubuntu)
uses: insightsengineering/disk-space-reclaimer@v1
with:
tools-cache: true
android: false
dotnet: true
haskell: true
large-packages: true
swap-storage: true
docker-images: true
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: "temurin"
java-version: "17"
- name: Configure placeholder git details
run: | run: |
git config --global user.email "CI@cakewallet.com" git config --global user.email "ci@cakewallet.com"
git config --global user.name "Cake Github Actions" git config --global user.name "CakeWallet CI"
- name: Flutter action
uses: subosito/flutter-action@v1
with:
flutter-version: "3.24.0"
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 libtool libtinfo5 cmake clang
- name: Clone Repo
run: |
sudo mkdir -p /opt/android
sudo chown $USER /opt/android
cd /opt/android
git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }}
# - name: Cache Keystore
# id: cache-keystore
# uses: actions/cache@v3
# with:
# path: /opt/android/cake_wallet/android/app
# key: keystore
#
# - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
- name: Generate KeyStore
run: |
cd /opt/android/cake_wallet/android/app
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS
- name: Execute Build and Setup Commands
run: |
cd /opt/android
-y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install cargo-ndk
cd cake_wallet/scripts/android/
./install_ndk.sh
source ./app_env.sh cakewallet
chmod +x pubspec_gen.sh
./app_config.sh
- 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: ${{ 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/android/
source ./app_env.sh cakewallet
./build_monero_all.sh
- name: Install Flutter dependencies
run: |
cd /opt/android/cake_wallet
flutter pub get
- name: Install go and gomobile
run: |
# install go > 1.23:
wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:~/go/bin
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
- name: Build mwebd
run: |
# paths are reset after each step, so we need to set them again:
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:~/go/bin
cd /opt/android/cake_wallet/scripts/android/
./build_mwebd.sh --dont-install
- name: Generate key properties
run: |
cd /opt/android/cake_wallet
dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS
- name: Generate localization
run: |
cd /opt/android/cake_wallet
dart run tool/generate_localization.dart
- name: Build generated code
run: |
cd /opt/android/cake_wallet
./model_generator.sh
- name: Add secrets - name: Add secrets
run: | run: |
cd /opt/android/cake_wallet
touch lib/.secrets.g.dart touch lib/.secrets.g.dart
touch cw_evm/lib/.secrets.g.dart touch cw_evm/lib/.secrets.g.dart
touch cw_solana/lib/.secrets.g.dart touch cw_solana/lib/.secrets.g.dart
touch cw_core/lib/.secrets.g.dart touch cw_core/lib/.secrets.g.dart
touch cw_nano/lib/.secrets.g.dart touch cw_nano/lib/.secrets.g.dart
touch cw_tron/lib/.secrets.g.dart touch cw_tron/lib/.secrets.g.dart
echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart if [[ "x${{ secrets.SALT }}" == "x" ]];
echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart then
echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart echo "const salt = '954f787f12622067f7e548d9450c3832';" > lib/.secrets.g.dart
echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart else
echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart fi
echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart if [[ "x${{ secrets.KEY_CHAIN_SALT }}" == "x" ]];
then
echo "const keychainSalt = '2d2beba777dbf7dff7013b7a';" >> lib/.secrets.g.dart
else
echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.KEY }}" == "x" ]];
then
echo "const key = '638e98820ec10a2945e968435c9397a3';" >> lib/.secrets.g.dart
else
echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.WALLET_SALT }}" == "x" ]];
then
echo "const walletSalt = '8f7f1b70';" >> lib/.secrets.g.dart
else
echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.SHORT_KEY }}" == "x" ]];
then
echo "const shortKey = '653f270c2c152bc7ec864afe';" >> lib/.secrets.g.dart
else
echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.BACKUP_SALT }}" == "x" ]];
then
echo "const backupSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
else
echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.BACKUP_KEY_CHAIN_SALT }}" == "x" ]];
then
echo "const backupKeychainSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
else
echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
fi
echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> 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 changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
@ -213,86 +137,153 @@ jobs:
echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart
# for tests
echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const litecoinTestWalletSeeds = '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const bitcoinCashTestWalletSeeds = '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const nanoTestWalletSeeds = '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const bitcoinTestWalletReceiveAddress = '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const ethereumTestWalletReceiveAddress = '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const litecoinTestWalletReceiveAddress = '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const polygonTestWalletReceiveAddress = '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const solanaTestWalletReceiveAddress = '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const tronTestWalletReceiveAddress = '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const moneroTestWalletBlockHeight = '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart
- name: prepare monero_c and cache
run: |
export MONEROC_HASH=$(cat scripts/prepare_moneroc.sh | grep 'git checkout' | xargs | awk '{ print $3 }')
echo MONEROC_HASH=$MONEROC_HASH >> /etc/environment
mkdir -p "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
pushd scripts
ln -s "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
./prepare_moneroc.sh
popd
pushd scripts/monero_c
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" || true
rm -rf "$PWD/contrib/depends/built" "$PWD/monero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
rm -rf "$PWD/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
mkdir -p contrib/depends || true
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" "$PWD/contrib/depends/built"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" "$PWD/monero/contrib/depends/built"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" "$PWD/contrib/depends/sources"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" "$PWD/monero/contrib/depends/sources"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
popd
- name: Generate KeyStore
run: |
pushd /opt/generic_cache
if [[ ! -f key.jks ]];
then
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS
else
echo "$PWD/key.jks exist, not generating"
fi
popd
cp /opt/generic_cache/key.jks android/app
- name: Execute Build and Setup Commands
run: |
pushd scripts/android
source ./app_env.sh cakewallet
./app_config.sh
popd
- name: Build monero_c
run: |
pushd scripts/android/
source ./app_env.sh cakewallet
./build_monero_all.sh
popd
- name: Install Flutter dependencies
run: |
flutter pub get
- name: Build mwebd
run: |
set -x -e
export MWEBD_HASH=$(cat scripts/android/build_mwebd.sh | grep 'git reset --hard' | xargs | awk '{ print $4 }')
echo MWEBD_HASH=$MWEBD_HASH >> /etc/environment
pushd scripts/android
gomobile init;
./build_mwebd.sh --dont-install
popd
- name: Build generated code
run: |
./model_generator.sh async
- name: Generate key properties
run: |
dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS
- name: Generate localization
run: |
dart run tool/generate_localization.dart
- name: Rename app - name: Rename app
run: | run: |
echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties sanitized_branch_name=${BRANCH_NAME#origin/} # Remove 'origin/' prefix if it exists
sanitized_branch_name=${sanitized_branch_name:0:16} # Take only the first 16 characters
sanitized_branch_name=$(echo "$sanitized_branch_name" | tr '[:upper:]' '[:lower:]') # Convert to lowercase
sanitized_branch_name=$(echo "$sanitized_branch_name" | sed 's/[^a-z0-9]//g') # Remove all special characters
# Step 3: Download previous build number echo -e "id=com.cakewallet.test_${sanitized_branch_name}\nname=${BRANCH_NAME}" > android/app.properties
- name: Download previous build number
id: download-build-number
run: |
# Download the artifact if it exists
if [[ ! -f build_number.txt ]]; then
echo "1" > build_number.txt
fi
# Step 4: Read and Increment Build Number
- name: Increment Build Number
id: increment-build-number
run: |
# Read current build number from file
BUILD_NUMBER=$(cat build_number.txt)
BUILD_NUMBER=$((BUILD_NUMBER + 1))
echo "New build number: $BUILD_NUMBER"
# Save the incremented build number
echo "$BUILD_NUMBER" > build_number.txt
# Export the build number to use in later steps
echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
# Step 5: Update pubspec.yaml with new build number
- name: Update build number
run: |
cd /opt/android/cake_wallet
sed -i "s/^version: .*/version: 1.0.$BUILD_NUMBER/" pubspec.yaml
- name: Build - name: Build
run: | run: |
cd /opt/android/cake_wallet
flutter build apk --release --split-per-abi flutter build apk --release --split-per-abi
# - name: Push to App Center
# run: |
# echo 'Installing App Center CLI tools'
# npm install -g appcenter-cli
# echo "Publishing test to App Center"
# appcenter distribute release \
# --group "Testers" \
# --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \
# --release-notes ${{ env.BRANCH_NAME }} \
# --app Cake-Labs/Cake-Wallet \
# --token ${{ secrets.APP_CENTER_TOKEN }} \
# --quiet
- name: Rename apk file - name: Rename apk file
run: | run: |
cd /opt/android/cake_wallet/build/app/outputs/flutter-apk cd build/app/outputs/flutter-apk
mkdir test-apk mkdir test-apk
cp app-arm64-v8a-release.apk test-apk/${{env.BRANCH_NAME}}.apk cp app-arm64-v8a-release.apk test-apk/${BRANCH_NAME}.apk
cp app-x86_64-release.apk test-apk/${{env.BRANCH_NAME}}_x86.apk cp app-x86_64-release.apk test-apk/${BRANCH_NAME}_x86.apk
cd test-apk
cp ${BRANCH_NAME}.apk ${BRANCH_NAME}_slack.apk
- name: Upload Artifact - name: Find APK file
uses: kittaakos/upload-artifact-as-is@v0 id: find_apk
with: run: |
path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/ set -x
apk_file=$(ls build/app/outputs/flutter-apk/test-apk/*_slack.apk || exit 1)
# Re-upload updated build number for the next run echo "APK_FILE=$apk_file" >> $GITHUB_ENV
- name: Upload updated build number
uses: actions/upload-artifact@v3 - name: Upload artifact to slack
with: if: ${{ !contains(github.event.head_commit.message, 'skip slack') }}
name: build_number
path: build_number.txt
- name: Send Test APK
continue-on-error: true continue-on-error: true
uses: adrey/slack-file-upload-action@1.0.5 uses: adrey/slack-file-upload-action@1.0.5
with: with:
token: ${{ secrets.SLACK_APP_TOKEN }} token: ${{ secrets.SLACK_APP_TOKEN }}
path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk path: ${{ env.APK_FILE }}
channel: ${{ secrets.SLACK_APK_CHANNEL }} channel: ${{ secrets.SLACK_APK_CHANNEL }}
title: "${{ env.BRANCH_NAME }}.apk"
filename: ${{ env.BRANCH_NAME }}.apk
initial_comment: ${{ github.event.head_commit.message }} initial_comment: ${{ github.event.head_commit.message }}
- name: cleanup
run: rm -rf build/app/outputs/flutter-apk/test-apk/
- name: Upload Artifact to github
uses: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/build/app/outputs/flutter-apk
name: "android apk"

View file

@ -1,139 +1,89 @@
name: PR Test Build linux name: Cake Wallet Linux
on: on: [push]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
branch:
description: "Branch name to build"
required: true
default: "main"
defaults:
run:
shell: bash
jobs: jobs:
PR_test_build: PR_test_build:
runs-on: ubuntu-20.04 runs-on: linux-amd64
env: container:
STORE_PASS: test@cake_wallet image: ghcr.io/cake-tech/cake_wallet:main-linux
KEY_PASS: test@cake_wallet env:
PR_NUMBER: ${{ github.event.number }} STORE_PASS: test@cake_wallet
KEY_PASS: test@cake_wallet
MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
DESKTOP_FORCE_MOBILE: Y
volumes:
- /opt/cw_cache_linux/root/.cache:/root/.cache
- /opt/cw_cache_linux/root/.ccache:/root/.ccache
- /opt/cw_cache_linux/root/.pub-cache/:/root/.pub-cache
- /opt/cw_cache_linux/root/go/pkg:/root/go/pkg
- /opt/cw_cache_linux/opt/generic_cache:/opt/generic_cache
strategy:
matrix:
api-level: [29]
steps: steps:
- name: is pr - name: Fix github actions messing up $HOME...
if: github.event_name == 'pull_request' run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV'
run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV - uses: actions/checkout@v4
- name: configure git
- 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: | run: |
git config --global user.email "CI@cakewallet.com" git config --global user.email "ci@cakewallet.com"
git config --global user.name "Cake Github Actions" git config --global user.name "CakeWallet CI"
- name: Flutter action
uses: subosito/flutter-action@v1
with:
flutter-version: "3.24.0"
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: Install go and gomobile
run: |
# install go > 1.23:
wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:~/go/bin
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
- name: Build mwebd
run: |
# paths are reset after each step, so we need to set them again:
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:~/go/bin
# build mwebd:
cd /opt/android/cake_wallet/scripts/android/
./build_mwebd.sh --dont-install
- name: Generate localization
run: |
cd /opt/android/cake_wallet
dart run tool/generate_localization.dart
- name: Build generated code
run: |
cd /opt/android/cake_wallet
./model_generator.sh
- name: Add secrets - name: Add secrets
run: | run: |
cd /opt/android/cake_wallet
touch lib/.secrets.g.dart touch lib/.secrets.g.dart
touch cw_evm/lib/.secrets.g.dart touch cw_evm/lib/.secrets.g.dart
touch cw_solana/lib/.secrets.g.dart touch cw_solana/lib/.secrets.g.dart
touch cw_core/lib/.secrets.g.dart touch cw_core/lib/.secrets.g.dart
touch cw_nano/lib/.secrets.g.dart touch cw_nano/lib/.secrets.g.dart
touch cw_tron/lib/.secrets.g.dart touch cw_tron/lib/.secrets.g.dart
echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart if [[ "x${{ secrets.SALT }}" == "x" ]];
echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart then
echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart echo "const salt = '954f787f12622067f7e548d9450c3832';" > lib/.secrets.g.dart
echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart else
echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart fi
echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart if [[ "x${{ secrets.KEY_CHAIN_SALT }}" == "x" ]];
then
echo "const keychainSalt = '2d2beba777dbf7dff7013b7a';" >> lib/.secrets.g.dart
else
echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.KEY }}" == "x" ]];
then
echo "const key = '638e98820ec10a2945e968435c9397a3';" >> lib/.secrets.g.dart
else
echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.WALLET_SALT }}" == "x" ]];
then
echo "const walletSalt = '8f7f1b70';" >> lib/.secrets.g.dart
else
echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.SHORT_KEY }}" == "x" ]];
then
echo "const shortKey = '653f270c2c152bc7ec864afe';" >> lib/.secrets.g.dart
else
echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.BACKUP_SALT }}" == "x" ]];
then
echo "const backupSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
else
echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
fi
if [[ "x${{ secrets.BACKUP_KEY_CHAIN_SALT }}" == "x" ]];
then
echo "const backupKeychainSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
else
echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
fi
echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> 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 changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
@ -144,8 +94,6 @@ jobs:
echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> 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 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 simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> 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 anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart
echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart
@ -156,8 +104,11 @@ jobs:
echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> lib/.secrets.g.dart echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> lib/.secrets.g.dart
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/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 moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> 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 exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
@ -165,7 +116,6 @@ jobs:
echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> 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 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 polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart
echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart
echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
@ -178,39 +128,172 @@ jobs:
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/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 echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart
echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dart
echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart
echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart
# tests
- name: Rename app echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const litecoinTestWalletSeeds = '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const bitcoinCashTestWalletSeeds = '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const nanoTestWalletSeeds = '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const bitcoinTestWalletReceiveAddress = '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const ethereumTestWalletReceiveAddress = '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const litecoinTestWalletReceiveAddress = '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const polygonTestWalletReceiveAddress = '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const solanaTestWalletReceiveAddress = '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const tronTestWalletReceiveAddress = '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
echo "const moneroTestWalletBlockHeight = '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart
- name: prepare monero_c and cache
run: | run: |
echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties export MONEROC_HASH=$(cat scripts/prepare_moneroc.sh | grep 'git checkout' | xargs | awk '{ print $3 }')
echo MONEROC_HASH=$MONEROC_HASH >> /etc/environment
mkdir -p "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
pushd scripts
ln -s "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
./prepare_moneroc.sh
popd
pushd scripts/monero_c
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" || true
mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" || true
- name: Build rm -rf "$PWD/contrib/depends/built" "$PWD/monero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
rm -rf "$PWD/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
mkdir -p contrib/depends || true
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" "$PWD/contrib/depends/built"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" "$PWD/monero/contrib/depends/built"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" "$PWD/contrib/depends/sources"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" "$PWD/monero/contrib/depends/sources"
ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
popd
- name: Execute Build and Setup Commands
run: |
pushd scripts/linux
source ./app_env.sh cakewallet
./app_config.sh
popd
- name: Build monero_c
run: |
pushd scripts/linux/
source ./app_env.sh cakewallet
./build_monero_all.sh
popd
- name: Install Flutter dependencies
run: |
flutter pub get
- name: Build generated code
run: |
./model_generator.sh async
- name: Generate localization
run: |
dart run tool/generate_localization.dart
- name: Build linux
run: | run: |
cd /opt/android/cake_wallet
flutter build linux --release flutter build linux --release
- name: Prepare release zip file - name: Compress release
run: | run: |
cd /opt/android/cake_wallet/build/linux/x64/release pushd build/linux/x64/release
zip -r ${{env.BRANCH_NAME}}.zip bundle zip -r cakewallet_linux.zip bundle
popd
- name: Upload Artifact - name: Upload Artifact to github
uses: kittaakos/upload-artifact-as-is@v0 uses: actions/upload-artifact@v4
with: with:
path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip path: ${{ github.workspace }}/build/linux/x64/release/cakewallet_linux.zip
name: cakewallet_linux
# Just as an artifact would be enough - name: Prepare virtual desktop
# - name: Send Test APK if: ${{ contains(github.event.head_commit.message, 'run tests') }}
# continue-on-error: true run: |
# uses: adrey/slack-file-upload-action@1.0.5 nohup Xvfb :99 -screen 0 720x1280x16 &
# with: echo DISPLAY=:99 | sudo tee -a $GITHUB_ENV
# token: ${{ secrets.SLACK_APP_TOKEN }} dbus-daemon --system --fork
# path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip nohup NetworkManager &
# channel: ${{ secrets.SLACK_APK_CHANNEL }} nohup ffmpeg -framerate 60 -video_size 720x1280 -f x11grab -i :99 -c:v libx264 -c:a aac /opt/screen_grab.mkv &
# title: "${{ env.BRANCH_NAME }}_linux.zip"
# filename: ${{ env.BRANCH_NAME }}_linux.zip # Note for people adding tests:
# initial_comment: ${{ github.event.head_commit.message }} # - Tests are ran on Linux, with some things being mocked out.
# - Screen recording is being provided for the entire length of the test, you can download it in github articats.
# - Screen recordeding is encrypted, look at step "Stop screen recording, encrypt and upload", and add your key if you want
# Reason for encryption is the fact that we restore the wallet from seed, and we don't want to leak that, while there
# isn't much in those wallets anyway, we still wouldn't like to leak it to anyone who is able to access github.
- name: Test [confirm_seeds_flow_test]
if: ${{ contains(github.event.head_commit.message, 'run tests') }}
timeout-minutes: 20
run: |
xmessage -timeout 30 "confirm_seeds_flow_test" &
rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/confirm_seeds_flow_test.dart
- name: Test [create_wallet_flow_test]
if: ${{ contains(github.event.head_commit.message, 'run tests') }}
timeout-minutes: 20
run: |
xmessage -timeout 30 "create_wallet_flow_test" &
rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/create_wallet_flow_test.dart
- name: Test [exchange_flow_test]
if: ${{ contains(github.event.head_commit.message, 'run tests') }}
timeout-minutes: 20
run: |
xmessage -timeout 30 "exchange_flow_test" &
rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/exchange_flow_test.dart
- name: Test [restore_wallet_through_seeds_flow_test]
if: ${{ contains(github.event.head_commit.message, 'run tests') }}
timeout-minutes: 20
run: |
xmessage -timeout 30 "restore_wallet_through_seeds_flow_test" &
rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
- name: Stop screen recording, encrypt and upload
if: always()
run: |
if [[ ! -f "/opt/screen_grab.mkv" ]];
then
exit 0;
fi
killall ffmpeg
sleep 5
killall -9 ffmpeg || true
sleep 5
# Feel free to add your own public key if you wish
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 6B3199AD9B3D23B8 # konstantin@cakewallet.com
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 35C8DBAFB8D9ACAC # cyjan@mrcyjanek.net
gpg --trust-model always --encrypt --output /opt/screen_grab.mkv.gpg \
--recipient 6B3199AD9B3D23B8 \
--recipient 35C8DBAFB8D9ACAC \
/opt/screen_grab.mkv
rm /opt/screen_grab.mkv
mv /opt/screen_grab.mkv.gpg ./screen_grab.mkv.gpg
- name: Upload Artifact to github
if: always()
continue-on-error: true
uses: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/screen_grab.mkv.gpg
name: tests_screen_grab

View file

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_adaptive_back"/> <background android:drawable="@mipmap/ic_launcher_adaptive_back"/>
<foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/> <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/>
<monochrome android:drawable="@mipmap/ic_launcher_adaptive_mono"/>
</adaptive-icon> </adaptive-icon>

Binary file not shown.

After

(image error) Size: 2.3 KiB

Binary file not shown.

After

(image error) Size: 1.5 KiB

Binary file not shown.

After

(image error) Size: 3.2 KiB

Binary file not shown.

After

(image error) Size: 5.1 KiB

Binary file not shown.

After

(image error) Size: 7.5 KiB

View file

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_adaptive_back"/> <background android:drawable="@mipmap/ic_launcher_adaptive_back"/>
<foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/> <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/>
<monochrome android:drawable="@mipmap/ic_launcher_adaptive_mono"/>
</adaptive-icon> </adaptive-icon>

Binary file not shown.

After

(image error) Size: 2.3 KiB

Binary file not shown.

After

(image error) Size: 1.5 KiB

Binary file not shown.

After

(image error) Size: 3 KiB

Binary file not shown.

After

(image error) Size: 4.8 KiB

Binary file not shown.

After

(image error) Size: 6.8 KiB

View file

@ -115,7 +115,7 @@ Install Flutter package dependencies with this command:
> `$ ./cakewallet.sh` > `$ ./cakewallet.sh`
> and back to project root directory: > and back to project root directory:
> `$ cd ../..` > `$ cd ../..`
> and fetch dependecies again > and fetch dependencies again
> `$ flutter pub get` > `$ 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: 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:

View file

@ -16,14 +16,14 @@ These steps will help you configure and execute a build of CakeWallet from its s
### 1. Installing Package Dependencies ### 1. Installing Package Dependencies
For build CakeWallet windows application from sources you will be needed to have: For build CakeWallet windows application from sources you will be needed to have:
> [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windwos`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`. > [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windows`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`.
> [Install WSL] for building monero dependencies need to install Windows WSL (https://learn.microsoft.com/en-us/windows/wsl/install) and required packages for WSL (Ubuntu): > [Install WSL] for building monero dependencies need to install Windows WSL (https://learn.microsoft.com/en-us/windows/wsl/install) and required packages for WSL (Ubuntu):
`$ sudo apt update ` `$ sudo apt update `
`$ sudo apt build-essential cmake gcc-mingw-w64 g++-mingw-w64 autoconf libtool pkg-config` `$ sudo apt build-essential cmake gcc-mingw-w64 g++-mingw-w64 autoconf libtool pkg-config`
### 2. Pull CakeWallet source code ### 2. Pull CakeWallet source code
You can downlaod CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command: You can download CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command:
`$ git clone https://github.com/cake-tech/cake_wallet.git --branch MrCyjaneK-cyjan-monerodart` `$ git clone https://github.com/cake-tech/cake_wallet.git --branch MrCyjaneK-cyjan-monerodart`
OR you can download it as [Zip archive](https://github.com/cake-tech/cake_wallet/archive/refs/heads/MrCyjaneK-cyjan-monerodart.zip) OR you can download it as [Zip archive](https://github.com/cake-tech/cake_wallet/archive/refs/heads/MrCyjaneK-cyjan-monerodart.zip)

View file

@ -1,13 +1,18 @@
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'package:cw_core/keyable.dart'; import 'package:cw_core/keyable.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/hive_type_ids.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:http/io_client.dart' as ioc; import 'package:http/io_client.dart' as ioc;
import 'dart:math' as math;
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart' as crypto;
// import 'package:tor/tor.dart'; import 'package:crypto/crypto.dart';
part 'node.g.dart'; part 'node.g.dart';
@ -170,34 +175,43 @@ class Node extends HiveObject with Keyable {
} }
Future<bool> requestMoneroNode() async { Future<bool> requestMoneroNode() async {
if (uri.toString().contains(".onion") || useSocksProxy) { if (useSocksProxy) {
return await requestNodeWithProxy(); return await requestNodeWithProxy();
} }
final path = '/json_rpc'; final path = '/json_rpc';
final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path);
final realm = 'monero-rpc';
final body = {'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'}; final body = {'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'};
try { try {
final authenticatingClient = HttpClient(); final authenticatingClient = HttpClient();
authenticatingClient.badCertificateCallback = authenticatingClient.badCertificateCallback =
((X509Certificate cert, String host, int port) => true); ((X509Certificate cert, String host, int port) => true);
authenticatingClient.addCredentials(
rpcUri,
realm,
HttpClientDigestCredentials(login ?? '', password ?? ''),
);
final http.Client client = ioc.IOClient(authenticatingClient); final http.Client client = ioc.IOClient(authenticatingClient);
final jsonBody = json.encode(body);
final response = await client.post( final response = await client.post(
rpcUri, rpcUri,
headers: {'Content-Type': 'application/json'}, headers: {'Content-Type': 'application/json'},
body: json.encode(body), body: jsonBody,
); );
client.close(); // Check if we received a 401 Unauthorized response
if (response.statusCode == 401) {
final daemonRpc = DaemonRpc(
rpcUri.toString(),
username: login??'',
password: password??'',
);
final response = await daemonRpc.call('get_info', {});
return !(response['offline'] as bool);
}
printV("node check response: ${response.body}");
if ((response.body.contains("400 Bad Request") // Some other generic error if ((response.body.contains("400 Bad Request") // Some other generic error
|| ||
@ -225,7 +239,8 @@ class Node extends HiveObject with Keyable {
final resBody = json.decode(response.body) as Map<String, dynamic>; final resBody = json.decode(response.body) as Map<String, dynamic>;
return !(resBody['result']['offline'] as bool); return !(resBody['result']['offline'] as bool);
} catch (_) { } catch (e) {
printV("error: $e");
return false; return false;
} }
} }
@ -316,3 +331,150 @@ class Node extends HiveObject with Keyable {
} }
} }
} }
/// https://github.com/ManyMath/digest_auth/
/// HTTP Digest authentication.
///
/// Adapted from https://github.com/dart-lang/http/issues/605#issue-963962341.
///
/// Created because http_auth was not working for Monero daemon RPC responses.
class DigestAuth {
final String username;
final String password;
String? realm;
String? nonce;
String? uri;
String? qop = "auth";
int _nonceCount = 0;
DigestAuth(this.username, this.password);
/// Initialize Digest parameters from the `WWW-Authenticate` header.
void initFromAuthorizationHeader(String authInfo) {
final Map<String, String>? values = _splitAuthenticateHeader(authInfo);
if (values != null) {
realm = values['realm'];
// Check if the nonce has changed.
if (nonce != values['nonce']) {
nonce = values['nonce'];
_nonceCount = 0; // Reset nonce count when nonce changes.
}
}
}
/// Generate the Digest Authorization header.
String getAuthString(String method, String uri) {
this.uri = uri;
_nonceCount++;
String cnonce = _computeCnonce();
String nc = _formatNonceCount(_nonceCount);
String ha1 = md5Hash("$username:$realm:$password");
String ha2 = md5Hash("$method:$uri");
String response = md5Hash("$ha1:$nonce:$nc:$cnonce:$qop:$ha2");
return 'Digest username="$username", realm="$realm", nonce="$nonce", uri="$uri", qop=$qop, nc=$nc, cnonce="$cnonce", response="$response"';
}
/// Helper to parse the `WWW-Authenticate` header.
Map<String, String>? _splitAuthenticateHeader(String? header) {
if (header == null || !header.startsWith('Digest ')) {
return null;
}
String token = header.substring(7); // Remove 'Digest '.
final Map<String, String> result = {};
final components = token.split(',').map((token) => token.trim());
for (final component in components) {
final kv = component.split('=');
final key = kv[0];
final value = kv.sublist(1).join('=').replaceAll('"', '');
result[key] = value;
}
return result;
}
/// Helper to compute a random cnonce.
String _computeCnonce() {
final math.Random rnd = math.Random();
final List<int> values = List<int>.generate(16, (i) => rnd.nextInt(256));
return hex.encode(values);
}
/// Helper to format the nonce count.
String _formatNonceCount(int count) =>
count.toRadixString(16).padLeft(8, '0');
/// Compute the MD5 hash of a string.
String md5Hash(String input) {
return md5.convert(utf8.encode(input)).toString();
}
}
class DaemonRpc {
final String rpcUrl;
final String username;
final String password;
DaemonRpc(this.rpcUrl, {required this.username, required this.password});
/// Perform a JSON-RPC call with Digest Authentication.
Future<Map<String, dynamic>> call(
String method, Map<String, dynamic> params) async {
final http.Client client = http.Client();
final DigestAuth digestAuth = DigestAuth(username, password);
// Initial request to get the `WWW-Authenticate` header.
final initialResponse = await client.post(
Uri.parse(rpcUrl),
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
'jsonrpc': '2.0',
'id': '0',
'method': method,
'params': params,
}),
);
if (initialResponse.statusCode != 401 ||
!initialResponse.headers.containsKey('www-authenticate')) {
throw Exception('Unexpected response: ${initialResponse.body}');
}
// Extract Digest details from `WWW-Authenticate` header.
final String authInfo = initialResponse.headers['www-authenticate']!;
digestAuth.initFromAuthorizationHeader(authInfo);
// Create Authorization header for the second request.
String uri = Uri.parse(rpcUrl).path;
String authHeader = digestAuth.getAuthString('POST', uri);
// Make the authenticated request.
final authenticatedResponse = await client.post(
Uri.parse(rpcUrl),
headers: {
'Content-Type': 'application/json',
'Authorization': authHeader,
},
body: jsonEncode({
'jsonrpc': '2.0',
'id': '0',
'method': method,
'params': params,
}),
);
if (authenticatedResponse.statusCode != 200) {
throw Exception('RPC call failed: ${authenticatedResponse.body}');
}
final Map<String, dynamic> result = jsonDecode(authenticatedResponse.body) as Map<String, dynamic>;
if (result['error'] != null) {
throw Exception('RPC Error: ${result['error']}');
}
return result['result'] as Map<String, dynamic>;
}
}

View file

@ -9,6 +9,8 @@ import 'package:flutter/foundation.dart';
import 'package:monero/monero.dart' as monero; import 'package:monero/monero.dart' as monero;
import 'package:mutex/mutex.dart'; import 'package:mutex/mutex.dart';
bool debugMonero = false;
int getSyncingHeight() { int getSyncingHeight() {
// final height = monero.MONERO_cw_WalletListener_height(getWlptr()); // final height = monero.MONERO_cw_WalletListener_height(getWlptr());
final h2 = monero.Wallet_blockChainHeight(wptr!); final h2 = monero.Wallet_blockChainHeight(wptr!);
@ -132,7 +134,7 @@ Future<bool> setupNodeSync(
} }
} }
if (kDebugMode) { if (kDebugMode && debugMonero) {
monero.Wallet_init3( monero.Wallet_init3(
wptr!, argv0: '', wptr!, argv0: '',
defaultLogBaseName: 'moneroc', defaultLogBaseName: 'moneroc',

View file

@ -1,9 +1,7 @@
import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/parseBoolFromString.dart';
import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/format_amount.dart'; import 'package:cw_core/format_amount.dart';
import 'package:cw_monero/api/transaction_history.dart';
class MoneroTransactionInfo extends TransactionInfo { class MoneroTransactionInfo extends TransactionInfo {
MoneroTransactionInfo(this.txHash, this.height, this.direction, this.date, MoneroTransactionInfo(this.txHash, this.height, this.direction, this.date,
@ -11,29 +9,6 @@ class MoneroTransactionInfo extends TransactionInfo {
this.confirmations) : this.confirmations) :
id = "${txHash}_${amount}_${accountIndex}_${addressIndex}"; id = "${txHash}_${amount}_${accountIndex}_${addressIndex}";
MoneroTransactionInfo.fromMap(Map<String, Object?> map)
: id = "${map['hash']}_${map['amount']}_${map['accountIndex']}_${map['addressIndex']}",
txHash = map['hash'] as String,
height = (map['height'] ?? 0) as int,
direction = map['direction'] != null
? parseTransactionDirectionFromNumber(map['direction'] as String)
: TransactionDirection.incoming,
date = DateTime.fromMillisecondsSinceEpoch(
(int.tryParse(map['timestamp'] as String? ?? '') ?? 0) * 1000),
isPending = parseBoolFromString(map['isPending'] as String),
amount = map['amount'] as int,
accountIndex = int.parse(map['accountIndex'] as String),
addressIndex = map['addressIndex'] as int,
confirmations = map['confirmations'] as int,
key = getTxKey((map['hash'] ?? '') as String),
fee = map['fee'] as int? ?? 0 {
additionalInfo = <String, dynamic>{
'key': key,
'accountIndex': accountIndex,
'addressIndex': addressIndex
};
}
final String id; final String id;
final String txHash; final String txHash;
final int height; final int height;

View file

@ -265,6 +265,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
} }
bool needExportOutputs(int amount) { bool needExportOutputs(int amount) {
if (int.tryParse(monero.Wallet_secretSpendKey(wptr!)) != 0) {
return false;
}
// viewOnlyBalance - balance that we can spend // viewOnlyBalance - balance that we can spend
// TODO(mrcyjanek): remove hasUnknownKeyImages when we cleanup coin control // TODO(mrcyjanek): remove hasUnknownKeyImages when we cleanup coin control
return (monero.Wallet_viewOnlyBalance(wptr!, return (monero.Wallet_viewOnlyBalance(wptr!,

View file

@ -32,6 +32,11 @@ class CommonTestCases {
expect(textWidget, hasWidget ? findsOneWidget : findsNothing); expect(textWidget, hasWidget ? findsOneWidget : findsNothing);
} }
void hasTextAtLestOnce(String text, {bool hasWidget = true}) {
final textWidget = find.text(text);
expect(textWidget, hasWidget ? findsAny : findsNothing);
}
void hasType<T>() { void hasType<T>() {
final typeWidget = find.byType(T); final typeWidget = find.byType(T);
expect(typeWidget, findsOneWidget); expect(typeWidget, findsOneWidget);

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/reactions/bip39_wallet_utils.dart'; import 'package:cake_wallet/reactions/bip39_wallet_utils.dart';
import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cake_wallet/wallet_types.g.dart';
@ -85,6 +87,7 @@ class CommonTestFlows {
await _confirmPreSeedInfo(); await _confirmPreSeedInfo();
await _confirmWalletDetails(); await _confirmWalletDetails();
await _commonTestCases.defaultSleepTime();
} }
//* ========== Handles flow from welcome to restoring wallet from seeds =============== //* ========== Handles flow from welcome to restoring wallet from seeds ===============
@ -168,8 +171,8 @@ class CommonTestFlows {
await _walletListPageRobot.navigateToRestoreWalletOptionsPage(); await _walletListPageRobot.navigateToRestoreWalletOptionsPage();
await _commonTestCases.defaultSleepTime(); await _commonTestCases.defaultSleepTime();
await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); if (!Platform.isLinux) await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
await _commonTestCases.defaultSleepTime(); if (!Platform.isLinux) await _commonTestCases.defaultSleepTime();
await _selectWalletTypeForWallet(walletType); await _selectWalletTypeForWallet(walletType);
await _commonTestCases.defaultSleepTime(); await _commonTestCases.defaultSleepTime();
@ -180,6 +183,7 @@ class CommonTestFlows {
//* ========== Handles setting up pin code for wallet on first install =============== //* ========== Handles setting up pin code for wallet on first install ===============
Future<void> setupPinCodeForWallet(List<int> pin) async { Future<void> setupPinCodeForWallet(List<int> pin) async {
if (Platform.isLinux) return;
// ----------- SetupPinCode Page ------------- // ----------- SetupPinCode Page -------------
// Confirm initial defaults - Widgets to be displayed etc // Confirm initial defaults - Widgets to be displayed etc
await _setupPinCodeRobot.isSetupPinCodePage(); await _setupPinCodeRobot.isSetupPinCodePage();
@ -212,7 +216,7 @@ class CommonTestFlows {
await _welcomePageRobot.navigateToRestoreWalletPage(); await _welcomePageRobot.navigateToRestoreWalletPage();
await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); if (!Platform.isLinux) await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
await _selectWalletTypeForWallet(walletTypeToRestore); await _selectWalletTypeForWallet(walletTypeToRestore);
} }
@ -234,6 +238,12 @@ class CommonTestFlows {
await _newWalletPageRobot.generateWalletName(); await _newWalletPageRobot.generateWalletName();
if (Platform.isLinux) {
// manual pin input
await _restoreFromSeedOrKeysPageRobot.enterPasswordForWalletRestore(CommonTestConstants.pin.join(""));
await _restoreFromSeedOrKeysPageRobot.enterPasswordRepeatForWalletRestore(CommonTestConstants.pin.join(""));
}
await _newWalletPageRobot.onNextButtonPressed(); await _newWalletPageRobot.onNextButtonPressed();
} }
@ -252,11 +262,15 @@ class CommonTestFlows {
_walletSeedPageRobot.confirmWalletSeedReminderDisplays(); _walletSeedPageRobot.confirmWalletSeedReminderDisplays();
await _walletSeedPageRobot.onCopySeedsButtonPressed(); // await _walletSeedPageRobot.onCopySeedsButtonPressed();
await _walletSeedPageRobot.onNextButtonPressed(); await _walletSeedPageRobot.onSeedPageVerifyButtonPressed();
// Turns out the popup about "Copied to clipboard" prevents
await _walletSeedPageRobot.onConfirmButtonOnSeedAlertDialogPressed(); //the button from being pressed on the first try, by just
//tapping it again we fix it.
// await _walletSeedPageRobot.onSeedPageVerifyButtonPressed();
await _walletSeedPageRobot.onOpenWalletButtonPressed();
} }
//* Main Restore Actions - On the RestoreFromSeed/Keys Page - Restore from Seeds Action //* Main Restore Actions - On the RestoreFromSeed/Keys Page - Restore from Seeds Action
@ -277,6 +291,12 @@ class CommonTestFlows {
.enterBlockHeightForWalletRestore(secrets.moneroTestWalletBlockHeight); .enterBlockHeightForWalletRestore(secrets.moneroTestWalletBlockHeight);
} }
if (Platform.isLinux) {
// manual pin input
await _restoreFromSeedOrKeysPageRobot.enterPasswordForWalletRestore(CommonTestConstants.pin.join(""));
await _restoreFromSeedOrKeysPageRobot.enterPasswordRepeatForWalletRestore(CommonTestConstants.pin.join(""));
}
await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed(); await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
} }

View file

@ -67,6 +67,11 @@ void main() {
await authPageRobot.enterPinCode(CommonTestConstants.pin); await authPageRobot.enterPinCode(CommonTestConstants.pin);
} }
final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
if (onAuthPageDesktop) {
await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
}
// ----------- Exchange Confirm Page ------------- // ----------- Exchange Confirm Page -------------
await exchangeConfirmPageRobot.isExchangeConfirmPage(); await exchangeConfirmPageRobot.isExchangeConfirmPage();

View file

@ -20,6 +20,11 @@ class AuthPageRobot extends PinCodeWidgetRobot {
return hasPin; return hasPin;
} }
bool onAuthPageDesktop() {
final hasWalletPasswordInput = find.byKey(ValueKey('enter_wallet_password'));
return hasWalletPasswordInput.tryEvaluate();
}
Future<void> isAuthPage() async { Future<void> isAuthPage() async {
await commonTestCases.isSpecificPage<AuthPage>(); await commonTestCases.isSpecificPage<AuthPage>();
} }

View file

@ -24,6 +24,20 @@ class PinCodeWidgetRobot {
commonTestCases.hasValueKey('pin_code_button_0_key'); commonTestCases.hasValueKey('pin_code_button_0_key');
} }
Future<void> enterPassword(String password, {int pumpDuration = 100}) async {
await commonTestCases.enterText(
password,
'enter_wallet_password',
);
await tester.pumpAndSettle();
await commonTestCases.tapItemByKey(
'unlock',
);
await tester.pumpAndSettle();
await commonTestCases.defaultSleepTime();
}
Future<void> enterPinCode(List<int> pinCode, {int pumpDuration = 100}) async { Future<void> enterPinCode(List<int> pinCode, {int pumpDuration = 100}) async {
for (int pin in pinCode) { for (int pin in pinCode) {
await commonTestCases.tapItemByKey( await commonTestCases.tapItemByKey(

View file

@ -1,7 +1,9 @@
import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
import 'package:cake_wallet/src/widgets/seed_widget.dart';
import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart'; import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../components/common_test_cases.dart'; import '../components/common_test_cases.dart';
@ -65,12 +67,28 @@ class RestoreFromSeedOrKeysPageRobot {
Future<void> enterSeedPhraseForWalletRestore(String text) async { Future<void> enterSeedPhraseForWalletRestore(String text) async {
ValidatableAnnotatedEditableTextState seedTextState = ValidatableAnnotatedEditableTextState seedTextState =
await tester.state(find.byType(ValidatableAnnotatedEditableText)); await tester.state(find.byType(ValidatableAnnotatedEditableText));
seedTextState.widget.controller.text = text; seedTextState.widget.controller.text = text;
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} }
Future<void> enterPasswordForWalletRestore(String text) async {
await commonTestCases.enterText(
text,
'password',
);
await tester.pumpAndSettle();
}
Future<void> enterPasswordRepeatForWalletRestore(String text) async {
await commonTestCases.enterText(
text,
'repeat_wallet_password',
);
await tester.pumpAndSettle();
}
Future<void> enterBlockHeightForWalletRestore(String blockHeight) async { Future<void> enterBlockHeightForWalletRestore(String blockHeight) async {
await commonTestCases.enterText( await commonTestCases.enterText(
blockHeight, blockHeight,

View file

@ -183,32 +183,15 @@ class SendPageRobot {
} }
Future<void> _handleAuthPage() async { Future<void> _handleAuthPage() async {
tester.printToConsole('Inside _handleAuth'); final onAuthPage = authPageRobot.onAuthPage();
await tester.pump(); if (onAuthPage) {
tester.printToConsole('starting auth checks'); await authPageRobot.enterPinCode(CommonTestConstants.pin);
}
final authPage = authPageRobot.onAuthPage();
final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
tester.printToConsole('hasAuth:$authPage'); if (onAuthPageDesktop) {
await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
if (authPage) {
await tester.pump();
tester.printToConsole('Starting inner _handleAuth loop checks');
try {
await authPageRobot.enterPinCode(CommonTestConstants.pin, pumpDuration: 500);
tester.printToConsole('Auth done');
await tester.pump();
tester.printToConsole('Auth pump done');
} catch (e) {
tester.printToConsole('Auth failed, retrying');
await tester.pump();
_handleAuthPage();
}
} }
await tester.pump();
} }
Future<void> handleSendResult() async { Future<void> handleSendResult() async {
@ -221,7 +204,7 @@ class SendPageRobot {
tester.printToConsole('Has an Error in the handle: $hasError'); tester.printToConsole('Has an Error in the handle: $hasError');
int maxRetries = 20; int maxRetries = 3;
int retries = 0; int retries = 0;
while (hasError && retries < maxRetries) { while (hasError && retries < maxRetries) {

View file

@ -14,8 +14,13 @@ class WalletSeedPageRobot {
await commonTestCases.isSpecificPage<WalletSeedPage>(); await commonTestCases.isSpecificPage<WalletSeedPage>();
} }
Future<void> onNextButtonPressed() async { Future<void> onSeedPageVerifyButtonPressed() async {
await commonTestCases.tapItemByKey('wallet_seed_page_next_button_key'); await commonTestCases.tapItemByKey('wallet_seed_page_verify_seed_button_key');
await commonTestCases.defaultSleepTime();
}
Future<void> onOpenWalletButtonPressed() async {
await commonTestCases.tapItemByKey('wallet_seed_page_open_wallet_button_key');
await commonTestCases.defaultSleepTime(); await commonTestCases.defaultSleepTime();
} }
@ -38,11 +43,14 @@ class WalletSeedPageRobot {
final walletSeeds = walletSeedViewModel.seed; final walletSeeds = walletSeedViewModel.seed;
commonTestCases.hasText(walletName); commonTestCases.hasText(walletName);
commonTestCases.hasText(walletSeeds); final seedList = walletSeeds.trim().split(" ");
for (final seedWord in seedList) {
commonTestCases.hasTextAtLestOnce(seedWord);
}
} }
void confirmWalletSeedReminderDisplays() { void confirmWalletSeedReminderDisplays() {
commonTestCases.hasText(S.current.seed_reminder); commonTestCases.hasText(S.current.cake_seeds_save_disclaimer);
} }
Future<void> onSaveSeedsButtonPressed() async { Future<void> onSaveSeedsButtonPressed() async {

View file

@ -1,9 +1,13 @@
import 'dart:io';
import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cake_wallet/wallet_types.g.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
import '../components/common_test_cases.dart';
import '../components/common_test_constants.dart'; import '../components/common_test_constants.dart';
import '../components/common_test_flows.dart'; import '../components/common_test_flows.dart';
import '../robots/auth_page_robot.dart'; import '../robots/auth_page_robot.dart';
@ -95,6 +99,10 @@ Future<void> _confirmSeedsFlowForWalletType(
await authPageRobot.enterPinCode(CommonTestConstants.pin); await authPageRobot.enterPinCode(CommonTestConstants.pin);
} }
final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
if (onAuthPageDesktop) {
await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
}
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await walletKeysAndSeedPageRobot.isWalletKeysAndSeedPage(); await walletKeysAndSeedPageRobot.isWalletKeysAndSeedPage();

View file

@ -56,6 +56,10 @@ void main() {
await authPageRobot.enterPinCode(CommonTestConstants.pin); await authPageRobot.enterPinCode(CommonTestConstants.pin);
} }
final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
if (onAuthPageDesktop) {
await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
}
await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed(); await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed();
await exchangeTradePageRobot.onGotItButtonPressed(); await exchangeTradePageRobot.onGotItButtonPressed();
}); });

View file

@ -1,4 +1,7 @@
import 'dart:io';
import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cake_wallet/wallet_types.g.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';

View file

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
export DESKTOP_FORCE_MOBILE="Y"
declare -a targets declare -a targets
declare -a passed_tests declare -a passed_tests
@ -12,6 +13,10 @@ done < <(find integration_test/test_suites -name "*.dart" -type f -print0)
# Run each test and collect results # Run each test and collect results
for target in "${targets[@]}" for target in "${targets[@]}"
do do
if [[ "x$REMOVE_DATA_DIRECTORY" == "xY" ]];
then
rm -rf ~/.local/share/com.example.cake_wallet ~/Documents/cake_wallet
fi
echo "Running test: $target" echo "Running test: $target"
if flutter drive \ if flutter drive \
--driver=test_driver/integration_test.dart \ --driver=test_driver/integration_test.dart \

View file

@ -293,6 +293,7 @@ class BackupService {
final lookupsUnstoppableDomains = data[PreferencesKey.lookupsUnstoppableDomains] as bool?; final lookupsUnstoppableDomains = data[PreferencesKey.lookupsUnstoppableDomains] as bool?;
final lookupsOpenAlias = data[PreferencesKey.lookupsOpenAlias] as bool?; final lookupsOpenAlias = data[PreferencesKey.lookupsOpenAlias] as bool?;
final lookupsENS = data[PreferencesKey.lookupsENS] as bool?; final lookupsENS = data[PreferencesKey.lookupsENS] as bool?;
final lookupsWellKnown = data[PreferencesKey.lookupsWellKnown] as bool?;
final syncAll = data[PreferencesKey.syncAllKey] as bool?; final syncAll = data[PreferencesKey.syncAllKey] as bool?;
final syncMode = data[PreferencesKey.syncModeKey] as int?; final syncMode = data[PreferencesKey.syncModeKey] as int?;
final autoGenerateSubaddressStatus = final autoGenerateSubaddressStatus =
@ -403,6 +404,9 @@ class BackupService {
if (lookupsENS != null) await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS); if (lookupsENS != null) await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS);
if (lookupsWellKnown != null)
await _sharedPreferences.setBool(PreferencesKey.lookupsWellKnown, lookupsWellKnown);
if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
if (syncMode != null) await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode); if (syncMode != null) await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode);
@ -542,6 +546,8 @@ class BackupService {
_sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains), _sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains),
PreferencesKey.lookupsOpenAlias: _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias), PreferencesKey.lookupsOpenAlias: _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias),
PreferencesKey.lookupsENS: _sharedPreferences.getBool(PreferencesKey.lookupsENS), PreferencesKey.lookupsENS: _sharedPreferences.getBool(PreferencesKey.lookupsENS),
PreferencesKey.lookupsWellKnown:
_sharedPreferences.getBool(PreferencesKey.lookupsWellKnown),
PreferencesKey.syncModeKey: _sharedPreferences.getInt(PreferencesKey.syncModeKey), PreferencesKey.syncModeKey: _sharedPreferences.getInt(PreferencesKey.syncModeKey),
PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey), PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey),
PreferencesKey.autoGenerateSubaddressStatusKey: PreferencesKey.autoGenerateSubaddressStatusKey:

View file

@ -334,20 +334,20 @@ Future<void> defaultSettingsMigration(
); );
break; break;
case 46: case 46:
_fixNodesUseSSLFlag(nodes); await _fixNodesUseSSLFlag(nodes);
updateWalletTypeNodesWithNewNode( await updateWalletTypeNodesWithNewNode(
newNodeUri: 'litecoin.stackwallet.com:20063', newNodeUri: 'litecoin.stackwallet.com:20063',
nodes: nodes, nodes: nodes,
type: WalletType.litecoin, type: WalletType.litecoin,
useSSL: true, useSSL: true,
); );
updateWalletTypeNodesWithNewNode( await updateWalletTypeNodesWithNewNode(
newNodeUri: 'electrum-ltc.bysh.me:50002', newNodeUri: 'electrum-ltc.bysh.me:50002',
nodes: nodes, nodes: nodes,
type: WalletType.litecoin, type: WalletType.litecoin,
useSSL: true, useSSL: true,
); );
_changeDefaultNode( await _changeDefaultNode(
nodes: nodes, nodes: nodes,
sharedPreferences: sharedPreferences, sharedPreferences: sharedPreferences,
type: WalletType.solana, type: WalletType.solana,
@ -360,13 +360,13 @@ Future<void> defaultSettingsMigration(
'solana-rpc.publicnode.com:443', 'solana-rpc.publicnode.com:443',
], ],
); );
_updateNode( await _updateNode(
nodes: nodes, nodes: nodes,
currentUri: "ethereum.publicnode.com", currentUri: "ethereum.publicnode.com",
newUri: "ethereum-rpc.publicnode.com", newUri: "ethereum-rpc.publicnode.com",
useSSL: true, useSSL: true,
); );
_updateNode( await _updateNode(
nodes: nodes, nodes: nodes,
currentUri: "polygon-bor.publicnode.com", currentUri: "polygon-bor.publicnode.com",
newUri: "polygon-bor-rpc.publicnode.com", newUri: "polygon-bor-rpc.publicnode.com",
@ -387,12 +387,12 @@ Future<void> defaultSettingsMigration(
await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
} }
void _updateNode({ Future<void> _updateNode({
required Box<Node> nodes, required Box<Node> nodes,
required String currentUri, required String currentUri,
String? newUri, String? newUri,
bool? useSSL, bool? useSSL,
}) { }) async {
for (Node node in nodes.values) { for (Node node in nodes.values) {
if (node.uriRaw == currentUri) { if (node.uriRaw == currentUri) {
if (newUri != null) { if (newUri != null) {
@ -401,6 +401,7 @@ void _updateNode({
if (useSSL != null) { if (useSSL != null) {
node.useSSL = useSSL; node.useSSL = useSSL;
} }
await node.save();
} }
} }
} }
@ -481,7 +482,7 @@ void _deselectExchangeProvider(SharedPreferences sharedPreferences, String provi
); );
} }
void _fixNodesUseSSLFlag(Box<Node> nodes) { Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async {
for (Node node in nodes.values) { for (Node node in nodes.values) {
switch (node.uriRaw) { switch (node.uriRaw) {
case cakeWalletLitecoinElectrumUri: case cakeWalletLitecoinElectrumUri:
@ -490,6 +491,7 @@ void _fixNodesUseSSLFlag(Box<Node> nodes) {
case newCakeWalletMoneroUri: case newCakeWalletMoneroUri:
node.useSSL = true; node.useSSL = true;
node.trusted = true; node.trusted = true;
await node.save();
} }
} }
} }

View file

@ -5,6 +5,7 @@ import 'package:cake_wallet/entities/openalias_record.dart';
import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/parsed_address.dart';
import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
import 'package:cake_wallet/entities/emoji_string_extension.dart'; import 'package:cake_wallet/entities/emoji_string_extension.dart';
import 'package:cake_wallet/entities/wellknown_record.dart';
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
import 'package:cake_wallet/mastodon/mastodon_api.dart'; import 'package:cake_wallet/mastodon/mastodon_api.dart';
import 'package:cake_wallet/nostr/nostr_api.dart'; import 'package:cake_wallet/nostr/nostr_api.dart';
@ -208,6 +209,17 @@ class AddressResolver {
} }
} }
// .well-known scheme:
if (text.contains('.') && text.contains('@')) {
if (settingsStore.lookupsWellKnown) {
final record =
await WellKnownRecord.fetchAddressAndName(formattedName: text, currency: currency);
if (record != null) {
return ParsedAddress.fetchWellKnownAddress(address: record.address, name: text);
}
}
}
if (!text.startsWith('@') && text.contains('@') && !text.contains('.')) { if (!text.startsWith('@') && text.contains('@') && !text.contains('.')) {
final bool isFioRegistered = await FioAddressProvider.checkAvail(text); final bool isFioRegistered = await FioAddressProvider.checkAvail(text);
if (isFioRegistered) { if (isFioRegistered) {

View file

@ -12,7 +12,8 @@ enum ParseFrom {
contact, contact,
mastodon, mastodon,
nostr, nostr,
thorChain thorChain,
wellKnown
} }
class ParsedAddress { class ParsedAddress {
@ -142,6 +143,14 @@ class ParsedAddress {
); );
} }
factory ParsedAddress.fetchWellKnownAddress({required String address, required String name}) {
return ParsedAddress(
addresses: [address],
name: name,
parseFrom: ParseFrom.wellKnown,
);
}
final List<String> addresses; final List<String> addresses;
final String name; final String name;
final String description; final String description;

View file

@ -76,6 +76,7 @@ class PreferencesKey {
static const lookupsUnstoppableDomains = 'looks_up_unstoppable_domain'; static const lookupsUnstoppableDomains = 'looks_up_unstoppable_domain';
static const lookupsOpenAlias = 'looks_up_open_alias'; static const lookupsOpenAlias = 'looks_up_open_alias';
static const lookupsENS = 'looks_up_ens'; static const lookupsENS = 'looks_up_ens';
static const lookupsWellKnown = 'looks_up_well_known';
static const showCameraConsent = 'show_camera_consent'; static const showCameraConsent = 'show_camera_consent';
static String moneroWalletUpdateV1Key(String name) => static String moneroWalletUpdateV1Key(String name) =>

View file

@ -0,0 +1,92 @@
import 'dart:convert';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:http/http.dart' as http;
class WellKnownRecord {
WellKnownRecord({
required this.address,
required this.name,
});
final String name;
final String address;
static Future<String?> checkWellKnownUsername(String username, CryptoCurrency currency) async {
String jsonLocation = "";
switch (currency) {
case CryptoCurrency.nano:
jsonLocation = "nano-currency";
break;
// TODO: add other currencies
default:
return null;
}
// split the string by the @ symbol:
try {
final List<String> splitStrs = username.split("@");
String name = splitStrs.first.toLowerCase();
final String domain = splitStrs.last;
if (splitStrs.length == 3) {
// for username like @alice@domain.org instead of alice@domain.org
name = splitStrs[1];
}
if (name.isEmpty) {
name = "_";
}
// lookup domain/.well-known/nano-currency.json and check if it has a nano address:
final http.Response response = await http.get(
Uri.parse("https://$domain/.well-known/$jsonLocation.json?names=$name"),
headers: <String, String>{"Accept": "application/json"},
);
if (response.statusCode != 200) {
return null;
}
final Map<String, dynamic> decoded = json.decode(response.body) as Map<String, dynamic>;
// Access the first element in the names array and retrieve its address
final List<dynamic> names = decoded["names"] as List<dynamic>;
for (final dynamic item in names) {
if (item["name"].toLowerCase() == name) {
return item["address"] as String;
}
}
} catch (e) {
printV("error checking well-known username: $e");
}
return null;
}
static String formatDomainName(String name) {
String formattedName = name;
if (name.contains("@")) {
formattedName = name.replaceAll("@", ".");
}
return formattedName;
}
static Future<WellKnownRecord?> fetchAddressAndName({
required String formattedName,
required CryptoCurrency currency,
}) async {
String name = formattedName;
printV("formattedName: $formattedName");
final address = await checkWellKnownUsername(formattedName, currency);
if (address == null) {
return null;
}
return WellKnownRecord(address: address, name: name);
}
}

View file

@ -50,6 +50,7 @@ import 'package:cake_wallet/src/screens/new_wallet/advanced_privacy_settings_pag
import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart'; import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart';
import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart';
import 'package:cake_wallet/src/screens/new_wallet/wallet_group_description_page.dart'; import 'package:cake_wallet/src/screens/new_wallet/wallet_group_description_page.dart';
import 'package:cake_wallet/src/screens/new_wallet/wallet_group_existing_seed_description_page.dart';
import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart';
import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart'; import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart';
import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; import 'package:cake_wallet/src/screens/order_details/order_details_page.dart';
@ -587,6 +588,11 @@ Route<dynamic> createRoute(RouteSettings settings) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (_) => getIt.get<PreSeedPage>(param1: settings.arguments as int)); builder: (_) => getIt.get<PreSeedPage>(param1: settings.arguments as int));
case Routes.walletGroupExistingSeedDescriptionPage:
return MaterialPageRoute<void>(
builder: (_) => WalletGroupExistingSeedDescriptionPage(
seedPhraseWordsLength: settings.arguments as int));
case Routes.transactionSuccessPage: case Routes.transactionSuccessPage:
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (_) => getIt.get<TransactionSuccessPage>(param1: settings.arguments as String)); builder: (_) => getIt.get<TransactionSuccessPage>(param1: settings.arguments as String));

View file

@ -116,5 +116,6 @@ class Routes {
static const urqrAnimatedPage = '/urqr/animated_page'; static const urqrAnimatedPage = '/urqr/animated_page';
static const walletGroupsDisplayPage = '/wallet_groups_display_page'; static const walletGroupsDisplayPage = '/wallet_groups_display_page';
static const walletGroupDescription = '/wallet_group_description'; static const walletGroupDescription = '/wallet_group_description';
static const walletGroupExistingSeedDescriptionPage = '/wallet_group_existing_seed_description_page';
static const walletSeedVerificationPage = '/wallet_seed_verification_page'; static const walletSeedVerificationPage = '/wallet_seed_verification_page';
} }

View file

@ -231,6 +231,8 @@ class ExchangePage extends BasePage {
key: ValueKey('exchange_page_exchange_button_key'), key: ValueKey('exchange_page_exchange_button_key'),
text: S.of(context).exchange, text: S.of(context).exchange,
onPressed: () { onPressed: () {
FocusScope.of(context).unfocus();
if (_formKey.currentState != null && if (_formKey.currentState != null &&
_formKey.currentState!.validate()) { _formKey.currentState!.validate()) {
if ((exchangeViewModel.depositCurrency == CryptoCurrency.xmr) && if ((exchangeViewModel.depositCurrency == CryptoCurrency.xmr) &&

View file

@ -101,8 +101,14 @@ class _WalletNameFormState extends State<WalletNameForm> {
void initState() { void initState() {
_stateReaction ??= reaction((_) => _walletNewVM.state, (ExecutionState state) async { _stateReaction ??= reaction((_) => _walletNewVM.state, (ExecutionState state) async {
if (state is ExecutedSuccessfullyState) { if (state is ExecutedSuccessfullyState) {
Navigator.of(navigatorKey.currentContext ?? context) if (widget.isChildWallet) {
.pushNamed(Routes.preSeedPage, arguments: _walletNewVM.seedPhraseWordsLength); Navigator.of(navigatorKey.currentContext ?? context)
.pushNamed(Routes.walletGroupExistingSeedDescriptionPage,
arguments: _walletNewVM.seedPhraseWordsLength);
} else {
Navigator.of(navigatorKey.currentContext ?? context)
.pushNamed(Routes.preSeedPage, arguments: _walletNewVM.seedPhraseWordsLength);
}
} }
if (state is FailureState) { if (state is FailureState) {
@ -221,6 +227,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
), ),
if (_walletNewVM.hasWalletPassword) ...[ if (_walletNewVM.hasWalletPassword) ...[
TextFormField( TextFormField(
key: ValueKey('password'),
onChanged: (value) => _walletNewVM.walletPassword = value, onChanged: (value) => _walletNewVM.walletPassword = value,
controller: _passwordController, controller: _passwordController,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -257,6 +264,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
), ),
), ),
TextFormField( TextFormField(
key: ValueKey('repeat_wallet_password'),
onChanged: (value) => _walletNewVM.repeatedWalletPassword = value, onChanged: (value) => _walletNewVM.repeatedWalletPassword = value,
controller: _repeatedPasswordController, controller: _repeatedPasswordController,
textAlign: TextAlign.center, textAlign: TextAlign.center,

View file

@ -7,6 +7,7 @@ import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/themes/extensions/theme_type_images.dart';
class WalletGroupDescriptionPage extends BasePage { class WalletGroupDescriptionPage extends BasePage {
WalletGroupDescriptionPage({required this.selectedWalletType}); WalletGroupDescriptionPage({required this.selectedWalletType});
@ -25,10 +26,7 @@ class WalletGroupDescriptionPage extends BasePage {
padding: EdgeInsets.all(24), padding: EdgeInsets.all(24),
child: Column( child: Column(
children: [ children: [
Image.asset( Image.asset(currentTheme.type.walletGroupImage, height: 200),
_getThemedWalletGroupImage(currentTheme.type),
height: 200,
),
SizedBox(height: 32), SizedBox(height: 32),
Expanded( Expanded(
child: Text.rich( child: Text.rich(
@ -91,19 +89,4 @@ class WalletGroupDescriptionPage extends BasePage {
), ),
); );
} }
String _getThemedWalletGroupImage(ThemeType theme) {
final lightImage = 'assets/images/wallet_group_light.png';
final darkImage = 'assets/images/wallet_group_dark.png';
final brightImage = 'assets/images/wallet_group_bright.png';
switch (theme) {
case ThemeType.bright:
return brightImage;
case ThemeType.light:
return lightImage;
default:
return darkImage;
}
}
} }

View file

@ -4,12 +4,13 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/theme_type_images.dart';
import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/view_model/wallet_groups_display_view_model.dart'; import 'package:cake_wallet/view_model/wallet_groups_display_view_model.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import '../../../themes/extensions/cake_text_theme.dart';
class WalletGroupsDisplayPage extends BasePage { class WalletGroupsDisplayPage extends BasePage {
WalletGroupsDisplayPage(this.walletGroupsDisplayViewModel); WalletGroupsDisplayPage(this.walletGroupsDisplayViewModel);
@ -165,10 +166,7 @@ class WalletGroupEmptyStateWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
children: [ children: [
Image.asset( Image.asset(currentTheme.type.walletGroupImage, scale: 1.8),
_getThemedWalletGroupImage(currentTheme.type),
scale: 1.8,
),
SizedBox(height: 32), SizedBox(height: 32),
Text.rich( Text.rich(
TextSpan( TextSpan(
@ -194,19 +192,4 @@ class WalletGroupEmptyStateWidget extends StatelessWidget {
], ],
); );
} }
String _getThemedWalletGroupImage(ThemeType theme) {
final lightImage = 'assets/images/wallet_group_light.png';
final darkImage = 'assets/images/wallet_group_dark.png';
final brightImage = 'assets/images/wallet_group_bright.png';
switch (theme) {
case ThemeType.bright:
return brightImage;
case ThemeType.light:
return lightImage;
default:
return darkImage;
}
}
} }

View file

@ -0,0 +1,106 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/theme_type_images.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:flutter/material.dart';
class WalletGroupExistingSeedDescriptionPage extends BasePage {
WalletGroupExistingSeedDescriptionPage({required this.seedPhraseWordsLength});
final int seedPhraseWordsLength;
@override
String get title => S.current.wallet_group;
@override
Widget body(BuildContext context) {
final textStyle = TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
);
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(24),
child: Column(
children: [
Image.asset(currentTheme.type.walletGroupImage, height: 200),
SizedBox(height: 32),
Expanded(
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: S.current.wallet_group_description_existing_seed + '\n\n',
style: textStyle),
TextSpan(
text: S.current.wallet_group_description_open_wallet + '\n\n',
style: textStyle),
TextSpan(
text: S.current.wallet_group_description_view_seed + '\n', style: textStyle),
TextSpan(
text: S.current.seed_display_path,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w800,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
),
),
],
),
textAlign: TextAlign.center,
),
),
Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: PrimaryButton(
key: ValueKey(
'wallet_group_existing_seed_description_page_verify_seed_button_key'),
onPressed: () => Navigator.pushNamed(context, Routes.preSeedPage,
arguments: seedPhraseWordsLength),
text: S.current.verify_seed,
color: Theme.of(context).cardColor,
textColor: currentTheme.type == ThemeType.dark
? Theme.of(context).extension<DashboardPageTheme>()!.textColor
: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
),
),
),
Flexible(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Builder(
builder: (context) => PrimaryButton(
key: ValueKey(
'wallet_group_existing_seed_description_page_open_wallet_button_key'),
onPressed: () {
Navigator.of(context).popUntil((route) => route.isFirst);
},
text: S.current.open_wallet,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
),
),
),
)
],
),
SizedBox(height: 12),
],
)
],
),
);
}
}

View file

@ -148,12 +148,14 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
), ),
if (widget.displayWalletPassword) if (widget.displayWalletPassword)
...[Container( ...[Container(
key: ValueKey('password'),
padding: EdgeInsets.only(top: 20.0), padding: EdgeInsets.only(top: 20.0),
child: BaseTextFormField( child: BaseTextFormField(
controller: passwordTextEditingController, controller: passwordTextEditingController,
hintText: S.of(context).password, hintText: S.of(context).password,
obscureText: true)), obscureText: true)),
Container( Container(
key: ValueKey('repeat_wallet_password'),
padding: EdgeInsets.only(top: 20.0), padding: EdgeInsets.only(top: 20.0),
child: BaseTextFormField( child: BaseTextFormField(
controller: repeatedPasswordTextEditingController, controller: repeatedPasswordTextEditingController,

View file

@ -223,12 +223,14 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
), ),
if (widget.displayWalletPassword) if (widget.displayWalletPassword)
...[BaseTextFormField( ...[BaseTextFormField(
key: ValueKey('password'),
controller: passwordTextEditingController, controller: passwordTextEditingController,
hintText: S hintText: S
.of(context) .of(context)
.password, .password,
obscureText: true), obscureText: true),
BaseTextFormField( BaseTextFormField(
key: ValueKey('repeat_wallet_password'),
controller: repeatedPasswordTextEditingController, controller: repeatedPasswordTextEditingController,
hintText: S hintText: S
.of(context) .of(context)

View file

@ -525,6 +525,10 @@ class SendPage extends BasePage {
if (state is TransactionCommitted) { if (state is TransactionCommitted) {
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
if (!context.mounted) {
return;
}
final successMessage = S.of(context).send_success( final successMessage = S.of(context).send_success(
sendViewModel.selectedCryptoCurrency.toString()); sendViewModel.selectedCryptoCurrency.toString());

View file

@ -30,6 +30,11 @@ Future<String> extractAddressFromParsed(
content = S.of(context).extracted_address_content('${parsedAddress.name} (OpenAlias)'); content = S.of(context).extracted_address_content('${parsedAddress.name} (OpenAlias)');
address = parsedAddress.addresses.first; address = parsedAddress.addresses.first;
break; break;
case ParseFrom.wellKnown:
title = S.of(context).address_detected;
content = S.of(context).extracted_address_content('${parsedAddress.name} (Well-Known)');
address = parsedAddress.addresses.first;
break;
case ParseFrom.fio: case ParseFrom.fio:
title = S.of(context).address_detected; title = S.of(context).address_detected;
content = S.of(context).extracted_address_content('${parsedAddress.name} (FIO)'); content = S.of(context).extracted_address_content('${parsedAddress.name} (FIO)');

View file

@ -45,6 +45,10 @@ class DomainLookupsPage extends BasePage {
title: 'Ethereum Name Service', title: 'Ethereum Name Service',
value: _privacySettingsViewModel.looksUpENS, value: _privacySettingsViewModel.looksUpENS,
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsENS(value)), onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsENS(value)),
SettingsSwitcherCell(
title: '.well-known',
value: _privacySettingsViewModel.looksUpWellKnown,
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsWellKnown(value)),
//if (!isHaven) it does not work correctly //if (!isHaven) it does not work correctly
], ],

View file

@ -170,6 +170,7 @@ class WalletUnlockPageState extends AuthPageState<WalletUnlockPage> {
SizedBox(height: 24), SizedBox(height: 24),
Form( Form(
child: TextFormField( child: TextFormField(
key: ValueKey('enter_wallet_password'),
onChanged: (value) => null, onChanged: (value) => null,
controller: _passwordController, controller: _passwordController,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -205,6 +206,7 @@ class WalletUnlockPageState extends AuthPageState<WalletUnlockPage> {
), ),
), ),
Padding( Padding(
key: ValueKey('unlock'),
padding: EdgeInsets.only(bottom: 24), padding: EdgeInsets.only(bottom: 24),
child: Observer( child: Observer(
builder: (_) => LoadingPrimaryButton( builder: (_) => LoadingPrimaryButton(

View file

@ -91,7 +91,10 @@ class LoadingPrimaryButton extends StatelessWidget {
width: double.infinity, width: double.infinity,
height: 52.0, height: 52.0,
child: TextButton( child: TextButton(
onPressed: (isLoading || isDisabled) ? null : onPressed, onPressed: (isLoading || isDisabled) ? null : () {
FocusScope.of(context).unfocus();
onPressed.call();
},
style: ButtonStyle( style: ButtonStyle(
backgroundColor: backgroundColor:
MaterialStateProperty.all(isDisabled ? color.withOpacity(0.5) : color), MaterialStateProperty.all(isDisabled ? color.withOpacity(0.5) : color),

View file

@ -115,6 +115,7 @@ abstract class SettingsStoreBase with Store {
required this.lookupsUnstoppableDomains, required this.lookupsUnstoppableDomains,
required this.lookupsOpenAlias, required this.lookupsOpenAlias,
required this.lookupsENS, required this.lookupsENS,
required this.lookupsWellKnown,
required this.customBitcoinFeeRate, required this.customBitcoinFeeRate,
required this.silentPaymentsCardDisplay, required this.silentPaymentsCardDisplay,
required this.silentPaymentsAlwaysScan, required this.silentPaymentsAlwaysScan,
@ -459,6 +460,11 @@ abstract class SettingsStoreBase with Store {
reaction((_) => lookupsENS, reaction((_) => lookupsENS,
(bool looksUpENS) => _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS)); (bool looksUpENS) => _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS));
reaction(
(_) => lookupsWellKnown,
(bool looksUpWellKnown) =>
_sharedPreferences.setBool(PreferencesKey.lookupsWellKnown, looksUpWellKnown));
// secure storage keys: // secure storage keys:
reaction( reaction(
(_) => allowBiometricalAuthentication, (_) => allowBiometricalAuthentication,
@ -772,6 +778,8 @@ abstract class SettingsStoreBase with Store {
@observable @observable
bool lookupsENS; bool lookupsENS;
@observable
bool lookupsWellKnown;
@observable @observable
SyncMode currentSyncMode; SyncMode currentSyncMode;
@ -967,6 +975,7 @@ abstract class SettingsStoreBase with Store {
sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true;
final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
final lookupsWellKnown = sharedPreferences.getBool(PreferencesKey.lookupsWellKnown) ?? true;
final customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1; final customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1;
final silentPaymentsCardDisplay = final silentPaymentsCardDisplay =
sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true; sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
@ -1245,6 +1254,7 @@ abstract class SettingsStoreBase with Store {
lookupsUnstoppableDomains: lookupsUnstoppableDomains, lookupsUnstoppableDomains: lookupsUnstoppableDomains,
lookupsOpenAlias: lookupsOpenAlias, lookupsOpenAlias: lookupsOpenAlias,
lookupsENS: lookupsENS, lookupsENS: lookupsENS,
lookupsWellKnown: lookupsWellKnown,
customBitcoinFeeRate: customBitcoinFeeRate, customBitcoinFeeRate: customBitcoinFeeRate,
silentPaymentsCardDisplay: silentPaymentsCardDisplay, silentPaymentsCardDisplay: silentPaymentsCardDisplay,
silentPaymentsAlwaysScan: silentPaymentsAlwaysScan, silentPaymentsAlwaysScan: silentPaymentsAlwaysScan,
@ -1414,6 +1424,7 @@ abstract class SettingsStoreBase with Store {
sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true;
lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
lookupsWellKnown = sharedPreferences.getBool(PreferencesKey.lookupsWellKnown) ?? true;
customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1; customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1;
silentPaymentsCardDisplay = silentPaymentsCardDisplay =
sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true; sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;

View file

@ -0,0 +1,14 @@
import 'package:cake_wallet/themes/theme_base.dart';
extension ThemeTypeImages on ThemeType {
String get walletGroupImage {
switch (this) {
case ThemeType.bright:
return 'assets/images/wallet_group_bright.png';
case ThemeType.light:
return 'assets/images/wallet_group_light.png';
default:
return 'assets/images/wallet_group_dark.png';
}
}
}

View file

@ -94,6 +94,9 @@ abstract class PrivacySettingsViewModelBase with Store {
@computed @computed
bool get looksUpENS => _settingsStore.lookupsENS; bool get looksUpENS => _settingsStore.lookupsENS;
@computed
bool get looksUpWellKnown => _settingsStore.lookupsWellKnown;
bool get canUseEtherscan => _wallet.type == WalletType.ethereum; bool get canUseEtherscan => _wallet.type == WalletType.ethereum;
bool get canUsePolygonScan => _wallet.type == WalletType.polygon; bool get canUsePolygonScan => _wallet.type == WalletType.polygon;
@ -130,6 +133,9 @@ abstract class PrivacySettingsViewModelBase with Store {
@action @action
void setLookupsENS(bool value) => _settingsStore.lookupsENS = value; void setLookupsENS(bool value) => _settingsStore.lookupsENS = value;
@action
void setLookupsWellKnown(bool value) => _settingsStore.lookupsWellKnown = value;
@action @action
void setLookupsYatService(bool value) => _settingsStore.lookupsYatService = value; void setLookupsYatService(bool value) => _settingsStore.lookupsYatService = value;

View file

@ -46,8 +46,11 @@ static void my_application_activate(GApplication* application) {
} else { } else {
gtk_window_set_title(window, "Cake Wallet"); gtk_window_set_title(window, "Cake Wallet");
} }
if (getenv("DESKTOP_FORCE_MOBILE")) {
gtk_window_set_default_size(window, 1280, 720); gtk_window_set_default_size(window, 720, 1280);
} else {
gtk_window_set_default_size(window, 1280, 720);
}
gtk_widget_show(GTK_WIDGET(window)); gtk_widget_show(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlDartProject) project = fl_dart_project_new();

View file

@ -1,18 +1,24 @@
#!/bin/bash #!/bin/bash
set -x -e set -x -e
cd cw_core; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. for cwcoin in cw_{core,evm,monero,bitcoin,haven,nano,bitcoin_cash,solana,tron,wownero}
cd cw_evm; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. do
cd cw_monero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. if [[ "x$1" == "xasync" ]];
cd cw_bitcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. then
cd cw_haven; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. bash -c "cd $cwcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .." &
cd cw_nano; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. else
cd cw_bitcoin_cash; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. bash -c "cd $cwcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .."
cd cw_solana; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. fi
cd cw_tron; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. done
cd cw_wownero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. for cwcoin in cw_{polygon,ethereum,mwebd};
cd cw_polygon; flutter pub get; cd .. do
cd cw_ethereum; flutter pub get; cd .. if [[ "x$1" == "xasync" ]];
cd cw_mweb && flutter pub get && cd .. then
dart run build_runner build --delete-conflicting-outputs bash -c "cd $cwcoin; flutter pub get; cd .." &
else
bash -c "cd $cwcoin; flutter pub get; cd .."
fi
done
flutter pub get
dart run build_runner build --delete-conflicting-outputs

View file

@ -107,7 +107,10 @@ dependencies:
polyseed: ^0.0.6 polyseed: ^0.0.6
nostr_tools: ^1.0.9 nostr_tools: ^1.0.9
solana: ^0.31.0+1 solana: ^0.31.0+1
ledger_flutter_plus: ^1.4.1 ledger_flutter_plus:
git:
url: https://github.com/vespr-wallet/ledger-flutter-plus
ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
hashlib: ^1.19.2 hashlib: ^1.19.2
dev_dependencies: dev_dependencies:
@ -146,6 +149,10 @@ dependency_overrides:
url: https://github.com/cake-tech/bitcoin_base url: https://github.com/cake-tech/bitcoin_base
ref: cake-update-v9 ref: cake-update-v9
ffi: 2.1.0 ffi: 2.1.0
ledger_flutter_plus:
git:
url: https://github.com/vespr-wallet/ledger-flutter-plus
ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
flutter_icons: flutter_icons:
image_path: "assets/images/app_logo.png" image_path: "assets/images/app_logo.png"

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", "waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ",
"wallet": "محفظة", "wallet": "محفظة",
"wallet_group": "مجموعة محفظة", "wallet_group": "مجموعة محفظة",
"wallet_group_description_existing_seed": "لقد اخترت استخدام بذرة موجودة لهذه المحفظة. يمكنك التحقق من البذرة مرة أخرى إذا كنت بحاجة إلى تأكيدها أو كتابتها.",
"wallet_group_description_four": "لإنشاء محفظة مع بذرة جديدة تماما.", "wallet_group_description_four": "لإنشاء محفظة مع بذرة جديدة تماما.",
"wallet_group_description_one": "في محفظة الكيك ، يمكنك إنشاء ملف", "wallet_group_description_one": "في محفظة الكيك ، يمكنك إنشاء ملف",
"wallet_group_description_open_wallet": "خلاف ذلك ، يمكنك الاستمرار في فتح المحفظة",
"wallet_group_description_three": "لرؤية المحافظ المتاحة و/أو شاشة مجموعات المحفظة. أو اختر", "wallet_group_description_three": "لرؤية المحافظ المتاحة و/أو شاشة مجموعات المحفظة. أو اختر",
"wallet_group_description_two": "عن طريق اختيار محفظة موجودة لتبادل البذور مع. يمكن أن تحتوي كل مجموعة محفظة على محفظة واحدة من كل نوع من العملة. \n\n يمكنك تحديدها", "wallet_group_description_two": "عن طريق اختيار محفظة موجودة لتبادل البذور مع. يمكن أن تحتوي كل مجموعة محفظة على محفظة واحدة من كل نوع من العملة. \n\n يمكنك تحديدها",
"wallet_group_description_view_seed": "يمكنك دائمًا عرض هذه البذرة مرة أخرى تحت",
"wallet_group_empty_state_text_one": "يبدو أنه ليس لديك أي مجموعات محفظة متوافقة !\n\n انقر", "wallet_group_empty_state_text_one": "يبدو أنه ليس لديك أي مجموعات محفظة متوافقة !\n\n انقر",
"wallet_group_empty_state_text_two": "أدناه لجعل واحدة جديدة.", "wallet_group_empty_state_text_two": "أدناه لجعل واحدة جديدة.",
"wallet_keys": "سييد المحفظة / المفاتيح", "wallet_keys": "سييد المحفظة / المفاتيح",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите", "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите",
"wallet": "Портфейл", "wallet": "Портфейл",
"wallet_group": "Група на портфейла", "wallet_group": "Група на портфейла",
"wallet_group_description_existing_seed": "Вие сте избрали да използвате съществуващо семе за този портфейл. Можете да проверите отново семето, ако трябва да го потвърдите или запишете.",
"wallet_group_description_four": "За да създадете портфейл с изцяло ново семе.", "wallet_group_description_four": "За да създадете портфейл с изцяло ново семе.",
"wallet_group_description_one": "В портфейла за торта можете да създадете a", "wallet_group_description_one": "В портфейла за торта можете да създадете a",
"wallet_group_description_open_wallet": "В противен случай можете да продължите да отваряте портфейла",
"wallet_group_description_three": "За да видите наличния екран за портфейли и/или групи за портфейли. Или изберете", "wallet_group_description_three": "За да видите наличния екран за портфейли и/или групи за портфейли. Или изберете",
"wallet_group_description_two": "Чрез избора на съществуващ портфейл, с който да споделите семе. Всяка група за портфейл може да съдържа по един портфейл от всеки тип валута. \n\n Можете да изберете", "wallet_group_description_two": "Чрез избора на съществуващ портфейл, с който да споделите семе. Всяка група за портфейл може да съдържа по един портфейл от всеки тип валута. \n\n Можете да изберете",
"wallet_group_description_view_seed": "Винаги можете да видите това семе отново под",
"wallet_group_empty_state_text_one": "Изглежда, че нямате съвместими групи портфейли !\n\n tap", "wallet_group_empty_state_text_one": "Изглежда, че нямате съвместими групи портфейли !\n\n tap",
"wallet_group_empty_state_text_two": "по -долу, за да се направи нов.", "wallet_group_empty_state_text_two": "по -долу, за да се направи нов.",
"wallet_keys": "Seed/keys на портфейла", "wallet_keys": "Seed/keys на портфейла",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí", "waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí",
"wallet": "Peněženka", "wallet": "Peněženka",
"wallet_group": "Skupina peněženky", "wallet_group": "Skupina peněženky",
"wallet_group_description_existing_seed": "Rozhodli jste se použít existující semeno pro tuto peněženku. Semeno můžete znovu ověřit, pokud potřebujete potvrdit nebo zapisovat.",
"wallet_group_description_four": "Vytvoření peněženky s zcela novým semenem.", "wallet_group_description_four": "Vytvoření peněženky s zcela novým semenem.",
"wallet_group_description_one": "V peněžence dortu můžete vytvořit a", "wallet_group_description_one": "V peněžence dortu můžete vytvořit a",
"wallet_group_description_open_wallet": "Jinak můžete pokračovat v otevírání peněženky",
"wallet_group_description_three": "Chcete -li zobrazit dostupnou obrazovku Skupina skupin peněženek a/nebo skupin peněženek. Nebo zvolit", "wallet_group_description_three": "Chcete -li zobrazit dostupnou obrazovku Skupina skupin peněženek a/nebo skupin peněženek. Nebo zvolit",
"wallet_group_description_two": "Výběrem existující peněženky pro sdílení semeno. Každá skupina peněženek může obsahovat jednu peněženku každého typu měny. \n\n Můžete si vybrat", "wallet_group_description_two": "Výběrem existující peněženky pro sdílení semeno. Každá skupina peněženek může obsahovat jednu peněženku každého typu měny. \n\n Můžete si vybrat",
"wallet_group_description_view_seed": "Toto semeno si můžete vždy znovu prohlédnout",
"wallet_group_empty_state_text_one": "Vypadá to, že nemáte žádné kompatibilní skupiny peněženky !\n\n", "wallet_group_empty_state_text_one": "Vypadá to, že nemáte žádné kompatibilní skupiny peněženky !\n\n",
"wallet_group_empty_state_text_two": "Níže vytvořit nový.", "wallet_group_empty_state_text_two": "Níže vytvořit nový.",
"wallet_keys": "Seed/klíče peněženky", "wallet_keys": "Seed/klíče peněženky",

View file

@ -929,10 +929,13 @@
"waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung",
"wallet": "Geldbörse", "wallet": "Geldbörse",
"wallet_group": "Walletgruppe", "wallet_group": "Walletgruppe",
"wallet_group_description_existing_seed": "Sie haben für diese Brieftasche einen vorhandenen Samen verwendet. Sie können den Samen erneut überprüfen, wenn Sie ihn bestätigen oder aufschreiben müssen.",
"wallet_group_description_four": "eine Wallet mit einem völlig neuen Seed schaffen.", "wallet_group_description_four": "eine Wallet mit einem völlig neuen Seed schaffen.",
"wallet_group_description_one": "In CakeWallet können Sie eine erstellen", "wallet_group_description_one": "In CakeWallet können Sie eine erstellen",
"wallet_group_description_open_wallet": "Andernfalls können Sie die Brieftasche weiter öffnen",
"wallet_group_description_three": "Sehen Sie den Bildschirm zur verfügbaren Wallet und/oder Walletgruppen. Oder wählen", "wallet_group_description_three": "Sehen Sie den Bildschirm zur verfügbaren Wallet und/oder Walletgruppen. Oder wählen",
"wallet_group_description_two": "Durch die Auswahl einer vorhandenen Wallet, mit der ein Seed geteilt werden kann. Jede Walletgruppe kann eine einzelne Wallet jedes Währungstyps enthalten. \n\n Sie können auswählen", "wallet_group_description_two": "Durch die Auswahl einer vorhandenen Wallet, mit der ein Seed geteilt werden kann. Jede Walletgruppe kann eine einzelne Wallet jedes Währungstyps enthalten. \n\n Sie können auswählen",
"wallet_group_description_view_seed": "Sie können diesen Samen immer wieder untersuchen",
"wallet_group_empty_state_text_one": "Sieht so aus, als hätten Sie keine kompatiblen Walletgruppen !\n\n TAP", "wallet_group_empty_state_text_one": "Sieht so aus, als hätten Sie keine kompatiblen Walletgruppen !\n\n TAP",
"wallet_group_empty_state_text_two": "unten, um einen neuen zu machen.", "wallet_group_empty_state_text_two": "unten, um einen neuen zu machen.",
"wallet_keys": "Wallet-Seed/-Schlüssel", "wallet_keys": "Wallet-Seed/-Schlüssel",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history", "waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history",
"wallet": "Wallet", "wallet": "Wallet",
"wallet_group": "Wallet Group", "wallet_group": "Wallet Group",
"wallet_group_description_existing_seed": "Youve chosen to use an existing seed for this wallet. You may verify the seed again if you need to confirm or write it down.",
"wallet_group_description_four": "to create a wallet with an entirely new seed.", "wallet_group_description_four": "to create a wallet with an entirely new seed.",
"wallet_group_description_one": "In Cake Wallet, you can create a", "wallet_group_description_one": "In Cake Wallet, you can create a",
"wallet_group_description_open_wallet": "Otherwise, you can continue to open the wallet",
"wallet_group_description_three": "to see the available wallets and/or wallet groups screen. Or choose", "wallet_group_description_three": "to see the available wallets and/or wallet groups screen. Or choose",
"wallet_group_description_two": "by selecting an existing wallet to share a seed with. Each wallet group can contain a single wallet of each currency type.\n\nYou can select", "wallet_group_description_two": "by selecting an existing wallet to share a seed with. Each wallet group can contain a single wallet of each currency type.\n\nYou can select",
"wallet_group_description_view_seed": "You can always view this seed again under",
"wallet_group_empty_state_text_one": "Looks like you don't have any compatible wallet groups!\n\nTap", "wallet_group_empty_state_text_one": "Looks like you don't have any compatible wallet groups!\n\nTap",
"wallet_group_empty_state_text_two": "below to make a new one.", "wallet_group_empty_state_text_two": "below to make a new one.",
"wallet_keys": "Wallet seed/keys", "wallet_keys": "Wallet seed/keys",

View file

@ -927,10 +927,13 @@
"waitFewSecondForTxUpdate": "Espera unos segundos para que la transacción se refleje en el historial de transacciones.", "waitFewSecondForTxUpdate": "Espera unos segundos para que la transacción se refleje en el historial de transacciones.",
"wallet": "Billetera", "wallet": "Billetera",
"wallet_group": "Grupo de billetera", "wallet_group": "Grupo de billetera",
"wallet_group_description_existing_seed": "Ha elegido usar una semilla existente para esta billetera. Puede verificar la semilla nuevamente si necesita confirmarla o escribirla.",
"wallet_group_description_four": "Para crear una billetera con una semilla completamente nueva.", "wallet_group_description_four": "Para crear una billetera con una semilla completamente nueva.",
"wallet_group_description_one": "En la billetera de pastel, puedes crear un", "wallet_group_description_one": "En la billetera de pastel, puedes crear un",
"wallet_group_description_open_wallet": "De lo contrario, puede continuar abriendo la billetera",
"wallet_group_description_three": "Para ver las billeteras disponibles y/o la pantalla de grupos de billeteras. O elegir", "wallet_group_description_three": "Para ver las billeteras disponibles y/o la pantalla de grupos de billeteras. O elegir",
"wallet_group_description_two": "Seleccionando una billetera existente para compartir una semilla con. Cada grupo de billetera puede contener una sola billetera de cada tipo de moneda. \n\n puedes seleccionar", "wallet_group_description_two": "Seleccionando una billetera existente para compartir una semilla con. Cada grupo de billetera puede contener una sola billetera de cada tipo de moneda. \n\n puedes seleccionar",
"wallet_group_description_view_seed": "Siempre puedes ver esta semilla nuevamente debajo",
"wallet_group_empty_state_text_one": "Parece que no tienes ningún grupo de billetera compatible !\n\n toque", "wallet_group_empty_state_text_one": "Parece que no tienes ningún grupo de billetera compatible !\n\n toque",
"wallet_group_empty_state_text_two": "a continuación para hacer uno nuevo.", "wallet_group_empty_state_text_two": "a continuación para hacer uno nuevo.",
"wallet_keys": "Billetera semilla/claves", "wallet_keys": "Billetera semilla/claves",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions.", "waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions.",
"wallet": "Portefeuille", "wallet": "Portefeuille",
"wallet_group": "Groupe de portefeuille", "wallet_group": "Groupe de portefeuille",
"wallet_group_description_existing_seed": "Vous avez choisi d'utiliser une graine existante pour ce portefeuille. Vous pouvez vérifier à nouveau la graine si vous avez besoin de le confirmer ou de le noter.",
"wallet_group_description_four": "Pour créer un portefeuille avec une graine entièrement nouvelle.", "wallet_group_description_four": "Pour créer un portefeuille avec une graine entièrement nouvelle.",
"wallet_group_description_one": "Dans Cake Wallet, vous pouvez créer un", "wallet_group_description_one": "Dans Cake Wallet, vous pouvez créer un",
"wallet_group_description_open_wallet": "Sinon, vous pouvez continuer à ouvrir le portefeuille",
"wallet_group_description_three": "Pour voir les portefeuilles et / ou les groupes de portefeuilles disponibles. Ou choisir", "wallet_group_description_three": "Pour voir les portefeuilles et / ou les groupes de portefeuilles disponibles. Ou choisir",
"wallet_group_description_two": "En sélectionnant un portefeuille existant pour partager une graine avec. Chaque groupe de portefeuille peut contenir un seul portefeuille de chaque type de devise. \n\n Vous pouvez sélectionner", "wallet_group_description_two": "En sélectionnant un portefeuille existant pour partager une graine avec. Chaque groupe de portefeuille peut contenir un seul portefeuille de chaque type de devise. \n\n Vous pouvez sélectionner",
"wallet_group_description_view_seed": "Vous pouvez toujours revoir cette graine sous",
"wallet_group_empty_state_text_one": "On dirait que vous n'avez pas de groupes de portefeuilles compatibles !\n\n Tap", "wallet_group_empty_state_text_one": "On dirait que vous n'avez pas de groupes de portefeuilles compatibles !\n\n Tap",
"wallet_group_empty_state_text_two": "Ci-dessous pour en faire un nouveau.", "wallet_group_empty_state_text_two": "Ci-dessous pour en faire un nouveau.",
"wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)", "wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)",

View file

@ -928,10 +928,13 @@
"waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala", "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala",
"wallet": "Zabira", "wallet": "Zabira",
"wallet_group": "Wallet kungiyar", "wallet_group": "Wallet kungiyar",
"wallet_group_description_existing_seed": "Kun zaɓi yin amfani da iri ɗaya na data kasance don wannan Wallet.you na iya tabbatar da zuriyar kuma idan kuna buƙatar tabbatarwa ko rubuta shi.",
"wallet_group_description_four": "Don ƙirƙirar walat tare da sabon iri.", "wallet_group_description_four": "Don ƙirƙirar walat tare da sabon iri.",
"wallet_group_description_one": "A cikin walat walat, zaka iya ƙirƙirar", "wallet_group_description_one": "A cikin walat walat, zaka iya ƙirƙirar",
"wallet_group_description_open_wallet": "In ba haka ba, zaku iya ci gaba da buɗe walat ɗin",
"wallet_group_description_three": "Don ganin wallets da / ko allon walat din. Ko zabi", "wallet_group_description_three": "Don ganin wallets da / ko allon walat din. Ko zabi",
"wallet_group_description_two": "ta hanyar zabar walat mai gudana don raba iri tare da. Kowane rukunin walat na iya ƙunsar watsarin kowane nau'in kuɗi. \n\n Zaka iya zaɓar", "wallet_group_description_two": "ta hanyar zabar walat mai gudana don raba iri tare da. Kowane rukunin walat na iya ƙunsar watsarin kowane nau'in kuɗi. \n\n Zaka iya zaɓar",
"wallet_group_description_view_seed": "Koyaushe zaka iya duba wannan zuriya",
"wallet_group_empty_state_text_one": "Kamar dai ba ku da wata ƙungiya matattara !\n\n Taɓa", "wallet_group_empty_state_text_one": "Kamar dai ba ku da wata ƙungiya matattara !\n\n Taɓa",
"wallet_group_empty_state_text_two": "da ke ƙasa don yin sabo.", "wallet_group_empty_state_text_two": "da ke ƙasa don yin sabo.",
"wallet_keys": "Iri/maɓalli na walat", "wallet_keys": "Iri/maɓalli na walat",

View file

@ -928,10 +928,13 @@
"waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें", "waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें",
"wallet": "बटुआ", "wallet": "बटुआ",
"wallet_group": "बटुए समूह", "wallet_group": "बटुए समूह",
"wallet_group_description_existing_seed": "आपने इस वॉलेट के लिए एक मौजूदा बीज का उपयोग करने के लिए चुना है। यदि आपको इसकी पुष्टि करने या लिखने की आवश्यकता है, तो आप फिर से बीज को सत्यापित कर सकते हैं।",
"wallet_group_description_four": "एक पूरी तरह से नए बीज के साथ एक बटुआ बनाने के लिए।", "wallet_group_description_four": "एक पूरी तरह से नए बीज के साथ एक बटुआ बनाने के लिए।",
"wallet_group_description_one": "केक बटुए में, आप एक बना सकते हैं", "wallet_group_description_one": "केक बटुए में, आप एक बना सकते हैं",
"wallet_group_description_open_wallet": "अन्यथा, आप बटुए खोलना जारी रख सकते हैं",
"wallet_group_description_three": "उपलब्ध वॉलेट और/या वॉलेट समूह स्क्रीन देखने के लिए। या चुनें", "wallet_group_description_three": "उपलब्ध वॉलेट और/या वॉलेट समूह स्क्रीन देखने के लिए। या चुनें",
"wallet_group_description_two": "एक बीज साझा करने के लिए एक मौजूदा बटुए का चयन करके। प्रत्येक वॉलेट समूह में प्रत्येक मुद्रा प्रकार का एक एकल वॉलेट हो सकता है।\n\nआप चयन कर सकते हैं", "wallet_group_description_two": "एक बीज साझा करने के लिए एक मौजूदा बटुए का चयन करके। प्रत्येक वॉलेट समूह में प्रत्येक मुद्रा प्रकार का एक एकल वॉलेट हो सकता है।\n\nआप चयन कर सकते हैं",
"wallet_group_description_view_seed": "आप हमेशा इस बीज को फिर से देख सकते हैं",
"wallet_group_empty_state_text_one": "लगता है कि आपके पास कोई संगत बटुआ समूह नहीं है!\n\nनल", "wallet_group_empty_state_text_one": "लगता है कि आपके पास कोई संगत बटुआ समूह नहीं है!\n\nनल",
"wallet_group_empty_state_text_two": "नीचे एक नया बनाने के लिए।", "wallet_group_empty_state_text_two": "नीचे एक नया बनाने के लिए।",
"wallet_keys": "बटुआ बीज / चाबियाँ", "wallet_keys": "बटुआ बीज / चाबियाँ",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija", "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija",
"wallet": "Novčanik", "wallet": "Novčanik",
"wallet_group": "Skupina novčanika", "wallet_group": "Skupina novčanika",
"wallet_group_description_existing_seed": "Odlučili ste koristiti postojeće sjeme za ovaj novčanik. Možete ponovno provjeriti sjeme ako ga trebate potvrditi ili zapisati.",
"wallet_group_description_four": "Da biste stvorili novčanik s potpuno novim sjemenom.", "wallet_group_description_four": "Da biste stvorili novčanik s potpuno novim sjemenom.",
"wallet_group_description_one": "U novčaniku kolača možete stvoriti a", "wallet_group_description_one": "U novčaniku kolača možete stvoriti a",
"wallet_group_description_open_wallet": "Inače možete nastaviti otvarati novčanik",
"wallet_group_description_three": "Da biste vidjeli zaslon dostupnih novčanika i/ili grupa novčanika. Ili odaberite", "wallet_group_description_three": "Da biste vidjeli zaslon dostupnih novčanika i/ili grupa novčanika. Ili odaberite",
"wallet_group_description_two": "Odabirom postojećeg novčanika s kojim ćete dijeliti sjeme. Svaka grupa novčanika može sadržavati jedan novčanik svake vrste valute. \n\n", "wallet_group_description_two": "Odabirom postojećeg novčanika s kojim ćete dijeliti sjeme. Svaka grupa novčanika može sadržavati jedan novčanik svake vrste valute. \n\n",
"wallet_group_description_view_seed": "Uvijek možete ponovo pogledati ovo sjeme ispod",
"wallet_group_empty_state_text_one": "Izgleda da nemate nikakve kompatibilne grupe novčanika !\n\n", "wallet_group_empty_state_text_one": "Izgleda da nemate nikakve kompatibilne grupe novčanika !\n\n",
"wallet_group_empty_state_text_two": "Ispod da napravite novi.", "wallet_group_empty_state_text_two": "Ispod da napravite novi.",
"wallet_keys": "Pristupni izraz/ključ novčanika", "wallet_keys": "Pristupni izraz/ključ novčanika",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Խնդրում ենք սպասել մի քանի վայրկյան, որպեսզի գործարքը արտացոլվի գործարքների պատմության մեջ", "waitFewSecondForTxUpdate": "Խնդրում ենք սպասել մի քանի վայրկյան, որպեսզի գործարքը արտացոլվի գործարքների պատմության մեջ",
"wallet": "Դրամապանակ", "wallet": "Դրամապանակ",
"wallet_group": "Դրամապանակների խումբ", "wallet_group": "Դրամապանակների խումբ",
"wallet_group_description_existing_seed": "Դուք ընտրել եք օգտագործել այս դրամապանակի համար գոյություն ունեցող սերմը: Կարող եք կրկին հաստատել սերմը, եթե անհրաժեշտ է հաստատել կամ գրել այն:",
"wallet_group_description_four": "Ամբողջովին նոր սերմով դրամապանակ ստեղծելու համար:", "wallet_group_description_four": "Ամբողջովին նոր սերմով դրամապանակ ստեղծելու համար:",
"wallet_group_description_one": "Տորթի դրամապանակում կարող եք ստեղծել ա", "wallet_group_description_one": "Տորթի դրամապանակում կարող եք ստեղծել ա",
"wallet_group_description_open_wallet": "Հակառակ դեպքում, դուք կարող եք շարունակել բացել դրամապանակը",
"wallet_group_description_three": "Տեսնել առկա դրամապանակներն ու (կամ) դրամապանակների խմբերի էկրանը: Կամ ընտրել", "wallet_group_description_three": "Տեսնել առկա դրամապանակներն ու (կամ) դրամապանակների խմբերի էկրանը: Կամ ընտրել",
"wallet_group_description_two": "ընտրելով գոյություն ունեցող դրամապանակ `սերմը կիսելու համար: Դրամապանակների յուրաքանչյուր խումբ կարող է պարունակել յուրաքանչյուր արժույթի տեսակի մեկ դրամապանակ:\n\nԿարող եք ընտրել", "wallet_group_description_two": "ընտրելով գոյություն ունեցող դրամապանակ `սերմը կիսելու համար: Դրամապանակների յուրաքանչյուր խումբ կարող է պարունակել յուրաքանչյուր արժույթի տեսակի մեկ դրամապանակ:\n\nԿարող եք ընտրել",
"wallet_group_description_view_seed": "Միշտ կարող եք կրկին դիտել այս սերմը ներքեւում",
"wallet_group_empty_state_text_one": "Կարծես թե որեւէ համատեղելի դրամապանակի խմբեր չունեք:\n\nԹակել", "wallet_group_empty_state_text_one": "Կարծես թե որեւէ համատեղելի դրամապանակի խմբեր չունեք:\n\nԹակել",
"wallet_group_empty_state_text_two": "ներքեւում `նորը կազմելու համար:", "wallet_group_empty_state_text_two": "ներքեւում `նորը կազմելու համար:",
"wallet_keys": "Դրամապանակի սերմ/բանալիներ", "wallet_keys": "Դրամապանակի սերմ/բանալիներ",

View file

@ -929,10 +929,13 @@
"waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi", "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi",
"wallet": "Dompet", "wallet": "Dompet",
"wallet_group": "Kelompok dompet", "wallet_group": "Kelompok dompet",
"wallet_group_description_existing_seed": "Anda telah memilih untuk menggunakan benih yang ada untuk dompet ini. Anda dapat memverifikasi benih lagi jika Anda perlu mengonfirmasi atau menuliskannya.",
"wallet_group_description_four": "Untuk membuat dompet dengan benih yang sama sekali baru.", "wallet_group_description_four": "Untuk membuat dompet dengan benih yang sama sekali baru.",
"wallet_group_description_one": "Di dompet kue, Anda dapat membuat file", "wallet_group_description_one": "Di dompet kue, Anda dapat membuat file",
"wallet_group_description_open_wallet": "Jika tidak, Anda dapat terus membuka dompet",
"wallet_group_description_three": "Untuk melihat layar dompet dan/atau grup dompet yang tersedia. Atau pilih", "wallet_group_description_three": "Untuk melihat layar dompet dan/atau grup dompet yang tersedia. Atau pilih",
"wallet_group_description_two": "dengan memilih dompet yang ada untuk berbagi benih dengan. Setiap grup dompet dapat berisi satu dompet dari setiap jenis mata uang. \n\n Anda dapat memilih", "wallet_group_description_two": "dengan memilih dompet yang ada untuk berbagi benih dengan. Setiap grup dompet dapat berisi satu dompet dari setiap jenis mata uang. \n\n Anda dapat memilih",
"wallet_group_description_view_seed": "Anda selalu dapat melihat benih ini lagi di bawah",
"wallet_group_empty_state_text_one": "Sepertinya Anda tidak memiliki grup dompet yang kompatibel !\n\n tap", "wallet_group_empty_state_text_one": "Sepertinya Anda tidak memiliki grup dompet yang kompatibel !\n\n tap",
"wallet_group_empty_state_text_two": "di bawah ini untuk membuat yang baru.", "wallet_group_empty_state_text_two": "di bawah ini untuk membuat yang baru.",
"wallet_keys": "Seed/kunci dompet", "wallet_keys": "Seed/kunci dompet",

View file

@ -929,10 +929,13 @@
"waiting_payment_confirmation": "In attesa di conferma del pagamento", "waiting_payment_confirmation": "In attesa di conferma del pagamento",
"wallet": "Portafoglio", "wallet": "Portafoglio",
"wallet_group": "Gruppo di portafoglio", "wallet_group": "Gruppo di portafoglio",
"wallet_group_description_existing_seed": "Hai scelto di utilizzare un seme esistente per questo portafoglio. Puoi verificare di nuovo il seme se devi confermarlo o scriverlo.",
"wallet_group_description_four": "Per creare un portafoglio con un seme completamente nuovo.", "wallet_group_description_four": "Per creare un portafoglio con un seme completamente nuovo.",
"wallet_group_description_one": "Nel portafoglio di torte, puoi creare un", "wallet_group_description_one": "Nel portafoglio di torte, puoi creare un",
"wallet_group_description_open_wallet": "Altrimenti, puoi continuare ad aprire il portafoglio",
"wallet_group_description_three": "Per vedere la schermata di portafogli e/o gruppi di portafogli disponibili. O scegli", "wallet_group_description_three": "Per vedere la schermata di portafogli e/o gruppi di portafogli disponibili. O scegli",
"wallet_group_description_two": "Selezionando un portafoglio esistente con cui condividere un seme. Ogni gruppo di portafoglio può contenere un singolo portafoglio di ciascun tipo di valuta. \n\n È possibile selezionare", "wallet_group_description_two": "Selezionando un portafoglio esistente con cui condividere un seme. Ogni gruppo di portafoglio può contenere un singolo portafoglio di ciascun tipo di valuta. \n\n È possibile selezionare",
"wallet_group_description_view_seed": "Puoi sempre visualizzare di nuovo questo seme sotto",
"wallet_group_empty_state_text_one": "Sembra che tu non abbia alcun gruppo di portafoglio compatibile !\n\n TAP", "wallet_group_empty_state_text_one": "Sembra che tu non abbia alcun gruppo di portafoglio compatibile !\n\n TAP",
"wallet_group_empty_state_text_two": "Di seguito per crearne uno nuovo.", "wallet_group_empty_state_text_two": "Di seguito per crearne uno nuovo.",
"wallet_keys": "Seme Portafoglio /chiavi", "wallet_keys": "Seme Portafoglio /chiavi",

View file

@ -927,10 +927,13 @@
"waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。", "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。",
"wallet": "財布", "wallet": "財布",
"wallet_group": "ウォレットグループ", "wallet_group": "ウォレットグループ",
"wallet_group_description_existing_seed": "この財布に既存の種子を使用することを選択しました。確認または書き留める必要がある場合は、シードをもう一度確認できます。",
"wallet_group_description_four": "まったく新しい種子の財布を作成します。", "wallet_group_description_four": "まったく新しい種子の財布を作成します。",
"wallet_group_description_one": "ケーキウォレットでは、aを作成できます", "wallet_group_description_one": "ケーキウォレットでは、aを作成できます",
"wallet_group_description_open_wallet": "それ以外の場合は、ウォレットを開き続けることができます",
"wallet_group_description_three": "利用可能なウォレットおよび/またはウォレットグループの画面を表示します。または選択します", "wallet_group_description_three": "利用可能なウォレットおよび/またはウォレットグループの画面を表示します。または選択します",
"wallet_group_description_two": "既存のウォレットを選択して種子を共有します。各ウォレットグループには、各通貨タイプの単一のウォレットを含めることができます。\n\n選択できます", "wallet_group_description_two": "既存のウォレットを選択して種子を共有します。各ウォレットグループには、各通貨タイプの単一のウォレットを含めることができます。\n\n選択できます",
"wallet_group_description_view_seed": "いつでもこの種を再び見ることができます",
"wallet_group_empty_state_text_one": "互換性のあるウォレットグループがないようです!\n\nタップ", "wallet_group_empty_state_text_one": "互換性のあるウォレットグループがないようです!\n\nタップ",
"wallet_group_empty_state_text_two": "以下に新しいものを作るために。", "wallet_group_empty_state_text_two": "以下に新しいものを作るために。",
"wallet_keys": "ウォレットシード/キー", "wallet_keys": "ウォレットシード/キー",

View file

@ -512,7 +512,6 @@
"please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.",
"please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.",
"please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.",
"Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.",
"please_select": "선택 해주세요:", "please_select": "선택 해주세요:",
"please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.",
"please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오",
@ -927,10 +926,13 @@
"waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요.", "waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요.",
"wallet": "지갑", "wallet": "지갑",
"wallet_group": "지갑 그룹", "wallet_group": "지갑 그룹",
"wallet_group_description_existing_seed": "이 지갑에 기존 씨앗을 사용하기로 선택했습니다. 확인하거나 작성 해야하는 경우 씨앗을 다시 확인할 수 있습니다.",
"wallet_group_description_four": "완전히 새로운 씨앗으로 지갑을 만듭니다.", "wallet_group_description_four": "완전히 새로운 씨앗으로 지갑을 만듭니다.",
"wallet_group_description_one": "케이크 지갑에서는 a를 만들 수 있습니다", "wallet_group_description_one": "케이크 지갑에서는 a를 만들 수 있습니다",
"wallet_group_description_open_wallet": "그렇지 않으면 지갑을 계속 열 수 있습니다",
"wallet_group_description_three": "사용 가능한 지갑 및/또는 지갑 그룹 스크린을 볼 수 있습니다. 또는 선택하십시오", "wallet_group_description_three": "사용 가능한 지갑 및/또는 지갑 그룹 스크린을 볼 수 있습니다. 또는 선택하십시오",
"wallet_group_description_two": "씨앗을 공유 할 기존 지갑을 선택함으로써. 각 지갑 그룹은 각 통화 유형의 단일 지갑을 포함 할 수 있습니다. \n\n", "wallet_group_description_two": "씨앗을 공유 할 기존 지갑을 선택함으로써. 각 지갑 그룹은 각 통화 유형의 단일 지갑을 포함 할 수 있습니다. \n\n",
"wallet_group_description_view_seed": "이 씨앗을 언제든지 다시 볼 수 있습니다",
"wallet_group_empty_state_text_one": "호환 지갑 그룹이없는 것 같습니다 !\n\n TAP", "wallet_group_empty_state_text_one": "호환 지갑 그룹이없는 것 같습니다 !\n\n TAP",
"wallet_group_empty_state_text_two": "아래에서 새로운 것을 만들기 위해.", "wallet_group_empty_state_text_two": "아래에서 새로운 것을 만들기 위해.",
"wallet_keys": "지갑 시드 / 키", "wallet_keys": "지갑 시드 / 키",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။", "waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။",
"wallet": "ပိုက်ဆံအိတ်", "wallet": "ပိုက်ဆံအိတ်",
"wallet_group": "ပိုက်ဆံအိတ်အုပ်စု", "wallet_group": "ပိုက်ဆံအိတ်အုပ်စု",
"wallet_group_description_existing_seed": "ဒီပိုက်ဆံအိတ်အတွက်ရှိပြီးသားမျိုးစေ့ကိုသုံးဖို့သင်ရွေးချယ်ခဲ့တယ်။ သင်ကအတည်ပြုရန်သို့မဟုတ်ရေးရန်လိုအပ်လျှင်မျိုးစေ့ကိုထပ်မံအတည်ပြုနိုင်သည်။",
"wallet_group_description_four": "လုံးဝအသစ်သောမျိုးစေ့နှင့်အတူပိုက်ဆံအိတ်ဖန်တီးရန်။", "wallet_group_description_four": "လုံးဝအသစ်သောမျိုးစေ့နှင့်အတူပိုက်ဆံအိတ်ဖန်တီးရန်။",
"wallet_group_description_one": "ကိတ်မုန့်၌, သင်တစ် ဦး ဖန်တီးနိုင်ပါတယ်", "wallet_group_description_one": "ကိတ်မုန့်၌, သင်တစ် ဦး ဖန်တီးနိုင်ပါတယ်",
"wallet_group_description_open_wallet": "ဒီလိုမှမဟုတ်ရင်သင်ပိုက်ဆံအိတ်ကိုဆက်ဖွင့်နိုင်တယ်",
"wallet_group_description_three": "ရရှိနိုင်သည့်ပိုက်ဆံအိတ်နှင့် / သို့မဟုတ်ပိုက်ဆံအိတ်အုပ်စုများမြင်ကွင်းကိုကြည့်ရှုရန်။ သို့မဟုတ်ရွေးချယ်ပါ", "wallet_group_description_three": "ရရှိနိုင်သည့်ပိုက်ဆံအိတ်နှင့် / သို့မဟုတ်ပိုက်ဆံအိတ်အုပ်စုများမြင်ကွင်းကိုကြည့်ရှုရန်။ သို့မဟုတ်ရွေးချယ်ပါ",
"wallet_group_description_two": "နှင့်အတူမျိုးစေ့ဝေမျှဖို့ရှိပြီးသားပိုက်ဆံအိတ်တစ်ခုရွေးချယ်ခြင်းအားဖြင့်။ ပိုက်ဆံအိတ်အုပ်စုတစ်ခုစီတွင်ငွေကြေးအမျိုးအစားတစ်ခုစီ၏တစ်ခုတည်းသောပိုက်ဆံအိတ်တစ်ခုပါ 0 င်နိုင်သည်။ \n\n သင်ရွေးချယ်နိုင်သည်", "wallet_group_description_two": "နှင့်အတူမျိုးစေ့ဝေမျှဖို့ရှိပြီးသားပိုက်ဆံအိတ်တစ်ခုရွေးချယ်ခြင်းအားဖြင့်။ ပိုက်ဆံအိတ်အုပ်စုတစ်ခုစီတွင်ငွေကြေးအမျိုးအစားတစ်ခုစီ၏တစ်ခုတည်းသောပိုက်ဆံအိတ်တစ်ခုပါ 0 င်နိုင်သည်။ \n\n သင်ရွေးချယ်နိုင်သည်",
"wallet_group_description_view_seed": "သင်သည်ဤမျိုးစေ့ကိုနောက်တဖန်ရှုမြင်နိုင်သည်",
"wallet_group_empty_state_text_one": "သင့်တွင်သဟဇာတဖြစ်သောပိုက်ဆံအိတ်အုပ်စုများမရှိပါ။ !\n\n ကိုအသာပုတ်ပါ", "wallet_group_empty_state_text_one": "သင့်တွင်သဟဇာတဖြစ်သောပိုက်ဆံအိတ်အုပ်စုများမရှိပါ။ !\n\n ကိုအသာပုတ်ပါ",
"wallet_group_empty_state_text_two": "အသစ်တစ်ခုကိုတစ်ခုလုပ်ဖို့အောက်တွင်ဖော်ပြထားသော။", "wallet_group_empty_state_text_two": "အသစ်တစ်ခုကိုတစ်ခုလုပ်ဖို့အောက်တွင်ဖော်ပြထားသော။",
"wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ", "wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ",

View file

@ -927,10 +927,13 @@
"waiting_payment_confirmation": "In afwachting van betalingsbevestiging", "waiting_payment_confirmation": "In afwachting van betalingsbevestiging",
"wallet": "Portemonnee", "wallet": "Portemonnee",
"wallet_group": "Portemonnee", "wallet_group": "Portemonnee",
"wallet_group_description_existing_seed": "U hebt ervoor gekozen om een bestaand zaadje voor deze portemonnee te gebruiken. U kunt het zaad opnieuw verifiëren als u het moet bevestigen of opschrijven.",
"wallet_group_description_four": "om een portemonnee te maken met een geheel nieuw zaadje.", "wallet_group_description_four": "om een portemonnee te maken met een geheel nieuw zaadje.",
"wallet_group_description_one": "In cakeballet kun je een", "wallet_group_description_one": "In cakeballet kun je een",
"wallet_group_description_open_wallet": "Anders kunt u de portemonnee blijven openen",
"wallet_group_description_three": "Om de beschikbare portefeuilles en/of portefeuillegroepen te zien. Of kies", "wallet_group_description_three": "Om de beschikbare portefeuilles en/of portefeuillegroepen te zien. Of kies",
"wallet_group_description_two": "Door een bestaande portemonnee te selecteren om een zaadje mee te delen. Elke portemonnee -groep kan een enkele portemonnee van elk valutietype bevatten. \n\n U kunt selecteren", "wallet_group_description_two": "Door een bestaande portemonnee te selecteren om een zaadje mee te delen. Elke portemonnee -groep kan een enkele portemonnee van elk valutietype bevatten. \n\n U kunt selecteren",
"wallet_group_description_view_seed": "Je kunt dit zaad altijd opnieuw bekijken",
"wallet_group_empty_state_text_one": "Het lijkt erop dat je geen compatibele portemonnee -groepen hebt !\n\n TAP", "wallet_group_empty_state_text_one": "Het lijkt erop dat je geen compatibele portemonnee -groepen hebt !\n\n TAP",
"wallet_group_empty_state_text_two": "hieronder om een nieuwe te maken.", "wallet_group_empty_state_text_two": "hieronder om een nieuwe te maken.",
"wallet_keys": "Portemonnee zaad/sleutels", "wallet_keys": "Portemonnee zaad/sleutels",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji", "waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji",
"wallet": "Portfel", "wallet": "Portfel",
"wallet_group": "Grupa portfela", "wallet_group": "Grupa portfela",
"wallet_group_description_existing_seed": "Zdecydowałeś się użyć istniejącego ziarna do tego portfela. Możesz ponownie zweryfikować ziarno, jeśli chcesz je potwierdzić lub zapisać.",
"wallet_group_description_four": "Aby stworzyć portfel z zupełnie nowym ziarnem.", "wallet_group_description_four": "Aby stworzyć portfel z zupełnie nowym ziarnem.",
"wallet_group_description_one": "W portfelu ciasta możesz stworzyć", "wallet_group_description_one": "W portfelu ciasta możesz stworzyć",
"wallet_group_description_open_wallet": "W przeciwnym razie możesz nadal otwierać portfel",
"wallet_group_description_three": "Aby zobaczyć dostępny ekran portfeli i/lub grup portfeli. Lub wybierz", "wallet_group_description_three": "Aby zobaczyć dostępny ekran portfeli i/lub grup portfeli. Lub wybierz",
"wallet_group_description_two": "Wybierając istniejący portfel do podzielenia nasion. Każda grupa portfela może zawierać pojedynczy portfel każdego typu waluty. \n\n możesz wybrać", "wallet_group_description_two": "Wybierając istniejący portfel do podzielenia nasion. Każda grupa portfela może zawierać pojedynczy portfel każdego typu waluty. \n\n możesz wybrać",
"wallet_group_description_view_seed": "Zawsze możesz ponownie zobaczyć to ziarno pod",
"wallet_group_empty_state_text_one": "Wygląda na to, że nie masz żadnych kompatybilnych grup portfeli !\n\n Tap", "wallet_group_empty_state_text_one": "Wygląda na to, że nie masz żadnych kompatybilnych grup portfeli !\n\n Tap",
"wallet_group_empty_state_text_two": "poniżej, aby zrobić nowy.", "wallet_group_empty_state_text_two": "poniżej, aby zrobić nowy.",
"wallet_keys": "Klucze portfela", "wallet_keys": "Klucze portfela",

View file

@ -929,10 +929,13 @@
"waiting_payment_confirmation": "Aguardando confirmação de pagamento", "waiting_payment_confirmation": "Aguardando confirmação de pagamento",
"wallet": "Carteira", "wallet": "Carteira",
"wallet_group": "Grupo de carteira", "wallet_group": "Grupo de carteira",
"wallet_group_description_existing_seed": "Você optou por usar uma semente existente para esta carteira. Você pode verificar a semente novamente se precisar confirmar ou anotá -la.",
"wallet_group_description_four": "Para criar uma carteira com uma semente totalmente nova.", "wallet_group_description_four": "Para criar uma carteira com uma semente totalmente nova.",
"wallet_group_description_one": "Na carteira de bolo, você pode criar um", "wallet_group_description_one": "Na carteira de bolo, você pode criar um",
"wallet_group_description_open_wallet": "Caso contrário, você pode continuar a abrir a carteira",
"wallet_group_description_three": "Para ver as carteiras disponíveis e/ou os grupos de carteiras. Ou escolha", "wallet_group_description_three": "Para ver as carteiras disponíveis e/ou os grupos de carteiras. Ou escolha",
"wallet_group_description_two": "Selecionando uma carteira existente para compartilhar uma semente. Cada grupo de carteira pode conter uma única carteira de cada tipo de moeda. \n\n você pode selecionar", "wallet_group_description_two": "Selecionando uma carteira existente para compartilhar uma semente. Cada grupo de carteira pode conter uma única carteira de cada tipo de moeda. \n\n você pode selecionar",
"wallet_group_description_view_seed": "Você sempre pode ver esta semente novamente em",
"wallet_group_empty_state_text_one": "Parece que você não tem nenhum grupo de carteira compatível !\n\n Toque", "wallet_group_empty_state_text_one": "Parece que você não tem nenhum grupo de carteira compatível !\n\n Toque",
"wallet_group_empty_state_text_two": "abaixo para fazer um novo.", "wallet_group_empty_state_text_two": "abaixo para fazer um novo.",
"wallet_keys": "Semente/chaves da carteira", "wallet_keys": "Semente/chaves da carteira",

View file

@ -927,10 +927,13 @@
"waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций.", "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций.",
"wallet": "Кошелек", "wallet": "Кошелек",
"wallet_group": "Группа кошелька", "wallet_group": "Группа кошелька",
"wallet_group_description_existing_seed": "Вы решили использовать существующее семя для этого кошелька. Вы можете снова проверить семя, если вам нужно подтвердить или записать его.",
"wallet_group_description_four": "создать кошелек с совершенно новым семенем.", "wallet_group_description_four": "создать кошелек с совершенно новым семенем.",
"wallet_group_description_one": "В кошельке для торта вы можете создать", "wallet_group_description_one": "В кошельке для торта вы можете создать",
"wallet_group_description_open_wallet": "В противном случае вы можете продолжать открывать кошелек",
"wallet_group_description_three": "Чтобы увидеть доступные кошельки и/или экраны групп кошельков. Или выберите", "wallet_group_description_three": "Чтобы увидеть доступные кошельки и/или экраны групп кошельков. Или выберите",
"wallet_group_description_two": "выбирая существующий кошелек, чтобы поделиться семенами. Каждая группа кошелька может содержать один кошелек каждого типа валюты. \n\n Вы можете выбрать", "wallet_group_description_two": "выбирая существующий кошелек, чтобы поделиться семенами. Каждая группа кошелька может содержать один кошелек каждого типа валюты. \n\n Вы можете выбрать",
"wallet_group_description_view_seed": "Вы всегда можете просматривать это семя снова под",
"wallet_group_empty_state_text_one": "Похоже, у вас нет никаких совместимых групп кошелька !\n\n tap", "wallet_group_empty_state_text_one": "Похоже, у вас нет никаких совместимых групп кошелька !\n\n tap",
"wallet_group_empty_state_text_two": "ниже, чтобы сделать новый.", "wallet_group_empty_state_text_two": "ниже, чтобы сделать новый.",
"wallet_keys": "Мнемоническая фраза/ключи кошелька", "wallet_keys": "Мнемоническая фраза/ключи кошелька",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม", "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม",
"wallet": "กระเป๋าสตางค์", "wallet": "กระเป๋าสตางค์",
"wallet_group": "กลุ่มกระเป๋าเงิน", "wallet_group": "กลุ่มกระเป๋าเงิน",
"wallet_group_description_existing_seed": "คุณเลือกที่จะใช้เมล็ดพันธุ์ที่มีอยู่สำหรับกระเป๋าเงินนี้คุณอาจตรวจสอบเมล็ดได้อีกครั้งหากคุณต้องการยืนยันหรือเขียนลงไป",
"wallet_group_description_four": "เพื่อสร้างกระเป๋าเงินที่มีเมล็ดพันธุ์ใหม่ทั้งหมด", "wallet_group_description_four": "เพื่อสร้างกระเป๋าเงินที่มีเมล็ดพันธุ์ใหม่ทั้งหมด",
"wallet_group_description_one": "ในกระเป๋าเงินเค้กคุณสามารถสร้างไฟล์", "wallet_group_description_one": "ในกระเป๋าเงินเค้กคุณสามารถสร้างไฟล์",
"wallet_group_description_open_wallet": "มิฉะนั้นคุณสามารถเปิดกระเป๋าเงินต่อไปได้",
"wallet_group_description_three": "หากต้องการดูกระเป๋าเงินและ/หรือกลุ่มกระเป๋าเงินที่มีอยู่ หรือเลือก", "wallet_group_description_three": "หากต้องการดูกระเป๋าเงินและ/หรือกลุ่มกระเป๋าเงินที่มีอยู่ หรือเลือก",
"wallet_group_description_two": "โดยการเลือกกระเป๋าเงินที่มีอยู่เพื่อแบ่งปันเมล็ดด้วย แต่ละกลุ่มกระเป๋าเงินสามารถมีกระเป๋าเงินเดียวของแต่ละประเภทสกุลเงิน \n\n คุณสามารถเลือกได้", "wallet_group_description_two": "โดยการเลือกกระเป๋าเงินที่มีอยู่เพื่อแบ่งปันเมล็ดด้วย แต่ละกลุ่มกระเป๋าเงินสามารถมีกระเป๋าเงินเดียวของแต่ละประเภทสกุลเงิน \n\n คุณสามารถเลือกได้",
"wallet_group_description_view_seed": "คุณสามารถดูเมล็ดพันธุ์นี้ได้อีกครั้งภายใต้",
"wallet_group_empty_state_text_one": "ดูเหมือนว่าคุณจะไม่มีกลุ่มกระเป๋าเงินที่เข้ากันได้ !\n\n แตะ", "wallet_group_empty_state_text_one": "ดูเหมือนว่าคุณจะไม่มีกลุ่มกระเป๋าเงินที่เข้ากันได้ !\n\n แตะ",
"wallet_group_empty_state_text_two": "ด้านล่างเพื่อสร้างใหม่", "wallet_group_empty_state_text_two": "ด้านล่างเพื่อสร้างใหม่",
"wallet_keys": "ซีดของกระเป๋า/คีย์", "wallet_keys": "ซีดของกระเป๋า/คีย์",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon", "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon",
"wallet": "Wallet", "wallet": "Wallet",
"wallet_group": "Group ng Wallet", "wallet_group": "Group ng Wallet",
"wallet_group_description_existing_seed": "Pinili mong gumamit ng isang umiiral na binhi para sa pitaka na ito. Maaari mong mapatunayan muli ang binhi kung kailangan mong kumpirmahin o isulat ito.",
"wallet_group_description_four": "Upang lumikha ng isang pitaka na may ganap na bagong binhi.", "wallet_group_description_four": "Upang lumikha ng isang pitaka na may ganap na bagong binhi.",
"wallet_group_description_one": "Sa cake wallet, maaari kang lumikha ng isang", "wallet_group_description_one": "Sa cake wallet, maaari kang lumikha ng isang",
"wallet_group_description_open_wallet": "Kung hindi man, maaari mong magpatuloy upang buksan ang pitaka",
"wallet_group_description_three": "Upang makita ang magagamit na mga wallets at/o screen ng mga pangkat ng pitaka. O pumili", "wallet_group_description_three": "Upang makita ang magagamit na mga wallets at/o screen ng mga pangkat ng pitaka. O pumili",
"wallet_group_description_two": "Sa pamamagitan ng pagpili ng isang umiiral na pitaka upang magbahagi ng isang binhi. Ang bawat pangkat ng pitaka ay maaaring maglaman ng isang solong pitaka ng bawat uri ng pera.\n\nMaaari kang pumili", "wallet_group_description_two": "Sa pamamagitan ng pagpili ng isang umiiral na pitaka upang magbahagi ng isang binhi. Ang bawat pangkat ng pitaka ay maaaring maglaman ng isang solong pitaka ng bawat uri ng pera.\n\nMaaari kang pumili",
"wallet_group_description_view_seed": "Maaari mong palaging tingnan ang binhi na ito sa ilalim",
"wallet_group_empty_state_text_one": "Mukhang wala kang anumang mga katugmang pangkat ng pitaka!\n\ntap", "wallet_group_empty_state_text_one": "Mukhang wala kang anumang mga katugmang pangkat ng pitaka!\n\ntap",
"wallet_group_empty_state_text_two": "sa ibaba upang gumawa ng bago.", "wallet_group_empty_state_text_two": "sa ibaba upang gumawa ng bago.",
"wallet_keys": "Wallet seed/keys", "wallet_keys": "Wallet seed/keys",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin", "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin",
"wallet": "Cüzdan", "wallet": "Cüzdan",
"wallet_group": "Cüzdan grubu", "wallet_group": "Cüzdan grubu",
"wallet_group_description_existing_seed": "Bu cüzdan için mevcut bir tohum kullanmayı seçtiniz. Onaylamanız veya yazmanız gerekiyorsa tohumu tekrar doğrulayabilirsiniz.",
"wallet_group_description_four": "Tamamen yeni bir tohumla bir cüzdan oluşturmak için.", "wallet_group_description_four": "Tamamen yeni bir tohumla bir cüzdan oluşturmak için.",
"wallet_group_description_one": "Kek cüzdanında bir", "wallet_group_description_one": "Kek cüzdanında bir",
"wallet_group_description_open_wallet": "Aksi takdirde cüzdanı açmaya devam edebilirsiniz",
"wallet_group_description_three": "Mevcut cüzdan ve/veya cüzdan grupları ekranını görmek için. Veya seç", "wallet_group_description_three": "Mevcut cüzdan ve/veya cüzdan grupları ekranını görmek için. Veya seç",
"wallet_group_description_two": "Bir tohumu paylaşmak için mevcut bir cüzdan seçerek. Her cüzdan grubu, her para türünün tek bir cüzdanı içerebilir. \n\n Seçebilirsiniz", "wallet_group_description_two": "Bir tohumu paylaşmak için mevcut bir cüzdan seçerek. Her cüzdan grubu, her para türünün tek bir cüzdanı içerebilir. \n\n Seçebilirsiniz",
"wallet_group_description_view_seed": "Bu tohumu her zaman tekrar görebilirsiniz",
"wallet_group_empty_state_text_one": "Herhangi bir uyumlu cüzdan grubunuz yok gibi görünüyor !\n\n TAP", "wallet_group_empty_state_text_one": "Herhangi bir uyumlu cüzdan grubunuz yok gibi görünüyor !\n\n TAP",
"wallet_group_empty_state_text_two": "Yeni bir tane yapmak için aşağıda.", "wallet_group_empty_state_text_two": "Yeni bir tane yapmak için aşağıda.",
"wallet_keys": "Cüzdan tohumu/anahtarları", "wallet_keys": "Cüzdan tohumu/anahtarları",

View file

@ -927,10 +927,13 @@
"waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій", "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій",
"wallet": "Гаманець", "wallet": "Гаманець",
"wallet_group": "Група гаманців", "wallet_group": "Група гаманців",
"wallet_group_description_existing_seed": "Ви вирішили використовувати існуюче насіння для цього гаманця. Ви можете ще раз перевірити насіння, якщо вам потрібно підтвердити або записати його.",
"wallet_group_description_four": "створити гаманець з абсолютно новим насінням.", "wallet_group_description_four": "створити гаманець з абсолютно новим насінням.",
"wallet_group_description_one": "У гаманці тортів ви можете створити a", "wallet_group_description_one": "У гаманці тортів ви можете створити a",
"wallet_group_description_open_wallet": "В іншому випадку ви можете продовжувати відкривати гаманець",
"wallet_group_description_three": "Щоб побачити наявні гаманці та/або екран групи гаманців. Або вибрати", "wallet_group_description_three": "Щоб побачити наявні гаманці та/або екран групи гаманців. Або вибрати",
"wallet_group_description_two": "Вибираючи існуючий гаманець, щоб поділитися насінням. Кожна група гаманця може містити один гаманець кожного типу валюти. \n\n Ви можете вибрати", "wallet_group_description_two": "Вибираючи існуючий гаманець, щоб поділитися насінням. Кожна група гаманця може містити один гаманець кожного типу валюти. \n\n Ви можете вибрати",
"wallet_group_description_view_seed": "Ви завжди можете переглянути це насіння ще раз під",
"wallet_group_empty_state_text_one": "Схоже, у вас немає сумісних груп гаманця !\n\n Торкніться", "wallet_group_empty_state_text_one": "Схоже, у вас немає сумісних груп гаманця !\n\n Торкніться",
"wallet_group_empty_state_text_two": "нижче, щоб зробити новий.", "wallet_group_empty_state_text_two": "нижче, щоб зробити новий.",
"wallet_keys": "Мнемонічна фраза/ключі гаманця", "wallet_keys": "Мнемонічна фраза/ключі гаманця",

View file

@ -928,10 +928,13 @@
"waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ", "waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ",
"wallet": "پرس", "wallet": "پرس",
"wallet_group": "پرس گروپ", "wallet_group": "پرس گروپ",
"wallet_group_description_existing_seed": "آپ نے اس پرس کے لئے موجودہ بیج استعمال کرنے کا انتخاب کیا ہے۔ اگر آپ کو اس کی تصدیق یا لکھنے کی ضرورت ہے تو آپ دوبارہ بیج کی تصدیق کرسکتے ہیں۔",
"wallet_group_description_four": "مکمل طور پر نئے بیج کے ساتھ پرس بنانے کے ل.", "wallet_group_description_four": "مکمل طور پر نئے بیج کے ساتھ پرس بنانے کے ل.",
"wallet_group_description_one": "کیک پرس میں ، آپ بنا سکتے ہیں", "wallet_group_description_one": "کیک پرس میں ، آپ بنا سکتے ہیں",
"wallet_group_description_open_wallet": "بصورت دیگر ، آپ بٹوے کو کھول سکتے ہیں",
"wallet_group_description_three": "دستیاب بٹوے اور/یا پرس گروپوں کی اسکرین کو دیکھنے کے لئے۔ یا منتخب کریں", "wallet_group_description_three": "دستیاب بٹوے اور/یا پرس گروپوں کی اسکرین کو دیکھنے کے لئے۔ یا منتخب کریں",
"wallet_group_description_two": "بیج کے ساتھ بانٹنے کے لئے موجودہ پرس کا انتخاب کرکے۔ ہر بٹوے گروپ میں ہر کرنسی کی قسم کا ایک بٹوے شامل ہوسکتا ہے۔ \n\n آپ منتخب کرسکتے ہیں", "wallet_group_description_two": "بیج کے ساتھ بانٹنے کے لئے موجودہ پرس کا انتخاب کرکے۔ ہر بٹوے گروپ میں ہر کرنسی کی قسم کا ایک بٹوے شامل ہوسکتا ہے۔ \n\n آپ منتخب کرسکتے ہیں",
"wallet_group_description_view_seed": "آپ ہمیشہ اس بیج کو دوبارہ دیکھ سکتے ہیں",
"wallet_group_empty_state_text_one": "ایسا لگتا ہے کہ آپ کے پاس کوئی مطابقت پذیر والیٹ گروپس نہیں ہیں !\n\n نل", "wallet_group_empty_state_text_one": "ایسا لگتا ہے کہ آپ کے پاس کوئی مطابقت پذیر والیٹ گروپس نہیں ہیں !\n\n نل",
"wallet_group_empty_state_text_two": "ایک نیا بنانے کے لئے ذیل میں.", "wallet_group_empty_state_text_two": "ایک نیا بنانے کے لئے ذیل میں.",
"wallet_keys": "بٹوے کے بیج / چابیاں", "wallet_keys": "بٹوے کے بیج / چابیاں",

View file

@ -925,10 +925,13 @@
"waitFewSecondForTxUpdate": "Vui lòng đợi vài giây để giao dịch được phản ánh trong lịch sử giao dịch", "waitFewSecondForTxUpdate": "Vui lòng đợi vài giây để giao dịch được phản ánh trong lịch sử giao dịch",
"wallet": "Cái ví", "wallet": "Cái ví",
"wallet_group": "Nhóm ví", "wallet_group": "Nhóm ví",
"wallet_group_description_existing_seed": "Bạn đã chọn sử dụng một hạt giống hiện có cho ví này. Bạn có thể xác minh lại hạt giống nếu bạn cần xác nhận hoặc viết nó ra.",
"wallet_group_description_four": "Để tạo ra một ví với một hạt giống hoàn toàn mới.", "wallet_group_description_four": "Để tạo ra một ví với một hạt giống hoàn toàn mới.",
"wallet_group_description_one": "Trong ví bánh, bạn có thể tạo", "wallet_group_description_one": "Trong ví bánh, bạn có thể tạo",
"wallet_group_description_open_wallet": "Nếu không, bạn có thể tiếp tục mở ví",
"wallet_group_description_three": "Để xem ví trên ví và/hoặc màn hình nhóm ví. Hoặc chọn", "wallet_group_description_three": "Để xem ví trên ví và/hoặc màn hình nhóm ví. Hoặc chọn",
"wallet_group_description_two": "Bằng cách chọn một ví hiện có để chia sẻ một hạt giống với. Mỗi nhóm ví có thể chứa một ví của mỗi loại tiền tệ. \n\n Bạn có thể chọn", "wallet_group_description_two": "Bằng cách chọn một ví hiện có để chia sẻ một hạt giống với. Mỗi nhóm ví có thể chứa một ví của mỗi loại tiền tệ. \n\n Bạn có thể chọn",
"wallet_group_description_view_seed": "Bạn luôn có thể xem lại hạt giống này dưới",
"wallet_group_empty_state_text_one": "Có vẻ như bạn không có bất kỳ nhóm ví tương thích nào !\n\n Tap", "wallet_group_empty_state_text_one": "Có vẻ như bạn không có bất kỳ nhóm ví tương thích nào !\n\n Tap",
"wallet_group_empty_state_text_two": "Dưới đây để làm một cái mới.", "wallet_group_empty_state_text_two": "Dưới đây để làm một cái mới.",
"wallet_keys": "Hạt giống/khóa ví", "wallet_keys": "Hạt giống/khóa ví",

View file

@ -927,10 +927,13 @@
"waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo", "waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo",
"wallet": "Ohun apamọwọwọ", "wallet": "Ohun apamọwọwọ",
"wallet_group": "Ẹgbẹ apamọwọ", "wallet_group": "Ẹgbẹ apamọwọ",
"wallet_group_description_existing_seed": "O ti yan lati lo irugbin ti o wa tẹlẹ fun ogiriina yii.O le rii daju iru naa lẹẹkansii ti o ba nilo lati jẹrisi tabi kọ silẹ.",
"wallet_group_description_four": "Lati ṣẹda apamọwọ kan pẹlu irugbin tuntun tuntun.", "wallet_group_description_four": "Lati ṣẹda apamọwọ kan pẹlu irugbin tuntun tuntun.",
"wallet_group_description_one": "Ni apamọwọ akara oyinbo, o le ṣẹda a", "wallet_group_description_one": "Ni apamọwọ akara oyinbo, o le ṣẹda a",
"wallet_group_description_open_wallet": "Bibẹẹkọ, o le tẹsiwaju lati ṣii apamọwọ",
"wallet_group_description_three": "Lati wo awọn Woleti ti o wa ati / tabi Iboju Wallt. Tabi yan", "wallet_group_description_three": "Lati wo awọn Woleti ti o wa ati / tabi Iboju Wallt. Tabi yan",
"wallet_group_description_two": "nipa yiyan apamọwọ ti o wa tẹlẹ lati pin irugbin kan pẹlu. Ẹgbẹ apamọwọ kọọkan le ni apamọwọ kan ti iru owo kọọkan. \n\n O le yan", "wallet_group_description_two": "nipa yiyan apamọwọ ti o wa tẹlẹ lati pin irugbin kan pẹlu. Ẹgbẹ apamọwọ kọọkan le ni apamọwọ kan ti iru owo kọọkan. \n\n O le yan",
"wallet_group_description_view_seed": "O le nigbagbogbo wo irugbin yii lẹẹkansi labẹ",
"wallet_group_empty_state_text_one": "O dabi pe o ko ni eyikeyi awọn ẹgbẹ ti o ni ibamu!\n\ntẹ ni kia kia", "wallet_group_empty_state_text_one": "O dabi pe o ko ni eyikeyi awọn ẹgbẹ ti o ni ibamu!\n\ntẹ ni kia kia",
"wallet_group_empty_state_text_two": "ni isalẹ lati ṣe ọkan titun.", "wallet_group_empty_state_text_two": "ni isalẹ lati ṣe ọkan titun.",
"wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́", "wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́",

View file

@ -926,10 +926,13 @@
"waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中", "waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中",
"wallet": "钱包", "wallet": "钱包",
"wallet_group": "钱包组", "wallet_group": "钱包组",
"wallet_group_description_existing_seed": "您已经选择在此钱包中使用现有种子。如果需要确认或写下来,您可能会再次验证种子。",
"wallet_group_description_four": "创建一个带有全新种子的钱包。", "wallet_group_description_four": "创建一个带有全新种子的钱包。",
"wallet_group_description_one": "在蛋糕钱包中,您可以创建一个", "wallet_group_description_one": "在蛋糕钱包中,您可以创建一个",
"wallet_group_description_open_wallet": "否则,您可以继续打开钱包",
"wallet_group_description_three": "查看可用的钱包和/或钱包组屏幕。或选择", "wallet_group_description_three": "查看可用的钱包和/或钱包组屏幕。或选择",
"wallet_group_description_two": "通过选择现有的钱包与种子共享。每个钱包组都可以包含每种货币类型的单个钱包。\n\n您可以选择", "wallet_group_description_two": "通过选择现有的钱包与种子共享。每个钱包组都可以包含每种货币类型的单个钱包。\n\n您可以选择",
"wallet_group_description_view_seed": "您可以随时再次在下面查看此种子",
"wallet_group_empty_state_text_one": "看起来您没有任何兼容的钱包组!\n\n tap", "wallet_group_empty_state_text_one": "看起来您没有任何兼容的钱包组!\n\n tap",
"wallet_group_empty_state_text_two": "下面是一个新的。", "wallet_group_empty_state_text_two": "下面是一个新的。",
"wallet_keys": "钱包种子/密钥", "wallet_keys": "钱包种子/密钥",

1
scripts/android/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
mwebd

View file

@ -23,7 +23,7 @@ MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.22.1" CAKEWALLET_VERSION="4.22.1"
CAKEWALLET_BUILD_NUMBER=241 CAKEWALLET_BUILD_NUMBER=242
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet" CAKEWALLET_SCHEME="cakewallet"

View file

@ -8,50 +8,20 @@ cd "$(dirname "$0")"
NPROC="-j$(nproc)" NPROC="-j$(nproc)"
if [[ "x$(uname)" == "xDarwin" ]];
then
USE_DOCKER="ON"
NPROC="-j1"
fi
../prepare_moneroc.sh ../prepare_moneroc.sh
if [[ ! "x$RUNNER_OS" == "x" ]]; for COIN in monero wownero;
then do
REMOVE_CACHES=ON pushd ../monero_c
fi for target in {x86_64,aarch64}-linux-android armv7a-linux-androideabi
do
# NOTE: -j1 is intentional. Otherwise you will run into weird behaviour on macos if [[ -f "release/${COIN}/${target}_libwallet2_api_c.so" ]];
if [[ ! "x$USE_DOCKER" == "x" ]]; then
then echo "file exist, not building monero_c for ${COIN}/$target.";
for COIN in monero wownero; else
do env -i ./build_single.sh ${COIN} $target $NPROC
pushd ../monero_c unxz -f ../monero_c/release/${COIN}/${target}_libwallet2_api_c.so.xz
docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} x86_64-linux-android $NPROC" fi
# docker run --platform linux/amd64 -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} i686-linux-android $NPROC" done
docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} armv7a-linux-androideabi $NPROC" popd
docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} aarch64-linux-android $NPROC" done
popd
done
else
for COIN in monero wownero;
do
pushd ../monero_c
env -i ./build_single.sh ${COIN} x86_64-linux-android $NPROC
[[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/x86_64-linux-android
# ./build_single.sh ${COIN} i686-linux-android $NPROC
# [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/i686-linux-android
env -i ./build_single.sh ${COIN} armv7a-linux-androideabi $NPROC
[[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/armv7a-linux-androideabi
env -i ./build_single.sh ${COIN} aarch64-linux-android $NPROC
[[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/aarch64-linux-android
popd
unxz -f ../monero_c/release/${COIN}/x86_64-linux-android_libwallet2_api_c.so.xz
unxz -f ../monero_c/release/${COIN}/armv7a-linux-androideabi_libwallet2_api_c.so.xz
unxz -f ../monero_c/release/${COIN}/aarch64-linux-android_libwallet2_api_c.so.xz
[[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/{built,sources}
done
fi

View file

@ -16,7 +16,4 @@ cd mwebd
git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f
gomobile bind -target=android -androidapi 21 . gomobile bind -target=android -androidapi 21 .
mkdir -p ../../../cw_mweb/android/libs/ mkdir -p ../../../cw_mweb/android/libs/
mv ./mwebd.aar $_ cp ./mwebd.aar $_
# cleanup:
cd ..
rm -rf mwebd

View file

@ -19,7 +19,7 @@ MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.22.1" CAKEWALLET_VERSION="4.22.1"
CAKEWALLET_BUILD_NUMBER=288 CAKEWALLET_BUILD_NUMBER=289
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
HAVEN_NAME="Haven" HAVEN_NAME="Haven"

View file

@ -0,0 +1,148 @@
# Usage:
# docker build . -f Dockerfile.linux -t ghcr.io/cake-tech/cake_wallet:main-linux
# docker push ghcr.io/cake-tech/cake_wallet:main-linux
FROM --platform=linux/amd64 docker.io/debian:12
LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet
ENV GOLANG_VERSION=1.23.4
# comes from https://developer.android.com/studio/#command-tools
ENV ANDROID_SDK_TOOLS_VERSION=11076708
# https://developer.android.com/studio/releases/build-tools
ENV ANDROID_PLATFORM_VERSION=34
ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0
ENV FLUTTER_VERSION=3.24.0
# If we ever need to migrate the home directory...
RUN sed -i 's|^root:[^:]*:[^:]*:[^:]*:[^:]*:/root:|root:x:0:0:root:/root:|' /etc/passwd
# mkdir -p /root && rm -rf /root && cp -a /root /root
ENV HOME=/root
# Heavily inspired by cirrusci images
# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/tools/Dockerfile
# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34/Dockerfile
# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34-ndk/Dockerfile
# https://github.com/cirruslabs/docker-images-flutter/blob/master/sdk/Dockerfile
ENV ANDROID_HOME=/opt/android-sdk-linux \
LANG=en_US.UTF-8 \
LC_ALL=en_US.UTF-8 \
LANGUAGE=en_US:en
ENV ANDROID_SDK_ROOT=$ANDROID_HOME \
PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator
RUN set -o xtrace \
&& cd /opt \
&& apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y jq \
&& apt-get install -y default-jdk \
&& apt-get install -y sudo wget zip unzip git openssh-client curl bc software-properties-common build-essential ruby-full ruby-bundler libstdc++6 libpulse0 libglu1-mesa locales lcov libsqlite3-dev --no-install-recommends \
# for x86 emulators
&& apt-get install -y libxtst6 libnss3-dev libnspr4 libxss1 libatk-bridge2.0-0 libgtk-3-0 libgdk-pixbuf2.0-0 \
&& apt-get install -y -qq xxd \
&& apt-get install -y lftp \
&& apt-get install -qq -y sqlite3 libsqlite3-dev \
# linux desktop dependencies
&& apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev \
# monero_c dependencies
&& apt-get install -y ccache build-essential autoconf libtool gperf llvm \
# extra stuff for KVM
&& apt-get install -y udev qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils \
# for linux tests
&& apt-get install -y xvfb network-manager ffmpeg x11-utils \
&& rm -rf /var/lib/apt/lists/* \
&& sh -c 'echo "en_US.UTF-8 UTF-8" > /etc/locale.gen' \
&& locale-gen \
&& update-locale LANG=en_US.UTF-8
# install nodejs for actions
RUN apt-get update && \
apt-get install -y curl && \
curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \
apt-get install -y nodejs && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz &&\
rm -rf /usr/local/go &&\
tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz
ENV PATH=${PATH}:/usr/local/go/bin:${HOME}/go/bin
ENV GOROOT=/usr/local/go
ENV GOPATH=${HOME}/go
RUN go install golang.org/x/mobile/cmd/gomobile@latest
RUN gomobile init
RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip -O android-sdk-tools.zip \
&& mkdir -p ${ANDROID_HOME}/cmdline-tools/ \
&& unzip -q android-sdk-tools.zip -d ${ANDROID_HOME}/cmdline-tools/ \
&& mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \
&& chown -R root:root $ANDROID_HOME \
&& rm android-sdk-tools.zip \
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& yes | sdkmanager --licenses \
&& wget -O /usr/bin/android-wait-for-emulator https://raw.githubusercontent.com/travis-ci/travis-cookbooks/master/community-cookbooks/android-sdk/files/default/android-wait-for-emulator \
&& chmod +x /usr/bin/android-wait-for-emulator \
&& sdkmanager platform-tools \
&& mkdir -p ${HOME}/.android \
&& touch ${HOME}/.android/repositories.cfg \
&& git config --global user.email "czarek@cakewallet.com" \
&& git config --global user.name "CakeWallet CI"
# emulator is not available on linux/arm64 (https://issuetracker.google.com/issues/227219818)
RUN if [ $(uname -m) == "x86_64" ]; then sdkmanager emulator ; fi
# Extra dependencies to not download them for cake wallet build
RUN yes | sdkmanager \
"platforms;android-$ANDROID_PLATFORM_VERSION" \
"build-tools;$ANDROID_BUILD_TOOLS_VERSION" \
"platforms;android-33" \
"build-tools;33.0.2" \
"build-tools;33.0.1" \
"build-tools;33.0.0" \
"build-tools;35.0.0"
ENV ANDROID_NDK_VERSION=27.2.12479018
# Extra ndk dependency for sp_scanner
RUN yes | sdkmanager "ndk;$ANDROID_NDK_VERSION" \
"ndk;27.0.12077973"
# https://github.com/ReactiveCircus/android-emulator-runner dependencies for tests
RUN yes | sdkmanager "system-images;android-29;default;x86" \
"system-images;android-29;default;x86_64" \
"system-images;android-31;default;x86_64" \
"platforms;android-29"
# fake the KVM status so android emulator doesn't complain (that much)
RUN (addgroup kvm || true) && \
adduser root kvm && \
mkdir -p /etc/udev/rules.d/ && \
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | tee /etc/udev/rules.d/99-kvm4all.rules
ENV PATH=${HOME}/.cargo/bin:${PATH}
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
cargo install cargo-ndk && \
for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu; \
do \
rustup target add --toolchain stable $target; \
done
ENV HOME=${HOME}
ENV FLUTTER_HOME=${HOME}/sdks/flutter/${FLUTTER_VERSION}
ENV FLUTTER_ROOT=$FLUTTER_HOME
ENV PATH=${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin
RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME}
RUN yes | flutter doctor --android-licenses \
&& flutter doctor \
&& chown -R root:root ${FLUTTER_HOME}
RUN flutter precache

View file

@ -15,7 +15,7 @@ fi
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.12.1" CAKEWALLET_VERSION="1.12.1"
CAKEWALLET_BUILD_NUMBER=42 CAKEWALLET_BUILD_NUMBER=43
if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
echo "Wrong app type." echo "Wrong app type."

View file

@ -1,9 +1,5 @@
#!/bin/bash #!/bin/bash
. ./config.sh
set -x -e set -x -e
cd "$(dirname "$0")" cd "$(dirname "$0")"
@ -15,7 +11,15 @@ NPROC="-j$(nproc)"
for COIN in monero wownero; for COIN in monero wownero;
do do
pushd ../monero_c pushd ../monero_c
./build_single.sh ${COIN} $(gcc -dumpmachine) $NPROC for target in x86_64-linux-gnu
do
if [[ -f "release/${COIN}/${target}_libwallet2_api_c.so" ]];
then
echo "file exist, not building monero_c for ${COIN}/$target.";
else
./build_single.sh ${COIN} $target $NPROC
unxz -f ../monero_c/release/${COIN}/${target}_libwallet2_api_c.so.xz
fi
done
popd popd
unxz -f ../monero_c/release/${COIN}/$(gcc -dumpmachine)_libwallet2_api_c.so.xz done
done

View file

@ -22,7 +22,7 @@ MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.15.1" CAKEWALLET_VERSION="1.15.1"
CAKEWALLET_BUILD_NUMBER=100 CAKEWALLET_BUILD_NUMBER=101
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

View file

@ -4,9 +4,9 @@ set -x -e
cd "$(dirname "$0")" cd "$(dirname "$0")"
if [[ ! -d "monero_c" ]]; if [[ ! -d "monero_c/.git" ]];
then then
git clone https://github.com/mrcyjanek/monero_c --branch master git clone https://github.com/mrcyjanek/monero_c --branch master monero_c
cd monero_c cd monero_c
git checkout af5277f96073917185864d3596e82b67bee54e78 git checkout af5277f96073917185864d3596e82b67bee54e78
git reset --hard git reset --hard

1
scripts/windows/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
actions-runner

View file

@ -0,0 +1,68 @@
# Usage:
# docker build . -f Dockerfile.windows -t ghcr.io/cake-tech/cake_wallet:main-windows
# docker push ghcr.io/cake-tech/cake_wallet:main-windows
FROM mcr.microsoft.com/windows/servercore:ltsc2022
ENV FLUTTER_VERSION=3.24.0
ENV GIT_VERSION=2.47.1
ENV VS_INSTALLED_DIR="C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools"
ENV PATH="C:\Users\ContainerAdministrator\.cargo\bin;C:\ProgramData\chocolatey\bin;C:\flutter\flutter\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps"
ENV RUNNER_VERSION=2.321.0
ENV RUNNER_URL=https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-win-x64-${RUNNER_VERSION}.zip
ENV RUNNER_WORKDIR=_work
RUN powershell -Command \
curl.exe -L https://aka.ms/vs/17/release/vc_redist.x64.exe -o vc_redist.x64.exe ; \
Start-Process -Wait -FilePath .\vc_redist.x64.exe -ArgumentList '/quiet', '/install' ; \
Remove-Item -Force vc_redist.x64.exe
RUN powershell -Command \
$GIT_VERSION = [Environment]::GetEnvironmentVariable('GIT_VERSION'); \
curl.exe -L https://github.com/git-for-windows/git/releases/download/v$($GIT_VERSION).windows.1/Git-$($GIT_VERSION)-64-bit.exe -o git_installer.exe ; \
Start-Process -Wait -FilePath .\git_installer.exe -ArgumentList '/SILENT', '/NOICONS' ; \
Remove-Item -Force git_installer.exe
RUN powershell -NoProfile -ExecutionPolicy Bypass -Command \
Set-ExecutionPolicy RemoteSigned -Scope Process; \
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; \
Invoke-WebRequest https://chocolatey.org/install.ps1 -UseBasicP -OutFile install.ps1; \
powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1; \
Remove-Item -Force install.ps1
RUN choco install -y visualstudio2022community
RUN choco install -y visualstudio2022-workload-nativedesktop
RUN choco install -y nodejs
RUN choco install -y go
RUN choco install -y 7zip
RUN powershell -Command \
curl.exe -L https://win.rustup.rs -o rustup-init.exe; \
Start-Process -Wait -FilePath .\rustup-init.exe -ArgumentList "-y"; \
Remove-Item -Force .\rustup-init.exe
RUN powershell -Command \
curl.exe -L https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -o C:\Windows\System32\nuget.exe
RUN powershell -Command \
$FLUTTER_VERSION = [Environment]::GetEnvironmentVariable('FLUTTER_VERSION'); \
curl.exe -L https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_$($FLUTTER_VERSION)-stable.zip -o flutter.zip ; \
7z x flutter.zip -oC:\flutter -bsp1 -bse1 ; \
Remove-Item -Force flutter.zip
RUN flutter precache
WORKDIR C:\\actions-runner
RUN powershell -Command \
curl.exe -L $env:RUNNER_URL -o 'actions-runner.zip'; \
7z x actions-runner.zip -oC:\actions-runner -bsp1 -bse1 ; \
Remove-Item -Path 'actions-runner.zip'
COPY actions-runner/.credentials /actions-runner/.credentials
COPY actions-runner/.credentials_rsaparams /actions-runner/.credentials_rsaparams
COPY actions-runner/.runner /actions-runner/.runner
COPY ci_entrypoint.ps1 /actions-runner/ci_entrypoint.ps1
ENTRYPOINT ["powershell", "-File", "ci_entrypoint.ps1"]

View file

@ -0,0 +1,5 @@
$runnerDir = "C:\actions-runner"
$runCmd = "$runnerDir\run.cmd"
Write-Host "Starting the runner..."
& $runCmd

Some files were not shown because too many files have changed in this diff Show more