diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json
deleted file mode 100644
index b3db758e..00000000
--- a/.fvm/fvm_config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "flutterSdkVersion": "stable",
- "flavors": {}
-}
\ No newline at end of file
diff --git a/.github/scripts/firebase/README.md b/.github/scripts/firebase/README.md
new file mode 100644
index 00000000..f5b8e549
--- /dev/null
+++ b/.github/scripts/firebase/README.md
@@ -0,0 +1,50 @@
+# Firebase GitHub Secrets Scripts
+
+This directory contains scripts for managing Firebase service account secrets used by GitHub Actions workflows.
+
+## Scripts
+
+### setup-github-secrets.sh
+
+Automates the creation and configuration of Firebase service accounts and GitHub repository secrets.
+
+**What it does:**
+- Creates service accounts in Google Cloud projects (if they don't exist)
+- Grants required IAM permissions for Firebase deployments
+- Generates service account keys
+- Creates/updates GitHub repository secrets
+- Cleans up sensitive key files
+
+**Usage:**
+```bash
+./.github/scripts/firebase/setup-github-secrets.sh
+```
+
+### verify-github-secrets.sh
+
+Verifies that Firebase service accounts and GitHub secrets are properly configured.
+
+**What it checks:**
+- Prerequisites (gcloud, gh, jq installations)
+- Authentication status (Google Cloud and GitHub)
+- Firebase project accessibility
+- Service account existence and permissions
+- GitHub secret configuration
+
+**Usage:**
+```bash
+./.github/scripts/firebase/verify-github-secrets.sh
+```
+
+## Required Permissions
+
+To run these scripts, you need:
+- Admin access to Firebase projects (`komodo-defi-sdk` and `komodo-playground`)
+- Write access to GitHub repository secrets
+- Google Cloud CLI (`gcloud`) authenticated
+- GitHub CLI (`gh`) authenticated
+
+## Related Documentation
+
+For detailed setup instructions and troubleshooting, see:
+[Firebase Deployment Setup Guide](../../../docs/firebase/firebase-deployment-setup.md)
diff --git a/.github/scripts/firebase/setup-github-secrets.sh b/.github/scripts/firebase/setup-github-secrets.sh
new file mode 100755
index 00000000..9a1bf3c5
--- /dev/null
+++ b/.github/scripts/firebase/setup-github-secrets.sh
@@ -0,0 +1,260 @@
+#!/bin/bash
+
+# Setup Firebase GitHub Secrets Script
+# This script automates the creation and configuration of Firebase service accounts
+# and GitHub secrets for the Komodo DeFi SDK Flutter project
+
+set -e # Exit on error
+
+# Color codes for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Configuration
+GITHUB_REPO="KomodoPlatform/komodo-defi-sdk-flutter"
+SDK_PROJECT_ID="komodo-defi-sdk"
+PLAYGROUND_PROJECT_ID="komodo-playground"
+SDK_SERVICE_ACCOUNT_NAME="github-actions-deploy"
+PLAYGROUND_SERVICE_ACCOUNT_NAME="github-actions-deploy"
+
+# Function to print colored output
+print_status() {
+ echo -e "${BLUE}[INFO]${NC} $1"
+}
+
+print_success() {
+ echo -e "${GREEN}[SUCCESS]${NC} $1"
+}
+
+print_error() {
+ echo -e "${RED}[ERROR]${NC} $1"
+}
+
+print_warning() {
+ echo -e "${YELLOW}[WARNING]${NC} $1"
+}
+
+# Function to check if a command exists
+check_command() {
+ if ! command -v $1 &> /dev/null; then
+ print_error "$1 is not installed. Please install it first."
+ return 1
+ fi
+ return 0
+}
+
+# Function to check if user is authenticated with gcloud
+check_gcloud_auth() {
+ if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" | grep -q .; then
+ print_error "Not authenticated with gcloud. Please run: gcloud auth login"
+ return 1
+ fi
+ return 0
+}
+
+# Function to check if user is authenticated with gh
+check_gh_auth() {
+ if ! gh auth status &> /dev/null; then
+ print_error "Not authenticated with GitHub CLI. Please run: gh auth login"
+ return 1
+ fi
+ return 0
+}
+
+# Function to create service account if it doesn't exist
+create_service_account_if_needed() {
+ local project_id=$1
+ local service_account_name=$2
+ local service_account_email="${service_account_name}@${project_id}.iam.gserviceaccount.com"
+
+ print_status "Checking if service account ${service_account_email} exists..."
+
+ if gcloud iam service-accounts describe "${service_account_email}" --project="${project_id}" &> /dev/null; then
+ print_status "Service account already exists"
+ else
+ print_status "Creating service account..."
+ gcloud iam service-accounts create "${service_account_name}" \
+ --display-name="GitHub Actions Deploy" \
+ --description="Service account for GitHub Actions Firebase deployments" \
+ --project="${project_id}"
+ print_success "Service account created"
+ fi
+}
+
+# Function to grant necessary permissions to service account
+grant_permissions() {
+ local project_id=$1
+ local service_account_email=$2
+
+ print_status "Granting permissions to ${service_account_email}..."
+
+ # Array of roles to grant
+ local roles=(
+ "roles/firebase.hosting.admin"
+ "roles/firebase.rules.admin"
+ "roles/iam.serviceAccountTokenCreator"
+ )
+
+ for role in "${roles[@]}"; do
+ print_status "Granting ${role}..."
+ gcloud projects add-iam-policy-binding "${project_id}" \
+ --member="serviceAccount:${service_account_email}" \
+ --role="${role}" \
+ --quiet &> /dev/null || true
+ done
+
+ print_success "Permissions granted"
+}
+
+# Function to generate service account key
+generate_service_account_key() {
+ local project_id=$1
+ local service_account_name=$2
+ local key_file=$3
+ local service_account_email="${service_account_name}@${project_id}.iam.gserviceaccount.com"
+
+ print_status "Generating service account key for ${service_account_email}..."
+
+ gcloud iam service-accounts keys create "${key_file}" \
+ --iam-account="${service_account_email}" \
+ --project="${project_id}"
+
+ print_success "Service account key generated: ${key_file}"
+}
+
+# Function to create or update GitHub secret
+create_github_secret() {
+ local secret_name=$1
+ local key_file=$2
+
+ print_status "Creating/updating GitHub secret: ${secret_name}..."
+
+ # Check if running in GitHub Actions or local
+ if [ -n "$GITHUB_REPOSITORY" ]; then
+ # Running in GitHub Actions
+ gh secret set "${secret_name}" < "${key_file}" --repo "${GITHUB_REPOSITORY}"
+ else
+ # Running locally
+ gh secret set "${secret_name}" < "${key_file}" --repo "${GITHUB_REPO}"
+ fi
+
+ print_success "GitHub secret ${secret_name} created/updated"
+}
+
+# Main execution
+main() {
+ print_status "Starting Firebase GitHub secrets setup..."
+
+ # Step 1: Check prerequisites
+ print_status "Checking prerequisites..."
+
+ if ! check_command "gcloud"; then
+ print_error "Please install Google Cloud SDK: https://cloud.google.com/sdk/docs/install"
+ exit 1
+ fi
+
+ if ! check_command "gh"; then
+ print_error "Please install GitHub CLI: https://cli.github.com/manual/installation"
+ exit 1
+ fi
+
+ if ! check_gcloud_auth; then
+ exit 1
+ fi
+
+ if ! check_gh_auth; then
+ exit 1
+ fi
+
+ print_success "All prerequisites met"
+
+ # Step 2: Set up komodo-defi-sdk project
+ print_status "Setting up komodo-defi-sdk project..."
+
+ # Set the project
+ gcloud config set project "${SDK_PROJECT_ID}" --quiet
+
+ # Create service account if needed
+ create_service_account_if_needed "${SDK_PROJECT_ID}" "${SDK_SERVICE_ACCOUNT_NAME}"
+
+ # Grant permissions
+ grant_permissions "${SDK_PROJECT_ID}" "${SDK_SERVICE_ACCOUNT_NAME}@${SDK_PROJECT_ID}.iam.gserviceaccount.com"
+
+ # Generate key
+ SDK_KEY_FILE="komodo-defi-sdk-key.json"
+ generate_service_account_key "${SDK_PROJECT_ID}" "${SDK_SERVICE_ACCOUNT_NAME}" "${SDK_KEY_FILE}"
+
+ # Create GitHub secret
+ create_github_secret "FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK" "${SDK_KEY_FILE}"
+
+ # Step 3: Set up komodo-playground project
+ print_status "Setting up komodo-playground project..."
+
+ # Set the project
+ gcloud config set project "${PLAYGROUND_PROJECT_ID}" --quiet
+
+ # Create service account if needed
+ create_service_account_if_needed "${PLAYGROUND_PROJECT_ID}" "${PLAYGROUND_SERVICE_ACCOUNT_NAME}"
+
+ # Grant permissions
+ grant_permissions "${PLAYGROUND_PROJECT_ID}" "${PLAYGROUND_SERVICE_ACCOUNT_NAME}@${PLAYGROUND_PROJECT_ID}.iam.gserviceaccount.com"
+
+ # Generate key
+ PLAYGROUND_KEY_FILE="komodo-playground-key.json"
+ generate_service_account_key "${PLAYGROUND_PROJECT_ID}" "${PLAYGROUND_SERVICE_ACCOUNT_NAME}" "${PLAYGROUND_KEY_FILE}"
+
+ # Create GitHub secret
+ create_github_secret "FIREBASE_SERVICE_ACCOUNT_KOMODO_PLAYGROUND" "${PLAYGROUND_KEY_FILE}"
+
+ # Step 4: Clean up sensitive files
+ print_status "Cleaning up sensitive files..."
+
+ if [ -f "${SDK_KEY_FILE}" ]; then
+ rm -f "${SDK_KEY_FILE}"
+ print_success "Removed ${SDK_KEY_FILE}"
+ fi
+
+ if [ -f "${PLAYGROUND_KEY_FILE}" ]; then
+ rm -f "${PLAYGROUND_KEY_FILE}"
+ print_success "Removed ${PLAYGROUND_KEY_FILE}"
+ fi
+
+ # Step 5: Verify setup
+ print_status "Verifying setup..."
+
+ # Check if secrets exist
+ if gh secret list --repo "${GITHUB_REPO}" | grep -q "FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK"; then
+ print_success "FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK secret exists"
+ else
+ print_error "FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK secret not found"
+ fi
+
+ if gh secret list --repo "${GITHUB_REPO}" | grep -q "FIREBASE_SERVICE_ACCOUNT_KOMODO_PLAYGROUND"; then
+ print_success "FIREBASE_SERVICE_ACCOUNT_KOMODO_PLAYGROUND secret exists"
+ else
+ print_error "FIREBASE_SERVICE_ACCOUNT_KOMODO_PLAYGROUND secret not found"
+ fi
+
+ print_success "Firebase GitHub secrets setup completed!"
+ print_status "You can now test the deployment by creating a pull request or pushing to the dev branch."
+}
+
+# Display banner
+echo "================================================"
+echo "Firebase GitHub Secrets Setup Script"
+echo "================================================"
+echo
+
+# Confirm before proceeding
+read -p "This script will set up Firebase service accounts and GitHub secrets. Continue? (y/N) " -n 1 -r
+echo
+if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ print_warning "Setup cancelled"
+ exit 0
+fi
+
+# Run main function
+main
diff --git a/.github/scripts/firebase/verify-github-secrets.sh b/.github/scripts/firebase/verify-github-secrets.sh
new file mode 100755
index 00000000..91d43073
--- /dev/null
+++ b/.github/scripts/firebase/verify-github-secrets.sh
@@ -0,0 +1,255 @@
+#!/bin/bash
+
+# Verify Firebase GitHub Secrets Script (Updated)
+# This script checks the current status of Firebase service accounts and GitHub secrets
+# Updated to check for the actual service accounts in use
+
+set -e # Exit on error
+
+# Color codes for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Configuration
+GITHUB_REPO="KomodoPlatform/komodo-defi-sdk-flutter"
+SDK_PROJECT_ID="komodo-defi-sdk"
+PLAYGROUND_PROJECT_ID="komodo-playground"
+# Updated to use the actual service account names
+SDK_SERVICE_ACCOUNT_NAME="github-action-839744467"
+PLAYGROUND_SERVICE_ACCOUNT_NAME="github-action-839744467"
+
+# Function to print colored output
+print_status() {
+ echo -e "${BLUE}[INFO]${NC} $1"
+}
+
+print_success() {
+ echo -e "${GREEN}[✓]${NC} $1"
+}
+
+print_error() {
+ echo -e "${RED}[✗]${NC} $1"
+}
+
+print_warning() {
+ echo -e "${YELLOW}[!]${NC} $1"
+}
+
+# Function to check if a command exists
+check_command() {
+ if command -v $1 &> /dev/null; then
+ print_success "$1 is installed"
+ return 0
+ else
+ print_error "$1 is not installed"
+ return 1
+ fi
+}
+
+# Function to check gcloud authentication
+check_gcloud_auth() {
+ if gcloud auth list --filter=status:ACTIVE --format="value(account)" | grep -q .; then
+ local account=$(gcloud auth list --filter=status:ACTIVE --format="value(account)" | head -n1)
+ print_success "Authenticated with gcloud as: ${account}"
+ return 0
+ else
+ print_error "Not authenticated with gcloud"
+ return 1
+ fi
+}
+
+# Function to check GitHub CLI authentication
+check_gh_auth() {
+ if gh auth status &> /dev/null; then
+ print_success "Authenticated with GitHub CLI"
+ return 0
+ else
+ print_error "Not authenticated with GitHub CLI"
+ return 1
+ fi
+}
+
+# Function to check if service account exists
+check_service_account() {
+ local project_id=$1
+ local service_account_name=$2
+ local service_account_email="${service_account_name}@${project_id}.iam.gserviceaccount.com"
+
+ if gcloud iam service-accounts describe "${service_account_email}" --project="${project_id}" &> /dev/null; then
+ print_success "Service account exists: ${service_account_email}"
+ return 0
+ else
+ print_error "Service account does not exist: ${service_account_email}"
+ return 1
+ fi
+}
+
+# Function to check service account permissions
+check_permissions() {
+ local project_id=$1
+ local service_account_email=$2
+
+ print_status "Checking permissions for ${service_account_email}..."
+
+ # Get the IAM policy for the project
+ local policy=$(gcloud projects get-iam-policy "${project_id}" --format=json 2>/dev/null)
+
+ # Updated required roles - only checking for the essential ones
+ local required_roles=(
+ "roles/firebasehosting.admin"
+ )
+
+ # Optional but recommended roles
+ local optional_roles=(
+ "roles/firebase.rules.admin"
+ "roles/iam.serviceAccountTokenCreator"
+ "roles/firebaseauth.admin"
+ )
+
+ local missing_required=()
+ local missing_optional=()
+
+ # Check required roles
+ for role in "${required_roles[@]}"; do
+ if echo "${policy}" | jq -e ".bindings[] | select(.role == \"${role}\") | .members[] | select(. == \"serviceAccount:${service_account_email}\")" &> /dev/null; then
+ print_success " Has required permission: ${role}"
+ else
+ print_error " Missing required permission: ${role}"
+ missing_required+=("${role}")
+ fi
+ done
+
+ # Check optional roles
+ for role in "${optional_roles[@]}"; do
+ if echo "${policy}" | jq -e ".bindings[] | select(.role == \"${role}\") | .members[] | select(. == \"serviceAccount:${service_account_email}\")" &> /dev/null; then
+ print_success " Has optional permission: ${role}"
+ else
+ print_warning " Missing optional permission: ${role}"
+ missing_optional+=("${role}")
+ fi
+ done
+
+ if [ ${#missing_required[@]} -eq 0 ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Function to check GitHub secret
+check_github_secret() {
+ local secret_name=$1
+
+ # Check if running in GitHub Actions or local
+ local repo="${GITHUB_REPOSITORY:-${GITHUB_REPO}}"
+
+ if gh secret list --repo "${repo}" 2>/dev/null | grep -q "^${secret_name}"; then
+ local updated=$(gh secret list --repo "${repo}" | grep "^${secret_name}" | awk '{print $2}')
+ print_success "GitHub secret exists: ${secret_name} (Updated: ${updated})"
+ return 0
+ else
+ print_error "GitHub secret does not exist: ${secret_name}"
+ return 1
+ fi
+}
+
+# Function to check Firebase project
+check_firebase_project() {
+ local project_id=$1
+
+ if gcloud projects describe "${project_id}" &> /dev/null; then
+ print_success "Firebase project exists: ${project_id}"
+ return 0
+ else
+ print_error "Firebase project does not exist or you don't have access: ${project_id}"
+ return 1
+ fi
+}
+
+# Main verification
+main() {
+ local all_checks_passed=true
+
+ echo "================================================"
+ echo "Firebase GitHub Secrets Verification (Updated)"
+ echo "================================================"
+ echo
+
+ # Check prerequisites
+ print_status "Checking prerequisites..."
+ echo
+
+ check_command "gcloud" || all_checks_passed=false
+ check_command "gh" || all_checks_passed=false
+ check_command "jq" || all_checks_passed=false
+ echo
+
+ # Check authentication
+ print_status "Checking authentication..."
+ echo
+
+ check_gcloud_auth || all_checks_passed=false
+ check_gh_auth || all_checks_passed=false
+ echo
+
+ # Check Firebase projects
+ print_status "Checking Firebase projects..."
+ echo
+
+ check_firebase_project "${SDK_PROJECT_ID}" || all_checks_passed=false
+ check_firebase_project "${PLAYGROUND_PROJECT_ID}" || all_checks_passed=false
+ echo
+
+ # Check komodo-defi-sdk setup
+ print_status "Checking komodo-defi-sdk setup..."
+ echo
+
+ if check_service_account "${SDK_PROJECT_ID}" "${SDK_SERVICE_ACCOUNT_NAME}"; then
+ check_permissions "${SDK_PROJECT_ID}" "${SDK_SERVICE_ACCOUNT_NAME}@${SDK_PROJECT_ID}.iam.gserviceaccount.com" || all_checks_passed=false
+ else
+ all_checks_passed=false
+ fi
+ echo
+
+ # Check komodo-playground setup
+ print_status "Checking komodo-playground setup..."
+ echo
+
+ if check_service_account "${PLAYGROUND_PROJECT_ID}" "${PLAYGROUND_SERVICE_ACCOUNT_NAME}"; then
+ check_permissions "${PLAYGROUND_PROJECT_ID}" "${PLAYGROUND_SERVICE_ACCOUNT_NAME}@${PLAYGROUND_PROJECT_ID}.iam.gserviceaccount.com" || all_checks_passed=false
+ else
+ all_checks_passed=false
+ fi
+ echo
+
+ # Check GitHub secrets
+ print_status "Checking GitHub secrets..."
+ echo
+
+ check_github_secret "FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK" || all_checks_passed=false
+ check_github_secret "FIREBASE_SERVICE_ACCOUNT_KOMODO_PLAYGROUND" || all_checks_passed=false
+ echo
+
+ # Summary
+ echo "================================================"
+ echo "Summary:"
+ echo
+ print_status "Service Accounts in use:"
+ echo " - SDK: github-action-839744467@komodo-defi-sdk.iam.gserviceaccount.com"
+ echo " - Playground: github-action-839744467@komodo-playground.iam.gserviceaccount.com"
+ echo
+
+ if [ "${all_checks_passed}" = true ]; then
+ print_success "All required checks passed! Firebase secrets are properly configured."
+ print_warning "Note: Some optional permissions may be missing but the setup should work fine."
+ else
+ print_error "Some required checks failed. Please review the errors above."
+ fi
+ echo "================================================"
+}
+
+# Run main function
+main
diff --git a/.github/workflows/firebase-hosting-merge.yml b/.github/workflows/firebase-hosting-merge.yml
index fd8416a2..e8e0fa4b 100644
--- a/.github/workflows/firebase-hosting-merge.yml
+++ b/.github/workflows/firebase-hosting-merge.yml
@@ -14,10 +14,14 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- - name: Install Melos
- run: dart pub global activate melos
- - name: Bootstrap workspace
- run: melos bootstrap
+ # Disabled melos generation due to circular dependency issues caused by komodo_defi_rpc_methods
+ # and komodo_defi_types packages. This will be revisited in the future.
+ # The app should already have the necessary generated files committed to the repository. If
+ # this is not the case, we have bigger issues.
+ # - name: Install Melos
+ # run: dart pub global activate melos
+ # - name: Bootstrap workspace
+ # run: melos bootstrap
- name: Cache dependencies
uses: actions/cache@v3
with:
@@ -38,13 +42,18 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- - name: Install Melos
- run: dart pub global activate melos
- - name: Bootstrap workspace
- run: melos bootstrap
+ # See Melos comment above
+ # - name: Install Melos
+ # run: dart pub global activate melos
+ # - name: Bootstrap workspace
+ # run: melos bootstrap
- name: Run dry web build to generate assets (expected to fail)
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd playground && flutter build web --release || echo "Dry build completed (failure expected)"
- name: Build playground web
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd playground && flutter build web --release
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
@@ -64,11 +73,14 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- - name: Install Melos
- run: dart pub global activate melos
- - name: Bootstrap workspace
- run: melos bootstrap
+ # See Melos comment above
+ # - name: Install Melos
+ # run: dart pub global activate melos
+ # - name: Bootstrap workspace
+ # run: melos bootstrap
- name: Build SDK example web
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd packages/komodo_defi_sdk/example && flutter build web --release
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
@@ -77,5 +89,6 @@ jobs:
channelId: live
projectId: komodo-defi-sdk
entryPoint: ./packages/komodo_defi_sdk/example
+ target: kdf-sdk
env:
FIREBASE_CLI_EXPERIMENTS: webframeworks
diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml
index e9ff40f4..3e464fd0 100644
--- a/.github/workflows/firebase-hosting-pull-request.yml
+++ b/.github/workflows/firebase-hosting-pull-request.yml
@@ -16,21 +16,25 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- - name: Install Melos
- run: dart pub global activate melos
- - name: Bootstrap workspace
- run: melos bootstrap
- - name: Cache dependencies
- uses: actions/cache@v3
- with:
- path: |
- ~/.pub-cache
- **/.dart_tool
- **/.flutter-plugins
- **/.flutter-plugins-dependencies
- key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
- restore-keys: |
- ${{ runner.os }}-pub-
+ # Disabled melos generation due to circular dependency issues caused by komodo_defi_rpc_methods
+ # and komodo_defi_types packages. This will be revisited in the future.
+ # The app should already have the necessary generated files committed to the repository. If
+ # this is not the case, we have bigger issues.
+ # - name: Install Melos
+ # run: dart pub global activate melos
+ # - name: Bootstrap workspace
+ # run: melos bootstrap
+ # - name: Cache dependencies
+ # uses: actions/cache@v3
+ # with:
+ # path: |
+ # ~/.pub-cache
+ # **/.dart_tool
+ # **/.flutter-plugins
+ # **/.flutter-plugins-dependencies
+ # key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
+ # restore-keys: |
+ # ${{ runner.os }}-pub-
build_and_preview_playground_preview:
needs: setup
@@ -41,13 +45,18 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- - name: Install Melos
- run: dart pub global activate melos
- - name: Bootstrap workspace
- run: melos bootstrap
+ # See Melos comment above
+ # - name: Install Melos
+ # run: dart pub global activate melos
+ # - name: Bootstrap workspace
+ # run: melos bootstrap
- name: Run dry web build to generate assets (expected to fail)
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd playground && flutter build web --release || echo "Dry build completed (failure expected)"
- name: Build playground web
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd playground && flutter build web --release
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
@@ -67,13 +76,18 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- - name: Install Melos
- run: dart pub global activate melos
- - name: Bootstrap workspace
- run: melos bootstrap
+ # See Melos comment above
+ # - name: Install Melos
+ # run: dart pub global activate melos
+ # - name: Bootstrap workspace
+ # run: melos bootstrap
- name: Run dry web build to generate assets (expected to fail)
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd packages/komodo_defi_sdk/example && flutter build web --release || echo "Dry build completed (failure expected)"
- name: Build SDK example web
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd packages/komodo_defi_sdk/example && flutter build web --release
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
@@ -81,5 +95,6 @@ jobs:
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK }}
projectId: komodo-defi-sdk
entryPoint: ./packages/komodo_defi_sdk/example
+ target: kdf-sdk
env:
FIREBASE_CLI_EXPERIMENTS: webframeworks
diff --git a/.github/workflows/flutter-tests.yml b/.github/workflows/flutter-tests.yml
new file mode 100644
index 00000000..58d0758a
--- /dev/null
+++ b/.github/workflows/flutter-tests.yml
@@ -0,0 +1,198 @@
+name: Flutter package tests (consolidated)
+permissions:
+ contents: read
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main, dev, feat/**, bugfix/**, hotfix/**]
+ workflow_dispatch:
+ inputs:
+ package:
+ description: "Optional package path to test (e.g., packages/komodo_coin_updates or komodo_coin_updates)"
+ required: false
+ package_regex:
+ description: "Optional regex to filter packages (applied to full path under packages/*)"
+ required: false
+
+jobs:
+ test-all:
+ name: Flutter tests (all packages)
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Flutter (stable)
+ uses: subosito/flutter-action@v2
+ with:
+ channel: stable
+ flutter-version: "3.35.1"
+ architecture: x64
+
+ - name: Cache pub dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.pub-cache
+ **/.dart_tool
+ key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-pub-
+
+ - name: Discover packages
+ id: discover
+ shell: bash
+ run: |
+ set -euo pipefail
+ input_pkg="${{ github.event.inputs.package || '' }}"
+ input_re="${{ github.event.inputs.package_regex || '' }}"
+
+ # Discover all packages with pubspec.yaml
+ mapfile -t all_pkgs < <(find packages -mindepth 1 -maxdepth 1 -type d -exec test -e '{}/pubspec.yaml' ';' -print | sort)
+
+ filter_pkgs=()
+ if [ -n "$input_pkg" ]; then
+ # Normalize to packages/
+ if [[ "$input_pkg" != packages/* ]]; then
+ input_pkg="packages/$input_pkg"
+ fi
+ if [ -e "$input_pkg/pubspec.yaml" ]; then
+ filter_pkgs+=("$input_pkg")
+ else
+ echo "No pubspec.yaml found at $input_pkg; no packages to test" >&2
+ echo "packages=" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+ elif [ -n "$input_re" ]; then
+ while IFS= read -r p; do
+ if echo "$p" | grep -Eq "$input_re"; then
+ filter_pkgs+=("$p")
+ fi
+ done < <(printf '%s\n' "${all_pkgs[@]}")
+ else
+ filter_pkgs=("${all_pkgs[@]}")
+ fi
+
+ # Keep only packages that contain a test/ directory
+ with_tests=()
+ for p in "${filter_pkgs[@]}"; do
+ if [ -d "$p/test" ]; then
+ with_tests+=("$p")
+ fi
+ done
+
+ if [ ${#with_tests[@]} -eq 0 ]; then
+ echo "packages=" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+
+ # Output space-separated list of packages
+ echo "packages=${with_tests[*]}" >> "$GITHUB_OUTPUT"
+ echo "Found packages with tests: ${with_tests[*]}"
+
+ - name: Install dependencies for all packages
+ if: steps.discover.outputs.packages != ''
+ shell: bash
+ run: |
+ packages="${{ steps.discover.outputs.packages }}"
+ if [ -n "$packages" ]; then
+ for pkg in $packages; do
+ echo "Installing dependencies for $pkg..."
+ cd "$pkg"
+ flutter pub get
+ cd - > /dev/null
+ done
+ fi
+
+ - name: Run dry web build to generate assets (expected to fail)
+ if: steps.discover.outputs.packages != ''
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ working-directory: packages/komodo_defi_sdk/example
+ run: flutter build web --release || echo "Dry build completed (failure expected)"
+
+ - name: Run tests for all packages
+ if: steps.discover.outputs.packages != ''
+ env:
+ GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ shell: bash
+ run: |
+ packages="${{ steps.discover.outputs.packages }}"
+
+ # Initialize results tracking
+ declare -A test_results
+ declare -A test_outputs
+ overall_success=true
+
+ echo "# Test Results" > test_summary.md
+ echo "" >> test_summary.md
+ echo "| Package | Status | Details |" >> test_summary.md
+ echo "|---------|--------|---------|" >> test_summary.md
+
+ # Run tests for each package
+ for pkg in $packages; do
+ echo ""
+ echo "========================================="
+ echo "Testing package: $pkg"
+ echo "========================================="
+
+ cd "$pkg"
+
+ # Run flutter test and capture output and exit code
+ if flutter_output=$(flutter test -r expanded 2>&1); then
+ test_results["$pkg"]="✅ PASS"
+ test_outputs["$pkg"]="Tests passed successfully"
+ echo "✅ $pkg: PASSED"
+ else
+ test_results["$pkg"]="❌ FAIL"
+ test_outputs["$pkg"]=$(echo "$flutter_output" | tail -n 10) # Last 10 lines for brevity
+ echo "❌ $pkg: FAILED"
+ overall_success=false
+ fi
+
+ cd - > /dev/null
+ done
+
+ echo ""
+ echo "========================================="
+ echo "TEST SUMMARY"
+ echo "========================================="
+
+ # Generate summary table
+ for pkg in $packages; do
+ status="${test_results[$pkg]}"
+ details="${test_outputs[$pkg]}"
+ # Escape pipe characters in details for markdown table
+ details=$(echo "$details" | sed 's/|/\\|/g' | tr '\n' ' ' | sed 's/ */ /g' | cut -c1-100)
+ if [ ${#details} -eq 100 ]; then
+ details="${details}..."
+ fi
+ echo "| \`$pkg\` | $status | $details |" >> test_summary.md
+ echo "$status $pkg"
+ done
+
+ echo ""
+ cat test_summary.md
+
+ # Set step summary for GitHub Actions
+ cat test_summary.md >> "$GITHUB_STEP_SUMMARY"
+
+ # Fail the job if any tests failed
+ if [ "$overall_success" = false ]; then
+ echo ""
+ echo "❌ One or more test suites failed!"
+ exit 1
+ else
+ echo ""
+ echo "✅ All test suites passed!"
+ fi
+
+ - name: Upload test summary
+ if: always() && steps.discover.outputs.packages != ''
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-summary
+ path: test_summary.md
+ retention-days: 30
diff --git a/.gitignore b/.gitignore
index e86bea09..d5991c11 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,7 +41,6 @@ migrate_working_dir/
.pub-cache/
.pub/
/build/
-contrib/coins_config.json
**/.plugin_symlinks/*
# Web related
@@ -91,12 +90,13 @@ macos/kdf
# Android C++ files
**/.cxx
-# Coins asset files
+# Coins asset files
assets/config/coins.json
assets/config/coins_config.json
+assets/config/seed_nodes.json
assets/config/coins_ci.json
-assets/coin_icons/
-
+assets/coin_icons/**/*.png
+assets/coin_icons/**/*.jpg
# MacOS
# Flutter-related
@@ -114,6 +114,11 @@ macos/Frameworks/*
key.txt
.firebaserc
firebase.json
+# Exception for Firebase config in example and playground apps
+!packages/komodo_defi_sdk/example/.firebaserc
+!packages/komodo_defi_sdk/example/firebase.json
+!playground/.firebaserc
+!playground/firebase.json
*_combined.txt
# /packages/komodo_defi_framework/web/kdf
diff --git a/ACTIVATION_PARAMS_REFACTORING_PLAN.md b/ACTIVATION_PARAMS_REFACTORING_PLAN.md
new file mode 100644
index 00000000..ab9ae103
--- /dev/null
+++ b/ACTIVATION_PARAMS_REFACTORING_PLAN.md
@@ -0,0 +1,750 @@
+## Activation Parameters Architecture Refactoring Plan
+
+### Purpose
+
+Create a clean, extensible, and type‑safe activation parameters architecture for all supported protocols (UTXO, ZHTLC, ETH/ERC, Tendermint, etc.), with a unified approach to serialization, first‑class user configuration, persistence, and explicit state management for user interaction and timeouts.
+
+### Scope
+
+- No backward compatibility constraints. Design a clean architecture and migrate the SDK internals accordingly.
+- Follow OOP principles and the relevant design patterns (Strategy, Repository, State, Factory, Builder).
+- Follow BLoC naming conventions for any bloc code.
+- Use `freezed` for type‑safe configuration schemas, and the existing JSON utilities from `json_type_utils.dart` for parsing/serialization helpers.
+- Use `AssetId` in all public SDK APIs.
+
+## 1) Architecture Design
+
+### 1.1 Class Hierarchy (clean split of protocol concerns)
+
+- Activation parameters WILL be protocol‑specific. The base class must only contain protocol‑agnostic fields.
+ - Move ZHTLC‑specific fields out of the base class into `ZhtlcActivationParams`.
+ - Keep ETH/ERC specific serialization in its subclass.
+ - Keep UTXO extensions in its subclass.
+
+Proposed structure:
+
+```mermaid
+classDiagram
+ class RpcRequestParams { <> }
+ class ActivationParams {
+ +int? requiredConfirmations
+ +bool requiresNotarization
+ +PrivateKeyPolicy? privKeyPolicy
+ +int? minAddressesNumber
+ +ScanPolicy? scanPolicy
+ +int? gapLimit
+ +ActivationMode? mode
+ +JsonMap toRpcParams()
+ }
+
+ class UtxoActivationParams {
+ +bool? txHistory
+ +int? txVersion
+ +int? txFee
+ +int? dustAmount
+ +int? pubtype
+ +int? p2shtype
+ +int? wiftype
+ +int? overwintered
+ +override JsonMap toRpcParams()
+ }
+
+ class ZhtlcActivationParams {
+ +String? zcashParamsPath
+ +int? scanBlocksPerIteration
+ +int? scanIntervalMs
+ +override JsonMap toRpcParams()
+ }
+
+ class EthActivationParams {
+ +List nodes
+ +String swapContractAddress
+ +String? fallbackSwapContract
+ +List erc20Tokens
+ +bool? txHistory
+ +override JsonMap toRpcParams()
+ }
+
+ RpcRequestParams <|.. ActivationParams
+ ActivationParams <|-- UtxoActivationParams
+ ActivationParams <|-- ZhtlcActivationParams
+ ActivationParams <|-- EthActivationParams
+```
+
+Key rules:
+
+- Base `ActivationParams` contains only protocol‑agnostic fields.
+- Each subclass is solely responsible for its protocol‑specific fields and serialization.
+- `toRpcParams()` follows a consistent pattern: base JSON merged with subclass JSON using `deepMerge` (from `json_type_utils.dart`).
+
+### 1.2 Serialization Strategy (consistent approach)
+
+- Introduce a small utility to normalize private key policy serialization across protocols while respecting API expectations.
+- ETH/ERC requires JSON object form; other protocols use PascalCase enum string.
+
+```dart
+class PrivKeyPolicySerializer {
+ static dynamic toRpc(PrivateKeyPolicy policy, {required CoinSubClass protocol}) {
+ if (protocol == CoinSubClass.eth || protocol == CoinSubClass.erc20) {
+ return policy.toJson(); // object form
+ }
+ return policy.pascalCaseName; // legacy PascalCase string
+ }
+}
+```
+
+Usage pattern in `toRpcParams()`:
+
+- Base class sets all protocol‑agnostic fields EXCEPT `priv_key_policy`.
+- Subclasses set `priv_key_policy` via `PrivKeyPolicySerializer.toRpc(policy, protocol: ...)` and merge their own fields.
+
+This keeps the approach consistent while producing the protocol‑specific shape needed by the KDF API.
+
+### 1.3 User Configuration Framework
+
+Goals:
+
+- Users can pre‑configure activation options per `AssetId`.
+- If configuration exists, use automatically.
+- Otherwise, enter an explicit “awaiting user action” state with a 60s timeout, then fallback (defaults) or fail gracefully.
+
+Components:
+
+- Configuration models (freezed) per protocol
+- Repository abstraction for persistence
+- Service for orchestration (read‑or‑request‑then‑persist)
+- BLoC for state management and UI handoff (awaiting user input / timeout)
+
+```mermaid
+classDiagram
+ class ActivationConfigRepository { <>
+ +Future getConfig(AssetId id)
+ +Future saveConfig(AssetId id, TConfig config)
+ }
+
+ class KeyValueStore { <>
+ +Future get(String key)
+ +Future set(String key, JsonMap value)
+ }
+
+ class ActivationConfigService {
+ +Future getOrRequest(AssetId id, Duration timeout)
+ }
+
+ ActivationConfigRepository <|.. JsonActivationConfigRepository
+ JsonActivationConfigRepository --> KeyValueStore
+ ActivationConfigService --> ActivationConfigRepository
+```
+
+Example freezed config for ZHTLC:
+
+```dart
+@freezed
+class ZhtlcUserConfig with _$ZhtlcUserConfig {
+ const factory ZhtlcUserConfig({
+ required String zcashParamsPath,
+ @Default(1000) int scanBlocksPerIteration,
+ @Default(0) int scanIntervalMs,
+ }) = _ZhtlcUserConfig;
+
+ factory ZhtlcUserConfig.fromJson(Map json) => _$$ZhtlcUserConfigFromJson(json);
+}
+```
+
+Repository example (JSON‑backed):
+
+```dart
+class JsonActivationConfigRepository implements ActivationConfigRepository {
+ JsonActivationConfigRepository(this.store);
+ final KeyValueStore store;
+
+ String _key(AssetId id) => 'activation_config:${id.id}';
+
+ @override
+ Future getConfig(AssetId id) async {
+ final data = await store.get(_key(id));
+ if (data == null) return null;
+ // Use a registry/mapper for different configs
+ return ActivationConfigMapper.decode(data);
+ }
+
+ @override
+ Future saveConfig(AssetId id, TConfig config) async {
+ final json = ActivationConfigMapper.encode(config);
+ await store.set(_key(id), json);
+ }
+}
+```
+
+### 1.4 Persistence Layer Design
+
+- `KeyValueStore` abstraction for portability (Flutter, CLI, web):
+ - Default: in‑memory (SDK core dependency‑free)
+ - Optional adapters: `shared_preferences` (Flutter), `localstorage` (web), file‑based JSON (CLI)
+- `ActivationConfigRepository` uses `KeyValueStore` and a `ActivationConfigMapper` to encode/decode typed configs.
+- Stored shape is `JsonMap` compatible with `jsonEncode`/`jsonDecode`.
+
+### 1.5 State Management System
+
+- Introduce a dedicated BLoC to manage the read‑or‑request flow with timeout.
+- Naming follows BLoC conventions: Events end with `Event`, States end with `State`, Bloc ends with `Bloc`.
+
+States:
+
+- `ActivationConfigInitialState`
+- `ActivationConfigCheckingState`
+- `ActivationConfigAwaitingInputState` (includes `deadlineAt`, optional suggested defaults)
+- `ActivationConfigReadyState` (contains the resolved config)
+- `ActivationConfigTimeoutState`
+- `ActivationConfigFailureState`
+
+Events:
+
+- `ActivationConfigRequestedEvent(AssetId assetId)`
+- `ActivationConfigSubmittedEvent(TConfig config)`
+- `ActivationConfigCancelledEvent()`
+- `ActivationConfigTimeoutEvent()`
+
+Timeout policy:
+
+- Default 60 seconds. On timeout: if required fields missing, fail; otherwise use defaults.
+
+ActivationProgress integration (type‑safe):
+
+- Avoid using `additionalInfo` for control‑flow signals. Use typed fields or dedicated events/states.
+- When entering the awaiting state, emit a standard `ActivationProgress` message with `currentStep: ActivationStep.planning` for display, while the control signal is represented by the BLoC state `ActivationConfigAwaitingInputState`.
+
+### 1.6 Integration Points (SDK)
+
+- `KomodoDefiSdk` gains an `ActivationConfigService` dependency (optionally provided) used by activation strategies.
+- `ZhtlcActivationStrategy` reads persisted config or requests it before calling RPC `enable_zhtlc::init`.
+- `UtxoActivationStrategy`, `Eth*` strategies can opt‑in to the same pattern as needed.
+
+### 1.7 KDF API alignment: endpoints and JSON shapes
+
+The design must match the KDF API contract for activation tasks across protocols.
+
+- Common task flow per protocol:
+
+ - `task::enable_::init` — starts activation with `{ ticker, activation_params }`
+ - `task::enable_::status` — polls activation status with `{ task_id, forget_if_finished }`
+ - `task::enable_::user_action` — optional, awaited user input (protocol‑specific)
+ - `task::enable_::cancel` — optional, cancels activation task
+
+- Base request envelope includes `mmrpc: "2.0"`, `method`, and `params`.
+
+- Activation mode and rpc_data serialization:
+
+ - `mode.rpc` is one of `Electrum`, `Native`, `Light`.
+ - `mode.rpc_data` differs by mode:
+ - Electrum: `servers: [ActivationServer...]`
+ - Light (ZHTLC):
+ - `light_wallet_d_servers: [String]` (ZHTLC only)
+ - `electrum_servers: [ActivationServer...]` (note: key name differs from Electrum)
+ - `sync_params`: one of:
+ - `"earliest"`
+ - `{ "height": }`
+ - `{ "date": }`
+ - The SDK parser also supports legacy `` and heuristics, but requests should use the documented shapes above.
+
+- Activation server shape (as produced by `ActivationServers.toJsonRequest()`):
+
+ - `{ "url": , "ws_url": , "protocol": , "disable_cert_verification": }`
+
+- ZHTLC init example (shape):
+
+```json
+{
+ "mmrpc": "2.0",
+ "method": "task::enable_z_coin::init",
+ "params": {
+ "ticker": "ZEC",
+ "activation_params": {
+ "required_confirmations": 1,
+ "requires_notarization": false,
+ "priv_key_policy": "ContextPrivKey",
+ "min_addresses_number": 20,
+ "scan_policy": "do_not_scan",
+ "gap_limit": 20,
+ "mode": {
+ "rpc": "Light",
+ "rpc_data": {
+ "light_wallet_d_servers": ["https://lightd.example"],
+ "electrum_servers": [
+ {
+ "url": "ssl://electrum.example:50002",
+ "protocol": "TCP",
+ "disable_cert_verification": false
+ }
+ ],
+ "sync_params": "earliest"
+ }
+ },
+ "zcash_params_path": "/path/to/zcash-params",
+ "scan_blocks_per_iteration": 1000,
+ "scan_interval_ms": 0
+ }
+ }
+}
+```
+
+- UTXO init example (shape):
+
+```json
+{
+ "mmrpc": "2.0",
+ "method": "task::enable_utxo::init",
+ "params": {
+ "ticker": "KMD",
+ "activation_params": {
+ "required_confirmations": 1,
+ "requires_notarization": false,
+ "priv_key_policy": "ContextPrivKey",
+ "mode": {
+ "rpc": "Electrum",
+ "rpc_data": {
+ "servers": [
+ {
+ "url": "ssl://electrum.kmd:50002",
+ "protocol": "TCP",
+ "disable_cert_verification": false
+ }
+ ]
+ }
+ },
+ "tx_history": true,
+ "txversion": 4,
+ "txfee": 1000,
+ "dust_amount": 1000,
+ "pubtype": 60,
+ "p2shtype": 85,
+ "wiftype": 188,
+ "overwintered": 1
+ }
+ }
+}
+```
+
+- ETH/ERC init example (shape):
+
+```json
+{
+ "mmrpc": "2.0",
+ "method": "task::enable_eth::init",
+ "params": {
+ "ticker": "ETH",
+ "activation_params": {
+ "required_confirmations": 1,
+ "requires_notarization": false,
+ "priv_key_policy": { "type": "ContextPrivKey" },
+ "nodes": [{ "url": "https://rpc.example", "chain_id": 1 }],
+ "swap_contract_address": "0x...",
+ "fallback_swap_contract": "0x...",
+ "erc20_tokens_requests": [{ "ticker": "USDC" }],
+ "tx_history": true
+ }
+ }
+}
+```
+
+- Status and user action endpoints (examples):
+ - `task::enable_z_coin::status`/`user_action`/`cancel` (ZHTLC)
+ - `task::enable_utxo::status` (UTXO)
+ - `task::enable_eth::status` (ETH/ERC)
+ - `task::enable_qtum::status`/`user_action` (QTUM)
+ - All status endpoints accept `{ "task_id": , "forget_if_finished": }`.
+ - ZHTLC `user_action` accepts `{ "task_id": , "action_type": , "pin": , "passphrase": }`.
+
+## 2) Implementation Details
+
+### 2.1 Base and Subclass Edits
+
+Edits in `packages/komodo_defi_rpc_methods/lib/src/common_structures/activation/activation_params/activation_params.dart`:
+
+- Remove ZHTLC‑specific fields from base: `zcashParamsPath`, `scanBlocksPerIteration`, `scanIntervalMs`.
+- Ensure base `toRpcParams()` only includes protocol‑agnostic fields.
+
+Edits in `.../zhtlc_activation_params.dart`:
+
+- Keep ZHTLC‑specific fields and override `toRpcParams()` to add:
+ - `zcash_params_path`
+ - `scan_blocks_per_iteration`
+ - `scan_interval_ms`
+- Ensure `mode` is constructed with `ActivationModeType.lightWallet`.
+
+Edits in `.../utxo_activation_params.dart`:
+
+- No structural change required; already uses `deepMerge` properly.
+
+Edits in `.../eth_activation_params.dart`:
+
+- Keep override for `priv_key_policy` as JSON object.
+- Optionally route through `PrivKeyPolicySerializer` for consistency.
+
+PrivKey policy serialization utility:
+
+```dart
+extension ActivationParamsRpc on ActivationParams {
+ JsonMap toBaseRpc(Asset asset) {
+ final JsonMap base = {
+ if (requiredConfirmations != null) 'required_confirmations': requiredConfirmations,
+ 'requires_notarization': requiresNotarization,
+ if (minAddressesNumber != null) 'min_addresses_number': minAddressesNumber,
+ if (scanPolicy != null) 'scan_policy': scanPolicy!.value,
+ if (gapLimit != null) 'gap_limit': gapLimit,
+ if (mode != null) 'mode': mode!.toJsonRequest(),
+ };
+ final protocol = asset.protocol.subClass; // CoinSubClass
+ return base.deepMerge({
+ 'priv_key_policy': PrivKeyPolicySerializer.toRpc(
+ (privKeyPolicy ?? const PrivateKeyPolicy.contextPrivKey()),
+ protocol: protocol,
+ ),
+ });
+ }
+}
+```
+
+Then subclasses perform:
+
+```dart
+@override
+JsonMap toRpcParamsFor(Asset asset) => toBaseRpc(asset).deepMerge({
+ // protocol‑specific fields
+});
+```
+
+Note: If changing method signature is undesirable, keep `toRpcParams()` and pass required protocol context via constructor or a `withContext` builder that captures `Asset`.
+
+### 2.2 User Configuration (freezed types)
+
+ZHTLC config (required and optional fields):
+
+```dart
+@freezed
+class ZhtlcUserConfig with _$ZhtlcUserConfig {
+ const factory ZhtlcUserConfig({
+ required String zcashParamsPath,
+ @Default(1000) int scanBlocksPerIteration,
+ @Default(0) int scanIntervalMs,
+ }) = _ZhtlcUserConfig;
+
+ factory ZhtlcUserConfig.fromJson(JsonMap json) => _$$ZhtlcUserConfigFromJson(json);
+}
+```
+
+Mapper registry (simplified):
+
+```dart
+abstract class ActivationConfigMapper {
+ static JsonMap encode(Object config) {
+ if (config is ZhtlcUserConfig) return config.toJson();
+ throw UnsupportedError('Unsupported config type: ${config.runtimeType}');
+ }
+
+ static T decode(JsonMap json) {
+ if (T == ZhtlcUserConfig) return ZhtlcUserConfig.fromJson(json) as T;
+ throw UnsupportedError('Unsupported type for decode: $T');
+ }
+}
+```
+
+Service orchestration (timeout handling):
+
+```dart
+class ActivationConfigService {
+ ActivationConfigService(this.repo);
+ final ActivationConfigRepository repo;
+
+ Future getZhtlcOrRequest(AssetId id, {Duration timeout = const Duration(seconds: 60)}) async {
+ final existing = await repo.getConfig(id);
+ if (existing != null) return existing;
+
+ // Emit BLoC awaiting state externally; wait for submission or timeout
+ final completer = Completer();
+ _awaitingControllers[id] = completer;
+
+ try {
+ final result = await completer.future.timeout(timeout, onTimeout: () => null);
+ if (result == null) return null; // timeout: signal caller to fallback/fail
+ await repo.saveConfig(id, result);
+ return result;
+ } finally {
+ _awaitingControllers.remove(id);
+ }
+ }
+
+ // Called by UI when user submits config
+ void submitZhtlc(AssetId id, ZhtlcUserConfig config) {
+ _awaitingControllers[id]?.complete(config);
+ }
+
+ final Map> _awaitingControllers = {};
+}
+```
+
+### 2.3 BLoC for User Configuration
+
+Events:
+
+```dart
+abstract class ActivationConfigEvent {}
+class ActivationConfigRequestedEvent extends ActivationConfigEvent {
+ ActivationConfigRequestedEvent(this.assetId);
+ final AssetId assetId;
+}
+class ActivationConfigSubmittedEvent extends ActivationConfigEvent {
+ ActivationConfigSubmittedEvent(this.assetId, this.config);
+ final AssetId assetId; final T config;
+}
+class ActivationConfigTimeoutEvent extends ActivationConfigEvent {}
+class ActivationConfigCancelledEvent extends ActivationConfigEvent {}
+```
+
+States:
+
+```dart
+abstract class ActivationConfigState {}
+class ActivationConfigInitialState extends ActivationConfigState {}
+class ActivationConfigCheckingState extends ActivationConfigState {}
+class ActivationConfigAwaitingInputState extends ActivationConfigState {
+ ActivationConfigAwaitingInputState({required this.assetId, required this.deadlineAt, required this.requiredFields, this.defaults = const {}});
+ final AssetId assetId; final DateTime deadlineAt; final List requiredFields; final JsonMap defaults;
+}
+class ActivationConfigReadyState extends ActivationConfigState {
+ ActivationConfigReadyState(this.assetId, this.config);
+ final AssetId assetId; final T config;
+}
+class ActivationConfigTimeoutState extends ActivationConfigState {}
+class ActivationConfigFailureState extends ActivationConfigState { ActivationConfigFailureState(this.message); final String message; }
+```
+
+Bloc:
+
+```dart
+class ActivationConfigBloc extends Bloc {
+ ActivationConfigBloc(this.service) : super(ActivationConfigInitialState()) {
+ on(_onRequested);
+ on(_onSubmitted);
+ on((_, emit) => emit(ActivationConfigTimeoutState()));
+ on((_, emit) => emit(ActivationConfigFailureState('Cancelled')));
+ }
+
+ final ActivationConfigService service;
+
+ Future _onRequested(ActivationConfigRequestedEvent e, Emitter emit) async {
+ emit(ActivationConfigCheckingState());
+ // ZHTLC example; add branching by protocol if needed
+ final result = await service.getZhtlcOrRequest(e.assetId);
+ if (result == null) {
+ emit(ActivationConfigAwaitingInputState(
+ assetId: e.assetId,
+ deadlineAt: DateTime.now().add(const Duration(seconds: 60)),
+ requiredFields: const ['zcashParamsPath'],
+ defaults: {'scanBlocksPerIteration': 1000, 'scanIntervalMs': 0},
+ ));
+ return;
+ }
+ emit(ActivationConfigReadyState(e.assetId, result));
+ }
+
+ Future _onSubmitted(ActivationConfigSubmittedEvent e, Emitter emit) async {
+ if (e.config is ZhtlcUserConfig) {
+ service.submitZhtlc(e.assetId, e.config as ZhtlcUserConfig);
+ emit(ActivationConfigReadyState(e.assetId, e.config as ZhtlcUserConfig));
+ } else {
+ emit(ActivationConfigFailureState('Unsupported config type'));
+ }
+ }
+}
+```
+
+### 2.4 Proper Use of JSON Utilities
+
+- Use `JsonMap` (`Map`) and `deepMerge` to compose RPC params.
+- Use `.value()` / `.valueOrNull()` for safe JSON extraction.
+- Use `jsonEncode/jsonDecode` helpers and `tryParseJson` when handling dynamic inputs.
+
+## 3) SDK Integration
+
+### 3.1 KomodoDefiSdk integration
+
+Add a configurable dependency for activation configuration:
+
+```dart
+class KomodoDefiSdk {
+ KomodoDefiSdk({required this.apiClient, ActivationConfigService? activationConfigService})
+ : activationConfigService = activationConfigService ?? ActivationConfigService(JsonActivationConfigRepository(InMemoryKeyValueStore()));
+
+ final ApiClient apiClient;
+ final ActivationConfigService activationConfigService;
+}
+```
+
+Pass the service down to activation strategies via the existing strategy factory.
+
+### 3.2 ZHTLC Strategy changes
+
+- Before constructing `ZhtlcActivationParams`, get the user config or request it.
+- On timeout, either:
+ - If `zcashParamsPath` is still missing, emit an error `ActivationProgress` and abort, or
+ - If only optional fields are missing, use defaults and proceed.
+
+Sketch:
+
+```dart
+final config = await sdk.activationConfigService.getZhtlcOrRequest(asset.id);
+if (config == null || config.zcashParamsPath.trim().isEmpty) {
+ yield ActivationProgress.error(message: 'Zcash params path required');
+ return;
+}
+
+final params = ZhtlcActivationParams.fromConfigJson(protocol.config).copyWith(
+ zcashParamsPath: config.zcashParamsPath,
+ scanBlocksPerIteration: config.scanBlocksPerIteration,
+ scanIntervalMs: config.scanIntervalMs,
+ privKeyPolicy: privKeyPolicy,
+);
+// Start the task and use the SDK's task shepherd to poll:
+final stream = client.rpc.zhtlc
+ .enableZhtlcInit(ticker: asset.id.id, params: params)
+ .watch(
+ getTaskStatus: (taskId) => client.rpc.zhtlc.enableZhtlcStatus(
+ taskId,
+ forgetIfFinished: false,
+ ),
+ isTaskComplete: (s) => s.status == 'Ok' || s.status == 'Error',
+ cancelTask: (taskId) => client.rpc.zhtlc.enableZhtlcCancel(taskId: taskId),
+ pollingInterval: const Duration(milliseconds: 500),
+ );
+```
+
+### 3.3 AssetId extension for available user configurations
+
+Expose what configurable settings are available for a given asset/protocol for building UI. Do not depend on `additionalInfo` in `ActivationProgress` for this; use this typed API instead:
+
+```dart
+class ActivationSettingDescriptor {
+ ActivationSettingDescriptor({
+ required this.key,
+ required this.label,
+ required this.type, // 'path' | 'number' | 'string' | 'boolean' | 'select'
+ this.required = false,
+ this.defaultValue,
+ this.helpText,
+ });
+ final String key; final String label; final String type;
+ final bool required; final Object? defaultValue; final String? helpText;
+}
+
+extension AssetIdActivationSettings on AssetId {
+ List activationSettings() {
+ switch (protocolSubClass) { // implement based on your AssetId
+ case CoinSubClass.zhtlc:
+ return [
+ ActivationSettingDescriptor(
+ key: 'zcashParamsPath',
+ label: 'Zcash parameters path',
+ type: 'path',
+ required: true,
+ helpText: 'Folder containing Zcash parameters',
+ ),
+ ActivationSettingDescriptor(
+ key: 'scanBlocksPerIteration',
+ label: 'Blocks per scan iteration',
+ type: 'number',
+ defaultValue: 1000,
+ ),
+ ActivationSettingDescriptor(
+ key: 'scanIntervalMs',
+ label: 'Scan interval (ms)',
+ type: 'number',
+ defaultValue: 0,
+ ),
+ ];
+ default:
+ return const [];
+ }
+ }
+}
+```
+
+### 3.4 Example usage
+
+```dart
+final sdk = KomodoDefiSdk(apiClient: apiClient);
+
+// UI listens to a typed BLoC for control flow (awaiting input),
+// and separately renders ActivationProgress for user‑visible status.
+
+activationConfigBloc.add(ActivationConfigRequestedEvent(assetId));
+
+final sub = activationConfigBloc.stream.listen((state) {
+ if (state is ActivationConfigAwaitingInputState) {
+ // Present typed form derived from AssetId.activationSettings()
+ // On submit:
+ activationConfigBloc.add(
+ ActivationConfigSubmittedEvent(assetId, zhtlcConfig),
+ );
+ }
+});
+
+await for (final progress in sdk.activate(assetId)) {
+ // Render progress.userMessage and progress.progressDetails
+}
+```
+
+## 4) Migration Strategy (no backward compatibility required)
+
+Order of work:
+
+1. Introduce new user configuration types and persistence
+ - Add `ZhtlcUserConfig` (freezed) and repository/service skeletons
+ - Add `KeyValueStore` interface and in‑memory default
+2. Extract ZHTLC fields from base `ActivationParams`
+ - Remove `zcashParamsPath`, `scanBlocksPerIteration`, `scanIntervalMs` from base
+ - Ensure `ZhtlcActivationParams` owns and serializes these
+3. Normalize serialization approach
+ - Add `PrivKeyPolicySerializer`
+ - Route ETH/ERC and others accordingly
+4. Wire SDK integration
+ - Extend `KomodoDefiSdk` with `ActivationConfigService`
+ - Update `ZhtlcActivationStrategy` to request config before activation
+5. Add `AssetId.activationSettings()` extension
+6. Implement BLoC for configuration flow (optional for SDK core, shipped in `komodo_ui` or example app)
+7. Update and/or add tests
+ - Unit tests for mappers, repository, serializer, and `toRpcParams()` across protocols
+ - Strategy integration test for ZHTLC with and without pre‑saved config; timeout path
+8. Documentation and examples
+ - Document new APIs and include example usage
+9. Remove dead/legacy code paths from base class
+
+Suggested Conventional Commits sequence:
+
+- feat(core): add activation config repository and in‑memory store [[freezed models]]
+- refactor(rpc): move ZHTLC fields from ActivationParams into ZhtlcActivationParams
+- feat(rpc): add PrivKeyPolicySerializer and unify serialization usage
+- feat(sdk): integrate ActivationConfigService into KomodoDefiSdk and ZHTLC strategy
+- feat(types): add AssetId.activationSettings() extension
+- test(core): add unit tests for repo/mapper/serializer and protocol params
+- docs: add activation parameters architecture and usage examples
+
+## 5) Risks and Mitigations
+
+- Risk: ETH/ERC serialization divergence. Mitigation: centralize via `PrivKeyPolicySerializer` and test per protocol.
+- Risk: Platform persistence. Mitigation: keep `KeyValueStore` abstract; provide adapters outside core.
+- Risk: User flow complexity. Mitigation: explicit BLoC states (typed control) and `ActivationProgress` (display only); documented timeout/default behavior.
+- Risk: Mode/rpc_data mismatch. Mitigation: enforce `ActivationMode.toJsonRequest()` rules:
+ - Electrum uses `servers`, Light uses `electrum_servers` and optional `light_wallet_d_servers` and `sync_params`.
+ - Tests assert exact key names per mode.
+
+## 6) Acceptance Criteria
+
+- Base `ActivationParams` has no ZHTLC‑specific fields.
+- All subclasses merge their RPC params via `deepMerge` and follow the same serialization approach.
+- ZHTLC requires user config for `zcashParamsPath`; optional fields default as specified.
+- User configuration is persisted and reused on subsequent activations.
+- Missing config triggers an “awaiting user action” state with a 60s timeout.
+- Integration demonstrates `KomodoDefiSdk` + `AssetId.activationSettings()` and typed BLoC usage (no reliance on `additionalInfo` for control logic).
+- `mode.rpc_data` uses `servers` for Electrum and `electrum_servers` for Light; includes `light_wallet_d_servers` and `sync_params` for ZHTLC where applicable.
+- All activation `init` requests use `{ ticker, activation_params }` and match the KDF API shapes above.
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..5912d881
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,632 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## 2025-08-25
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+ - There are no breaking changes in this release.
+
+Packages with other changes:
+
+ - [`komodo_defi_types` - `v0.3.2+1`](#komodo_defi_types---v0321)
+ - [`komodo_wallet_cli` - `v0.4.0+1`](#komodo_wallet_cli---v0401)
+ - [`komodo_ui` - `v0.3.0+3`](#komodo_ui---v0303)
+ - [`komodo_defi_sdk` - `v0.4.0+3`](#komodo_defi_sdk---v0403)
+ - [`komodo_defi_rpc_methods` - `v0.3.1+1`](#komodo_defi_rpc_methods---v0311)
+ - [`komodo_defi_local_auth` - `v0.3.1+2`](#komodo_defi_local_auth---v0312)
+ - [`komodo_defi_framework` - `v0.3.1+2`](#komodo_defi_framework---v0312)
+ - [`komodo_coins` - `v0.3.1+2`](#komodo_coins---v0312)
+ - [`komodo_coin_updates` - `v1.1.1`](#komodo_coin_updates---v111)
+ - [`komodo_cex_market_data` - `v0.0.3+1`](#komodo_cex_market_data---v0031)
+
+Packages with dependency updates only:
+
+> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
+
+ - `komodo_ui` - `v0.3.0+3`
+ - `komodo_defi_sdk` - `v0.4.0+3`
+ - `komodo_defi_rpc_methods` - `v0.3.1+1`
+ - `komodo_defi_local_auth` - `v0.3.1+2`
+ - `komodo_defi_framework` - `v0.3.1+2`
+ - `komodo_coins` - `v0.3.1+2`
+ - `komodo_coin_updates` - `v1.1.1`
+ - `komodo_cex_market_data` - `v0.0.3+1`
+
+---
+
+#### `komodo_defi_types` - `v0.3.2+1`
+
+ - **DOCS**(komodo_defi_types): update CHANGELOG for 0.3.2 with pub submission fix.
+
+#### `komodo_wallet_cli` - `v0.4.0+1`
+
+ - **REFACTOR**(komodo_wallet_cli): replace print() with stdout/stderr and improve logging.
+
+
+## 2025-08-25
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+ - There are no breaking changes in this release.
+
+Packages with other changes:
+
+ - [`komodo_coins` - `v0.3.1+1`](#komodo_coins---v0311)
+ - [`komodo_defi_sdk` - `v0.4.0+2`](#komodo_defi_sdk---v0402)
+ - [`komodo_defi_framework` - `v0.3.1+1`](#komodo_defi_framework---v0311)
+ - [`komodo_defi_local_auth` - `v0.3.1+1`](#komodo_defi_local_auth---v0311)
+
+Packages with dependency updates only:
+
+> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
+
+ - `komodo_defi_sdk` - `v0.4.0+2`
+ - `komodo_defi_framework` - `v0.3.1+1`
+ - `komodo_defi_local_auth` - `v0.3.1+1`
+
+---
+
+#### `komodo_coins` - `v0.3.1+1`
+
+ - **FIX**: add missing deps.
+
+
+## 2025-08-25
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+ - There are no breaking changes in this release.
+
+Packages with other changes:
+
+ - [`komodo_defi_sdk` - `v0.4.0+1`](#komodo_defi_sdk---v0401)
+
+---
+
+#### `komodo_defi_sdk` - `v0.4.0+1`
+
+ - **FIX**: add missing dependency.
+
+
+## 2025-08-25
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+ - [`dragon_charts_flutter` - `v0.1.1-dev.3`](#dragon_charts_flutter---v011-dev3)
+ - [`dragon_logs` - `v2.0.0`](#dragon_logs---v200)
+ - [`komodo_defi_sdk` - `v0.4.0`](#komodo_defi_sdk---v040)
+ - [`komodo_wallet_build_transformer` - `v0.4.0`](#komodo_wallet_build_transformer---v040)
+ - [`komodo_wallet_cli` - `v0.4.0`](#komodo_wallet_cli---v040)
+
+Packages with other changes:
+
+ - [`komodo_cex_market_data` - `v0.0.3`](#komodo_cex_market_data---v003)
+ - [`komodo_coin_updates` - `v1.1.0`](#komodo_coin_updates---v110)
+ - [`komodo_coins` - `v0.3.1`](#komodo_coins---v031)
+ - [`komodo_defi_framework` - `v0.3.1`](#komodo_defi_framework---v031)
+ - [`komodo_defi_local_auth` - `v0.3.1`](#komodo_defi_local_auth---v031)
+ - [`komodo_defi_rpc_methods` - `v0.3.1`](#komodo_defi_rpc_methods---v031)
+ - [`komodo_defi_types` - `v0.3.1`](#komodo_defi_types---v031)
+ - [`komodo_ui` - `v0.3.0+2`](#komodo_ui---v0302)
+
+Packages with dependency updates only:
+
+> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
+
+ - `komodo_ui` - `v0.3.0+2`
+
+---
+
+#### `dragon_charts_flutter` - `v0.1.1-dev.3`
+
+ - **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `dragon_logs` - `v2.0.0`
+
+ - **FIX**(deps): misc deps fixes.
+ - **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_defi_sdk` - `v0.4.0`
+
+ - **FIX**(cex-market-data): coingecko ohlc parsing (#203).
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+ - **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_wallet_build_transformer` - `v0.4.0`
+
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+ - **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_wallet_cli` - `v0.4.0`
+
+ - **FIX**(pub): add non-generic description.
+ - **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_cex_market_data` - `v0.0.3`
+
+ - **FIX**(cex-market-data): coingecko ohlc parsing (#203).
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+#### `komodo_coin_updates` - `v1.1.0`
+
+ - **FIX**(deps): misc deps fixes.
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+#### `komodo_coins` - `v0.3.1`
+
+ - **FIX**: pub submission errors.
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+#### `komodo_defi_framework` - `v0.3.1`
+
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+#### `komodo_defi_local_auth` - `v0.3.1`
+
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+#### `komodo_defi_rpc_methods` - `v0.3.1`
+
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+#### `komodo_defi_types` - `v0.3.1`
+
+ - **FIX**: pub submission errors.
+ - **FIX**(deps): resolve deps error.
+ - **FEAT**(coin-updates): integrate komodo_coin_updates into komodo_coins (#190).
+
+
+## 2025-08-21
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+- [`dragon_charts_flutter` - `v0.1.1-dev.2`](#dragon_charts_flutter---v011-dev2)
+- [`dragon_logs` - `v1.2.1`](#dragon_logs---v121)
+- [`komodo_coin_updates` - `v1.0.1`](#komodo_coin_updates---v101)
+- [`komodo_coins` - `v0.3.0+1`](#komodo_coins---v0301)
+- [`komodo_defi_framework` - `v0.3.0+1`](#komodo_defi_framework---v0301)
+- [`komodo_defi_local_auth` - `v0.3.0+1`](#komodo_defi_local_auth---v0301)
+- [`komodo_defi_rpc_methods` - `v0.3.0+1`](#komodo_defi_rpc_methods---v0301)
+- [`komodo_defi_sdk` - `v0.3.0+1`](#komodo_defi_sdk---v0301)
+- [`komodo_defi_types` - `v0.3.0+2`](#komodo_defi_types---v0302)
+- [`komodo_symbol_converter` - `v0.3.0+1`](#komodo_symbol_converter---v0301)
+- [`komodo_ui` - `v0.3.0+1`](#komodo_ui---v0301)
+- [`komodo_wallet_build_transformer` - `v0.3.0+1`](#komodo_wallet_build_transformer---v0301)
+- [`komodo_wallet_cli` - `v0.3.0+1`](#komodo_wallet_cli---v0301)
+
+Packages with other changes:
+
+- [`komodo_cex_market_data` - `v0.0.2+1`](#komodo_cex_market_data---v0021)
+
+---
+
+#### `dragon_charts_flutter` - `v0.1.1-dev.2`
+
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **FEAT**(auth): poll trezor connection status and sign out when disconnected (#126).
+- **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `dragon_logs` - `v1.2.1`
+
+- **FIX**(deps): misc deps fixes.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+- **BREAKING** **FEAT**: add dragon_logs package with Wasm-compatible logging.
+- **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_coin_updates` - `v1.0.1`
+
+- **FIX**(deps): misc deps fixes.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FEAT**(seed): update seed node format (#87).
+- **FEAT**: add configurable seed node system with remote fetching (#85).
+- **FEAT**: runtime coin updates (#38).
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+
+#### `komodo_coins` - `v0.3.0+1`
+
+- **REFACTOR**(types): Restructure type packages.
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**: pub submission errors.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**(ui): resolve stale asset balance widget.
+- **FIX**: remove obsolete coins transformer.
+- **FIX**: revert ETH coins config migration transformer.
+- **FIX**: breaking tendermint config changes and build transformer not using branch-specific content URL for non-master branches (#55).
+- **FEAT**: offline private key export (#160).
+- **FEAT**(pubkey): add streamed new address API with Trezor confirmations (#123).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**: add configurable seed node system with remote fetching (#85).
+- **FEAT**: nft enable RPC and activation params (#39).
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(hd): HD withdrawal supporting widgets and (WIP) multi-instance example.
+- **FEAT**(sdk): Implement remaining SDK withdrawal functionality.
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+
+#### `komodo_defi_framework` - `v0.3.0+1`
+
+- **REFACTOR**(types): Restructure type packages.
+- **REFACTOR**(komodo_defi_framework): add static, global log verbosity flag (#41).
+- **PERF**: migrate packages to Dart workspace.
+- **PERF**: migrate packages to Dart workspace".
+- **FIX**(rpc-password-generator): update password validation to match KDF password policy (#58).
+- **FIX**(komodo-defi-framework): export coin icons (#8).
+- **FIX**: resolve bug with dispose logic.
+- **FIX**: stop KDF when disposed.
+- **FIX**: SIA support.
+- **FIX**(kdf_operations): reduce wasm log verbosity in release mode (#11).
+- **FIX**: kdf hashes.
+- **FIX**(auth_service): hd wallet registration deadlock (#12).
+- **FIX**: revert ETH coins config migration transformer.
+- **FIX**(kdf): enable p2p in noAuth mode (#86).
+- **FIX**(kdf-wasm-ops): response type conversion and migrate to js_interop (#14).
+- **FIX**: Fix breaking dependency upgrades.
+- **FIX**(debugging): Avoid unnecessary exceptions.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**(withdrawal-manager): use legacy RPCs for tendermint withdrawals (#57).
+- **FIX**: breaking tendermint config changes and build transformer not using branch-specific content URL for non-master branches (#55).
+- **FIX**(auth_service): legacy wallet bip39 validation (#18).
+- **FIX**(native-auth-ops): remove exceptions from logs in KDF restart function (#45).
+- **FIX**(kdf): Rebuild KDF checksums.
+- **FIX**(wasm-ops): fix example app login by improving JS call error handling (#185).
+- **FIX**(komodo-defi-framework): normalise kdf startup process between native and wasm (#7).
+- **FIX**(kdf): Update KDF for HD withdrawal bug.
+- **FIX**(bug): Fix JSON list parsing.
+- **FIX**(build): update config format.
+- **FIX**(native-ops): mobile kdf startup config requires dbdir parameter (#35).
+- **FIX**(build_transformer): npm error when building without `package.json` (#3).
+- **FIX**(local-exe-ops): local executable startup and registration (#33).
+- **FIX**(example): encrypted seed import (#16).
+- **FIX**(transaction-history): EVM StackOverflow exception (#30).
+- **FEAT**(sdk): Implement remaining SDK withdrawal functionality.
+- **FEAT**(build): Add regex support for KDF download.
+- **FEAT**(sdk): Balance manager WIP.
+- **FEAT**(builds): Add regex pattern support for KDF download.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(auth): Add update password feature.
+- **FEAT**(auth): Implement new exceptions for update password RPC.
+- **FEAT**(withdraw): add ibc source channel parameter (#63).
+- **FEAT**(operations): update KDF operations interface and implementations.
+- **FEAT**: add configurable seed node system with remote fetching (#85).
+- **FEAT**(sdk): add trezor support via RPC and SDK wrappers (#77).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**(seed): update seed node format (#87).
+- **FEAT**: offline private key export (#160).
+- **FEAT**(hd): HD withdrawal supporting widgets and (WIP) multi-instance example.
+- **BUG**(windows): Fix incompatibility between Nvidia Windows drivers and Rust.
+- **BUG**(wasm): remove validation for legacy methods.
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+
+#### `komodo_defi_local_auth` - `v0.3.0+1`
+
+- **REFACTOR**(types): Restructure type packages.
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**(local_auth): ensure kdf running before wallet deletion (#118).
+- **FIX**: resolve bug with dispose logic.
+- **FIX**(pubkey-strategy): use new PrivateKeyPolicy constructors for checks (#97).
+- **FIX**(activation): eth PrivateKeyPolicy enum breaking changes (#96).
+- **FIX**(auth): allow custom seeds for legacy wallets (#95).
+- **FIX**(withdrawal-manager): use legacy RPCs for tendermint withdrawals (#57).
+- **FIX**(auth): Translate KDF errors to auth errors.
+- **FIX**(native-auth-ops): remove exceptions from logs in KDF restart function (#45).
+- **FIX**(native-ops): mobile kdf startup config requires dbdir parameter (#35).
+- **FIX**(local-exe-ops): local executable startup and registration (#33).
+- **FIX**(transaction-storage): transaction streaming errors and hanging due to storage error (#28).
+- **FIX**(auth_service): legacy wallet bip39 validation (#18).
+- **FIX**(auth_service): hd wallet registration deadlock (#12).
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **FEAT**(auth): poll trezor connection status and sign out when disconnected (#126).
+- **FEAT**: offline private key export (#160).
+- **FEAT**(seed): update seed node format (#87).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**(sdk): add trezor support via RPC and SDK wrappers (#77).
+- **FEAT**: add configurable seed node system with remote fetching (#85).
+- **FEAT**(auth): allow weak password in auth options (#54).
+- **FEAT**(auth): Implement new exceptions for update password RPC.
+- **FEAT**(auth): Add update password feature.
+- **FEAT**(auth): enhance local authentication and secure storage.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(sdk): Balance manager WIP.
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+
+#### `komodo_defi_rpc_methods` - `v0.3.0+1`
+
+- **REFACTOR**(tx history): Fix misrepresented fees field.
+- **REFACTOR**: improve code quality and documentation.
+- **REFACTOR**(types): Restructure type packages.
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**(rpc): Remove flutter dependency from RPC package.
+- **FIX**(activation): eth PrivateKeyPolicy enum breaking changes (#96).
+- **FIX**(withdraw): revert temporary IBC channel type changes (#136).
+- **FIX**(activation): Fix eth activation parsing exception.
+- **FIX**(debugging): Avoid unnecessary exceptions.
+- **FEAT**(rpc): support max_connected on activation (#149).
+- **FEAT**(pubkey): add streamed new address API with Trezor confirmations (#123).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **FEAT**(sdk): add trezor support via RPC and SDK wrappers (#77).
+- **FEAT**(auth): poll trezor connection status and sign out when disconnected (#126).
+- **FEAT**(withdraw): add ibc source channel parameter (#63).
+- **FEAT**(auth): Implement new exceptions for update password RPC.
+- **FEAT**: nft enable RPC and activation params (#39).
+- **FEAT**(auth): Add update password feature.
+- **FEAT**: enhance balance and market data management in SDK.
+- **FEAT**(rpc): implement missing RPCs (#179) (#188).
+- **FEAT**(signing): Implement message signing + format.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(withdrawals): Implement HD withdrawals.
+- **FEAT**: custom token import (#22).
+- **FEAT**(sdk): Implement remaining SDK withdrawal functionality.
+- **FEAT**: offline private key export (#160).
+- **FEAT**(pubkeys): add unbanning support (#161).
+- **FEAT**(sdk): Balance manager WIP.
+- **FEAT**(fees): integrate fee management (#152).
+- **FEAT**(rpc): support max_connected on activation (#149)" (#150).
+- **BUG**(tx): Fix broken legacy UTXO tx history.
+- **BUG**: fix missing pubkey equality operators.
+- **BUG**(tx): Fix and optimise transaction history SDK.
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+
+#### `komodo_defi_sdk` - `v0.3.0+1`
+
+- **REFACTOR**: improve code quality and documentation.
+- **REFACTOR**(tx history): Fix misrepresented fees field.
+- **REFACTOR**(ui): improve balance text widget implementation.
+- **REFACTOR**(sdk): improve transaction history and withdrawal managers.
+- **REFACTOR**(sdk): update transaction history manager for new architecture.
+- **REFACTOR**(sdk): restructure activation and asset management flow.
+- **REFACTOR**(sdk): implement dependency injection with GetIt container.
+- **REFACTOR**(types): Restructure type packages.
+- **PERF**: migrate packages to Dart workspace.
+- **PERF**: migrate packages to Dart workspace".
+- **FIX**(activation): track activation status to avoid duplicate activation requests (#80)" (#153).
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**(activation): track activation status to avoid duplicate activation requests (#80).
+- **FIX**(withdraw): revert temporary IBC channel type changes (#136).
+- **FIX**: resolve bug with dispose logic.
+- **FIX**: stop KDF when disposed.
+- **FIX**(activation): eth PrivateKeyPolicy enum breaking changes (#96).
+- **FIX**(trezor,activation): add PrivateKeyPolicy to AuthOptions (#75).
+- **FIX**(withdrawal-manager): use legacy RPCs for tendermint withdrawals (#57).
+- **FIX**: breaking tendermint config changes and build transformer not using branch-specific content URL for non-master branches (#55).
+- **FIX**(native-auth-ops): remove exceptions from logs in KDF restart function (#45).
+- **FIX**(withdraw): update amount when isMaxAmount and show dropdown icon (#44).
+- **FIX**(transaction-storage): transaction streaming errors and hanging due to storage error (#28).
+- **FIX**(multi-sdk): Fix example app withdrawals SDK instance.
+- **FIX**(transaction-history): EVM StackOverflow exception (#30).
+- **FIX**(example): Fix registration form regression.
+- **FIX**(local-exe-ops): local executable startup and registration (#33).
+- **FIX**(asset-manager): add missing ticker index initialization (#24).
+- **FIX**(example): encrypted seed import (#16).
+- **FIX**(assets): Add ticker-safe asset lookup.
+- **FIX**(ui): resolve stale asset balance widget.
+- **FIX**(native-ops): mobile kdf startup config requires dbdir parameter (#35).
+- **FIX**(auth_service): hd wallet registration deadlock (#12).
+- **FIX**(market-data-price): try fetch current price from komodo price repository first before cex repository (#167).
+- **FIX**(auth_service): legacy wallet bip39 validation (#18).
+- **FIX**(transaction-history): non-hd transaction history support (#25).
+- **FEAT**(KDF): Make provision for HD mode signing.
+- **FEAT**(auth): Add update password feature.
+- **FEAT**: enhance balance and market data management in SDK.
+- **FEAT**: add configurable seed node system with remote fetching (#85).
+- **FEAT**(ui): improve asset list and authentication UI.
+- **FEAT**(error-handling): enhance balance and address loading error states.
+- **FEAT**(auth): poll trezor connection status and sign out when disconnected (#126).
+- **FEAT**(transactions): add activations and withdrawal priority features.
+- **FEAT**(ui): update asset components and SDK integrations.
+- **FEAT**(market-data): add support for multiple market data providers (#145).
+- **FEAT**(pubkey-manager): add pubkey watch function similar to balance watch (#178).
+- **FEAT**(withdrawals): Implement HD withdrawals.
+- **FEAT**(sdk): redesign balance manager with improved API and reliability.
+- **FEAT**: nft enable RPC and activation params (#39).
+- **FEAT**(signing): Implement message signing + format.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(auth): Implement new exceptions for update password RPC.
+- **FEAT**(ui): Address and fee UI enhancements + formatting.
+- **FEAT**(withdraw): add ibc source channel parameter (#63).
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **FEAT**(ui): add AssetLogo widget (#78).
+- **FEAT**(sdk): add trezor support via RPC and SDK wrappers (#77).
+- **FEAT**(hd): HD withdrawal supporting widgets and (WIP) multi-instance example.
+- **FEAT**(asset): add message signing support flag (#105).
+- **FEAT**: custom token import (#22).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**(ui): add helper constructors for AssetLogo from legacy ticker and AssetId (#109).
+- **FEAT**(pubkey): add streamed new address API with Trezor confirmations (#123).
+- **FEAT**: protect SDK after disposal (#116).
+- **FEAT**(asset): Add legacy asset transition helpers.
+- **FEAT**(sdk): Implement remaining SDK withdrawal functionality.
+- **FEAT**(HD): Implement GUI utility for asset status.
+- **FEAT**: offline private key export (#160).
+- **FEAT**(activation): disable tx history when using external strategy (#151).
+- **FEAT**(pubkeys): add unbanning support.
+- **FEAT**(fees): integrate fee management (#152).
+- **FEAT**(sdk): Balance manager WIP.
+- **BUG**(assets): Fix missing export for legacy extension.
+- **BUG**(tx): Fix broken legacy UTXO tx history.
+- **BUG**(auth): Fix registration failing on Windows and Windows web builds (#34).
+- **BUG**(tx): Fix and optimise transaction history SDK.
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+- **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_defi_types` - `v0.3.0+2`
+
+- **REFACTOR**(tx history): Fix misrepresented fees field.
+- **REFACTOR**(types): Restructure type packages.
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**(debugging): Avoid unnecessary exceptions.
+- **FIX**(deps): resolve deps error.
+- **FIX**(wasm-ops): fix example app login by improving JS call error handling (#185).
+- **FIX**(ui): resolve stale asset balance widget.
+- **FIX**(types): export missing RPC types.
+- **FIX**(activation): Fix eth activation parsing exception.
+- **FIX**(withdraw): revert temporary IBC channel type changes (#136).
+- **FIX**: SIA support.
+- **FIX**(pubkey-strategy): use new PrivateKeyPolicy constructors for checks (#97).
+- **FIX**(activation): eth PrivateKeyPolicy enum breaking changes (#96).
+- **FIX**: pub submission errors.
+- **FIX**: Add pubkey property needed for GUI.
+- **FIX**(trezor,activation): add PrivateKeyPolicy to AuthOptions (#75).
+- **FIX**: Fix breaking dependency upgrades.
+- **FIX**(fee-info): update tendermint, erc20, and qrc20 `fee_details` response format (#60).
+- **FIX**(rpc-password-generator): update password validation to match KDF password policy (#58).
+- **FIX**(withdrawal-manager): use legacy RPCs for tendermint withdrawals (#57).
+- **FIX**: breaking tendermint config changes and build transformer not using branch-specific content URL for non-master branches (#55).
+- **FIX**(native-auth-ops): remove exceptions from logs in KDF restart function (#45).
+- **FIX**(types): Fix Sub-class naming.
+- **FIX**(bug): Fix JSON list parsing.
+- **FIX**(local-exe-ops): local executable startup and registration (#33).
+- **FIX**(example): Fix registration form regression.
+- **FIX**(transaction-storage): transaction streaming errors and hanging due to storage error (#28).
+- **FIX**(types): Make types index private.
+- **FIX**(example): encrypted seed import (#16).
+- **FEAT**(sdk): add trezor support via RPC and SDK wrappers (#77).
+- **FEAT**(auth): Implement new exceptions for update password RPC.
+- **FEAT**(signing): Add message signing prefix to models.
+- **FEAT**(auth): poll trezor connection status and sign out when disconnected (#126).
+- **FEAT**(KDF): Make provision for HD mode signing.
+- **FEAT**(market-data): add support for multiple market data providers (#145).
+- **FEAT**: enhance balance and market data management in SDK.
+- **FEAT**(types): add new models and utility classes for reactive data handling.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(sdk): Balance manager WIP.
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **FEAT**(withdrawals): Implement HD withdrawals.
+- **FEAT**: add configurable seed node system with remote fetching (#85).
+- **FEAT**(hd): HD withdrawal supporting widgets and (WIP) multi-instance example.
+- **FEAT**(seed): update seed node format (#87).
+- **FEAT**: custom token import (#22).
+- **FEAT**(pubkey): add streamed new address API with Trezor confirmations (#123).
+- **FEAT**(sdk): Implement remaining SDK withdrawal functionality.
+- **FEAT**(types): Iterate on withdrawal-related types.
+- **FEAT**(withdraw): add ibc source channel parameter (#63).
+- **FEAT**(ui): add helper constructors for AssetLogo from legacy ticker and AssetId (#109).
+- **FEAT**: offline private key export (#160).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**(asset): add message signing support flag (#105).
+- **FEAT**(HD): Implement GUI utility for asset status.
+- **FEAT**(auth): allow weak password in auth options (#54).
+- **FEAT**(fees): integrate fee management (#152).
+- **BUG**(import): Fix incorrect encrypted seed parsing.
+- **BUG**: fix missing pubkey equality operators.
+- **BUG**(auth): Fix registration failing on Windows and Windows web builds (#34).
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+
+#### `komodo_symbol_converter` - `v0.3.0+1`
+
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FEAT**: offline private key export (#160).
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+
+#### `komodo_ui` - `v0.3.0+1`
+
+- **REFACTOR**: improve code quality and documentation.
+- **PERF**: migrate packages to Dart workspace.
+- **PERF**: migrate packages to Dart workspace".
+- **FIX**(ui): make Divided button min width.
+- **FIX**: Fix breaking dependency upgrades.
+- **FIX**(fee-info): update tendermint, erc20, and qrc20 `fee_details` response format (#60).
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**(ui): convert error display to stateful widget to toggle detailed error message (#46).
+- **FIX**(withdraw): update amount when isMaxAmount and show dropdown icon (#44).
+- **FEAT**(ui): Address and fee UI enhancements + formatting.
+- **FEAT**(ui): allow customizing SourceAddressField header (#135).
+- **FEAT**: offline private key export (#160).
+- **FEAT**(ui): add helper constructors for AssetLogo from legacy ticker and AssetId (#109).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**(KDF): Make provision for HD mode signing.
+- **FEAT**(source-address-field): add show balance toggle (#43).
+- **FEAT**: enhance balance and market data management in SDK.
+- **FEAT**(ui): add AssetLogo widget (#78).
+- **FEAT**(transactions): add activations and withdrawal priority features.
+- **FEAT**(ui): update asset components and SDK integrations.
+- **FEAT**(ui): enhance withdrawal form components with better validation and feedback.
+- **FEAT**(ui): add hero support for coin icons (#159).
+- **FEAT**(signing): Implement message signing + format.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(sdk): Balance manager WIP.
+- **FEAT**(hd): HD withdrawal supporting widgets and (WIP) multi-instance example.
+- **FEAT**: custom token import (#22).
+- **FEAT**(ui): Migrate withdrawal-related widgets from KW.
+- **FEAT**(sdk): Implement remaining SDK withdrawal functionality.
+- **FEAT**(UI): Migrate QR code scanner from KW.
+- **FEAT**(ui): redesign core input components with improved UX.
+- **DOCS**(ui): Document UI package structure.
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+
+#### `komodo_wallet_build_transformer` - `v0.3.0+1`
+
+- **REFACTOR**(build_transformer): move api release download and extraction to separate files (#23).
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**: breaking tendermint config changes and build transformer not using branch-specific content URL for non-master branches (#55).
+- **FIX**(build-transformer): ios xcode errors (#6).
+- **FIX**(build_transformer): npm error when building without `package.json` (#3).
+- **FEAT**: offline private key export (#160).
+- **FEAT**(wallet_build_transformer): add flexible CDN support (#144).
+- **FEAT**(ui): adjust error display layout for narrow screens (#114).
+- **FEAT**: enhance balance and market data management in SDK.
+- **FEAT**(dev): Install `melos`.
+- **FEAT**(hd): HD withdrawal supporting widgets and (WIP) multi-instance example.
+- **FEAT**(build): Add regex support for KDF download.
+- **FEAT**(builds): Add regex pattern support for KDF download.
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+- **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_wallet_cli` - `v0.3.0+1`
+
+- **PERF**: migrate packages to Dart workspace".
+- **PERF**: migrate packages to Dart workspace.
+- **FIX**(pub): add non-generic description.
+- **FIX**: unify+upgrade Dart/Flutter versions.
+- **FIX**(cli): Fix encoding for KDF config updater script.
+- **FEAT**: offline private key export (#160).
+- **FEAT**(dev): Install `melos`.
+- **BUG**(auth): Fix registration failing on Windows and Windows web builds (#34).
+- **BREAKING** **FEAT**: add Flutter Web WASM support with OPFS interop extensions (#176).
+- **BREAKING** **FEAT**(sdk): Multi-SDK instance support.
+- **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+#### `komodo_cex_market_data` - `v0.0.2+1`
+
+- **FEAT**(market-data): add support for multiple market data providers (#145).
+- **FEAT**: offline private key export (#160).
+- **FEAT**: migrate komodo_cex_market_data from komod-wallet (#37).
diff --git a/PR_484_code_changes.patch b/PR_484_code_changes.patch
new file mode 100644
index 00000000..dc9124d7
--- /dev/null
+++ b/PR_484_code_changes.patch
@@ -0,0 +1,362 @@
+diff --git a/.github/workflows/trigger-cf-build.yml b/.github/workflows/trigger-cf-build.yml
+index 835a8a04..bee5a8ee 100644
+--- a/.github/workflows/trigger-cf-build.yml
++++ b/.github/workflows/trigger-cf-build.yml
+@@ -5,7 +5,7 @@ on:
+ - main
+ jobs:
+ build-and-deploy:
+- runs-on: ubuntu-22.04
++ runs-on: ubuntu-20.04
+ steps:
+ - name: Invoke deployment hook
+ uses: distributhor/workflow-webhook@v3
+diff --git a/src/pages/komodo-defi-framework/api/common_structures/orders/index.mdx b/src/pages/komodo-defi-framework/api/common_structures/orders/index.mdx
+index 53e3030e..9df60aa2 100644
+--- a/src/pages/komodo-defi-framework/api/common_structures/orders/index.mdx
++++ b/src/pages/komodo-defi-framework/api/common_structures/orders/index.mdx
+@@ -253,7 +253,7 @@ export const description = "Each order on the Komodo Defi oderbook can be querie
+ | pubkey | string | The pubkey of the offer provider |
+ | age | number | The age of the offer (in seconds) |
+ | zcredits | number | The zeroconf deposit amount (deprecated) |
+-| netid | number | The id of the network on which the request is made (default is `0`) |
++| netid | number | The id of the network on which the request is made |
+ | uuid | string | The uuid of order |
+ | is\_mine | bool | Whether the order is placed by me |
+ | base\_max\_volume | string (decimal) | The maximum amount of `base` coin the offer provider is willing to buy or sell |
+diff --git a/src/pages/komodo-defi-framework/api/legacy/orderbook/index.mdx b/src/pages/komodo-defi-framework/api/legacy/orderbook/index.mdx
+index f15705b4..2a15cdbd 100644
+--- a/src/pages/komodo-defi-framework/api/legacy/orderbook/index.mdx
++++ b/src/pages/komodo-defi-framework/api/legacy/orderbook/index.mdx
+@@ -25,7 +25,7 @@ The `orderbook` method requests from the network the currently available orders
+ | base | string | the name of the coin the user desires to receive |
+ | rel | string | the name of the coin the user will trade |
+ | timestamp | number | the timestamp of the orderbook request |
+-| netid | number | the id of the network on which the request is made (default is `0`) |
++| netid | number | the id of the network on which the request is made |
+ | total\_asks\_base\_vol | string (decimal) | the base volumes sum of all asks |
+ | total\_asks\_base\_vol\_rat | rational | the `total_asks_base_vol` represented as a standard [RationalValue](/komodo-defi-framework/api/common_structures/#rational-value) object. |
+ | total\_asks\_base\_vol\_fraction | fraction | the `total_asks_base_vol` represented as a standard [FractionalValue](/komodo-defi-framework/api/common_structures/#fractional-value) object. |
+diff --git a/src/pages/komodo-defi-framework/api/v20/swaps_and_orders/orderbook/index.mdx b/src/pages/komodo-defi-framework/api/v20/swaps_and_orders/orderbook/index.mdx
+index 19de2bb8..fb4517a2 100644
+--- a/src/pages/komodo-defi-framework/api/v20/swaps_and_orders/orderbook/index.mdx
++++ b/src/pages/komodo-defi-framework/api/v20/swaps_and_orders/orderbook/index.mdx
+@@ -22,7 +22,7 @@ The v2 `orderbook` method requests from the network the currently available orde
+ | rel | string | The name of the coin the user will trade |
+ | numasks | integer | The number of outstanding asks |
+ | numbids | integer | The number of outstanding bids |
+-| netid | integer | The id of the network on which the request is made (default is `8762`) |
++| netid | integer | The id of the network on which the request is made |
+ | asks | array of objects | An array of standard [OrderDataV2](/komodo-defi-framework/api/common_structures/orders/#order-data-v2) objects containing outstanding asks |
+ | bids | array of objects | An array of standard [OrderDataV2](/komodo-defi-framework/api/common_structures/orders/#order-data-v2) objects containing outstanding bids |
+ | timestamp | integer | A UNIX timestamp representing when the orderbook was requested |
+diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/fee_management/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/fee_management/index.mdx
+index 532169bb..674bcbe1 100644
+--- a/src/pages/komodo-defi-framework/api/v20/wallet/fee_management/index.mdx
++++ b/src/pages/komodo-defi-framework/api/v20/wallet/fee_management/index.mdx
+@@ -77,6 +77,7 @@ If `gas_fee_estimator` is set to `provider`, you'll also need to add the `gas_ap
+ ```json
+ {
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpcport": 8777,
+ ...
+ "gas_api": {
+diff --git a/src/pages/komodo-defi-framework/setup/configure-mm2-json/index.mdx b/src/pages/komodo-defi-framework/setup/configure-mm2-json/index.mdx
+index 2106f7c6..9d2bd2e7 100644
+--- a/src/pages/komodo-defi-framework/setup/configure-mm2-json/index.mdx
++++ b/src/pages/komodo-defi-framework/setup/configure-mm2-json/index.mdx
+@@ -23,7 +23,9 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ | rpcport | integer | Optional, defaults to `7783`. Port to use for RPC communication. If set to `0`, an available port will be chosen randomly. |
+ | rpc\_local\_only | boolean | Optional, defaults to `true`. If `false` the Komodo DeFi Framework API will allow rpc methods sent from external IP addresses. **Warning:** Only use this if you know what you are doing, and have put the appropriate security measures in place. |
+ | i\_am\_seed | boolean | Optional, defaults to `false`. Runs Komodo DeFi Framework API as a seed node mode (acting as a relay for Komodo DeFi Framework API clients). Use of this mode is not reccomended on the main network (8762) as it could result in a pubkey ban if non-compliant. On alternative testing or private networks, at least one seed node is required to relay information to other Komodo DeFi Framework API clients using the same netID. |
+-| seednodes | list of strings | Optional. If operating on a test or private netID, the IP address of at least one seed node is required (on the main network, these are already hardcoded) |
++| seednodes | list of strings | The domain or IP address of at least one seed node running on the same `netid` is required for KDF to launch (unless `disable_p2p` is set to `true`). Seednodes are used for peer discovery, orderbook propagation and transmitting swap events. |
++| disable\_p2p | boolean | Optional, defaults to `false`. If `true`, KDF will not attempt to use P2P for peer discovery, orderbook propagation and transmitting swap events. This is useful for running KDF in a controlled environment, such as a local network. |
++| is\_bootstrap\_node | boolean | Optional, defaults to `false`. If `true`, and `i_am_seed` is also true, KDF will act as a bootstrap node for the network. |
+ | enable\_hd | boolean | Optional. If `true`, the Komodo DeFi-API will work in only the [HD mode](/komodo-defi-framework/api/v20/wallet/hd/), and coins will need to have a coin derivation path entry in the `coins` file for activation. Defaults to `false`. |
+ | gas\_api | object | Optional, Used for [EVM gas fee management](/komodo-defi-framework/api/v20/wallet/fee_management/). Contains fields for `provider` and `url` to source third party fee market information. |
+ | message\_service\_cfg | object | Optional. This data is used to configure [Telegram](https://telegram.org/) messenger alerts for swap events when running using the [makerbot functionality](/komodo-defi-framework/api/v20/swaps_and_orders/start_simple_market_maker_bot/). For more information check out the [telegram alerts guide](/komodo-defi-framework/api/v20/utils/telegram_alerts/) |
+@@ -47,6 +49,7 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "ENTER_UNIQUE_PASSWORD",
+ "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU",
+ "allow_weak_password": true,
+@@ -60,6 +63,7 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd",
+ "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU",
+ "allow_weak_password": false,
+@@ -73,6 +77,7 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd",
+ "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU",
+ "gas_api": {
+@@ -88,6 +93,7 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd",
+ "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU",
+ "wss_certs": {
+@@ -104,6 +110,7 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd",
+ "wallet_name": "Gringotts Retirement Fund",
+ "wallet_password": "Q^wJZg~Ck3.tPW~asnM-WrL"
+@@ -116,6 +123,7 @@ When running the Komodo DeFi API via commandline with the `kdf` binary, some bas
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd",
+ "1inch_api": "https://api.1inch.dev"
+ }
+@@ -145,6 +153,7 @@ If you are using HD wallets, you will need to set `enable_hd` to `true` in to yo
+ {
+ "gui": "DEVDOCS_CLI",
+ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
+ "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd",
+ "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU",
+ "allow_weak_password": false,
+@@ -153,6 +162,57 @@ If you are using HD wallets, you will need to set `enable_hd` to `true` in to yo
+ }
+ ```
+
++#### Examples for Seed nodes:
++
++For bootstrap nodes:
++
++* set `is_bootstrap_node` to `true`.
++* the `seednodes` list paramater is not required.
++* the `i_am_seed` paramater must be set to `true`.
++* the `disable_p2p` paramater must be set to `false`.
++
++```json
++{
++ "gui": "DEVDOCS_CLI",
++ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
++ "is_bootstrap_node": true,
++ "i_am_seed": true,
++ "disable_p2p": false
++}
++```
++
++For a normal seed node:
++
++* set `is_bootstrap_node` to `false`.
++* the `seednodes` list paramater is required.
++* the `i_am_seed` paramater must be set to `true`.
++* the `disable_p2p` paramater must be set to `false`.
++
++```json
++{
++ "gui": "DEVDOCS_CLI",
++ "netid": 8762,
++ "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"],
++ "is_bootstrap_node": false,
++ "i_am_seed": true,
++ "disable_p2p": false
++}
++```
++
++Some warning or errors may appear in logs on launch if these parameters are not set correctly.
++- `WARN P2P is disabled. Features that require a P2P network (like swaps, peer health checks, etc.) will not work.`
++- `P2P initializing error: 'Precheck failed: 'Seed nodes cannot disable P2P.'`
++- `P2P initializing error: 'Precheck failed: 'Bootstrap node must also be a seed node.'`
++- `Precheck failed: 'Non-bootstrap node must have seed nodes configured to connect.'
++
++
++
++ From v2.5.0-beta, there will be no default seed nodes, and the `seednodes` list parameter will be required,
++ unless `disable_p2p` is set to `true`. In this state, all KDF functionality related to orderbooks, swaps, and peer discovery will be disabled, but coins can still be activated and transactions can still be sent.
++
++
++
+ ## Coins file configuration
+
+ You can download and use [this file](https://github.com/KomodoPlatform/coins/blob/master/coins) as a starting point for your own `coins` file. It contains all of the coins that are currently supported by the Komodo DeFi API, and is maintained by the Komodo Platform team.
+diff --git a/src/pages/komodo-defi-framework/tutorials/api-docker-telegram/index.mdx b/src/pages/komodo-defi-framework/tutorials/api-docker-telegram/index.mdx
+index 63bb74d4..9c190542 100644
+--- a/src/pages/komodo-defi-framework/tutorials/api-docker-telegram/index.mdx
++++ b/src/pages/komodo-defi-framework/tutorials/api-docker-telegram/index.mdx
+@@ -136,7 +136,7 @@ start.sh
+
+
+ ```bash
+- root 30 17.5 3.8 879940 154996 pts/0 Sl+ 10:09 0:00 /usr/local/bin/kdf {"gui":"MM2GUI","netid":9999, "userhome":"/root", "passphrase":"L1XXXXXXXXXXXXXXXXXXXRY", "rpc_password":"HlXXXXXXXKW"}
++ root 30 17.5 3.8 879940 154996 pts/0 Sl+ 10:09 0:00 /usr/local/bin/kdf {"gui":"MM2GUI","netid":8762, "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"], "userhome":"/root", "passphrase":"L1XXXXXXXXXXXXXXXXXXXRY", "rpc_password":"HlXXXXXXXKW"}
+ ```
+
+
+diff --git a/src/pages/komodo-defi-framework/tutorials/api-walkthrough/index.mdx b/src/pages/komodo-defi-framework/tutorials/api-walkthrough/index.mdx
+index 70b9c7f6..92353f48 100644
+--- a/src/pages/komodo-defi-framework/tutorials/api-walkthrough/index.mdx
++++ b/src/pages/komodo-defi-framework/tutorials/api-walkthrough/index.mdx
+@@ -73,12 +73,13 @@ We also need to create an MM2.json file in the same directory as the `coins` fil
+
+ ### MM2.json Minimal Configuration
+
+-| Parameter | Type | Description |
+-| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+-| gui | string | Information to identify which app, tool or product is using the API, e.g. `KomodoWallet iOS 1.0.1`. Helps developers identify if an issue is related to specific builds or operating systems etc. |
+-| netid | integer | Nework ID number, telling the Komodo DeFi Framework API which network to join. 8762 is the current main network, though alternative netids can be used for testing or "private" trades as long as seed nodes exist to support it. |
+-| passphrase | string | Your passphrase; this is the source of each of your coins private keys. KEEP IT SAFE! |
+-| rpc\_password | string | For RPC requests that need authentication, this will need to match the `userpass` value in the request body. |
++| Parameter | Type | Description |
++| ------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
++| gui | string | Information to identify which app, tool or product is using the API, e.g. `KomodoWallet iOS 1.0.1`. Helps developers identify if an issue is related to specific builds or operating systems etc. |
++| netid | integer | Nework ID number, telling the Komodo DeFi Framework API which network to join. At least one seed node domain or IP address needs to be specified on the same `netid` to support it. |
++| seednodes | list of strings | The domain or IP address of at least one seed node running on the same `netid` is required for peer discovery, orderbook propagation and transmitting swap events. |
++| passphrase | string | Your passphrase; this is the source of each of your coins private keys. KEEP IT SAFE! |
++| rpc\_password | string | For RPC requests that need authentication, this will need to match the `userpass` value in the request body. |
+
+
+ Unless you include the `allow_weak_password` paramater and set it to `true`, your `rpc_password`:
+@@ -92,7 +93,7 @@ We also need to create an MM2.json file in the same directory as the `coins` fil
+ The MM2.json configuration commands can also be supplied at runtime, as below:
+
+ ```bash
+-stdbuf -oL ./kdf "{\"gui\":\"Docs_Walkthru\",\"netid\":8762, \"passphrase\":\"YOUR_PASSPHRASE_HERE\", \"rpc_password\":\"YOUR_PASSWORD_HERE\"}" &
++stdbuf -oL ./kdf "{\"gui\":\"Docs_Walkthru\",\"netid\":8762, "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"], \"passphrase\":\"YOUR_PASSPHRASE_HERE\", \"rpc_password\":\"YOUR_PASSWORD_HERE\"}" &
+ ```
+
+ Replace `YOUR_PASSPHRASE_HERE` and `YOUR_PASSWORD_HERE` with your actual passphrase and password, and then execute the command in the terminal.
+@@ -137,7 +138,8 @@ If you see something similar, the Komodo DeFi Framework API is up and running!
+ When using the Komodo DeFi Framework API on a VPS without accompanying tools such as `tmux` or `screen`, it is recommended to use [`nohup`](https://www.digitalocean.com/community/tutorials/nohup-command-in-linux). This will ensure that the Komodo DeFi Framework API instance is not shutdown when the user logs out.
+
+ ```bash
+- stdbuf -oL nohup ./mm2 "{\"gui\":\"Docs_Walkthru\",\"netid\":8762, \"passphrase\":\"YOUR_PASSPHRASE_HERE\", \"rpc_password\":\"YOUR_PASSWORD_HERE\"}" &
++ stdbuf -oL nohup ./mm2 "{\"gui\":\"Docs_Walkthru\",\"netid\":8762, "seednodes": ["seed01.kmdefi.net", "seed02.kmdefi.net"]
++ , \"passphrase\":\"YOUR_PASSPHRASE_HERE\", \"rpc_password\":\"YOUR_PASSWORD_HERE\"}" &
+ ```
+
+
+diff --git a/src/pages/komodo-defi-framework/tutorials/setup-komodefi-api-aws/index.mdx b/src/pages/komodo-defi-framework/tutorials/setup-komodefi-api-aws/index.mdx
+index 2ccddb27..d68ee648 100644
+--- a/src/pages/komodo-defi-framework/tutorials/setup-komodefi-api-aws/index.mdx
++++ b/src/pages/komodo-defi-framework/tutorials/setup-komodefi-api-aws/index.mdx
+@@ -19,7 +19,7 @@ apt-get install -y unzip jq curl
+ wget $(curl --silent https://api.github.com/repos/KomodoPlatform/komodo-defi-framework/releases | jq -r '.[0].assets[] | select(.name | endswith("Linux-Release.zip")).browser_download_url')
+ wget https://raw.githubusercontent.com/KomodoPlatform/coins/master/coins
+ unzip *Linux-Release.zip
+-./kdf "{\"netid\":8762,\"gui\":\"aws_cli\",\"passphrase\":\"SEED_WORDS_PLEASE_REPLACE\",\"rpc_password\":\"RPC_PASS_PLEASE_REPLACE\",\"myipaddr\":\"0.0.0.0\"}"
++./kdf "{\"netid\":8762,\"seednodes\":[\"seed01.kmdefi.net\", \"seed02.kmdefi.net\"],\"gui\":\"aws_cli\",\"passphrase\":\"SEED_WORDS_PLEASE_REPLACE\",\"rpc_password\":\"RPC_PASS_PLEASE_REPLACE\",\"myipaddr\":\"0.0.0.0\"}"
+ ```
+
+ ## Install AWS CLI , get AWS access credentials
+diff --git a/src/pages/komodo/setup-electrumx-server/index.mdx b/src/pages/komodo/setup-electrumx-server/index.mdx
+index d474f570..ae07fb43 100644
+--- a/src/pages/komodo/setup-electrumx-server/index.mdx
++++ b/src/pages/komodo/setup-electrumx-server/index.mdx
+@@ -156,7 +156,7 @@ ws.close()
+ To keep your electrum server running smoothly, it is recommended to compact the database once a week. We can do this with a [crontab](https://crontab.guru/) entry as below:
+
+ ```bash
+-10 8 * * 2 sudo systemctl stop electrumx_RICK && COIN=Rick DB_DIRECTORY=/electrumdb/RICK /home//electrumx-1/electrumx_compact_history && sudo systemctl start electrumx_RICK
++33 3 * * 3 sudo systemctl stop electrumx_RICK && COIN=Rick; DB_DIRECTORY=/electrumdb/RICK; /home//electrumx-1/electrumx_compact_history && sudo systemctl start electrumx_RICK
+ ```
+
+ This means that every Wednesday at 3:33am, we'll stop the electrum service, compact the database, then restart the service. You should change the day of week for each of your electrum servers so that they dont all go down for maintainence at the same time.
+diff --git a/utils/js/create_search_index.js b/utils/js/create_search_index.js
+index d3b336fc..64cf7dec 100644
+--- a/utils/js/create_search_index.js
++++ b/utils/js/create_search_index.js
+@@ -18,25 +18,11 @@ const listOfAllowedElementsToCheck = [
+ // "a",
+ "p",
+ "li",
+- // "ul", // enabling this means `ul` returns `li` content(text) causing duplicates
++ "ul",
+ "pre",
+ "table",
+ ];
+
+-const textContentElementArrayToCheck = [
+- "h1",
+- "h2",
+- "h3",
+- "h4",
+- "h5",
+- "h6",
+- "p",
+- "li",
+- "pre",
+- "code",
+- "td",
+-];
+-
+ const jsonFile = JSON.parse(fs.readFileSync("./src/data/sidebar.json"));
+
+ const extractSidebarTitles = (jsonData, linksArray = []) => {
+@@ -119,23 +105,10 @@ const getStringContentFromElement = (elementTree, contentList = []) => {
+ return contentList;
+ };
+
+-// Helper function to extract text from a node and its children
+-function extractTextFromNode(node) {
+- if (node.type === "text") {
+- return node.value;
+- }
+-
+- if (node.children) {
+- return node.children.map(extractTextFromNode).join(" ");
+- }
+-
+- return "";
+-}
+-
+ function elementTreeChecker(mdxFilePathToCompile) {
+ return async (tree) => {
+ let textContentOfElement = "";
+- let closestElementReference = "";
++ let closestElementReference = null;
+ let slugify = slugifyWithCounter();
+ let documentTree = [];
+ const docPath = transformFilePath(mdxFilePathToCompile);
+@@ -165,14 +138,12 @@ function elementTreeChecker(mdxFilePathToCompile) {
+ path: docPath,
+ };
+ }
+- visit(node, "element", (elementNode) => {
+- if (!textContentElementArrayToCheck.includes(node.tagName)) return;
+- const completeText = extractTextFromNode(elementNode);
+- if (!!completeText.trim()) {
++ visit(node, "text", (text) => {
++ if (!!text.value.trim()) {
+ // For searchPreview
+ let lineData = {
+- text: completeText,
+- tagName: elementNode.tagName,
++ text: text.value,
++ tagName: node.tagName,
+ path: docPath,
+ closestElementReference,
+ };
+@@ -181,10 +152,9 @@ function elementTreeChecker(mdxFilePathToCompile) {
+
+ textContentOfElement = textContentOfElement.concat(
+ " ",
+- completeText
++ text.value
+ );
+ }
+- return visit.SKIP;
+ });
+ }
+ });
diff --git a/README.md b/README.md
index 53bf046d..3f6d42ba 100644
--- a/README.md
+++ b/README.md
@@ -4,121 +4,91 @@
-# Komodo Defi Framework SDK for Flutter
+# Komodo DeFi SDK for Flutter
-This is a series of Flutter packages for integrating the [Komodo DeFi Framework](https://komodoplatform.com/en/komodo-defi-framework.html) into Flutter applications. This enhances devex by providing an intuitive abstraction layer and handling all binary/media file fetching, reducing what previously would have taken months to understand the API and build a Flutter dApp with KDF integration into a few days.
+Komodo’s Flutter SDK lets you build cross-platform DeFi apps on top of the Komodo DeFi Framework (KDF) with a few lines of code. The SDK provides a high-level, batteries-included developer experience while still exposing the low-level framework and RPC methods when you need them.
-See the Komodo DeFi Framework (API) source repository at [KomodoPlatform/komodo-defi-framework](https://github.com/KomodoPlatform/komodo-defi-framework) and view the demo site (source in [example](./example)) project at [https://komodo-playground.web.app](https://komodo-playground.web.app).
+- Primary entry point: see `packages/komodo_defi_sdk`.
+- Full KDF access: see `packages/komodo_defi_framework`.
+- RPC models and namespaces: see `packages/komodo_defi_rpc_methods`.
+- Core types: see `packages/komodo_defi_types`.
+- Coins metadata utilities: see `packages/komodo_coins`.
+- Market data: see `packages/komodo_cex_market_data`.
+- UI widgets: see `packages/komodo_ui`.
+- Build hooks and artifacts: see `packages/komodo_wallet_build_transformer`.
-The recommended entry point ([komodo_defi_sdk](/packages/komodo_defi_sdk/README.md)) is a high-level opinionated library that provides a simple way to build cross-platform Komodo Defi Framework applications (primarily focused on wallets). This repository consists of multiple other child packages in the [packages](./packages) folder, which is orchestrated by the [komodo_defi_sdk](/packages/komodo_defi_sdk/README.md) package.
+Supported platforms: Android, iOS, macOS, Windows, Linux, and Web (WASM).
-Note: Most of this README focuses on the lower-level `komodo-defi-framework` package and still needs to be updated to focus on the primary package, `komodo_defi_sdk`.
+See the Komodo DeFi Framework (API) source at `https://github.com/KomodoPlatform/komodo-defi-framework` and a hosted demo at `https://komodo-playground.web.app`.
-This project supports building for macOS (more native platforms coming soon) and the web. KDF can either be run as a local Rust binary or you can connect to a remote instance. 1-Click setup for DigitalOcean and AWS deployment is in progress.
+## Quick start (SDK)
-Use the [komodo_defi_framework](packages/komodo_defi_sdk) package for an unopinionated implementation that gives access to the underlying KDF methods.
+Add the SDK to your app and initialize it:
-The structure for this repository is inspired by the [Flutter BLoC](https://github.com/felangel/bloc) project.
+```dart
+import 'package:komodo_defi_sdk/komodo_defi_sdk.dart';
+
+void main() async {
+ final sdk = KomodoDefiSdk(
+ // Local by default; use RemoteConfig to connect to a remote node
+ host: LocalConfig(https: false, rpcPassword: 'your-secure-password'),
+ config: const KomodoDefiSdkConfig(
+ defaultAssets: {'KMD', 'BTC', 'ETH'},
+ ),
+ );
+
+ await sdk.initialize();
+
+ // Register or sign in
+ await sdk.auth.register(walletName: 'my_wallet', password: 'strong-pass');
+
+ // Activate assets and get a balance
+ final btc = sdk.assets.findAssetsByConfigId('BTC').first;
+ await sdk.assets.activateAsset(btc).last;
+ final balance = await sdk.balances.getBalance(btc.id);
+ print('BTC balance: ${balance.total}');
+
+ // Direct RPC access when needed
+ final myKmd = await sdk.client.rpc.wallet.myBalance(coin: 'KMD');
+ print('KMD: ${myKmd.balance}');
+}
+```
-This project generally follows the guidelines and high standards set by [Very Good Ventures](https://vgv.dev/).
+## Architecture overview
-TODO: Add a comprehensive README
+- `komodo_defi_sdk`: High-level orchestration (auth, assets, balances, tx history, withdrawals, signing, market data).
+- `komodo_defi_framework`: Platform client for KDF with multiple backends (native/WASM/local process, remote). Provides the `ApiClient` used by the SDK.
+- `komodo_defi_rpc_methods`: Typed RPC request/response models and method namespaces available via `client.rpc.*`.
+- `komodo_defi_types`: Shared, lightweight domain types (e.g., `Asset`, `AssetId`, `BalanceInfo`, `WalletId`).
+- `komodo_coins`: Fetch/transform Komodo coins metadata, filtering strategies, seed-node utilities.
+- `komodo_cex_market_data`: Price providers (Komodo, Binance, CoinGecko) with repository selection and fallbacks.
+- `komodo_ui`: Reusable, SDK-friendly Flutter UI components.
+- `komodo_wallet_build_transformer`: Build-time artifact & assets fetcher (KDF binaries, coins, icons) integrated via Flutter’s asset transformers.
-TODO: Contribution guidelines and architecture overview
+## Remote vs Local
-## Example
+- Local (default): Uses native FFI on desktop/mobile and WASM in Web builds. The SDK handles artifact provisioning via the build transformer.
+- Remote: Connect with `RemoteConfig(ipAddress: 'host', port: 7783, rpcPassword: '...', https: true/false)`. You manage the remote KDF lifecycle.
-Below is an extract from the [example project](https://github.com/KomodoPlatform/komodo-defi-sdk-flutter/blob/dev/example/lib/main.dart) showing the straightforward integration. Note that this is for the [komodo_defi_framework](packages/komodo_defi_framework), and the [komodo_defi_sdk](/packages/komodo_defi_sdk/README.md) will provide a higher-layer abstraction.
+Seed nodes: From KDF v2.5.0-beta, `seednodes` are required unless `disable_p2p` is `true`. The framework includes a validator and helpers. See `packages/komodo_defi_framework/README.md`.
-Create the configuration for the desired runtime:
-```dart
- switch (_selectedHostType) {
- case 'remote':
- config = RemoteConfig(
- userpass: _userpassController.text,
- ipAddress: '$_selectedProtocol://${_ipController.text}',
- port: int.parse(_portController.text),
- );
- break;
- case 'aws':
- config = AwsConfig(
- userpass: _userpassController.text,
- region: _awsRegionController.text,
- accessKey: _awsAccessKeyController.text,
- secretKey: _awsSecretKeyController.text,
- instanceType: _awsInstanceTypeController.text,
- );
- break;
- case 'local':
- config = LocalConfig(userpass: _userpassController.text);
- break;
- default:
- throw Exception(
- 'Invalid/unsupported host type: $_selectedHostType',
- );
- }
-```
+## Packages in this monorepo
-Start KDF:
+- `packages/komodo_defi_sdk` – High-level SDK (start here)
+- `packages/komodo_defi_framework` – Low-level KDF client + lifecycle
+- `packages/komodo_defi_rpc_methods` – Typed RPC surfaces
+- `packages/komodo_defi_types` – Shared domain types
+- `packages/komodo_coins` – Coins metadata + filters
+- `packages/komodo_cex_market_data` – CEX price data
+- `packages/komodo_ui` – UI widgets
+- `packages/dragon_logs` – Cross-platform logging
+- `packages/komodo_wallet_build_transformer` – Build artifacts/hooks
+- `packages/dragon_charts_flutter` – Lightweight charts (moved here)
-```dart
-void _startKdf(String passphrase) async {
- _statusMessage = null;
-
- if (_kdfFramework == null) {
- _showMessage('Please configure the framework first.');
- return;
- }
-
- try {
- final result = await _kdfFramework!.startKdf(passphrase);
- setState(() {
- _statusMessage = 'KDF running: $result';
- _isRunning = true;
- });
-
- if (!result.isRunning()) {
- _showMessage('Failed to start KDF: $result');
- // return;
- }
- } catch (e) {
- _showMessage('Failed to start KDF: $e');
- }
-
- await _saveData();
- }
-```
+## Contributing
-Execute RPC requests:
-```dart
-executeRequest: (rpcInput) async {
- if (_kdfFramework == null || !_isRunning) {
- _showMessage('KDF is not running.');
- throw Exception('KDF is not running.');
- }
- return (await _kdfFramework!.executeRpc(rpcInput)).toString();
- },
-```
+We follow practices inspired by Flutter BLoC and Very Good Ventures’ standards. Please open PRs and issues in this repository.
-Stop KDF:
-```dart
+## License
- void _stopKdf() async {
- if (_kdfFramework == null) {
- _showMessage('Please configure the framework first.');
- return;
- }
-
- try {
- final result = await _kdfFramework!.kdfStop();
- setState(() {
- _statusMessage = 'KDF stopped: $result';
- _isRunning = false;
- });
-
- _checkStatus().ignore();
- } catch (e) {
- _showMessage('Failed to stop KDF: $e');
- }
- }
-```
+MIT. See individual package LICENSE files where present.
diff --git a/docs/act-local-testing.md b/docs/act-local-testing.md
new file mode 100644
index 00000000..633f99e5
--- /dev/null
+++ b/docs/act-local-testing.md
@@ -0,0 +1,90 @@
+# Run GitHub Actions locally with act
+
+This guide shows how to run the Flutter test workflow locally using act, filter to a single package, and re-run failed jobs on GitHub.
+
+## Prerequisites
+
+- Docker (required by act)
+ - Windows: [Install Docker Desktop on Windows](https://docs.docker.com/desktop/install/windows-install/)
+ - macOS: [Install Docker Desktop on Mac](https://docs.docker.com/desktop/install/mac-install/)
+ - Ubuntu: [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/)
+
+- act
+ - macOS (Homebrew):
+
+ ```bash
+ brew install act
+ ```
+
+ - Other platforms: download a binary from [nektos/act releases](https://github.com/nektos/act/releases) and put it on your PATH
+ - Repo/docs: [nektos/act](https://github.com/nektos/act)
+
+- (Optional) GitHub CLI (to re-run failed jobs on GitHub):
+ - Install: [GitHub CLI](https://cli.github.com/)
+
+## Notes for Apple Silicon (M-series) Macs
+
+- act may need to run containers as amd64:
+ - Add: `--container-architecture linux/amd64`
+ - Map `ubuntu-latest` to an image: `-P ubuntu-latest=catthehacker/ubuntu:act-latest`
+
+## Common commands
+
+- List jobs in this workflow:
+
+ ```bash
+ act -l -W .github/workflows/flutter-tests.yml
+ ```
+
+- Run the test job for all packages (verbose):
+
+ ```bash
+ act -j test --verbose \
+ -W .github/workflows/flutter-tests.yml \
+ -P ubuntu-latest=catthehacker/ubuntu:act-latest \
+ --container-architecture linux/amd64
+ ```
+
+- Run only a single package (e.g., packages/komodo_coin_updates) via workflow_dispatch input (verbose):
+
+ ```bash
+ act workflow_dispatch -j test --verbose \
+ -W .github/workflows/flutter-tests.yml \
+ -P ubuntu-latest=catthehacker/ubuntu:act-latest \
+ --container-architecture linux/amd64 \
+ --input package=komodo_coin_updates
+ ```
+
+- Filter packages by regex (matches paths under `packages/*`):
+
+ ```bash
+ act workflow_dispatch -j test --verbose \
+ -W .github/workflows/flutter-tests.yml \
+ -P ubuntu-latest=catthehacker/ubuntu:act-latest \
+ --container-architecture linux/amd64 \
+ --input package_regex='komodo_coin_updates'
+ ```
+
+## Re-run only failed jobs on GitHub
+
+- GitHub UI: Actions → select the failed run → Re-run jobs → Re-run failed jobs
+- GitHub CLI:
+
+ ```bash
+ gh run rerun --failed
+ ```
+
+## Verify installation
+
+- Docker:
+
+ ```bash
+ docker --version
+ docker run hello-world
+ ```
+
+- act:
+
+ ```bash
+ act --version
+ ```
diff --git a/docs/firebase/firebase-deployment-setup.md b/docs/firebase/firebase-deployment-setup.md
new file mode 100644
index 00000000..88e2549b
--- /dev/null
+++ b/docs/firebase/firebase-deployment-setup.md
@@ -0,0 +1,232 @@
+# Firebase GitHub Secrets Setup
+
+This document provides instructions for setting up Firebase GitHub secrets using the automated scripts or manual process.
+
+## Overview
+
+The Komodo DeFi SDK Flutter project uses Firebase Hosting for deploying two web applications:
+
+1. **SDK Example** - Deployed to `komodo-defi-sdk` Firebase project
+2. **Playground** - Deployed to `komodo-playground` Firebase project
+
+GitHub Actions workflows require service account credentials to deploy to these Firebase projects.
+
+## Prerequisites
+
+### Required Tools
+
+- **Google Cloud SDK (gcloud)** - [Installation Guide](https://cloud.google.com/sdk/docs/install)
+- **GitHub CLI (gh)** - [Installation Guide](https://cli.github.com/manual/installation)
+- **jq** (for verification script) - JSON processor
+
+### Required Access
+
+- Admin access to both Firebase projects:
+ - `komodo-defi-sdk`
+ - `komodo-playground`
+- Write access to the GitHub repository secrets
+
+## Automated Setup
+
+We provide scripts to automate the entire setup process:
+
+### 1. Setup Script
+
+Run the setup script to create service accounts and configure GitHub secrets:
+
+```bash
+./.github/scripts/firebase/setup-github-secrets.sh
+```
+
+This script will:
+
+- Check all prerequisites
+- Create service accounts (if they don't exist)
+- Grant necessary IAM permissions
+- Generate service account keys
+- Create/update GitHub repository secrets
+- Clean up sensitive key files
+
+### 2. Verification Script
+
+Verify your setup is correct:
+
+```bash
+./.github/scripts/firebase/verify-github-secrets.sh
+```
+
+This script will check:
+
+- Tool installations
+- Authentication status
+- Service account existence
+- IAM permissions
+- GitHub secrets existence
+
+## Manual Setup
+
+If you prefer to set up manually or need to troubleshoot:
+
+### Step 1: Authenticate with Google Cloud
+
+```bash
+gcloud auth login
+gcloud auth application-default login
+```
+
+### Step 2: Create Service Accounts
+
+For komodo-defi-sdk:
+
+```bash
+gcloud config set project komodo-defi-sdk
+gcloud iam service-accounts create github-actions-deploy \
+ --display-name="GitHub Actions Deploy" \
+ --description="Service account for GitHub Actions Firebase deployments"
+```
+
+For komodo-playground:
+
+```bash
+gcloud config set project komodo-playground
+gcloud iam service-accounts create github-actions-deploy \
+ --display-name="GitHub Actions Deploy" \
+ --description="Service account for GitHub Actions Firebase deployments"
+```
+
+### Step 3: Grant Permissions
+
+For each project, grant the required roles:
+
+```bash
+# Set project (komodo-defi-sdk or komodo-playground)
+PROJECT_ID="komodo-defi-sdk" # or "komodo-playground"
+SERVICE_ACCOUNT_EMAIL="github-actions-deploy@${PROJECT_ID}.iam.gserviceaccount.com"
+
+# Grant roles
+gcloud projects add-iam-policy-binding ${PROJECT_ID} \
+ --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
+ --role="roles/firebase.hosting.admin"
+
+gcloud projects add-iam-policy-binding ${PROJECT_ID} \
+ --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
+ --role="roles/firebase.rules.admin"
+
+gcloud projects add-iam-policy-binding ${PROJECT_ID} \
+ --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
+ --role="roles/iam.serviceAccountTokenCreator"
+```
+
+### Step 4: Generate Service Account Keys
+
+For komodo-defi-sdk:
+
+```bash
+gcloud iam service-accounts keys create komodo-defi-sdk-key.json \
+ --iam-account="github-actions-deploy@komodo-defi-sdk.iam.gserviceaccount.com" \
+ --project="komodo-defi-sdk"
+```
+
+For komodo-playground:
+
+```bash
+gcloud iam service-accounts keys create komodo-playground-key.json \
+ --iam-account="github-actions-deploy@komodo-playground.iam.gserviceaccount.com" \
+ --project="komodo-playground"
+```
+
+### Step 5: Create GitHub Secrets
+
+```bash
+# Authenticate with GitHub CLI
+gh auth login
+
+# Create secrets
+gh secret set FIREBASE_SERVICE_ACCOUNT_KOMODO_DEFI_SDK \
+ < komodo-defi-sdk-key.json \
+ --repo KomodoPlatform/komodo-defi-sdk-flutter
+
+gh secret set FIREBASE_SERVICE_ACCOUNT_KOMODO_PLAYGROUND \
+ < komodo-playground-key.json \
+ --repo KomodoPlatform/komodo-defi-sdk-flutter
+```
+
+### Step 6: Clean Up Key Files
+
+⚠️ **IMPORTANT**: Delete the key files after creating GitHub secrets:
+
+```bash
+rm -f komodo-defi-sdk-key.json
+rm -f komodo-playground-key.json
+```
+
+## Testing the Setup
+
+After setting up the secrets, you can test the deployment:
+
+1. **Create a Pull Request** - This triggers the PR preview workflow
+2. **Push to `dev` branch** - This triggers the merge deployment workflow
+
+Check the GitHub Actions tab in the repository to monitor the deployment status.
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Authentication Errors**
+
+ - Ensure you're logged in: `gcloud auth login` and `gh auth login`
+ - Check you have the correct permissions in both Google Cloud and GitHub
+
+2. **Service Account Permission Errors**
+
+ - Verify all three required roles are granted
+ - Wait a few minutes for IAM changes to propagate
+
+3. **GitHub Secret Errors**
+ - Ensure the entire JSON key file content is copied
+ - Check for any extra whitespace or formatting issues
+
+### Debugging Commands
+
+Check current gcloud configuration:
+
+```bash
+gcloud config list
+gcloud auth list
+```
+
+List service accounts:
+
+```bash
+gcloud iam service-accounts list --project=komodo-defi-sdk
+gcloud iam service-accounts list --project=komodo-playground
+```
+
+Check IAM bindings:
+
+```bash
+gcloud projects get-iam-policy komodo-defi-sdk
+gcloud projects get-iam-policy komodo-playground
+```
+
+List GitHub secrets:
+
+```bash
+gh secret list --repo KomodoPlatform/komodo-defi-sdk-flutter
+```
+
+## Security Best Practices
+
+1. **Never commit service account keys** to the repository
+2. **Delete local key files** immediately after use
+3. **Rotate keys periodically** for security
+4. **Use least privilege** - only grant necessary permissions
+5. **Monitor usage** through Google Cloud Console
+
+## Additional Resources
+
+- [Firebase Admin SDK Service Accounts](https://firebase.google.com/docs/admin/setup#initialize-sdk)
+- [GitHub Encrypted Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
+- [Google Cloud IAM Documentation](https://cloud.google.com/iam/docs)
+- [Firebase Hosting GitHub Action](https://github.com/FirebaseExtended/action-hosting-deploy)
diff --git a/docs/tech_debt/Activation_and_ZHTLC_Tech_Debt.md b/docs/tech_debt/Activation_and_ZHTLC_Tech_Debt.md
new file mode 100644
index 00000000..65027d3e
--- /dev/null
+++ b/docs/tech_debt/Activation_and_ZHTLC_Tech_Debt.md
@@ -0,0 +1,119 @@
+## Tech Debt Report: Activation and ZHTLC
+
+### Context and scope
+
+- New components introduced: `ActivationConfigService`, `HiveActivationConfigRepository`, `ZhtlcActivationStrategy`, `SharedActivationCoordinator`, wiring in `bootstrap.dart`, UI prompts in example.
+- Primary concerns: activation orchestration, ZHTLC activation/config, persistence, concurrency, and UI flow.
+
+### Design pattern alignment (good)
+
+- Strategy: protocol-specific activation strategies (e.g., `ZhtlcActivationStrategy`) selected via `ActivationStrategyFactory`.
+- Factory: `ActivationStrategyFactory` composes per-protocol activators.
+- Repository: `ActivationConfigRepository` and `HiveActivationConfigRepository`.
+- Mediator/Coordinator: `SharedActivationCoordinator` synchronizes activation across managers.
+- Observer: activation progress streams, failed/pending streams.
+- Mutex: `ActivationManager`’s `Mutex` for critical sections.
+
+### Tech-debt inventory
+
+- Architecture and flow
+
+ - Primary/child grouping bug in `ActivationManager`
+
+ - Risk: child asset may be treated as group primary, confusing strategy selection and completion bookkeeping.
+ - Reference: `packages/komodo_defi_sdk/lib/src/activation/activation_manager.dart` (`_groupByPrimary`).
+ - Refactoring: Ensure true primary resolution for group key and members.
+
+ - Duplication of activation orchestration
+
+ - Both `ActivationManager` and `SharedActivationCoordinator` track activation state and deduplication.
+ - Refactoring: Make Coordinator the single entrypoint (Facade); slim `ActivationManager` to strategy runner.
+
+ - Flutter-only dependency in SDK bootstrap
+ - `Hive.initFlutter()` in SDK couples core to Flutter.
+ - Refactoring: Inject `ActivationConfigRepository` via DI; provide Flutter Hive impl at app layer.
+
+- API/serialization consistency
+
+ - `priv_key_policy` serialization not centralized
+
+ - Base emits PascalCase string; EVM needs JSON object.
+ - Refactoring: Use `PrivKeyPolicySerializer` consistently in base or subclasses; add tests.
+
+ - ZHTLC parameter extraction
+ - `ZhtlcActivationParams` correctly owns `zcash_params_path` and scan tuning (good).
+
+- Config, persistence, and UI flow
+
+ - Service/UI coupling without a formal BLoC
+
+ - Example pre-prompts and saves config; strategy also awaits service completer.
+ - Refactoring: Introduce `ActivationConfigBloc`; UI uses descriptors; strategies pull via service only.
+
+ - Activation settings descriptors unused in UI
+
+ - Add dynamic form generation using `AssetId.activationSettings()`.
+
+ - Repository granularity
+
+ - Single map per wallet entry can cause coarse updates.
+ - Consider per-asset keys or transactional update helper.
+
+ - Zcash params path UX
+ - Provide platform helpers or discovery to reduce user friction.
+
+- Concurrency and timing
+
+ - Coin availability backoff short and hard-coded
+
+ - Make policy configurable; add metrics.
+
+ - No public cancellation API
+ - Add `cancelActivation(assetId)` on Coordinator; propagate.
+
+- Naming and API
+
+ - Legacy RPC method name for ZHTLC is acceptable but document it clearly.
+
+- Code quality
+ - `ActivationProgressDetails.toJson` optional-field serialization bug; fix with conditional inserts.
+ - Outdated TODO in `ZhtlcActivationStrategy` re: sync mode; update.
+
+### Recommendations
+
+- Unify activation orchestration in `SharedActivationCoordinator`; treat it as Facade/Mediator.
+- Fix `_groupByPrimary` to always use true primary; add tests.
+- Normalize `priv_key_policy` serialization using `PrivKeyPolicySerializer`; add per-protocol tests.
+- Decouple persistence from SDK; inject `ActivationConfigRepository` and remove direct `Hive.initFlutter()` from core.
+- Implement `ActivationConfigBloc` and adopt `ActivationSettingDescriptor` in UI.
+- Expose `cancelActivation(assetId)` and configurable coin-availability wait.
+- Add unit/integration tests and structured logs around activation timing.
+
+### Prioritized action plan
+
+1. Correctness: fix `toJson`, fix grouping, update ZHTLC TODO.
+2. Architecture: coordinator as single entrypoint; cancellation + wait policy.
+3. Serialization: apply serializer; tests.
+4. Config/Persistence: BLoC + descriptors; DI for repository.
+5. Tests/Docs: coverage + documentation.
+
+### Suggested conventional commits
+
+- fix(types): correct ActivationProgressDetails.toJson optional fields
+- fix(activation): ensure \_groupByPrimary uses true primary asset
+- refactor(activation): centralize orchestration in SharedActivationCoordinator
+- feat(activation): add cancelActivation and configurable availability wait
+- refactor(rpc): use PrivKeyPolicySerializer across protocols; add tests
+- feat(config): add ActivationConfigBloc and adopt ActivationSettingDescriptor in example UI
+- refactor(sdk): inject ActivationConfigRepository via bootstrap; remove direct Hive.initFlutter dependency
+- docs: update ZHTLC activation docs and RPC naming notes
+- test(activation): add ZHTLC activation flow tests
+
+### Acceptance criteria
+
+- Single activation Facade with deduplication and coin-availability guard.
+- Correct grouping semantics; passing tests.
+- Consistent `priv_key_policy` serialization per protocol; tests pass.
+- ZHTLC config via BLoC; UI built from descriptors.
+- SDK no longer depends on Flutter for persistence wiring.
+- Cancellation and availability wait are configurable and documented.
diff --git a/docs/tech_debt/PR227_ZHTLC_Tech_Debt.md b/docs/tech_debt/PR227_ZHTLC_Tech_Debt.md
new file mode 100644
index 00000000..02e898bc
--- /dev/null
+++ b/docs/tech_debt/PR227_ZHTLC_Tech_Debt.md
@@ -0,0 +1,139 @@
+# Tech Debt: PR #227 – ZHTLC Activation Fixes
+
+Date: 2025-10-02
+PR: https://github.com/KomodoPlatform/komodo-defi-sdk-flutter/pull/227
+Head commit: 1af4278
+
+This document compiles AI review findings into actionable tech-debt items with severity, impact, and recommended fixes. Items are grouped by concern.
+
+## Build/Web-Safety
+
+- [CRITICAL] Remove `dart:io` and `Platform.*` usage in web-visible factory
+ - Files: `packages/komodo_defi_sdk/lib/src/zcash_params/zcash_params_downloader_factory.dart` (import at top, branches at ~49–71, ~121–130)
+ - Problem: Unconditional `import 'dart:io';` and `Platform.*` branching break web/wasm builds.
+ - Impact: Web builds fail at compile time.
+ - Fix:
+ - Replace `dart:io` import with `package:flutter/foundation.dart`.
+ - Use `kIsWeb` and `defaultTargetPlatform`/`TargetPlatform` for branching.
+ - Ensure `detectPlatform()` is web-safe and does not reference `Platform.*`.
+ - If a dedicated `WebZcashParamsDownloader` exists, prefer it on `kIsWeb`.
+ - Example branching:
+ ```dart
+ import 'package:flutter/foundation.dart';
+ // ...
+ if (kIsWeb) {
+ return WebZcashParamsDownloader(/* ... */);
+ }
+ final platform = defaultTargetPlatform;
+ if (platform == TargetPlatform.windows) { /* windows */ }
+ else if (platform == TargetPlatform.iOS || platform == TargetPlatform.android) { /* mobile */ }
+ else { /* unix-like (macOS, linux, fuchsia) */ }
+ ```
+
+## Mobile Storage Policy
+
+- [MAJOR] Store Zcash params under Application Support, not Documents
+ - File: `packages/komodo_defi_sdk/lib/src/zcash_params/platforms/mobile_zcash_params_downloader.dart` (header comment ~14–20; path resolution ~120–131)
+ - Problem: Using Documents risks iCloud/backup violations on iOS and exposes internal assets to users.
+ - Impact: Policy violations, user-visible clutter.
+ - Fix:
+ - Update comments to reference Application Support.
+ - Use `getApplicationSupportDirectory()` and join `ZcashParams`.
+ - Ensure directory exists before use (create recursively if missing).
+ - Example:
+ ```dart
+ final supportDir = await getApplicationSupportDirectory();
+ final paramsDir = Directory(path.join(supportDir.path, 'ZcashParams'));
+ if (!(await paramsDir.exists())) {
+ await paramsDir.create(recursive: true);
+ }
+ return paramsDir.path;
+ ```
+
+## Networking/Resilience
+
+- [MAJOR] Add timeout to remote HEAD probe to prevent hangs
+ - File: `packages/komodo_defi_sdk/lib/src/zcash_params/services/zcash_params_download_service.dart` (~311–319)
+ - Problem: `_httpClient.head` is awaited without a timeout; if the server stalls, activation hangs.
+ - Impact: Stalled activation; poor UX.
+ - Fix:
+ - Wrap in `.timeout(...)`; reuse `config.downloadTimeout` if available; otherwise a bounded default.
+ - Catch `TimeoutException`, log at least at `fine`/`warning`, and return `null` for size.
+ - Example:
+ ```dart
+ try {
+ final response = await _httpClient
+ .head(Uri.parse(url))
+ .timeout(config.downloadTimeout);
+ // ... handle 200 + content-length ...
+ } on TimeoutException {
+ _logger.warning('HEAD timeout for $url');
+ return null;
+ }
+ ```
+
+## Null-Safety/Defensive Coding
+
+- [CRITICAL] Guard nullable `zcashParamsPath` before `.trim()`
+ - File: `packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/zhtlc_activation_strategy.dart` (~55–85)
+ - Problem: `userConfig.zcashParamsPath.trim()` dereferences nullable; throws before friendly progress is emitted.
+ - Impact: Activation crashes instead of returning error progress.
+ - Fix:
+ - Sanitize into a local: `final zcashParamsPath = userConfig?.zcashParamsPath?.trim();`
+ - If null/empty: yield error `ActivationProgress` with `ActivationStep.error` and return.
+ - Pass the sanitized `zcashParamsPath` into `params.copyWith(...)`.
+
+## URL Handling
+
+- [MAJOR] Percent-encode file URLs; fix test expectations
+ - Files:
+ - `packages/komodo_defi_sdk/lib/src/zcash_params/models/zcash_params_config.dart` (method building URLs ~152–159)
+ - `packages/komodo_defi_sdk/test/zcash_params/models/zcash_params_config_test.dart` (URL with spaces ~497–503)
+ - Problem: URLs with spaces are not encoded; test expects unencoded URL.
+ - Impact: Invalid URLs and brittle tests.
+ - Fix:
+ - Build with `Uri.parse(baseUrl).resolve(fileName).toString()`.
+ - Update tests to expect `%20`-encoded spaces.
+
+## Tests/Determinism
+
+- [MAJOR] Avoid host-dependent APPDATA assumptions in Windows downloader tests
+ - File: `packages/komodo_defi_sdk/test/zcash_params/platforms/windows_zcash_params_downloader_test.dart` (~47–57, also ~60–80)
+ - Problem: Tests assume `APPDATA` missing; on Windows CI this becomes flaky/non-deterministic.
+ - Impact: Intermittent CI failures.
+ - Fix:
+ - Inject an `environmentProvider` into `WindowsZcashParamsDownloader` (e.g., `Map Function()`).
+ - Stub in tests with/without `APPDATA` to assert behavior deterministically.
+
+- [MAJOR] Fix invalid string multiplication in Dart test
+ - File: `packages/komodo_defi_sdk/test/zcash_params/models/zcash_params_config_test.dart` (~491–495)
+ - Problem: Uses Python-style `'string' * 10`; invalid in Dart.
+ - Impact: Test compilation error.
+ - Fix:
+ - Construct repeated string via `List.filled(10, 'very-long-file-name').join() + '.params'` (or similar).
+
+## Nice-to-Have Enhancements
+
+- [MINOR] Logging for timeouts and failures in size probe
+ - Context: Same HEAD probe fix above.
+ - Suggestion: Log at `warning` on timeout/network errors to aid telemetry.
+
+- [MINOR] Ensure directory creation in mobile path getter
+ - Context: Same mobile support path fix above.
+ - Suggestion: Create the `ZcashParams` directory if missing before returning.
+
+---
+
+## Checklist (proposed follow-up PR)
+
+- [ ] Factory: remove `dart:io` import; use `kIsWeb`/`defaultTargetPlatform` in all branches
+- [ ] Factory: web branch returns `WebZcashParamsDownloader` (or define it if missing)
+- [ ] Factory: `detectPlatform()` made web-safe (no `Platform.*`)
+- [ ] Mobile downloader: switch to Application Support; ensure dir exists
+- [ ] Download service: add timeout + handling to HEAD probe
+- [ ] ZHTLC strategy: null-safe trim and sanitized injection of `zcashParamsPath`
+- [ ] URL builder: use `Uri.resolve`; update tests to expect encoded URL
+- [ ] Windows tests: inject env provider and stub `APPDATA`
+- [ ] Dart test: replace string multiplication with `List.filled(...).join()`
+
+Notes: Severity reflects build-breakers (critical), runtime bugs (major), and smaller quality improvements (minor).
\ No newline at end of file
diff --git a/melos.yaml b/melos.yaml
deleted file mode 100644
index adf3b950..00000000
--- a/melos.yaml
+++ /dev/null
@@ -1,41 +0,0 @@
-name: komodo_defi_framework
-repository: https://github.com/KomodoPlatform/komodo_defi_framework
-
-packages:
- - packages/**
-
-command:
- bootstrap:
- hooks:
- post: melos run prepare
-
-scripts:
- prepare:
- run: melos run indexes:generate --no-select && melos run runners:generate --no-select
- indexes:generate:
- run: dart run index_generator
- exec:
- concurrency: 5
- packageFilters:
- dependsOn: index_generator
-
- runners:generate:
- run: dart run build_runner build --delete-conflicting-outputs
- exec:
- concurrency: 5
- packageFilters:
- dependsOn:
- - build_runner
-
- upgrade:major:
- run: flutter pub upgrade --major-versions
- exec:
- concurrency: 1
-
- assets:generate:
- run: flutter build bundle
- exec:
- concurrency: 1
- packageFilters:
- dependsOn:
- - flutter
diff --git a/packages/dragon_charts_flutter/.gitignore b/packages/dragon_charts_flutter/.gitignore
new file mode 100644
index 00000000..6be69aeb
--- /dev/null
+++ b/packages/dragon_charts_flutter/.gitignore
@@ -0,0 +1,8 @@
+# See https://www.dartlang.org/guides/libraries/private-files
+
+# Files and directories created by pub
+.dart_tool/
+.packages
+build/
+/web/
+pubspec.lock
\ No newline at end of file
diff --git a/packages/dragon_charts_flutter/.metadata b/packages/dragon_charts_flutter/.metadata
new file mode 100644
index 00000000..d36dfbcc
--- /dev/null
+++ b/packages/dragon_charts_flutter/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3"
+ channel: "stable"
+
+project_type: package
diff --git a/packages/dragon_charts_flutter/CHANGELOG.md b/packages/dragon_charts_flutter/CHANGELOG.md
new file mode 100644
index 00000000..b6928b01
--- /dev/null
+++ b/packages/dragon_charts_flutter/CHANGELOG.md
@@ -0,0 +1,61 @@
+## 0.1.1-dev.3
+
+> Note: This release has breaking changes.
+
+ - **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+ - **FEAT**: allow sparkline charts to customize the baseline calculation for positive/negative value classification, defaulting to the initial value.
+
+## 0.1.1-dev.2
+
+> Note: This release has breaking changes.
+
+- **FEAT**(rpc): trading-related RPCs/types (#191).
+- **FEAT**(auth): poll trezor connection status and sign out when disconnected (#126).
+- **BREAKING** **CHORE**: unify Dart SDK (^3.9.0) and Flutter (>=3.35.0 <3.36.0) constraints across workspace.
+
+## 0.0.1-pre1 (2024-05-26)
+
+- First stable MVP PoC with line graphs implemented.
+
+## 0.0.1 (2024-05-26)
+
+- Visual improvements to the line graphs and tooltips.
+- Partial API documentation.
+- Improvements to animations, especially when changing data set size.
+- Other miscellaneous bug fixes and improvements.
+
+## 0.0.2 - 2024-06-17
+
+### Added
+
+- **Minor visual tweaks**: Improved the visual appearance of the application with minor tweaks for better user experience. (`2fc0171e`)
+- **QoL improvements and miscellaneous changes**: Added various quality-of-life improvements and miscellaneous changes for better functionality and user experience. (`f2c39896`)
+- **Multiple point selection/highlighting strategies**: Introduced new strategies for selecting and highlighting multiple points on the chart, enhancing interactivity. (`bb94c136`)
+
+### Changed
+
+- **Cartesian selection configuration**: Enhanced the configuration options for cartesian selection, providing more flexibility and customization options. (`dc49710f`)
+- **Tooltip functionality**: Improved the tooltip functionality, ensuring accurate and clear information display. (`b44b0833`)
+
+### Fixed
+
+- **Further lint fixes**: Addressed additional linting issues to maintain code quality and consistency. (`7231300c`)
+- **Chart padding for labels**: Fixed padding issues to ensure labels are correctly displayed without overlapping, improving chart readability. (`344c2014`)
+
+### Documentation
+
+- **Rename reference of Graph to Chart**: Refactored code to rename references from `Graph` to `Chart` for better clarity and consistency. (`6a790fbb`)
+- **README updates**:
+ - Updated references from `GraphExtent` to `ChartExtent`.
+ - Improved documentation for chart components and their properties.
+
+## 0.0.3 - 2024-07-01
+
+### Added
+
+- **Sparkline Chart**: Added support for sparkline charts, allowing users to visualize data trends in a compact format. (`8124e08`)
+
+## 0.1.0 - 2024-07-05
+
+- **Initial release with support for line charts.**: The first stable release of the library, providing support for line charts. No functional changes from the previous version.
+- **Linter Fixes**: Apply linter fixes. There are no functional changes.
diff --git a/packages/komodo_defi_framework/assets/.transformer_invoker b/packages/dragon_charts_flutter/CONTRIBUTING.md
similarity index 100%
rename from packages/komodo_defi_framework/assets/.transformer_invoker
rename to packages/dragon_charts_flutter/CONTRIBUTING.md
diff --git a/packages/dragon_charts_flutter/LICENSE b/packages/dragon_charts_flutter/LICENSE
new file mode 100644
index 00000000..569710a8
--- /dev/null
+++ b/packages/dragon_charts_flutter/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Komodo Platform
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/dragon_charts_flutter/README.md b/packages/dragon_charts_flutter/README.md
new file mode 100644
index 00000000..e8f7348c
--- /dev/null
+++ b/packages/dragon_charts_flutter/README.md
@@ -0,0 +1,151 @@
+# Dragon Charts Flutter
+
+Lightweight, declarative, and customizable charting library for Flutter with minimal dependencies. This package now lives in the Komodo DeFi SDK monorepo.
+
+## Features
+
+- **Lightweight:** Minimal dependencies and optimized for performance.
+- **Declarative:** Define charts using a declarative API that makes customization straightforward.
+- **Customizable:** Highly customizable with support for different line types, colors, and more.
+- **Expandable:** Designed with a modular architecture to easily add new chart types.
+
+## Installation
+
+Pub is the recommended way to install this package, but you can also install it from GitHub.
+
+### From Pub
+
+Run this command:
+
+```bash
+flutter pub add dragon_charts_flutter
+```
+
+Then, run `flutter pub get` to install the package.
+
+## Usage
+
+Here is a simple example to get you started:
+
+```dart
+import 'dart:async';
+import 'dart:math';
+import 'package:flutter/material.dart';
+import 'package:dragon_charts_flutter/dragon_charts_flutter.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: BlocProvider(
+ create: (_) => ChartBloc(),
+ child: const ChartScreen(),
+ ),
+ );
+ }
+}
+
+class ChartScreen extends StatelessWidget {
+ const ChartScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Custom Line Chart with Animation')),
+ body: Padding(
+ padding: const EdgeInsets.all(32),
+ child: BlocBuilder(
+ builder: (context, state) {
+ return CustomLineChart(
+ domainExtent: const ChartExtent.tight(),
+ elements: [
+ ChartGridLines(isVertical: false, count: 5),
+ ChartAxisLabels(
+ isVertical: true,
+ count: 5,
+ labelBuilder: (value) => value.toStringAsFixed(2)),
+ ChartAxisLabels(
+ isVertical: false,
+ count: 5,
+ labelBuilder: (value) => value.toStringAsFixed(2)),
+ ChartDataSeries(data: state.data1, color: Colors.blue),
+ ChartDataSeries(
+ data: state.data2,
+ color: Colors.red,
+ lineType: LineType.bezier),
+ ],
+ tooltipBuilder: (context, dataPoints) {
+ return ChartTooltip(
+ dataPoints: dataPoints, backgroundColor: Colors.black);
+ },
+ );
+ },
+ ),
+ ),
+ );
+ }
+}
+```
+
+## Documentation
+
+### ChartData
+
+Represents a data point in the chart.
+
+#### Properties
+
+- `x`: `double` - The x-coordinate of the data point.
+- `y`: `double` - The y-coordinate of the data point.
+
+### ChartDataSeries
+
+Represents a series of data points to be plotted on the chart.
+
+#### Properties
+
+- `data`: `List` - The list of data points.
+- `color`: `Color` - The color of the series.
+- `lineType`: `LineType` - The type of line (straight or bezier).
+
+### CustomLineChart
+
+The main widget for displaying a line chart.
+
+#### Properties
+
+- `elements`: `List` - The elements to be drawn on the chart.
+- `tooltipBuilder`: `Widget Function(BuildContext, List)` - The builder for custom tooltips.
+- `domainExtent`: `ChartExtent` - The extent of the domain (x-axis).
+- `rangeExtent`: `ChartExtent` - The extent of the range (y-axis).
+- `backgroundColor`: `Color` - The background color of the chart.
+
+## Roadmap (high level)
+
+- Additional chart types (bar, pie, scatter)
+- Legends and interactions
+- Large dataset performance
+- Export as image
+
+## Why Dragon Charts Flutter?
+
+Dragon Charts Flutter is an excellent solution for your charting needs because:
+
+- **Lightweight:** It has minimal dependencies and is optimized for performance, making it suitable for both small and large projects.
+- **Declarative:** The declarative API makes it easy to define and customize charts, reducing the complexity of your code.
+- **Customizable:** The library is highly customizable, allowing you to create unique and visually appealing charts tailored to your application's needs.
+- **Expandable:** The modular architecture enables easy addition of new chart types and features, ensuring the library can grow with your requirements.
+
+## Contributing
+
+Contributions are welcome! Please open issues/PRs in the monorepo.
+
+## License
+
+MIT
\ No newline at end of file
diff --git a/packages/dragon_charts_flutter/analysis_options.yaml b/packages/dragon_charts_flutter/analysis_options.yaml
new file mode 100644
index 00000000..ac2d6d8b
--- /dev/null
+++ b/packages/dragon_charts_flutter/analysis_options.yaml
@@ -0,0 +1,6 @@
+include: package:very_good_analysis/analysis_options.yaml
+linter:
+ rules:
+ public_member_api_docs: false
+ prefer_int_literals: false
+ omit_local_variable_types: false
\ No newline at end of file
diff --git a/packages/dragon_charts_flutter/example/.gitignore b/packages/dragon_charts_flutter/example/.gitignore
new file mode 100644
index 00000000..29a3a501
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/.gitignore
@@ -0,0 +1,43 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/packages/dragon_charts_flutter/example/.metadata b/packages/dragon_charts_flutter/example/.metadata
new file mode 100644
index 00000000..421f246e
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/.metadata
@@ -0,0 +1,42 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3"
+ channel: "stable"
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ - platform: android
+ create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ - platform: ios
+ create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ - platform: macos
+ create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ - platform: web
+ create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ - platform: windows
+ create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+ base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/packages/dragon_charts_flutter/example/README.md b/packages/dragon_charts_flutter/example/README.md
new file mode 100644
index 00000000..1b7a4e3d
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/README.md
@@ -0,0 +1,3 @@
+# example
+
+A new Flutter project.
diff --git a/packages/dragon_charts_flutter/example/analysis_options.yaml b/packages/dragon_charts_flutter/example/analysis_options.yaml
new file mode 100644
index 00000000..e8cdb94a
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/analysis_options.yaml
@@ -0,0 +1,7 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
+linter:
+ rules:
+ - require-trailing-commas: true
\ No newline at end of file
diff --git a/packages/dragon_charts_flutter/example/android/.gitignore b/packages/dragon_charts_flutter/example/android/.gitignore
new file mode 100644
index 00000000..6f568019
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/packages/dragon_charts_flutter/example/android/app/build.gradle b/packages/dragon_charts_flutter/example/android/app/build.gradle
new file mode 100644
index 00000000..2a2d082b
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/build.gradle
@@ -0,0 +1,58 @@
+plugins {
+ id "com.android.application"
+ id "kotlin-android"
+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+ id "dev.flutter.flutter-gradle-plugin"
+}
+
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file("local.properties")
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader("UTF-8") { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
+if (flutterVersionCode == null) {
+ flutterVersionCode = "1"
+}
+
+def flutterVersionName = localProperties.getProperty("flutter.versionName")
+if (flutterVersionName == null) {
+ flutterVersionName = "1.0"
+}
+
+android {
+ namespace = "com.example.example"
+ compileSdk = flutter.compileSdkVersion
+ ndkVersion = flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId = "com.example.example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
+ minSdk = flutter.minSdkVersion
+ targetSdk = flutter.targetSdkVersion
+ versionCode = flutterVersionCode.toInteger()
+ versionName = flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig = signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source = "../.."
+}
diff --git a/packages/dragon_charts_flutter/example/android/app/src/debug/AndroidManifest.xml b/packages/dragon_charts_flutter/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 00000000..399f6981
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/AndroidManifest.xml b/packages/dragon_charts_flutter/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..74a78b93
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/packages/dragon_charts_flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
new file mode 100644
index 00000000..70f8f08f
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
@@ -0,0 +1,5 @@
+package com.example.example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity()
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/dragon_charts_flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 00000000..f74085f3
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/drawable/launch_background.xml b/packages/dragon_charts_flutter/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 00000000..304732f8
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..db77bb4b
Binary files /dev/null and b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..17987b79
Binary files /dev/null and b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..09d43914
Binary files /dev/null and b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..d5f1c8d3
Binary files /dev/null and b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..4d6372ee
Binary files /dev/null and b/packages/dragon_charts_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/values-night/styles.xml b/packages/dragon_charts_flutter/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 00000000..06952be7
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/app/src/main/res/values/styles.xml b/packages/dragon_charts_flutter/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..cb1ef880
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/app/src/profile/AndroidManifest.xml b/packages/dragon_charts_flutter/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 00000000..399f6981
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/android/build.gradle b/packages/dragon_charts_flutter/example/android/build.gradle
new file mode 100644
index 00000000..d2ffbffa
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/build.gradle
@@ -0,0 +1,18 @@
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = "../build"
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(":app")
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/packages/dragon_charts_flutter/example/android/gradle.properties b/packages/dragon_charts_flutter/example/android/gradle.properties
new file mode 100644
index 00000000..3b5b324f
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/dragon_charts_flutter/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/dragon_charts_flutter/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..e1ca574e
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
diff --git a/packages/dragon_charts_flutter/example/android/settings.gradle b/packages/dragon_charts_flutter/example/android/settings.gradle
new file mode 100644
index 00000000..536165d3
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/android/settings.gradle
@@ -0,0 +1,25 @@
+pluginManagement {
+ def flutterSdkPath = {
+ def properties = new Properties()
+ file("local.properties").withInputStream { properties.load(it) }
+ def flutterSdkPath = properties.getProperty("flutter.sdk")
+ assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+ return flutterSdkPath
+ }()
+
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+plugins {
+ id "dev.flutter.flutter-plugin-loader" version "1.0.0"
+ id "com.android.application" version "7.3.0" apply false
+ id "org.jetbrains.kotlin.android" version "1.7.10" apply false
+}
+
+include ":app"
diff --git a/packages/dragon_charts_flutter/example/ios/.gitignore b/packages/dragon_charts_flutter/example/ios/.gitignore
new file mode 100644
index 00000000..7a7f9873
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/.gitignore
@@ -0,0 +1,34 @@
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/packages/dragon_charts_flutter/example/ios/Flutter/AppFrameworkInfo.plist b/packages/dragon_charts_flutter/example/ios/Flutter/AppFrameworkInfo.plist
new file mode 100644
index 00000000..7c569640
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 12.0
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Flutter/Debug.xcconfig b/packages/dragon_charts_flutter/example/ios/Flutter/Debug.xcconfig
new file mode 100644
index 00000000..592ceee8
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Flutter/Debug.xcconfig
@@ -0,0 +1 @@
+#include "Generated.xcconfig"
diff --git a/packages/dragon_charts_flutter/example/ios/Flutter/Release.xcconfig b/packages/dragon_charts_flutter/example/ios/Flutter/Release.xcconfig
new file mode 100644
index 00000000..592ceee8
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Flutter/Release.xcconfig
@@ -0,0 +1 @@
+#include "Generated.xcconfig"
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.pbxproj b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..fec4719a
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,619 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 97C146E61CF9000F007C117D /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 97C146ED1CF9000F007C117D;
+ remoteInfo = Runner;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 331C8082294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXGroup;
+ children = (
+ 331C807B294A618700263BE5 /* RunnerTests.swift */,
+ );
+ path = RunnerTests;
+ sourceTree = "";
+ };
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ 331C8082294A63A400263BE5 /* RunnerTests */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 331C8080294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
+ buildPhases = (
+ 331C807D294A63A400263BE5 /* Sources */,
+ 331C807F294A63A400263BE5 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */,
+ );
+ name = RunnerTests;
+ productName = RunnerTests;
+ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 97C146E61CF9000F007C117D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ LastUpgradeCheck = 1510;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 331C8080294A63A400263BE5 = {
+ CreatedOnToolsVersion = 14.0;
+ TestTargetID = 97C146ED1CF9000F007C117D;
+ };
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ LastSwiftMigration = 1100;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ 331C8080294A63A400263BE5 /* RunnerTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 331C807F294A63A400263BE5 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 97C146EC1CF9000F007C117D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
+ );
+ name = "Thin Binary";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
+ };
+ 9740EEB61CF901F6004384FC /* Run Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Run Script";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 331C807D294A63A400263BE5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 97C146ED1CF9000F007C117D /* Runner */;
+ targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C146FB1CF9000F007C117D /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C147001CF9000F007C117D /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 249021D3217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Profile;
+ };
+ 249021D4217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 8HPBYKKKQP;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 331C8088294A63A400263BE5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Debug;
+ };
+ 331C8089294A63A400263BE5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Release;
+ };
+ 331C808A294A63A400263BE5 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Profile;
+ };
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 8HPBYKKKQP;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 8HPBYKKKQP;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 331C8088294A63A400263BE5 /* Debug */,
+ 331C8089294A63A400263BE5 /* Release */,
+ 331C808A294A63A400263BE5 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147031CF9000F007C117D /* Debug */,
+ 97C147041CF9000F007C117D /* Release */,
+ 249021D3217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147061CF9000F007C117D /* Debug */,
+ 97C147071CF9000F007C117D /* Release */,
+ 249021D4217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..f9b0d7c5
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 00000000..8e3ca5df
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..1d526a16
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..f9b0d7c5
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/AppDelegate.swift b/packages/dragon_charts_flutter/example/ios/Runner/AppDelegate.swift
new file mode 100644
index 00000000..9074fee9
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+import Flutter
+import UIKit
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..d36b1fab
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,122 @@
+{
+ "images" : [
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-20x20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-20x20@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-40x40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-40x40@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-60x60@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-60x60@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-20x20@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-20x20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-29x29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-29x29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-40x40@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-40x40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-76x76@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-76x76@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "83.5x83.5",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-83.5x83.5@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "1024x1024",
+ "idiom" : "ios-marketing",
+ "filename" : "Icon-App-1024x1024@1x.png",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
new file mode 100644
index 00000000..dc9ada47
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100644
index 00000000..7353c41e
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100644
index 00000000..797d452e
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100644
index 00000000..6ed2d933
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100644
index 00000000..4cd7b009
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100644
index 00000000..fe730945
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100644
index 00000000..321773cd
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100644
index 00000000..797d452e
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100644
index 00000000..502f463a
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100644
index 00000000..0ec30343
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100644
index 00000000..0ec30343
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100644
index 00000000..e9f5fea2
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100644
index 00000000..84ac32ae
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100644
index 00000000..8953cba0
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100644
index 00000000..0467bf12
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100644
index 00000000..0bedcf2f
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100644
index 00000000..9da19eac
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
new file mode 100644
index 00000000..9da19eac
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
new file mode 100644
index 00000000..9da19eac
Binary files /dev/null and b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
new file mode 100644
index 00000000..89c2725b
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
@@ -0,0 +1,5 @@
+# Launch Screen Assets
+
+You can customize the launch screen with your own desired assets by replacing the image files in this directory.
+
+You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/dragon_charts_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..f2e259c7
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Base.lproj/Main.storyboard b/packages/dragon_charts_flutter/example/ios/Runner/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..f3c28516
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Info.plist b/packages/dragon_charts_flutter/example/ios/Runner/Info.plist
new file mode 100644
index 00000000..5458fc41
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Info.plist
@@ -0,0 +1,49 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Example
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ example
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ CADisableMinimumFrameDurationOnPhone
+
+ UIApplicationSupportsIndirectInputEvents
+
+
+
diff --git a/packages/dragon_charts_flutter/example/ios/Runner/Runner-Bridging-Header.h b/packages/dragon_charts_flutter/example/ios/Runner/Runner-Bridging-Header.h
new file mode 100644
index 00000000..308a2a56
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/Runner/Runner-Bridging-Header.h
@@ -0,0 +1 @@
+#import "GeneratedPluginRegistrant.h"
diff --git a/packages/dragon_charts_flutter/example/ios/RunnerTests/RunnerTests.swift b/packages/dragon_charts_flutter/example/ios/RunnerTests/RunnerTests.swift
new file mode 100644
index 00000000..86a7c3b1
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/ios/RunnerTests/RunnerTests.swift
@@ -0,0 +1,12 @@
+import Flutter
+import UIKit
+import XCTest
+
+class RunnerTests: XCTestCase {
+
+ func testExample() {
+ // If you add code to the Runner application, consider adding tests here.
+ // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
+ }
+
+}
diff --git a/packages/dragon_charts_flutter/example/lib/blocs/chart_bloc.dart b/packages/dragon_charts_flutter/example/lib/blocs/chart_bloc.dart
new file mode 100644
index 00000000..53bff46f
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/lib/blocs/chart_bloc.dart
@@ -0,0 +1,67 @@
+import 'dart:async';
+import 'dart:math';
+import 'package:bloc/bloc.dart';
+import 'chart_event.dart';
+import 'chart_state.dart';
+import 'package:dragon_charts_flutter/dragon_charts_flutter.dart';
+
+// For the purpose of simplifying this example, we are generating the data in
+// the bloc class. However, in a real-world scenario, the data should be
+// fetched from a repository class. See https://bloclibrary.dev/why-bloc/
+class ChartBloc extends Bloc {
+ ChartBloc() : super(ChartState.initial()) {
+ on(_onChartUpdated);
+ on(_onChartDataPointAdded);
+
+ add(const ChartDataPointCountChanged(50));
+
+ // Timer to periodically update chart data
+ Timer.periodic(const Duration(seconds: 5), (timer) {
+ // add(ChartUpdated());
+ if (Random().nextBool() || true) {
+ add(ChartDataPointCountChanged(
+
+ // Randomly add or remove 5 to 50 data points
+ (Random().nextInt(50) + 5) * (Random().nextBool() ? 1 : -1)));
+ }
+ });
+ }
+
+ Future _onChartUpdated(
+ ChartUpdated event, Emitter emit) async {
+ final updatedData1 = state.data1
+ .map((element) => ChartData(x: element.x, y: Random().nextDouble()))
+ .toList();
+ final updatedData2 = state.data2
+ .map((element) => ChartData(x: element.x, y: Random().nextDouble()))
+ .toList();
+ emit(state.copyWith(data1: updatedData1, data2: updatedData2));
+ }
+
+ Future _onChartDataPointAdded(
+ ChartDataPointCountChanged event, Emitter emit) async {
+ if (event.count.abs() == 0) return;
+
+ final currentCount = state.data1.length;
+
+ final updatedData1 = List.from(state.data1);
+ final updatedData2 = List.from(state.data2);
+
+ if (event.count > 0) {
+ for (int i = 0; i < event.count; i++) {
+ updatedData1.add(ChartData(
+ x: (currentCount + i).toDouble(), y: Random().nextDouble()));
+ updatedData2.add(ChartData(
+ x: (currentCount + i).toDouble(), y: Random().nextDouble()));
+ }
+ } else {
+ for (int i = 0; i < event.count.abs(); i++) {
+ if (updatedData1.isEmpty) break;
+ updatedData1.removeLast();
+ updatedData2.removeLast();
+ }
+ }
+
+ emit(state.copyWith(data1: updatedData1, data2: updatedData2));
+ }
+}
diff --git a/packages/dragon_charts_flutter/example/lib/blocs/chart_event.dart b/packages/dragon_charts_flutter/example/lib/blocs/chart_event.dart
new file mode 100644
index 00000000..dc3e2ce2
--- /dev/null
+++ b/packages/dragon_charts_flutter/example/lib/blocs/chart_event.dart
@@ -0,0 +1,16 @@
+import 'package:equatable/equatable.dart';
+
+abstract class ChartEvent extends Equatable {
+ const ChartEvent();
+
+ @override
+ List