[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug report\ndescription: Create a report to help us improve\ntitle: \"Bug: \"\nlabels: [\"type: bug\"]\n\nbody:\n  - type: input\n    id: description\n    attributes:\n      label: Describe the bug\n      description: A clear and concise description of what the bug is.\n      placeholder: Tell us what you see!\n    validations:\n      required: true\n\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps\n      description: Steps to reproduce the behavior.\n      placeholder: |\n        1. Go to '...'\n        2. Click on '....'\n        3. Scroll down to '....'\n        4. See error\n    validations:\n      required: true\n\n  - type: textarea\n    id: expected\n    attributes:\n      label: Expected behavior\n      description: A clear and concise description of what you expected to happen.\n    validations:\n      required: true\n\n  - type: input\n    id: version\n    attributes:\n      label: Version\n      description: Which version of Coinbase Wallet SDK\n\n  - type: textarea\n    id: additional\n    attributes:\n      label: Additional info\n      description: If applicable, include links to screenshots or error logs\n\n  - type: textarea\n    id: desktop\n    attributes:\n      label: Desktop\n      description: Please fill in details for bugs reported on desktop\n      placeholder: |\n        - OS: [e.g. iOS]\n        - Browser [e.g. chrome, safari]\n        - Version [e.g. 22]\n\n  - type: textarea\n    id: smartphone\n    attributes:\n      label: Smartphone\n      description: Please fill in details for bugs reported on smartphone devices\n      placeholder: |\n        - Device: [e.g. iPhone6]\n        - OS: [e.g. iOS8.1]\n        - Browser [e.g. stock browser, safari]\n        - Version [e.g. 22]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Coinbase Wallet Developer Docs\n    url: https://docs.cloud.coinbase.com/wallet-sdk/docs\n    about: Coinbase Wallet's developer documentation\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature request\ndescription: Suggest an idea for this project\ntitle: \"Feature Request: \"\nlabels: [\"type: enhancement\"]\n\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        This issue form is for feature requests only!\n        If you've found a bug, please use [bug_report](/new?template=bug_report.yml)\n  - type: textarea\n    id: problem\n    attributes:\n      label: Is your feature request related to a problem? Please describe.\n      description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n  - type: textarea\n    id: solution\n    attributes:\n      label: Describe the solution you'd like\n      description: A clear and concise description of what you want to happen.\n    validations:\n      required: true\n\n  - type: textarea\n    id: alternatives\n    attributes:\n      label: Describe alternatives you've considered\n      description: Describe any alternative solutions or features you've considered.\n\n  - type: textarea\n    id: other\n    attributes:\n      label: Additional context\n      description: Add any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "### _Summary_\n\n<!--\n  What changed? Link to relevant issues.\n-->\n\n### _How did you test your changes?_\n\n<!--\n  Verify changes. Include relevant screenshots/videos\n-->\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Tag & Publish [auto]\n\non:\n  push:\n    branches:\n      - master\n\njobs:\n  environment: release\n  permissions:\n    contents: write\n    pull-requests: write\n    id-token: write\n  authorize:\n    name: Authorize\n    runs-on: ubuntu-latest\n    steps:\n      - name: ${{ github.actor }} permission check to update release version\n        uses: \"lannonbr/repo-permission-check-action@2.0.2\"\n        with:\n          permission: \"write\"\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  autotag:\n    name: Auto Tag\n    needs: authorize\n    runs-on: ubuntu-latest\n    outputs:\n      tagcreated: ${{ steps.autotag.outputs.tagcreated }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - id: autotag\n        uses: ButlerLogic/action-autotag@1.1.1\n        with:\n          strategy: regex\n          root: \"CoinbaseWalletSDK.podspec\"\n          regex_pattern: \"s.version\\\\s*=\\\\s*'(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)'\"\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  publish_ios:\n    name: Publish iOS SDK\n    needs: autotag\n    if: ${{ needs.autotag.outputs.tagcreated == 'yes' }}\n    runs-on: macOS-latest\n    steps: \n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Setup ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: '2.7.5'\n          bundler-cache: true\n      \n      - name: Publish to Cocoapods\n        run: |\n          set -eo pipefail\n          pod trunk push CoinbaseWalletSDK.podspec --allow-warnings\n        env:\n          COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}\n\n  publish_android:\n    name: Publish Android SDK\n    needs: autotag\n    if: ${{ needs.autotag.outputs.tagcreated == 'yes' }}\n    runs-on: macOS-latest\n    defaults:\n      run:\n        working-directory: android\n    steps: \n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Setup java\n        uses: actions/setup-java@v3\n        with:\n          distribution: temurin\n          java-version: 11\n      \n      - name: Setup Gradle\n        uses: gradle/gradle-build-action@v2\n    \n      - name: Execute Gradle build\n        run: ./gradlew publishReleasePublicationToSonatypeRepository closeAndReleaseSonatypeStagingRepository\n        env:\n          SIGNING_KEY_ID: ${{ secrets.ANDROID_SIGNING_KEYID }}\n          SIGNING_PASSWORD: ${{ secrets.ANDROID_SIGNING_PASSWORD }}\n          SIGNING_KEY: ${{ secrets.ANDROID_SIGNING_KEY }}\n          OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}\n          OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}\n          SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }}\n\n  publish_rn:\n    name: Publish React Native SDK\n    needs: [publish_ios, publish_android]\n    runs-on: macOS-latest\n    defaults:\n      run:\n        working-directory: react-native\n    steps: \n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Setup node\n        uses: actions/setup-node@v3\n        with:\n          node-version: '16.x'\n          registry-url: 'https://registry.npmjs.org'\n\n      - name: Publish to npm\n        run: |\n          npm install\n          npm run prepare\n          npm publish\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPMJS_ACCESS_TOKEN }}\n\n  publish_flutter:\n    name: Publish Flutter SDK\n    needs: [publish_ios, publish_android]\n    runs-on: macOS-latest\n    defaults:\n      run:\n        working-directory: flutter\n    steps: \n      - name: Checkout\n        uses: actions/checkout@v3\n        \n      - name: Setup Dart\n        uses: dart-lang/setup-dart@v1.3\n\n      - name: Authenticate\n        run: |\n          mkdir -p $PUB_CACHE\n          cd $PUB_CACHE\n          echo \"$PUBDEV_CREDENTIALSJSON\" > credentials.json\n        env:\n          PUBDEV_CREDENTIALSJSON: ${{ secrets.PUBDEV_CREDENTIALSJSON }}\n\n      - name: Publish to pub.dev\n        run: dart pub publish --force # TODO: automatically update CHANGELOG to run this without --force\n        \n      - name: Clean up\n        if: ${{ always() }} \n        run: rm -r $PUB_CACHE\n"
  },
  {
    "path": ".github/workflows/run_tests.yml",
    "content": "name: Run Tests\n\non:\n  pull_request:\n    branches:\n      - master\n\njobs:\n  android:\n    name: Android\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      # config java sdk version\n      - name: Setup java\n        uses: actions/setup-java@v3\n        with:\n          distribution: temurin\n          java-version: 11\n\n      - name: Setup Gradle\n        uses: gradle/gradle-build-action@v2\n\n      # Run Android unit tests\n      - name: Run unit testing\n        run: |\n          cd android\n          ./gradlew :walletsdk:testDebugUnitTest\n\n  ios:\n    name: iOS\n    runs-on: macOS-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Setup ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: '2.7.5'\n          bundler-cache: true\n\n      - name: Run unit test\n        run: bundle exec pod lib lint --verbose\n"
  },
  {
    "path": ".github/workflows/version_update.yml",
    "content": "name: Version Update PR\n\non:\n  workflow_dispatch:\n    inputs:\n      packageVersion:\n        description: \"The version to publish in MAJOR.MINOR.PATCH format\"\n        required: true\n        default: \"\"\n\njobs:\n  environment: release\n  permissions:\n    contents: write\n    pull-requests: write\n    id-token: write\n  authorize:\n    name: Authorize\n    runs-on: ubuntu-latest\n    steps:\n      - name: ${{ github.actor }} permission check to update release version\n        uses: \"lannonbr/repo-permission-check-action@2.0.2\"\n        with:\n          permission: \"write\"\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  version:\n    name: Update package version\n    runs-on: macOS-latest\n    needs: authorize\n    env:\n      V_REGEX: '[0-9]+\\.[0-9]+\\.[0-9]+'\n      NEW_VERSION: ${{ github.event.inputs.packageVersion }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Update iOS version\n        run: |\n          sed -i '' -E \"s/= '${{env.V_REGEX}}/= '${{env.NEW_VERSION}}/\" CoinbaseWalletSDK.podspec\n          sed -i '' -E 's/= \"${{env.V_REGEX}}/= \"${{env.NEW_VERSION}}/' ios/CoinbaseWalletSDK/Resources/CoinbaseWalletSDK+version.swift\n      \n      - name: Update Android version\n        run: |\n          sed -i '' -E 's/(sdk-version =) \"${{env.V_REGEX}}/\\1 \"${{env.NEW_VERSION}}/' android/gradle/libs.versions.toml\n\n      - name: Update React Native version\n        run: |\n          sed -i '' -E \"s/(CoinbaseWalletSDK\\/CrossPlatform',) '${{env.V_REGEX}}/\\1 '${{env.NEW_VERSION}}/\" react-native/ios/CoinbaseWalletSDKExpo.podspec\n          sed -i '' -E 's/(com.coinbase:coinbase-wallet-sdk):${{env.V_REGEX}}/\\1:${{env.NEW_VERSION}}/' react-native/android/build.gradle\n          sed -i '' -E 's/(version\":) \"${{env.V_REGEX}}/\\1 \"${{env.NEW_VERSION}}/' react-native/package.json\n\n      - name: Update Flutter version\n        run: |\n          sed -i '' -E \"s/(CoinbaseWalletSDK\\/CrossPlatform',) '${{env.V_REGEX}}/\\1 '${{env.NEW_VERSION}}/\" flutter/ios/coinbase_wallet_sdk.podspec\n          sed -i '' -E 's/(com.coinbase:coinbase-wallet-sdk):${{env.V_REGEX}}/\\1:${{env.NEW_VERSION}}/' flutter/android/build.gradle\n          sed -i '' -E 's/(version:) ${{env.V_REGEX}}/\\1 ${{env.NEW_VERSION}}/' flutter/pubspec.yaml\n\n      - name: Setup ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: '2.7.5'\n          bundler-cache: true\n\n      - name: Update iOS example\n        run: bundle exec pod install\n        working-directory: ios/example\n\n      # - name: Update React Native example\n      #   run: bundle exec pod install\n      #   working-directory: react-native/example/ios\n        \n      # - name: Update Flutter example\n      #   run: bundle exec pod install\n      #   working-directory: flutter/example/ios\n      \n      - name: Open pull request\n        uses: peter-evans/create-pull-request@v4\n        with:\n          add-paths: |\n            CoinbaseWalletSDK.podspec\n            ios/CoinbaseWalletSDK/Resources/CoinbaseWalletSDK+version.swift\n            ios/example/Podfile.lock\n            android/gradle/libs.versions.toml\n            react-native/ios/CoinbaseWalletSDKExpo.podspec\n            react-native/android/build.gradle\n            react-native/package.json\n            flutter/ios/coinbase_wallet_sdk.podspec\n            flutter/android/build.gradle\n            flutter/pubspec.yaml\n          title: \"[Version update] v${{env.NEW_VERSION}}\"\n          body: \"Automated workflow: version update\"\n          branch: version-update-v${{env.NEW_VERSION}}\n          reviewers: |\n            bangtoven\n            vishnumad\n            AMITGOELNY\n          commit-message: \"[Version update] v${{env.NEW_VERSION}}\"\n          labels: version-update\n          delete-branch: true\n"
  },
  {
    "path": ".gitignore",
    "content": "# misc\n.DS_Store\n\n# Native mobile\n\n## User settings\nxcuserdata/\n\n## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)\n*.xcscmblueprint\n*.xccheckout\n\n## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)\nbuild/\nDerivedData/\n*.moved-aside\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\n\n## Obj-C/Swift specific\n*.hmap\n\n## App packaging\n*.ipa\n*.dSYM.zip\n*.dSYM\n\n## Playgrounds\ntimeline.xctimeline\nplayground.xcworkspace\n\n# Swift Package Manager\n#\n# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.\n# Packages/\n# Package.pins\n# Package.resolved\n# *.xcodeproj\n#\n# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata\n# hence it is not needed unless you have added a package configuration file to your project\n# .swiftpm\n\n.build/\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\nPods/\n#\n# Add this line if you want to avoid checking in source code from the Xcode workspace\n*.xcworkspace\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build/\n\n# Accio dependency management\nDependencies/\n.accio/\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo.\n# Instead, use fastlane to re-generate the screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/#source-control\n\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots/**/*.png\nfastlane/test_output\n\n# Code Injection\n#\n# After new code Injection tools there's a generated folder /iOSInjectionProject\n# https://github.com/johnno1962/injectionforxcode\n\niOSInjectionProject/\n.DS_Store\nxcshareddata\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Log/OS Files\n*.log\n\n# Android Studio generated files and folders\ncaptures/\n.externalNativeBuild/\n.cxx/\n*.apk\noutput.json\n\n# IntelliJ\n*.iml\n.idea/\nmisc.xml\ndeploymentTargetDropDown.xml\nrender.experimental.xml\n\n# Keystore files\n*.jks\n*.keystore\n\n# Google Services (e.g. APIs or Firebase)\ngoogle-services.json\n\n# Android Profiling\n*.hprof\n\nnode_modules/\n\n"
  },
  {
    "path": "CODEOWNERS",
    "content": "* @coinbase/wallet-mobile-sdk\n.github/workflows/* @bangtoven\n"
  },
  {
    "path": "CoinbaseWalletSDK.podspec",
    "content": "Pod::Spec.new do |s|\n  s.name                  = 'CoinbaseWalletSDK'\n  s.version               = '1.1.2'\n  s.summary               = 'Swift implementation of WalletSegue protocol to interact with Coinbase Wallet iOS app'\n  s.source                = { :git => 'https://github.com/MobileWalletProtocol/wallet-mobile-sdk.git', :tag => s.version }\n  s.author                = 'Coinbase Wallet'\n  s.social_media_url      = 'https://twitter.com/CoinbaseWallet'\n  s.homepage              = 'https://github.com/MobileWalletProtocol/wallet-mobile-sdk'\n  s.license               = { :type => 'Apache', :file => 'LICENSE' }\n  s.ios.deployment_target = '13.0'\n  s.swift_version         = '5.0'\n  \n  SDK_PATH = 'ios/CoinbaseWalletSDK'\n  \n  s.subspec 'Client' do |ss|\n    ss.source_files = \"#{SDK_PATH}/**/*.swift\"\n    ss.exclude_files = [\n      \"#{SDK_PATH}/Host/**/*.swift\",\n      \"#{SDK_PATH}/Test/**/*.swift\"\n    ]\n  end\n  \n  s.subspec 'Host' do |ss|\n    ss.dependency 'CoinbaseWalletSDK/Client'\n    ss.source_files = \"#{SDK_PATH}/Host/**/*.swift\"\n  end\n  \n  s.subspec 'CrossPlatform' do |ss|\n    ss.dependency 'CoinbaseWalletSDK/Client'\n    ss.pod_target_xcconfig = {\n      'OTHER_SWIFT_FLAGS' => '-DCROSS_PLATFORM'\n    }\n  end\n  \n  s.test_spec 'Test' do |ts|\n    ts.ios.deployment_target = '13.0'\n    ts.source_files = \"#{SDK_PATH}/Test/**/*.swift\"\n  end\n  \n  s.default_subspec = 'Client'\nend\n"
  },
  {
    "path": "Gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'cocoapods'\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2022 Coinbase, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version: 5.4\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"CoinbaseWalletSDK\",\n    platforms: [.iOS(.v13)],\n    products: [\n        .library(\n            name: \"CoinbaseWalletSDK\",\n            targets: [\"CoinbaseWalletSDK\"]\n        )\n    ],\n    targets: [\n        .target(\n            name: \"CoinbaseWalletSDK\",\n            path: \"ios/CoinbaseWalletSDK\",\n            exclude: [\"Host\", \"Test\"]\n        ),\n        .testTarget(\n            name: \"CoinbaseWalletSDKTests\",\n            dependencies: [\"CoinbaseWalletSDK\"],\n            path: \"ios/CoinbaseWalletSDK/Test\"\n        )\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "# Coinbase Wallet Mobile SDK\n\n[![Cocoapods](https://img.shields.io/cocoapods/v/CoinbaseWalletSDK)](https://cocoapods.org/pods/CoinbaseWalletSDK)\n[![Maven](https://img.shields.io/maven-central/v/com.coinbase/coinbase-wallet-sdk?label=maven)](https://mavenlibs.com/maven/dependency/com.coinbase/coinbase-wallet-sdk)\n[![npm](https://img.shields.io/npm/v/@coinbase/wallet-mobile-sdk)](https://www.npmjs.com/package/@coinbase/wallet-mobile-sdk)\n[![pub.dev](https://img.shields.io/pub/v/coinbase_wallet_sdk)](https://pub.dev/packages/coinbase_wallet_sdk)\n\nCoinbase Wallet Mobile SDK is an open source SDK which allows you to connect your native mobile applications to millions of Coinbase Wallet users.\n\n## Getting Started\n\nThe SDK is available for the following platforms:\n\n- [iOS](https://github.com/coinbase/wallet-mobile-sdk/tree/master/ios)\n- [Android](https://github.com/coinbase/wallet-mobile-sdk/tree/master/android)\n\nWrapper libraries and modules are also available for the following platforms:\n\n- [React Native](https://github.com/coinbase/wallet-mobile-sdk/tree/master/react-native)\n- [Flutter](https://github.com/coinbase/wallet-mobile-sdk/tree/master/flutter)\n\nFor **Install** and **Usage** instructions of each platform, visit the links above or our [developer documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs/mobile-sdk-overview).\n\n## References\n- Mobile Wallet Protocol [Specification](https://mobilewalletprotocol.github.io/wallet-mobile-sdk/docs/spec)\n- Coinbase Wallet [Developer Documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs)\n- Questions? Visit our [Developer Forums](https://forums.coinbasecloud.dev/).\n- For bugs, please report an issue on Github.\n\n## License\n\n```\nCopyright © 2022 Coinbase, Inc. <https://www.coinbase.com/>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n"
  },
  {
    "path": "android/README.md",
    "content": "# Coinbase Wallet Mobile SDK\n\n[![Maven](https://img.shields.io/maven-central/v/com.coinbase/coinbase-wallet-sdk?label=maven)](https://mavenlibs.com/maven/dependency/com.coinbase/coinbase-wallet-sdk)\n\nCoinbase Wallet Mobile SDK is an open source SDK which allows you to connect your native mobile applications to millions of Coinbase Wallet users.\n\n## Install\n\nThe Coinbase Wallet Mobile SDK is available on [Maven Central](https://search.maven.org/artifact/com.coinbase/coinbase-wallet-sdk/0.1.0/aar).\n\n### Gradle\n\nAdd Coinbase Wallet SDK to your `build.gradle` file.\n\n```groovy\nrepositories {\n   mavenCentral()\n}\n\ndependencies {\n   implementation \"com.coinbase:coinbase-wallet-sdk:1.0.3\"\n}\n```\n\n### Maven\n\nAdd Coinbase Wallet SDK to your `pom.xml` file.\n\n```xml\n<dependency>\n\t<groupId>com.coinbase</groupId>\n\t<artifactId>coinbase-wallet-sdk</artifactId>\n\t<version>1.0.3</version>\n</dependency>\n```\n\n## Usage\n\n### Setup\n\nIn order for your app to interact with Coinbase Wallet, you must add a [queries element](https://developer.android.com/guide/topics/manifest/queries-element) to your `AndroidManifest.xml` file, specifying the package name for Coinbase Wallet, `org.toshi`.\n\n```xml\n    <queries>\n        <package android:name=\"org.toshi\" />\n    </queries>\n```\n\nBefore the SDK can be used, it needs to be configured with an App Link to your application. This callback URL will be used by the Coinbase Wallet application to navigate back to your application.\n\n```kotlin\nCoinbaseWalletSDK(\n    appContext = applicationContext,\n    domain = Uri.parse(\"https://www.myappxyz.com\"),\n    openIntent = { intent -> launcher.launch(intent) }\n)\n```\n\nWhen your application receives a response from Coinbase Wallet via App Links, this URL needs to be handed off to the SDK via the handleResponse function.\n\n```kotlin\nlauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->\n   val uri = result.data?.data ?: return@registerForActivityResult\n   client.handleResponse(uri)\n}\n```\n\nAn example is provided in the sample [application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/android/example/src/main/java/com/coinbase/android/beta/MainActivity.kt#L27).\n\n### Establishing a connection\n\nA connection to Coinbase Wallet can be initiated by calling the `initiateHandshake` function provided by the SDK. The function also takes in an optional `initialActions` parameter which apps can use to take certain actions along with the initial handshake request.\n\n```kotlin\nval requestAccount = Web3JsonRPC.RequestAccounts().action()\nval handShakeActions = listOf(requestAccount)\n\nclient.initiateHandshake(\n   initialActions = handShakeActions\n) { result: Result<List<ActionResult>>, account: Account? ->\n    result.onSuccess { actionResults: List<ActionResult> ->\n        actionResults.handleSuccess(\"Handshake\", handShakeActions, account)\n    }\n    result.onFailure { err ->\n        err.handleError(\"HandShake\")\n    }\n}\n```\n\nAn example handshake request is provided in the sample [application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/android/example/src/main/java/com/coinbase/android/beta/MainActivity.kt#L52).\n\n### Making requests\n\nRequests to Coinbase Wallet can be made by calling the `makeRequest` function provided by the SDK. This function also accepts a list of `actions` that can be taken in as a single batch request.\n\n```kotlin\nval signTypedDataV3 = Web3JsonRPC.SignTypedDataV3(\n   \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", // address\n   typedDataJson // typed data JSON\n).action()\nval requestActions = listOf(signTypedDataV3)\n\nclient.makeRequest(request = RequestContent.Request(actions = requestActions)) { result ->\n   result.fold(\n       onSuccess = { returnValues ->\n           returnValues.handleSuccess(\"Request\", requestActions)\n       },\n       onFailure = { err ->\n           err.handleError(\"Request\")\n       }\n   )\n}\n```\n\nAn example request is provided in the sample [application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/android/example/src/main/java/com/coinbase/android/beta/MainActivity.kt#L68).\n\nFor more information on the types of requests you can make, visit our [developer documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs/mobile-sdk-overview).\n\n## References\n- Coinbase Wallet [Developer Documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs)\n- Questions? Visit our [Developer Forums](https://forums.coinbasecloud.dev/).\n- For bugs, please report an issue on Github.\n\n## License\n\n```\nCopyright © 2022 Coinbase, Inc. <https://www.coinbase.com/>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n"
  },
  {
    "path": "android/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nplugins {\n    alias libs.plugins.android.application apply false\n    alias libs.plugins.android.library apply false\n    alias libs.plugins.kotlin.android apply false\n    alias libs.plugins.maven.publish\n}\n\napply from: \"${rootDir}/scripts/publish-root.gradle\"\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}"
  },
  {
    "path": "android/example/.editorconfig",
    "content": "[{*.kt, *.kts}]\nmax_line_length = 120"
  },
  {
    "path": "android/example/.gitignore",
    "content": "/build"
  },
  {
    "path": "android/example/build.gradle",
    "content": "plugins {\n    id 'com.android.application'\n    id 'org.jetbrains.kotlin.android'\n}\n\nandroid {\n    compileSdk 33\n\n    signingConfigs {\n        development {\n            storeFile file('debug.keystore')\n            storePassword 'android'\n            keyAlias 'androiddebugkey'\n            keyPassword 'android'\n        }\n    }\n\n    defaultConfig {\n        applicationId \"com.coinbase.android.beta\"\n        minSdk 23\n        targetSdk 33\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n            signingConfig signingConfigs.development\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n\n    buildFeatures {\n        viewBinding true\n    }\n\n    namespace 'com.coinbase.android.beta'\n}\n\ndependencies {\n    implementation libs.android.ktx\n    implementation libs.android.appcompat\n    implementation libs.android.constraintlayout\n    implementation libs.android.material\n\n    testImplementation libs.junit4\n    androidTestImplementation libs.androidx.junit4\n\n    implementation project(':walletsdk')\n}"
  },
  {
    "path": "android/example/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "android/example/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:dataExtractionRules=\"@xml/data_extraction_rules\"\n        android:fullBackupContent=\"@xml/backup_rules\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/Theme.ClientApp\"\n        tools:targetApi=\"31\">\n        <activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n    <queries>\n        <package android:name=\"org.toshi\" />\n        <package android:name=\"org.toshi.development\" />\n    </queries>\n</manifest>"
  },
  {
    "path": "android/example/src/main/java/com/coinbase/android/beta/ActionsManager.kt",
    "content": "package com.coinbase.android.beta\n\nimport android.content.Context\nimport android.content.SharedPreferences\nimport com.coinbase.android.nativesdk.message.request.Web3JsonRPC\n\nobject ActionsManager {\n\n    private val requestAccount = Web3JsonRPC.RequestAccounts().action()\n\n    private val personalSign = Web3JsonRPC.PersonalSign(\"\", \"Hello world\").action()\n\n    private val switchEthereumChain = Web3JsonRPC.SwitchEthereumChain(\"137\").action()\n\n    val addEthereumChain = Web3JsonRPC.AddEthereumChain(\"172222\").action()\n\n    private fun getSignTransaction(fromAddress: String, toAddress: String) = Web3JsonRPC.SignTransaction(\n        fromAddress = fromAddress,\n        toAddress = toAddress,\n        weiValue = \"10000000000000\",\n        data = \"0x\",\n        nonce = null,\n        gasPriceInWei = null,\n        maxFeePerGas = null,\n        maxPriorityFeePerGas = null,\n        gasLimit = \"1000\",\n        chainId = \"1\",\n    ).action()\n\n    private fun getSendTransaction(fromAddress: String, toAddress: String) = Web3JsonRPC.SendTransaction(\n        fromAddress = fromAddress,\n        toAddress = toAddress,\n        weiValue = \"10000000000000\",\n        data = \"0x\",\n        nonce = null,\n        gasPriceInWei = null,\n        maxFeePerGas = null,\n        maxPriorityFeePerGas = null,\n        gasLimit = \"1000\",\n        chainId = \"1\",\n    ).action()\n\n    val signTypedDataV3 = Web3JsonRPC.SignTypedDataV3(\"0xabcdefabcdefabcdefabcdefabcdefabcdef\", \"\").action()\n\n    val handShakeActions = listOf(requestAccount, personalSign)\n\n    fun getRequestActions(\n        fromAddress: String = SharedPrefsManager.account,\n        toAddress: String\n    ) = listOf(\n        requestAccount,\n        personalSign,\n        switchEthereumChain,\n        getSendTransaction(fromAddress, toAddress)\n    )\n}\n\nobject SharedPrefsManager {\n    lateinit var sharedPrefs: SharedPreferences\n\n    var account: String\n        get() = sharedPrefs.getString(\"eth_account\", \"\") ?: \"\"\n        set(value) {\n            with(sharedPrefs.edit()) {\n                putString(\"eth_account\", value)\n                apply()\n            }\n        }\n\n    fun init(context: Context) {\n        sharedPrefs = context.getSharedPreferences(\"DEMO_APP\", Context.MODE_PRIVATE)\n    }\n\n    fun removeAccount() {\n        with(sharedPrefs.edit()) {\n            remove(\"eth_account\")\n            apply()\n        }\n    }\n}\n"
  },
  {
    "path": "android/example/src/main/java/com/coinbase/android/beta/MainActivity.kt",
    "content": "package com.coinbase.android.beta\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport androidx.activity.result.ActivityResultLauncher\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.core.view.ViewCompat\nimport androidx.core.view.isVisible\nimport com.coinbase.android.beta.databinding.ActivityMainBinding\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDK\nimport com.coinbase.android.nativesdk.message.request.Account\nimport com.coinbase.android.nativesdk.message.request.Action\nimport com.coinbase.android.nativesdk.message.request.RequestContent\nimport com.coinbase.android.nativesdk.message.response.ActionResult\nimport com.google.android.material.shape.CornerFamily\nimport com.google.android.material.shape.MaterialShapeDrawable\nimport com.google.android.material.shape.ShapeAppearanceModel\n\nclass MainActivity : AppCompatActivity() {\n\n    private lateinit var binding: ActivityMainBinding\n    private lateinit var launcher: ActivityResultLauncher<Intent>\n\n    private val client by lazy {\n        CoinbaseWalletSDK(\n            appContext = applicationContext,\n            domain = Uri.parse(\"https://myappxyz.com\"),\n            openIntent = { intent -> launcher.launch(intent) }\n        )\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityMainBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n\n        SharedPrefsManager.init(this)\n        launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->\n            val uri = result.data?.data ?: return@registerForActivityResult\n            client.handleResponse(uri)\n        }\n    }\n\n    override fun onStart() = with(binding) {\n        super.onStart()\n\n        val mwpVersion = CoinbaseWalletSDK.getCoinbaseWalletMWPVersion(this@MainActivity)\n        textArea.text = \"Wallet MWP Version: $mwpVersion\"\n\n        setVisibility()\n        connectWalletButton.setOnClickListener {\n            val handShakeActions = ActionsManager.handShakeActions\n            client.initiateHandshake(\n                initialActions = handShakeActions\n            ) { result: Result<List<ActionResult>>, account: Account? ->\n                result.onSuccess { actionResults: List<ActionResult> ->\n                    actionResults.handleSuccess(\"Handshake\", handShakeActions, account)\n                }\n                result.onFailure { err ->\n                    err.handleError(\"HandShake\")\n                }\n            }\n        }\n\n        personalSign.setOnClickListener {\n            val requestActions = ActionsManager.getRequestActions(\n                toAddress = \"0x571a6a108adb08f9ca54fe8605280f9ee0ed4af6\"\n            )\n            client.makeRequest(request = RequestContent.Request(actions = requestActions)) { result ->\n                result.fold(\n                    onSuccess = { returnValues ->\n                        returnValues.handleSuccess(\"Request\", requestActions)\n                    },\n                    onFailure = { err ->\n                        err.handleError(\"Request\")\n                    }\n                )\n            }\n        }\n\n        removeAccount.setOnClickListener {\n            client.resetSession()\n            SharedPrefsManager.removeAccount()\n            textArea.setText(R.string.connection_removed)\n            setVisibility()\n        }\n    }\n\n    private fun List<ActionResult>.handleSuccess(\n        requestType: String,\n        actions: List<Action>,\n        account: Account? = null\n    ) = with(binding) {\n        textArea.text = buildString {\n            if (actions.isEmpty()) {\n                append(\"Handshake successful\")\n            } else {\n                this@handleSuccess.forEachIndexed { index, returnValue ->\n                    append(\n                        \"${actions[index].method} Result: \" +\n                                \"${if (returnValue is ActionResult.Result) \"Success\" else \"Error\"}\\n\"\n                    )\n\n                    if (account != null) {\n                        SharedPrefsManager.account = account.address\n                    }\n\n                    val result = when (returnValue) {\n                        is ActionResult.Result -> returnValue.value\n                        is ActionResult.Error -> returnValue.message\n                    }\n                    append(\"${result}\\n\\n\")\n                }\n            }\n        }\n        setVisibility()\n    }\n\n    private fun Throwable.handleError(requestType: String) = with(binding) {\n        textArea.text = buildString {\n            append(\"$requestType Error: \\n\\n\")\n            append(message)\n        }\n    }\n\n    private fun setVisibility() = with(binding) {\n        val isConnected = client.isConnected\n        connectContainer.isVisible = !isConnected\n        requestContainer.isVisible = isConnected\n\n\n        with(connectedStatus) {\n            val radius = 28f\n            val shapeAppearanceModel = ShapeAppearanceModel()\n                .toBuilder()\n                .setAllCorners(CornerFamily.ROUNDED, radius)\n                .build()\n\n            val shapeDrawable = MaterialShapeDrawable(shapeAppearanceModel)\n            ViewCompat.setBackground(connectedStatus, shapeDrawable)\n\n            if (isConnected) {\n                text = getString(\n                    R.string.connected_state,\n                    \"${SharedPrefsManager.account.take(5)}...${SharedPrefsManager.account.takeLast(4)}\"\n                )\n                setTextColor(getColor(R.color.teal_200))\n                shapeDrawable.setStroke(2.0f, getColor(R.color.teal_200))\n\n            } else {\n                setText(R.string.unconnected_state)\n                setTextColor(getColor(R.color.red_error))\n                shapeDrawable.setStroke(2.0f, getColor(R.color.red_error))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "android/example/src/main/java/com/coinbase/android/beta/SecondActivity.java",
    "content": "package com.coinbase.android.beta;\n\nimport static com.coinbase.android.nativesdk.CoinbaseWalletSDKKt.CBW_PACKAGE_NAME;\n\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.os.Bundle;\n\nimport androidx.annotation.Nullable;\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDK;\nimport com.coinbase.android.nativesdk.message.request.Action;\nimport com.coinbase.android.nativesdk.message.request.Web3JsonRPC;\nimport com.coinbase.android.nativesdk.message.response.ActionResult;\n\nimport java.util.ArrayList;\n\npublic class SecondActivity extends AppCompatActivity {\n\n    final int CBW_ACTIVITY_RESULT_CODE = 9182736;\n\n    CoinbaseWalletSDK client;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        client = new CoinbaseWalletSDK(\n                Uri.parse(\"https://myappxyz.com\"),\n                getApplicationContext(),\n                CBW_PACKAGE_NAME,\n                intent -> {\n                    startActivityForResult(intent, CBW_ACTIVITY_RESULT_CODE);\n                }\n        );\n    }\n\n    @Override\n    protected void onStart() {\n        super.onStart();\n\n        ArrayList<Action> actions = new ArrayList<>();\n        actions.add(\n                new Web3JsonRPC.RequestAccounts().action(false)\n        );\n\n        client.initiateHandshake(\n                actions,\n                (results, account) -> {\n                    for (ActionResult result : results) {\n                        if (result instanceof ActionResult.Result) {\n                            ((ActionResult.Result) result).getValue();\n                        }\n\n                        if (result instanceof ActionResult.Error) {\n                            ((ActionResult.Error) result).getCode();\n                            ((ActionResult.Error) result).getMessage();\n                        }\n                    }\n                },\n                error -> {\n                }\n        );\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n\n        if (requestCode != CBW_ACTIVITY_RESULT_CODE) {\n            return;\n        }\n\n        if (data == null) {\n            return;\n        }\n\n        Uri url = data.getData();\n        client.handleResponse(url);\n    }\n}\n"
  },
  {
    "path": "android/example/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#3DDC84\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "android/example/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "android/example/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:padding=\"16dp\"\n    tools:context=\".MainActivity\">\n\n    <TextView\n        android:id=\"@+id/title\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"start\"\n        android:text=\"@string/select_an_option\"\n        android:textSize=\"16sp\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintBottom_toBottomOf=\"@id/connected_status\"\n        app:layout_constraintTop_toTopOf=\"@id/connected_status\" />\n\n    <TextView\n        android:id=\"@+id/connected_status\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"12dp\"\n        android:text=\"@string/unconnected_state\"\n        android:textColor=\"@color/red_error\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@id/barrier\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:id=\"@+id/connect_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"20dp\"\n        app:layout_constraintTop_toBottomOf=\"@id/connected_status\">\n\n        <com.google.android.material.button.MaterialButton\n            android:id=\"@+id/connectWalletButton\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"50dp\"\n            android:text=\"@string/connect_wallet\"\n            app:cornerRadius=\"16dp\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:id=\"@+id/request_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"20dp\"\n        android:visibility=\"gone\"\n        app:layout_constraintTop_toBottomOf=\"@id/connected_status\"\n        tools:visibility=\"gone\">\n\n        <com.google.android.material.button.MaterialButton\n            android:id=\"@+id/personalSign\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"50dp\"\n            android:text=\"@string/request_personal_sign\"\n            app:cornerRadius=\"16dp\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <com.google.android.material.button.MaterialButton\n            android:id=\"@+id/remove_account\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"50dp\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/remove_account\"\n            app:cornerRadius=\"16dp\"\n            app:layout_constraintTop_toBottomOf=\"@+id/personalSign\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <androidx.constraintlayout.widget.Barrier\n        android:id=\"@+id/barrier\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        app:barrierDirection=\"bottom\"\n        app:constraint_referenced_ids=\"connect_container,request_container\" />\n\n    <TextView\n        android:id=\"@+id/textArea\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"20dp\"\n        android:fontFamily=\"monospace\"\n        app:layout_constraintTop_toBottomOf=\"@id/barrier\" />\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "android/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "android/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "android/example/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purple_500\">#FF6200EE</color>\n    <color name=\"purple_700\">#FF3700B3</color>\n    <color name=\"teal_200\">#FF03DAC5</color>\n    <color name=\"teal_700\">#FF018786</color>\n    <color name=\"black\">#FF000000</color>\n    <color name=\"white\">#FFFFFFFF</color>\n    <color name=\"red_error\">#F44336</color>\n</resources>"
  },
  {
    "path": "android/example/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">WalletSDK ClientApp</string>\n    <string name=\"connect_wallet\">Connect Wallet</string>\n    <string name=\"request_personal_sign\">Request personal_sign</string>\n    <string name=\"remove_account\">Remove Account</string>\n    <string name=\"select_an_option\">Select an option</string>\n    <string name=\"connection_removed\">Connection Removed</string>\n    <string name=\"connected_state\">Connected: %s</string>\n    <string name=\"unconnected_state\">Not Connected</string>\n</resources>"
  },
  {
    "path": "android/example/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.ClientApp\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">#F57C00</item>\n        <item name=\"colorPrimaryVariant\">#EF6C00</item>\n        <item name=\"colorOnPrimary\">@color/white</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_700</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\" tools:targetApi=\"l\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "android/example/src/main/res/values-night/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.ClientApp\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">#2196F3</item>\n        <item name=\"colorPrimaryVariant\">#03A9F4</item>\n        <item name=\"colorOnPrimary\">@color/black</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_200</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\" tools:targetApi=\"l\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "android/example/src/main/res/xml/backup_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample backup rules file; uncomment and customize as necessary.\n   See https://developer.android.com/guide/topics/data/autobackup\n   for details.\n   Note: This file is ignored for devices older that API 31\n   See https://developer.android.com/about/versions/12/backup-restore\n-->\n<full-backup-content>\n    <!--\n   <include domain=\"sharedpref\" path=\".\"/>\n   <exclude domain=\"sharedpref\" path=\"device.xml\"/>\n-->\n</full-backup-content>"
  },
  {
    "path": "android/example/src/main/res/xml/data_extraction_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample data extraction rules file; uncomment and customize as necessary.\n   See https://developer.android.com/about/versions/12/backup-restore#xml-changes\n   for details.\n-->\n<data-extraction-rules>\n    <cloud-backup>\n        <!-- TODO: Use <include> and <exclude> to control what is backed up.\n        <include .../>\n        <exclude .../>\n        -->\n    </cloud-backup>\n    <!--\n    <device-transfer>\n        <include .../>\n        <exclude .../>\n    </device-transfer>\n    -->\n</data-extraction-rules>"
  },
  {
    "path": "android/gradle/libs.versions.toml",
    "content": "[versions]\ngradleplugin = \"7.2.2\"\nkotlin = \"1.6.21\"\nkotlinSerialization = \"1.3.3\"\nnexus-publish = \"1.1.0\"\n\nsdk-version = \"1.2.0\"\n\n[libraries]\n\nandroid-ktx = { module = \"androidx.core:core-ktx\", version = \"1.9.0\" }\nandroid-appcompat = { module = \"androidx.appcompat:appcompat\", version = \"1.5.1\" }\nandroid-constraintlayout = { module = \"androidx.constraintlayout:constraintlayout\", version = \"2.1.4\" }\nandroid-material = { module = \"com.google.android.material:material\", version = \"1.6.1\" }\nkotlin-serialization = { module = \"org.jetbrains.kotlinx:kotlinx-serialization-json\", version.ref = \"kotlinSerialization\" }\nsecurity-crypto = { module = \"androidx.security:security-crypto\", version = \"1.0.0\" }\nsecurity-tink = { module = \"com.google.crypto.tink:tink-android\", version = \"1.6.1\" }\n\n# Test Libs\nandroidx-junit4 = { module = \"androidx.test.ext:junit\", version = \"1.1.3\" }\njunit4 = { module = \"junit:junit\", version = \"4.13.2\" }\nkotest = { module = \"io.kotest:kotest-assertions-core\", version = \"5.5.0\" }\n\n[plugins]\nandroid-application = { id = \"com.android.application\", version.ref = \"gradleplugin\" }\nandroid-library = { id = \"com.android.library\", version.ref = \"gradleplugin\" }\nkotlin-android = { id = \"org.jetbrains.kotlin.android\", version.ref = \"kotlin\" }\nmaven-publish = { id = \"io.github.gradle-nexus.publish-plugin\", version.ref = \"nexus-publish\" }"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.4.2-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "android/gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app\"s APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\n# Enables namespacing of each library's R class so that its R class includes only the\n# resources declared in the library itself and none from the library's dependencies,\n# thereby reducing the size of the R class for that library\nandroid.nonTransitiveRClass=true"
  },
  {
    "path": "android/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "android/gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n\n@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto execute\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "android/scripts/publish-root.gradle",
    "content": "// Create variables with empty default values\next[\"signing.keyId\"] = ''\next[\"signing.password\"] = ''\next[\"signing.key\"] = ''\next[\"ossrhUsername\"] = ''\next[\"ossrhPassword\"] = ''\next[\"sonatypeStagingProfileId\"] = ''\next[\"snapshot\"] = false\n\nFile secretPropsFile = project.rootProject.file('local.properties')\nif (secretPropsFile.exists()) {\n    // Read local.properties file first if it exists\n    Properties p = new Properties()\n    new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) }\n    p.each { name, value -> ext[name] = value }\n} else {\n    // Use system environment variables\n    ext[\"ossrhUsername\"] = System.getenv('OSSRH_USERNAME')\n    ext[\"ossrhPassword\"] = System.getenv('OSSRH_PASSWORD')\n    ext[\"sonatypeStagingProfileId\"] = '61a7f2c94aea57'\n    ext[\"signing.keyId\"] = System.getenv('SIGNING_KEY_ID')\n    ext[\"signing.password\"] = System.getenv('SIGNING_PASSWORD')\n    ext[\"signing.key\"] = System.getenv('SIGNING_KEY')\n    ext[\"snapshot\"] = System.getenv('SNAPSHOT')\n}\ndef versionName = libs.versions.sdk.version\ndef snapshotVersionName = \"${versionName}-SNAPSHOT\"\n\nif (snapshot) {\n    ext[\"rootVersionName\"] = snapshotVersionName\n} else {\n    ext[\"rootVersionName\"] = versionName\n}\n\n// Set up Sonatype repository\nnexusPublishing {\n    repositories {\n        sonatype {\n            stagingProfileId = sonatypeStagingProfileId\n            username = ossrhUsername\n            password = ossrhPassword\n            version = versionName\n        }\n    }\n}\n"
  },
  {
    "path": "android/settings.gradle",
    "content": "pluginManagement {\n    repositories {\n        gradlePluginPortal()\n        google()\n        mavenCentral()\n    }\n}\n\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\nrootProject.name = \"Wallet SDK\"\ninclude ':example', ':walletsdk'\n"
  },
  {
    "path": "android/walletsdk/.editorconfig",
    "content": "[{*.kt, *.kts}]\nmax_line_length = 120"
  },
  {
    "path": "android/walletsdk/.gitignore",
    "content": "/build"
  },
  {
    "path": "android/walletsdk/build.gradle",
    "content": "plugins {\n    alias libs.plugins.android.library\n    alias libs.plugins.kotlin.android\n    id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21'\n    id 'maven-publish'\n    id 'signing'\n}\n\nandroid {\n    compileSdk 34\n\n    defaultConfig {\n        minSdk 23\n        targetSdk 34\n\n        versionCode 3\n        versionName libs.versions.sdk.version.get()\n\n        buildConfigField \"int\", \"LIBRARY_VERSION_CODE\", \"${versionCode}\"\n        buildConfigField \"String\", \"LIBRARY_VERSION_NAME\", \"\\\"${versionName}\\\"\"\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n        consumerProguardFiles \"consumer-rules.pro\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n\n    publishing {\n        singleVariant(\"release\") {\n            withSourcesJar()\n            withJavadocJar()\n        }\n    }\n\n    testOptions {\n        unitTests {\n            includeAndroidResources = true\n        }\n    }\n}\n\ndependencies {\n    implementation libs.kotlin.serialization\n    implementation libs.security.crypto\n    implementation libs.security.tink\n\n    testImplementation libs.junit4\n    testImplementation libs.kotest\n    androidTestImplementation libs.androidx.junit4\n}\n\nafterEvaluate {\n    publishing {\n        publications {\n            release(MavenPublication) {\n                from components.release\n                groupId 'com.coinbase'\n                artifactId 'coinbase-wallet-sdk'\n                version = android.defaultConfig.versionName\n\n                pom {\n                    name = 'coinbase-wallet-sdk'\n                    description = 'Coinbase Wallet Mobile SDK'\n                    url = 'https://github.com/MobileWalletProtocol/wallet-mobile-sdk'\n                    licenses {\n                        license {\n                            name = 'Coinbase License'\n                            url = 'https://github.com/MobileWalletProtocol/wallet-mobile-sdk/blob/master/LICENSE'\n                        }\n                    }\n                    developers {\n                        developer {\n                            id = 'bangtoven'\n                            name = 'Jungho Bang'\n                            email = 'me@bangtoven.com'\n                        }\n                        developer {\n                            id = 'vishnumad'\n                            name = 'Vishnu Madhusoodanan'\n                            email = 'vishnu.madhusoodanan@coinbase.com'\n                        }\n                    }\n                    scm {\n                        developerConnection = 'scm:git@github.com:MobileWalletProtocol/wallet-mobile-sdk.git'\n                        url = 'https://github.com/MobileWalletProtocol/wallet-mobile-sdk/tree/main'\n                    }\n                }\n            }\n        }\n    }\n}\n\nsigning {\n    useInMemoryPgpKeys(\n            rootProject.ext[\"signing.keyId\"],\n            rootProject.ext[\"signing.key\"],\n            rootProject.ext[\"signing.password\"],\n    )\n    sign publishing.publications\n}\n"
  },
  {
    "path": "android/walletsdk/consumer-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n\n# Keep `Companion` object fields of serializable classes.\n# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.\n-if @kotlinx.serialization.Serializable class **\n-keepclassmembers class <1> {\n    static <1>$Companion Companion;\n}\n\n# Keep `serializer()` on companion objects (both default and named) of serializable classes.\n-if @kotlinx.serialization.Serializable class ** {\n    static **$* *;\n}\n-keepclassmembers class <2>$<3> {\n    kotlinx.serialization.KSerializer serializer(...);\n}\n\n# Keep `INSTANCE.serializer()` of serializable objects.\n-if @kotlinx.serialization.Serializable class ** {\n    public static ** INSTANCE;\n}\n-keepclassmembers class <1> {\n    public static <1> INSTANCE;\n    kotlinx.serialization.KSerializer serializer(...);\n}\n\n# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.\n-keepattributes RuntimeVisibleAnnotations,AnnotationDefault\n\n# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.\n# If you have any, uncomment and replace classes with those containing named companion objects.\n#-keepattributes InnerClasses # Needed for `getDeclaredClasses`.\n#-if @kotlinx.serialization.Serializable class\n#com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.\n#com.example.myapplication.HasNamedCompanion2\n#{\n#    static **$* *;\n#}\n#-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.\n#    static <1>$$serializer INSTANCE;\n#}"
  },
  {
    "path": "android/walletsdk/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n\n# Keep `Companion` object fields of serializable classes.\n# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.\n-if @kotlinx.serialization.Serializable class **\n-keepclassmembers class <1> {\n    static <1>$Companion Companion;\n}\n\n# Keep `serializer()` on companion objects (both default and named) of serializable classes.\n-if @kotlinx.serialization.Serializable class ** {\n    static **$* *;\n}\n-keepclassmembers class <2>$<3> {\n    kotlinx.serialization.KSerializer serializer(...);\n}\n\n# Keep `INSTANCE.serializer()` of serializable objects.\n-if @kotlinx.serialization.Serializable class ** {\n    public static ** INSTANCE;\n}\n-keepclassmembers class <1> {\n    public static <1> INSTANCE;\n    kotlinx.serialization.KSerializer serializer(...);\n}\n\n# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.\n-keepattributes RuntimeVisibleAnnotations,AnnotationDefault\n\n# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.\n# If you have any, uncomment and replace classes with those containing named companion objects.\n#-keepattributes InnerClasses # Needed for `getDeclaredClasses`.\n#-if @kotlinx.serialization.Serializable class\n#com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.\n#com.example.myapplication.HasNamedCompanion2\n#{\n#    static **$* *;\n#}\n#-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.\n#    static <1>$$serializer INSTANCE;\n#}"
  },
  {
    "path": "android/walletsdk/src/androidTest/java/com/coinbase/android/nativesdk/ExampleInstrumentedTest.kt",
    "content": "package com.coinbase.android.nativesdk\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\n\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\nimport org.junit.Assert.*\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\n@RunWith(AndroidJUnit4::class)\nclass ExampleInstrumentedTest {\n    @Test\n    fun useAppContext() {\n        // Context of the app under test.\n        val appContext = InstrumentationRegistry.getInstrumentation().targetContext\n        assertEquals(\"com.coinbase.android.walletsegue.test\", appContext.packageName)\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.coinbase.android.nativesdk\">\n\n</manifest>"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/CoinbaseWalletSDK.kt",
    "content": "package com.coinbase.android.nativesdk\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.content.Intent\nimport android.net.Uri\nimport com.coinbase.android.nativesdk.key.KeyManager\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.coinbase.android.nativesdk.message.request.Account\nimport com.coinbase.android.nativesdk.message.request.Action\nimport com.coinbase.android.nativesdk.message.request.ETH_REQUEST_ACCOUNTS\nimport com.coinbase.android.nativesdk.message.request.RequestContent\nimport com.coinbase.android.nativesdk.message.request.RequestConverter\nimport com.coinbase.android.nativesdk.message.request.UnencryptedRequestContent\nimport com.coinbase.android.nativesdk.message.request.UnencryptedRequestMessage\nimport com.coinbase.android.nativesdk.message.request.nonHandshakeActions\nimport com.coinbase.android.nativesdk.message.response.FailureResponseCallback\nimport com.coinbase.android.nativesdk.message.response.ResponseHandler\nimport com.coinbase.android.nativesdk.message.response.ResponseResult\nimport com.coinbase.android.nativesdk.message.response.ActionResult\nimport com.coinbase.android.nativesdk.message.response.ResponseConverter\nimport com.coinbase.android.nativesdk.message.response.SuccessHandshakeResponseCallback\nimport com.coinbase.android.nativesdk.message.response.SuccessRequestResponseCallback\nimport com.coinbase.android.nativesdk.task.TaskManager\nimport kotlinx.serialization.decodeFromString\nimport java.security.interfaces.ECPublicKey\nimport java.util.Date\nimport java.util.UUID\n\nconst val CBW_PACKAGE_NAME = \"org.toshi\"\nprivate const val CBW_SCHEME = \"cbwallet://wsegue\"\n\nclass CoinbaseWalletSDK(\n    domain: Uri,\n    private val appContext: Context,\n    private val hostPackageName: String = CBW_PACKAGE_NAME,\n    private val openIntent: (Intent) -> Unit\n) {\n    private val domain: Uri\n    private var sdkVersion = BuildConfig.LIBRARY_VERSION_NAME\n    private val keyManager by lazy { KeyManager(appContext, hostPackageName) }\n    private val taskManager by lazy { TaskManager() }\n\n    private val launchWalletIntent: Intent?\n        get() = appContext.packageManager.getLaunchIntentForPackage(hostPackageName)\n\n    val isCoinbaseWalletInstalled get() = launchWalletIntent != null\n    val isConnected: Boolean get() = keyManager.peerPublicKey != null\n    val ownPublicKey: ECPublicKey get() = keyManager.ownPublicKey\n    val peerPublicKey: ECPublicKey? get() = keyManager.peerPublicKey\n\n    companion object {\n        fun getCoinbaseWalletMWPVersion(context: Context): String? {\n            val intents = listOf(\n                \"1.1\" to Intent(Intent.ACTION_VIEW, Uri.parse(\"mwp+1.1://\")),\n                \"1.0\" to Intent(Intent.ACTION_VIEW, Uri.parse(\"cbwallet://\"))\n            )\n\n            for ((version, intent) in intents) {\n                if (intent.resolveActivity(context.packageManager) != null) {\n                    return version\n                }\n            }\n\n            return null\n        }\n    }\n\n    init {\n        this.domain = if (domain.pathSegments.size < 2) {\n            domain.buildUpon()\n                .appendPath(\"wsegue\")\n                .build()\n        } else {\n            domain\n        }\n    }\n\n    constructor(\n        domain: Uri,\n        appContext: Context,\n        hostPackageName: String,\n        openIntent: OpenIntentCallback\n    ) : this(\n        domain,\n        appContext,\n        hostPackageName,\n        { intent -> openIntent.call(intent) }\n    )\n\n    fun appendVersionTag(tag: String) {\n        sdkVersion += \"/$tag\"\n    }\n\n    /**\n     * Make handshake request to get session key from wallet\n     * @param initialActions Batch of actions that you'd want to execute after successful handshake. `eth_requestAccounts` by default.\n     * @param onResponse Response callback with regular response result and optional parsed [Account] object.\n     */\n    fun initiateHandshake(\n        initialActions: List<Action>? = null,\n        onResponse: (ResponseResult, Account?) -> Unit\n    ) {\n        resetSession()\n\n        val hasIllegalAction = initialActions?.any { nonHandshakeActions.contains(it.method) } == true\n        if (hasIllegalAction) {\n            onResponse(Result.failure(CoinbaseWalletSDKError.InvalidHandshakeRequest), null)\n            return\n        }\n\n        val message = UnencryptedRequestMessage(\n            uuid = UUID.randomUUID().toString(),\n            version = sdkVersion,\n            timestamp = Date(),\n            sender = keyManager.ownPublicKey,\n            content = UnencryptedRequestContent(\n                handshake = RequestContent.Handshake(\n                    appId = appContext.packageName,\n                    callback = domain.toString(),\n                    initialActions = initialActions\n                )\n            ),\n            callbackUrl = domain.toString()\n        )\n\n        send(message) { result ->\n            // Get index of eth_requestAccounts action\n            val requestAccountsIndex = initialActions?.indexOfFirst { it.method == ETH_REQUEST_ACCOUNTS } ?: -1\n            if (requestAccountsIndex == -1) {\n                onResponse(result, null)\n                return@send\n            }\n\n            // Get response from Wallet at index\n            val requestAccountsResult = result.getOrNull()?.getOrNull(requestAccountsIndex)\n            if (requestAccountsResult !is ActionResult.Result) {\n                onResponse(result, null)\n                return@send\n            }\n\n            val account = try {\n                JSON.decodeFromString<Account>(requestAccountsResult.value)\n            } catch (e: Exception) {\n                null\n            }\n\n            onResponse(result, account)\n        }\n    }\n\n    fun initiateHandshake(\n        initialActions: List<Action>? = null,\n        onSuccess: SuccessHandshakeResponseCallback,\n        onFailure: FailureResponseCallback\n    ) {\n        initiateHandshake(initialActions) { result, account ->\n            result\n                .onSuccess { onSuccess.call(it, account) }\n                .onFailure { onFailure.call(it) }\n        }\n    }\n\n    /**\n     * Make regular requests. It requires session key you get after successful handshake.\n     */\n    fun makeRequest(\n        request: RequestContent.Request,\n        onResponse: ResponseHandler\n    ) {\n        val message = UnencryptedRequestMessage(\n            uuid = UUID.randomUUID().toString(),\n            version = sdkVersion,\n            timestamp = Date(),\n            sender = keyManager.ownPublicKey,\n            content = UnencryptedRequestContent(request = request),\n            callbackUrl = domain.toString()\n        )\n\n        send(message, onResponse)\n    }\n\n    fun makeRequest(\n        request: RequestContent.Request,\n        onSuccess: SuccessRequestResponseCallback,\n        onFailure: FailureResponseCallback\n    ) {\n        makeRequest(request) { result ->\n            result\n                .onSuccess { onSuccess.call(it) }\n                .onFailure { onFailure.call(it) }\n        }\n    }\n\n    /**\n     * Handle incoming deep links\n     * @param url deep link url\n     * @return `false` if the input was not response message type, or `true` if SDK handled the input\n     */\n    fun handleResponse(url: Uri): Boolean {\n        if (!isWalletSegueResponseURL(url)) {\n            return false\n        }\n\n        val ownPublicKey = keyManager.ownPublicKey\n        val peerPublicKey = keyManager.peerPublicKey\n\n        val message = ResponseConverter.decode(\n            url = url,\n            ownPublicKey = ownPublicKey,\n            ownPrivateKey = keyManager.ownPrivateKey,\n            peerPublicKey = peerPublicKey\n        )\n\n        if (peerPublicKey == null && message.sender != ownPublicKey) {\n            keyManager.storePeerPublicKey(message.sender as ECPublicKey)\n        }\n\n        return taskManager.handleResponse(message)\n    }\n\n    fun resetSession() {\n        taskManager.reset()\n        keyManager.resetKeys()\n    }\n\n    private fun send(message: UnencryptedRequestMessage, onResponse: ResponseHandler) {\n        val uri: Uri\n        try {\n            uri = RequestConverter.encode(\n                message = message,\n                recipient = Uri.parse(CBW_SCHEME),\n                ownPrivateKey = keyManager.ownPrivateKey,\n                peerPublicKey = keyManager.peerPublicKey\n            )\n        } catch (e: Throwable) {\n            when (e) {\n                is CoinbaseWalletSDKError -> onResponse(Result.failure(e))\n                else -> onResponse(Result.failure(CoinbaseWalletSDKError.EncodingFailed))\n            }\n            return\n        }\n\n        val intent = launchWalletIntent\n        if (intent == null) {\n            onResponse(Result.failure(CoinbaseWalletSDKError.OpenWalletFailed))\n            return\n        }\n\n        // Prevent intent from launching app in new window\n        intent.type = Intent.ACTION_VIEW\n        if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK > 0) {\n            intent.flags = intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK.inv()\n        }\n\n        intent.data = uri\n\n        taskManager.registerResponseHandler(message, onResponse)\n        openIntent(intent)\n    }\n\n    private fun isWalletSegueResponseURL(uri: Uri): Boolean {\n        return uri.host == domain.host && uri.path == domain.path && uri.getQueryParameter(\"p\") != null\n    }\n}\n"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/CoinbaseWalletSDKError.kt",
    "content": "package com.coinbase.android.nativesdk\n\nsealed class CoinbaseWalletSDKError(\n    errorMessage: String? = null,\n    cause: Throwable? = null\n) : Exception(errorMessage, cause) {\n    object EncodingFailed : CoinbaseWalletSDKError(\"Encoding failed\")\n    object DecodingFailed : CoinbaseWalletSDKError(\"Decoding failed\")\n    object MissingSharedSecret : CoinbaseWalletSDKError(\"Missing shared secret\")\n    object OpenWalletFailed : CoinbaseWalletSDKError(\"Could not open wallet\")\n    object InvalidHandshakeRequest : CoinbaseWalletSDKError(\"Could not process this request in handshake\")\n    class WalletReturnedError(error: String) : CoinbaseWalletSDKError(error)\n    class UserNotAuthenticated(message: String, cause: Throwable) : CoinbaseWalletSDKError(message, cause)\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/OpenIntentCallback.kt",
    "content": "package com.coinbase.android.nativesdk\n\nimport android.content.Intent\n\ninterface OpenIntentCallback {\n    fun call(intent: Intent)\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/key/KeyManager.kt",
    "content": "package com.coinbase.android.nativesdk.key\n\nimport KeyStore\nimport android.content.Context\nimport com.google.crypto.tink.subtle.EllipticCurves\nimport java.security.KeyPair\nimport java.security.interfaces.ECPrivateKey\nimport java.security.interfaces.ECPublicKey\n\nprivate const val OWN_KEY_PAIR_ALIAS = \"own_key_pair\"\n\ninternal class KeyManager(appContext: Context, host: String) {\n\n    private val keyStore: KeyStore\n    private var ownKeyPair: KeyPair? = null\n\n    val ownPublicKey: ECPublicKey\n        get() {\n            val own = ownKeyPair ?: getOrCreateKeyPair(OWN_KEY_PAIR_ALIAS)\n            if (ownKeyPair == null) ownKeyPair = own\n            return own.public as ECPublicKey\n        }\n\n    val ownPrivateKey: ECPrivateKey\n        get() {\n            val own = ownKeyPair ?: getOrCreateKeyPair(OWN_KEY_PAIR_ALIAS)\n            if (ownKeyPair == null) ownKeyPair = own\n            return own.private as ECPrivateKey\n        }\n\n    val peerPublicKey: ECPublicKey?\n        get() = keyStore.peerPublicKey\n\n    init {\n        keyStore = KeyStore(\n            fileName = \"${host}_wallet_segue_key_store\",\n            context = appContext\n        )\n    }\n\n    fun storePeerPublicKey(key: ECPublicKey) {\n        keyStore.peerPublicKey = key\n    }\n\n    fun resetKeys() {\n        keyStore.reset()\n\n        // Create new KeyPair\n        ownKeyPair = getOrCreateKeyPair(OWN_KEY_PAIR_ALIAS)\n    }\n\n    private fun deleteKeyPair(alias: String) {\n        keyStore.deleteKeyPair(alias)\n    }\n\n    private fun getOrCreateKeyPair(alias: String): KeyPair {\n        val keyPair = keyStore.getKeyPair(alias)\n        return if (keyPair != null) {\n            // Already have keys in encrypted storage\n            keyPair\n        } else {\n            // Generate new key pair and save to encrypted storage\n            val kp = EllipticCurves.generateKeyPair(EllipticCurves.CurveType.NIST_P256)\n            keyStore.saveKeyPair(alias, kp)\n            kp\n        }\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/key/KeyStore.kt",
    "content": "import android.app.KeyguardManager\nimport android.content.Context\nimport android.content.SharedPreferences\nimport android.security.keystore.KeyGenParameterSpec\nimport android.security.keystore.KeyProperties\nimport android.security.keystore.UserNotAuthenticatedException\nimport android.util.Log\nimport androidx.security.crypto.EncryptedSharedPreferences\nimport androidx.security.crypto.MasterKeys\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.google.crypto.tink.subtle.Base64\nimport com.google.crypto.tink.subtle.EllipticCurves\nimport java.security.KeyPair\nimport java.security.KeyStore\nimport java.security.interfaces.ECPublicKey\n\nprivate const val DEPRECATED_MAIN_KEY_ALIAS = \"wallet_segue_main_key\"\nprivate const val HAS_MIGRATED_TO_VERSION_120_ALIAS = \"has_migrated_to_version_1.2.0\"\n\nprivate const val PUBLIC_KEY_ALIAS = \"public_key\"\nprivate const val PRIVATE_KEY_ALIAS = \"private_key\"\nprivate const val PEER_PUBLIC_KEY_ALIAS = \"peer_public_key\"\nprivate const val OWN_KEY_PAIR_ALIAS = \"own_key_pair\"\n\nclass KeyStore(\n    private val fileName: String,\n    private val context: Context\n) {\n    private val storage: SharedPreferences\n\n    var peerPublicKey: ECPublicKey?\n        get() {\n            val encoded = storage.getString(PEER_PUBLIC_KEY_ALIAS, null) ?: return null\n            val bytes = Base64.decode(encoded)\n            return EllipticCurves.getEcPublicKey(bytes)\n        }\n        set(value) {\n            if (value != null) {\n                val encoded = Base64.encode(value.encoded)\n                storage.edit()\n                    .putString(PEER_PUBLIC_KEY_ALIAS, encoded)\n                    .commit()\n            }\n        }\n\n    init {\n        storage = getSharedPrefs()\n    }\n\n    fun getKeyPair(alias: String): KeyPair? {\n        val publicKeyAlias = \"${alias}-${PUBLIC_KEY_ALIAS}\"\n        val privateKeyAlias = \"${alias}-${PRIVATE_KEY_ALIAS}\"\n\n        val publicKeyB64 = storage.getString(publicKeyAlias, null)\n        val privateKeyB64 = storage.getString(privateKeyAlias, null)\n\n        return if (publicKeyB64 != null && privateKeyB64 != null) {\n            // Already have keys in encrypted storage\n            val publicKeyBytes = Base64.decode(publicKeyB64)\n            val privateKeyBytes = Base64.decode(privateKeyB64)\n\n            KeyPair(\n                EllipticCurves.getEcPublicKey(publicKeyBytes),\n                EllipticCurves.getEcPrivateKey(privateKeyBytes)\n            )\n        } else {\n            null\n        }\n    }\n\n    fun saveKeyPair(alias: String, keyPair: KeyPair) {\n        val publicKeyAlias = \"${alias}-${PUBLIC_KEY_ALIAS}\"\n        val privateKeyAlias = \"${alias}-${PRIVATE_KEY_ALIAS}\"\n\n        storage\n            .edit()\n            .putString(publicKeyAlias, Base64.encode(keyPair.public.encoded))\n            .putString(privateKeyAlias, Base64.encode(keyPair.private.encoded))\n            .commit()\n    }\n\n    fun deleteKeyPair(alias: String) {\n        val publicKeyAlias = \"${alias}-${PUBLIC_KEY_ALIAS}\"\n        val privateKeyAlias = \"${alias}-${PRIVATE_KEY_ALIAS}\"\n\n        storage.edit()\n            .remove(publicKeyAlias)\n            .remove(privateKeyAlias)\n            .commit()\n    }\n\n    fun reset() {\n        val publicKeyAlias = \"${OWN_KEY_PAIR_ALIAS}-${PUBLIC_KEY_ALIAS}\"\n        val privateKeyAlias = \"${OWN_KEY_PAIR_ALIAS}-${PRIVATE_KEY_ALIAS}\"\n\n        storage.edit()\n            .remove(publicKeyAlias)\n            .remove(privateKeyAlias)\n            .remove(PEER_PUBLIC_KEY_ALIAS)\n            .commit()\n    }\n\n    private fun getSharedPrefs(): SharedPreferences {\n        val sharedPrefs = context.getSharedPreferences(\"${fileName}_raw\", Context.MODE_PRIVATE)\n        val hasMigratedToVersion120 = sharedPrefs.getBoolean(HAS_MIGRATED_TO_VERSION_120_ALIAS, false)\n\n        if (!hasMigratedToVersion120) {\n            try {\n                // Perform the migration\n                migrateEncryptedPrefs(sharedPrefs)\n            } catch (e: Exception) {\n                // Clear Shared Prefs State\n                sharedPrefs.edit().clear().commit()\n            } finally {\n                // Mark as migrated\n                sharedPrefs.edit().putBoolean(HAS_MIGRATED_TO_VERSION_120_ALIAS, true).commit()\n            }\n        }\n\n        return sharedPrefs\n    }\n\n    private fun migrateEncryptedPrefs(newPrefs: SharedPreferences) {\n        // 1. Open the old EncryptedSharedPreferences\n        val encryptedPrefs = getEncryptedPrefs()\n\n        // 2. Copy all string typed key-value pairs from encrypted prefs to new prefs in plain text\n        val allEntries = encryptedPrefs.all\n        for ((key, value) in allEntries) {\n            if (value != null) {\n                when (value) {\n                    is String  -> newPrefs.edit().putString(key, value).commit()\n                }\n            }\n        }\n\n        // 3. Clear the old EncryptedSharedPreferences\n        encryptedPrefs.edit().clear().commit()\n    }\n\n    private fun getEncryptedPrefs(): SharedPreferences {\n        // Create main key that secures encrypted storage\n        val purposes = KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT\n\n        val keyGenSpec = with(KeyGenParameterSpec.Builder(DEPRECATED_MAIN_KEY_ALIAS, purposes)) {\n            val keyguard = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager\n            if (keyguard.isDeviceSecure) {\n                setUserAuthenticationRequired(true)\n                setUserAuthenticationValidityDurationSeconds(172_800) // 2 days\n            }\n\n            setBlockModes(KeyProperties.BLOCK_MODE_GCM)\n            setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)\n            setKeySize(256)\n            build()\n        }\n\n        val mainKey = MasterKeys.getOrCreate(keyGenSpec)\n\n        return EncryptedSharedPreferences.create(\n            fileName,\n            mainKey,\n            context,\n            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,\n            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM\n        )\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/key/PublicKeySerializer.kt",
    "content": "package com.coinbase.android.nativesdk.key\n\nimport com.google.crypto.tink.subtle.Base64\nimport com.google.crypto.tink.subtle.EllipticCurves\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.descriptors.PrimitiveKind\nimport kotlinx.serialization.descriptors.PrimitiveSerialDescriptor\nimport kotlinx.serialization.descriptors.SerialDescriptor\nimport kotlinx.serialization.encoding.Decoder\nimport kotlinx.serialization.encoding.Encoder\nimport java.security.PublicKey\n\ninternal object PublicKeySerializer : KSerializer<PublicKey> {\n    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(\"PublicKey\", PrimitiveKind.STRING)\n\n    override fun serialize(encoder: Encoder, value: PublicKey) = encoder.encodeString(Base64.encode(value.encoded))\n\n    override fun deserialize(decoder: Decoder): PublicKey =\n        EllipticCurves.getEcPublicKey(Base64.decode(decoder.decodeString()))\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/Cipher.kt",
    "content": "package com.coinbase.android.nativesdk.message\n\nimport com.google.crypto.tink.subtle.AesGcmJce\nimport com.google.crypto.tink.subtle.Base64\n\ninternal object Cipher {\n    fun encrypt(secret: ByteArray, message: String): String {\n        val associatedData = \"encrypted data\"\n        val encrypted = AesGcmJce(secret).encrypt(message.toByteArray(), associatedData.toByteArray())\n        return Base64.encode(encrypted)\n    }\n\n    fun decrypt(secret: ByteArray, encryptedMessage: String): String {\n        val encryptedBytes = Base64.decode(encryptedMessage)\n        val associatedData = \"encrypted data\"\n        val decryptedBytes = AesGcmJce(secret).decrypt(encryptedBytes, associatedData.toByteArray())\n        return String(decryptedBytes)\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/DateSerializer.kt",
    "content": "package com.coinbase.android.nativesdk.message\n\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.descriptors.PrimitiveKind\nimport kotlinx.serialization.descriptors.PrimitiveSerialDescriptor\nimport kotlinx.serialization.descriptors.SerialDescriptor\nimport kotlinx.serialization.encoding.Decoder\nimport kotlinx.serialization.encoding.Encoder\nimport java.util.Date\n\ninternal object DateSerializer : KSerializer<Date> {\n    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(\"Date\", PrimitiveKind.LONG)\n    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)\n    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/JSON.kt",
    "content": "package com.coinbase.android.nativesdk.message\n\nimport kotlinx.serialization.json.Json\n\ninternal val JSON = Json {\n    encodeDefaults = true\n    classDiscriminator = \"#wsegue_type\"\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/Message.kt",
    "content": "package com.coinbase.android.nativesdk.message\n\nimport com.coinbase.android.nativesdk.key.PublicKeySerializer\nimport kotlinx.serialization.Serializable\nimport java.security.PublicKey\nimport java.util.Date\n\n@Serializable\ndata class Message<Content>(\n    val uuid: String,\n    val version: String,\n    @Serializable(with = PublicKeySerializer::class)\n    val sender: PublicKey,\n    val content: Content,\n    @Serializable(with = DateSerializer::class)\n    val timestamp: Date,\n    val callbackUrl: String?\n) {\n    fun <T> copy(newContent: T): Message<T> {\n        return Message(\n            uuid = uuid,\n            version = version,\n            sender = sender,\n            content = newContent,\n            timestamp = timestamp,\n            callbackUrl = callbackUrl\n        )\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/MessageConverter.kt",
    "content": "package com.coinbase.android.nativesdk.message\n\nimport android.net.Uri\nimport com.google.crypto.tink.subtle.EllipticCurves\nimport java.security.interfaces.ECPrivateKey\nimport java.security.interfaces.ECPublicKey\n\ninterface MessageConverter<UnencryptedMessageType, EncryptedMessageType> {\n\n    fun encode(\n        message: UnencryptedMessageType,\n        recipient: Uri,\n        ownPrivateKey: ECPrivateKey? = null,\n        peerPublicKey: ECPublicKey? = null\n    ): Uri\n\n    fun decode(\n        url: Uri,\n        ownPublicKey: ECPublicKey? = null,\n        ownPrivateKey: ECPrivateKey? = null,\n        peerPublicKey: ECPublicKey? = null\n    ): UnencryptedMessageType\n\n    fun decodeWithoutDecryption(url: Uri): EncryptedMessageType\n\n    fun getSharedSecret(\n        ownPublicKey: ECPublicKey? = null,\n        ownPrivateKey: ECPrivateKey? = null,\n        peerPublicKey: ECPublicKey? = null,\n        messageSender: ECPublicKey? = null,\n    ): ByteArray? {\n        val myPrivateKey = ownPrivateKey ?: return null\n        val otherPublicKey = (peerPublicKey ?: messageSender) ?: return null\n\n        if (otherPublicKey == ownPublicKey) {\n            return null\n        }\n\n        return EllipticCurves.computeSharedSecret(myPrivateKey, otherPublicKey)\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/request/Account.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport kotlinx.serialization.Serializable\n\n@Serializable\nclass Account(\n    val chain: String,\n    val networkId: Long,\n    val address: String\n)"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/request/Action.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport kotlinx.serialization.Serializable\n\n@Serializable\nclass Action {\n    val method: String\n    private val paramsJson: String\n    private val optional: Boolean\n\n    constructor(method: String, paramsJson: String, optional: Boolean = false) {\n        this.method = method\n        this.paramsJson = paramsJson\n        this.optional = optional\n    }\n\n    constructor(rpc: Web3JsonRPC, optional: Boolean = false) {\n        val (method, paramsJson) = rpc.asJson\n        this.method = method\n        this.paramsJson = paramsJson\n        this.optional = optional\n    }\n\n    override fun equals(other: Any?): Boolean {\n        return if (other !is Action) {\n            false\n        } else {\n            // Compare the data members and return accordingly\n            this.method == other.method && this.paramsJson == other.paramsJson &&\n                    this.optional == other.optional\n        }\n    }\n\n    override fun hashCode(): Int {\n        var result = method.hashCode()\n        result = 31 * result + paramsJson.hashCode()\n        result = 31 * result + optional.hashCode()\n        return result\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/request/EncryptedRequestMessage.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.Cipher\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.coinbase.android.nativesdk.message.Message\nimport kotlinx.serialization.EncodeDefault\nimport kotlinx.serialization.EncodeDefault.Mode.NEVER\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.decodeFromString\n\ntypealias EncryptedRequestMessage = Message<EncryptedRequestContent>\n\n@Serializable\ndata class EncryptedRequest(val data: String)\n\n@OptIn(ExperimentalSerializationApi::class)\n@Serializable\ndata class EncryptedRequestContent(\n    @EncodeDefault(NEVER) val handshake: RequestContent.Handshake? = null,\n    @EncodeDefault(NEVER) val request: EncryptedRequest? = null\n)\n\nfun EncryptedRequestMessage.decrypt(secret: ByteArray?): UnencryptedRequestMessage {\n    val content = when {\n        this.content.handshake != null -> {\n            UnencryptedRequestContent(handshake = this.content.handshake)\n        }\n        this.content.request != null -> {\n            if (secret == null) throw CoinbaseWalletSDKError.MissingSharedSecret\n\n            val requestJson = Cipher.decrypt(secret, this.content.request.data)\n            val request: RequestContent.Request = JSON.decodeFromString(requestJson)\n            UnencryptedRequestContent(request = request)\n        }\n        else -> throw CoinbaseWalletSDKError.DecodingFailed\n    }\n\n    return copy(newContent = content)\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/request/RequestConverter.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport android.net.Uri\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.MessageConverter\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.google.crypto.tink.subtle.Base64\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.encodeToString\nimport java.security.interfaces.ECPrivateKey\nimport java.security.interfaces.ECPublicKey\n\nobject RequestConverter : MessageConverter<UnencryptedRequestMessage, EncryptedRequestMessage> {\n\n    override fun encode(\n        message: UnencryptedRequestMessage,\n        recipient: Uri,\n        ownPrivateKey: ECPrivateKey?,\n        peerPublicKey: ECPublicKey?\n    ): Uri {\n        val secret = getSharedSecret(ownPrivateKey = ownPrivateKey, peerPublicKey = peerPublicKey)\n        val encrypted = message.encrypt(secret)\n        val json = JSON.encodeToString(encrypted)\n\n        return recipient.buildUpon()\n            .appendQueryParameter(\"p\", Base64.encode(json.toByteArray()))\n            .build()\n    }\n\n    override fun decode(\n        url: Uri,\n        ownPublicKey: ECPublicKey?,\n        ownPrivateKey: ECPrivateKey?,\n        peerPublicKey: ECPublicKey?\n    ): UnencryptedRequestMessage {\n        val decoded = decodeWithoutDecryption(url)\n        val secret = getSharedSecret(\n            ownPublicKey = ownPublicKey,\n            ownPrivateKey = ownPrivateKey,\n            peerPublicKey = peerPublicKey,\n            messageSender = decoded.sender as ECPublicKey\n        )\n\n        return decoded.decrypt(secret)\n    }\n\n    override fun decodeWithoutDecryption(url: Uri): EncryptedRequestMessage {\n        val encoded = url.getQueryParameter(\"p\") ?: throw CoinbaseWalletSDKError.DecodingFailed\n        val messageJsonString = String(Base64.decode(encoded))\n        return JSON.decodeFromString(messageJsonString)\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/request/UnencryptedRequestMessage.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.Cipher\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.coinbase.android.nativesdk.message.Message\nimport kotlinx.serialization.EncodeDefault\nimport kotlinx.serialization.EncodeDefault.Mode.NEVER\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.encodeToString\n\ntypealias UnencryptedRequestMessage = Message<UnencryptedRequestContent>\n\nsealed interface RequestContent {\n    @Serializable\n    data class Handshake(\n        val appId: String,\n        val callback: String,\n        val appName: String? = null,\n        val appIconUrl: String? = null,\n        val initialActions: List<Action>? = null\n    ) : RequestContent\n\n    @Serializable\n    data class Request(\n        val actions: List<Action>,\n        val account: Account? = null\n    ) : RequestContent\n}\n\n@OptIn(ExperimentalSerializationApi::class)\n@Serializable\ndata class UnencryptedRequestContent(\n    @EncodeDefault(NEVER) val handshake: RequestContent.Handshake? = null,\n    @EncodeDefault(NEVER) val request: RequestContent.Request? = null\n) {\n    val sealed get() = handshake ?: request ?: throw IllegalStateException()\n}\n\nfun UnencryptedRequestMessage.encrypt(secret: ByteArray?): EncryptedRequestMessage {\n    val encryptedContent = when (val content = this.content.sealed) {\n        is RequestContent.Handshake -> {\n            EncryptedRequestContent(handshake = content)\n        }\n        is RequestContent.Request -> {\n            if (secret == null) throw CoinbaseWalletSDKError.MissingSharedSecret\n\n            val requestJson = JSON.encodeToString(content)\n            val encrypted = Cipher.encrypt(secret, requestJson)\n            EncryptedRequestContent(request = EncryptedRequest(encrypted))\n        }\n    }\n\n    return copy(newContent = encryptedContent)\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/request/Web3JsonRPC.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport com.coinbase.android.nativesdk.message.JSON\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.encodeToString\n\nprivate typealias BigInt = String\n\nconst val ETH_REQUEST_ACCOUNTS = \"eth_requestAccounts\"\nconst val PERSONAL_SIGN = \"personal_sign\"\nconst val ETH_SIGN_TYPED_DATA_V3 = \"eth_signTypedData_v3\"\nconst val ETH_SIGN_TYPED_DATA_V4 = \"eth_signTypedData_v4\"\nconst val ETH_SIGN_TRANSACTION = \"eth_signTransaction\"\nconst val ETH_SEND_TRANSACTION = \"eth_sendTransaction\"\nconst val WALLET_SWITCH_ETHEREUM_CHAIN = \"wallet_switchEthereumChain\"\nconst val WALLET_ADD_ETHEREUM_CHAIN = \"wallet_addEthereumChain\"\nconst val WALLET_WATCH_ASSET = \"wallet_watchAsset\"\n\nval nonHandshakeActions = listOf(ETH_SEND_TRANSACTION, ETH_SIGN_TRANSACTION)\n\n@Suppress(\"unused\")\n@Serializable\nsealed class Web3JsonRPC {\n\n    @Serializable\n    @SerialName(ETH_REQUEST_ACCOUNTS)\n    class RequestAccounts : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(PERSONAL_SIGN)\n    class PersonalSign(\n        val address: String,\n        val message: String\n    ) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(ETH_SIGN_TYPED_DATA_V3)\n    class SignTypedDataV3(\n        val address: String,\n        val typedDataJson: String\n    ) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(ETH_SIGN_TYPED_DATA_V4)\n    class SignTypedDataV4(\n        val address: String,\n        val typedDataJson: String\n    ) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(ETH_SIGN_TRANSACTION)\n    class SignTransaction(\n        val fromAddress: String,\n        val toAddress: String?,\n        val weiValue: BigInt,\n        val data: String,\n        val nonce: Int?,\n        val gasPriceInWei: BigInt?,\n        val maxFeePerGas: BigInt?,\n        val maxPriorityFeePerGas: BigInt?,\n        val gasLimit: BigInt?,\n        val chainId: String\n    ) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(ETH_SEND_TRANSACTION)\n    class SendTransaction(\n        val fromAddress: String,\n        val toAddress: String?,\n        val weiValue: BigInt,\n        val data: String,\n        val nonce: Int?,\n        val gasPriceInWei: BigInt?,\n        val maxFeePerGas: BigInt?,\n        val maxPriorityFeePerGas: BigInt?,\n        val gasLimit: BigInt?,\n        val chainId: String,\n        val actionSource: ActionSource? = null\n    ) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(WALLET_SWITCH_ETHEREUM_CHAIN)\n    class SwitchEthereumChain(val chainId: String) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(WALLET_ADD_ETHEREUM_CHAIN)\n    class AddEthereumChain(\n        val chainId: String,\n        val blockExplorerUrls: List<String>? = null,\n        val chainName: String? = null,\n        val iconUrls: List<String>? = null,\n        val nativeCurrency: AddChainNativeCurrency? = null,\n        val rpcUrls: List<String> = emptyList()\n    ) : Web3JsonRPC()\n\n    @Serializable\n    @SerialName(WALLET_WATCH_ASSET)\n    class WatchAsset(\n        val type: String,\n        val options: WatchAssetOptions\n    ) : Web3JsonRPC()\n\n    internal val asJson: Pair<String, String>\n        get() {\n            val json = JSON.encodeToString(this)\n            val method = when (this) {\n                is RequestAccounts -> ETH_REQUEST_ACCOUNTS\n                is SendTransaction -> ETH_SEND_TRANSACTION\n                is SignTransaction -> ETH_SIGN_TRANSACTION\n                is PersonalSign -> PERSONAL_SIGN\n                is SignTypedDataV3 -> ETH_SIGN_TYPED_DATA_V3\n                is SignTypedDataV4 -> ETH_SIGN_TYPED_DATA_V4\n                is AddEthereumChain -> WALLET_ADD_ETHEREUM_CHAIN\n                is SwitchEthereumChain -> WALLET_SWITCH_ETHEREUM_CHAIN\n                is WatchAsset -> WALLET_WATCH_ASSET\n            }\n\n            return method to json\n        }\n\n    fun action(optional: Boolean = false): Action = Action(rpc = this, optional = optional)\n}\n\n@Serializable\nclass AddChainNativeCurrency(val name: String, val symbol: String, val decimals: Int)\n\n@Serializable\nclass WatchAssetOptions(val address: String, val symbol: String?, val decimals: Int?, val image: String?)\n\n@Serializable\nclass ActionSource(val url: String)\n"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/response/ActionResult.kt",
    "content": "package com.coinbase.android.nativesdk.message.response\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.descriptors.SerialDescriptor\nimport kotlinx.serialization.descriptors.buildClassSerialDescriptor\nimport kotlinx.serialization.encoding.Decoder\nimport kotlinx.serialization.encoding.Encoder\nimport kotlinx.serialization.json.JsonDecoder\nimport kotlinx.serialization.json.JsonEncoder\nimport kotlinx.serialization.json.buildJsonObject\nimport kotlinx.serialization.json.decodeFromJsonElement\nimport kotlinx.serialization.json.encodeToJsonElement\nimport kotlinx.serialization.json.jsonObject\n\n@Serializable(with = ActionResultSerializer::class)\nsealed class ActionResult {\n    @Serializable\n    class Result(val value: String) : ActionResult()\n\n    @Serializable\n    class Error(val code: Long, val message: String) : ActionResult()\n}\n\ninternal object ActionResultSerializer : KSerializer<ActionResult> {\n    override val descriptor: SerialDescriptor = buildClassSerialDescriptor(\"ReturnValue\")\n\n    override fun serialize(encoder: Encoder, value: ActionResult) {\n        val output = encoder as? JsonEncoder ?: throw CoinbaseWalletSDKError.EncodingFailed\n        val formatter = output.json\n\n        val json = buildJsonObject {\n            when (value) {\n                is ActionResult.Result -> put(\"result\", formatter.encodeToJsonElement(value))\n                is ActionResult.Error -> put(\"error\", formatter.encodeToJsonElement(value))\n            }\n        }\n\n        output.encodeJsonElement(json)\n    }\n\n    override fun deserialize(decoder: Decoder): ActionResult {\n        val input = decoder as? JsonDecoder ?: throw CoinbaseWalletSDKError.DecodingFailed\n        val formatter = input.json\n        val json = input.decodeJsonElement().jsonObject\n\n        return when (val key = json.keys.firstOrNull()) {\n            \"result\" -> formatter.decodeFromJsonElement<ActionResult.Result>(json.getValue(key))\n            \"error\" -> formatter.decodeFromJsonElement<ActionResult.Error>(json.getValue(key))\n            else -> throw CoinbaseWalletSDKError.DecodingFailed\n        }\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/response/EncryptedResponseMessage.kt",
    "content": "package com.coinbase.android.nativesdk.message.response\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.Cipher\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.coinbase.android.nativesdk.message.Message\nimport kotlinx.serialization.EncodeDefault\nimport kotlinx.serialization.EncodeDefault.Mode.NEVER\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.decodeFromString\n\ntypealias EncryptedResponseMessage = Message<EncryptedResponseContent>\n\n@Serializable\ndata class EncryptedResponse(\n    val requestId: String? = null,\n    val data: String\n)\n\n@OptIn(ExperimentalSerializationApi::class)\n@Serializable\ndata class EncryptedResponseContent(\n    @EncodeDefault(NEVER) val response: EncryptedResponse? = null,\n    @EncodeDefault(NEVER) val failure: ResponseContent.Failure? = null\n)\n\nfun EncryptedResponseMessage.decrypt(secret: ByteArray?): UnencryptedResponseMessage {\n    val content: UnencryptedResponseContent = when {\n        this.content.failure != null -> {\n            UnencryptedResponseContent(failure = this.content.failure)\n        }\n        this.content.response != null -> {\n            if (secret == null) throw CoinbaseWalletSDKError.MissingSharedSecret\n\n            val responseJson = Cipher.decrypt(secret, this.content.response.data)\n            val response: ResponseContent.Response = JSON.decodeFromString(responseJson)\n            UnencryptedResponseContent(response = response)\n        }\n        else -> throw CoinbaseWalletSDKError.DecodingFailed\n    }\n\n    return copy(newContent = content)\n}\n"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/response/Response.kt",
    "content": "package com.coinbase.android.nativesdk.message.response\n\ntypealias ResponseResult = Result<List<ActionResult>>\ntypealias ResponseHandler = (ResponseResult) -> Unit"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/response/ResponseCallback.kt",
    "content": "package com.coinbase.android.nativesdk.message.response\n\nimport com.coinbase.android.nativesdk.message.request.Account\n\ninterface SuccessHandshakeResponseCallback {\n    fun call(result: List<ActionResult>, account: Account?)\n}\n\ninterface SuccessRequestResponseCallback {\n    fun call(result: List<ActionResult>)\n}\n\ninterface FailureResponseCallback {\n    fun call(error: Throwable)\n}\n"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/response/ResponseConverter.kt",
    "content": "package com.coinbase.android.nativesdk.message.response\n\nimport android.net.Uri\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.MessageConverter\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.google.crypto.tink.subtle.Base64\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.encodeToString\nimport java.security.interfaces.ECPrivateKey\nimport java.security.interfaces.ECPublicKey\n\nobject ResponseConverter : MessageConverter<UnencryptedResponseMessage, EncryptedResponseMessage> {\n\n    override fun encode(\n        message: UnencryptedResponseMessage,\n        recipient: Uri,\n        ownPrivateKey: ECPrivateKey?,\n        peerPublicKey: ECPublicKey?\n    ): Uri {\n        val secret = getSharedSecret(ownPrivateKey = ownPrivateKey, peerPublicKey = peerPublicKey)\n        val encrypted = message.encrypt(secret)\n        val json = JSON.encodeToString(encrypted)\n\n        return recipient.buildUpon()\n            .appendQueryParameter(\"p\", Base64.encode(json.toByteArray()))\n            .build()\n    }\n\n    override fun decode(\n        url: Uri,\n        ownPublicKey: ECPublicKey?,\n        ownPrivateKey: ECPrivateKey?,\n        peerPublicKey: ECPublicKey?\n    ): UnencryptedResponseMessage {\n        val decoded = decodeWithoutDecryption(url)\n        val secret = getSharedSecret(\n            ownPublicKey = ownPublicKey,\n            ownPrivateKey = ownPrivateKey,\n            peerPublicKey = peerPublicKey,\n            messageSender = decoded.sender as ECPublicKey\n        )\n\n        return decoded.decrypt(secret)\n    }\n\n    override fun decodeWithoutDecryption(url: Uri): EncryptedResponseMessage {\n        val encoded = url.getQueryParameter(\"p\") ?: throw CoinbaseWalletSDKError.DecodingFailed\n        val messageJsonString = String(Base64.decode(encoded))\n        return JSON.decodeFromString(messageJsonString)\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/message/response/UnencryptedResponseMessage.kt",
    "content": "package com.coinbase.android.nativesdk.message.response\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.Cipher\nimport com.coinbase.android.nativesdk.message.JSON\nimport com.coinbase.android.nativesdk.message.Message\nimport kotlinx.serialization.EncodeDefault\nimport kotlinx.serialization.EncodeDefault.Mode.NEVER\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.encodeToString\n\ntypealias UnencryptedResponseMessage = Message<UnencryptedResponseContent>\n\nsealed interface ResponseContent {\n    @Serializable\n    data class Response(\n        val requestId: String,\n        val values: List<ActionResult>\n    ) : ResponseContent\n\n    @Serializable\n    data class Failure(\n        val requestId: String,\n        val description: String\n    ) : ResponseContent\n}\n\n@OptIn(ExperimentalSerializationApi::class)\n@Serializable\ndata class UnencryptedResponseContent(\n    @EncodeDefault(NEVER) val failure: ResponseContent.Failure? = null,\n    @EncodeDefault(NEVER) val response: ResponseContent.Response? = null\n) {\n    val sealed get() = failure ?: response ?: throw IllegalStateException()\n}\n\nfun UnencryptedResponseMessage.encrypt(secret: ByteArray?): EncryptedResponseMessage {\n    val encryptedContent: EncryptedResponseContent = when (val content = this.content.sealed) {\n        is ResponseContent.Failure -> {\n            EncryptedResponseContent(failure = content)\n        }\n        is ResponseContent.Response -> {\n            if (secret == null) throw CoinbaseWalletSDKError.MissingSharedSecret\n\n            val responseJson = JSON.encodeToString(content)\n            val encrypted = Cipher.encrypt(secret, responseJson)\n            EncryptedResponseContent(\n                response = EncryptedResponse(\n                    requestId = content.requestId,\n                    data = encrypted\n                )\n            )\n        }\n    }\n\n    return copy(newContent = encryptedContent)\n}"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/task/Task.kt",
    "content": "package com.coinbase.android.nativesdk.task\n\nimport com.coinbase.android.nativesdk.message.request.UnencryptedRequestMessage\nimport com.coinbase.android.nativesdk.message.response.ResponseHandler\nimport java.util.Date\n\ninternal class Task(\n    val request: UnencryptedRequestMessage,\n    val handler: ResponseHandler,\n    val timestamp: Date\n)"
  },
  {
    "path": "android/walletsdk/src/main/java/com/coinbase/android/nativesdk/task/TaskManager.kt",
    "content": "package com.coinbase.android.nativesdk.task\n\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDKError\nimport com.coinbase.android.nativesdk.message.request.UnencryptedRequestMessage\nimport com.coinbase.android.nativesdk.message.response.ResponseContent\nimport com.coinbase.android.nativesdk.message.response.ResponseHandler\nimport com.coinbase.android.nativesdk.message.response.ResponseResult\nimport com.coinbase.android.nativesdk.message.response.UnencryptedResponseMessage\n\ninternal class TaskManager {\n    private val tasks = HashMap<String, Task>()\n\n    fun registerResponseHandler(message: UnencryptedRequestMessage, handler: ResponseHandler) {\n        tasks[message.uuid] = Task(\n            request = message,\n            handler = handler,\n            timestamp = message.timestamp\n        )\n    }\n\n    fun handleResponse(message: UnencryptedResponseMessage): Boolean {\n        val requestId: String\n        val result: ResponseResult = when (val response = message.content.sealed) {\n            is ResponseContent.Response -> {\n                requestId = response.requestId\n                Result.success(response.values)\n            }\n            is ResponseContent.Failure -> {\n                requestId = response.requestId\n                Result.failure(CoinbaseWalletSDKError.WalletReturnedError(response.description))\n            }\n        }\n\n        val task = tasks[requestId] ?: return false\n\n        task.handler(result)\n        tasks.remove(requestId)\n        return true\n    }\n\n    fun reset(){\n        tasks.clear()\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/test/java/com/coinbase/android/nativesdk/ExampleUnitTest.kt",
    "content": "package com.coinbase.android.nativesdk\n\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\nclass ExampleUnitTest {\n    @Test\n    fun addition_isCorrect() {\n        assertEquals(4, 2 + 2)\n    }\n}"
  },
  {
    "path": "android/walletsdk/src/test/java/com/coinbase/android/nativesdk/helper/InputStreamExtensions.kt",
    "content": "package com.coinbase.android.nativesdk.helper\n\nimport java.io.IOException\nimport java.io.InputStream\n\n@Throws(IOException::class)\nfun InputStream?.readFileWithNewLineFromResources(): String {\n    return this?.bufferedReader()\n        .use { bufferReader ->\n            val builder = StringBuilder()\n            var str: String? = bufferReader?.readLine()\n            while (str != null) {\n                builder.append(str)\n                str = bufferReader?.readLine()\n            }\n            builder.toString().replace(\" \", \"\")\n        }\n}\n\n"
  },
  {
    "path": "android/walletsdk/src/test/java/com/coinbase/android/nativesdk/message/request/Web3JsonRPCTest.kt",
    "content": "package com.coinbase.android.nativesdk.message.request\n\nimport com.coinbase.android.nativesdk.helper.readFileWithNewLineFromResources\nimport io.kotest.matchers.shouldBe\nimport org.junit.Test\n\nprivate const val typedData =\n    \"{\\\"types\\\":{\\\"EIP712Domain\\\":[{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"version\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"chainId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"verifyingContract\\\",\\\"type\\\":\\\"address\\\"},{\\\"name\\\":\\\"salt\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"Bid\\\":[{\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"bidder\\\",\\\"type\\\":\\\"Identity\\\"}],\\\"Identity\\\":[{\\\"name\\\":\\\"userId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"wallet\\\",\\\"type\\\":\\\"address\\\"}]},\\\"domain\\\":{\\\"name\\\":\\\"DApp Browser Test DApp\\\",\\\"version\\\":\\\"1\\\",\\\"chainId\\\":1,\\\"verifyingContract\\\":\\\"0x1C56346CD2A2Bf3202F771f50d3D14a367B48070\\\",\\\"salt\\\":\\\"0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558\\\"},\\\"primaryType\\\":\\\"Bid\\\",\\\"message\\\":{\\\"amount\\\":100,\\\"bidder\\\":{\\\"userId\\\":323,\\\"wallet\\\":\\\"0x3333333333333333333333333333333333333333\\\"}}}\"\n\nclass Web3JsonRPCTest {\n\n    @Test\n    fun action_Test_Eth_Request_Accounts_Action() {\n        val expectedAction = Action(\n            method = \"eth_requestAccounts\",\n            paramsJson = \"{\\\"#wsegue_type\\\":\\\"eth_requestAccounts\\\"}\",\n            optional = false\n        )\n\n        val action = Web3JsonRPC.RequestAccounts().action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Personal_Sign_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"personal_sign.json\")\n        val personalSignJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = \"personal_sign\",\n            paramsJson = personalSignJson,\n            optional = false\n        )\n\n        val action = Web3JsonRPC.PersonalSign(\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", \"hello\").action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Sign_TypedData_V3_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"sign_typed_data_v3.json\")\n        val paramsJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = \"eth_signTypedData_v3\",\n            paramsJson = paramsJson.replace(\"DAppBrowserTestDApp\", \"DApp Browser Test DApp\"),\n            optional = false\n        )\n        val action = Web3JsonRPC.SignTypedDataV3(\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", typedData).action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Sign_TypedData_V4_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"sign_typed_data_v4.json\")\n        val paramsJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = \"eth_signTypedData_v4\",\n            paramsJson = paramsJson.replace(\"DAppBrowserTestDApp\", \"DApp Browser Test DApp\"),\n            optional = false\n        )\n\n        val action = Web3JsonRPC.SignTypedDataV4(\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", typedData).action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Sign_Transaction_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"sign_transaction.json\")\n        val paramsJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = ETH_SIGN_TRANSACTION,\n            paramsJson = paramsJson,\n            optional = false\n        )\n\n        val action = Web3JsonRPC.SignTransaction(\n            fromAddress = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            toAddress = \"0x571a6a108adb08f9ca54fe8605280f9ee0ed4af6\",\n            weiValue = \"10000000000000\",\n            data = \"0x\",\n            nonce = null,\n            gasPriceInWei = null,\n            maxFeePerGas = null,\n            maxPriorityFeePerGas = null,\n            gasLimit = \"1000\",\n            chainId = \"1\",\n        ).action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Send_Transaction_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"send_transaction.json\")\n        val paramsJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = ETH_SEND_TRANSACTION,\n            paramsJson = paramsJson,\n            optional = false\n        )\n\n        val action = Web3JsonRPC.SendTransaction(\n            fromAddress = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            toAddress = \"0x571a6a108adb08f9ca54fe8605280f9ee0ed4af6\",\n            weiValue = \"10000000000000\",\n            data = \"0x\",\n            nonce = null,\n            gasPriceInWei = null,\n            maxFeePerGas = null,\n            maxPriorityFeePerGas = null,\n            gasLimit = \"1000\",\n            chainId = \"1\",\n        ).action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Switch_Chain_Action() {\n        val expectedAction = Action(\n            method = WALLET_SWITCH_ETHEREUM_CHAIN,\n            paramsJson = \"{\\\"#wsegue_type\\\":\\\"wallet_switchEthereumChain\\\",\\\"chainId\\\":\\\"1\\\"}\",\n            optional = false\n        )\n\n        val action = Web3JsonRPC.SwitchEthereumChain(chainId = \"1\").action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Add_Chain_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"add_chain.json\")\n        val paramsJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = WALLET_ADD_ETHEREUM_CHAIN,\n            paramsJson = paramsJson,\n            optional = false\n        )\n\n        val action = Web3JsonRPC.AddEthereumChain(chainId = \"137\").action()\n        action shouldBe expectedAction\n    }\n\n    @Test\n    fun action_Test_Watch_Asset_Action() {\n        val inputStream = javaClass.classLoader?.getResourceAsStream(\"watch_asset.json\")\n        val paramsJson = inputStream.readFileWithNewLineFromResources()\n        val expectedAction = Action(\n            method = WALLET_WATCH_ASSET,\n            paramsJson = paramsJson,\n            optional = false\n        )\n\n        val action = Web3JsonRPC.WatchAsset(\n            type = \"type\",\n            options = WatchAssetOptions(\n                address = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n                symbol = \"APE\",\n                decimals = 3,\n                image = \"image_site\"\n            )\n        ).action()\n        action shouldBe expectedAction\n    }\n}\n"
  },
  {
    "path": "android/walletsdk/src/test/resources/add_chain.json",
    "content": "{\n  \"#wsegue_type\": \"wallet_addEthereumChain\",\n  \"chainId\": \"137\",\n  \"blockExplorerUrls\": null,\n  \"chainName\": null,\n  \"iconUrls\": null,\n  \"nativeCurrency\": null,\n  \"rpcUrls\": []\n}"
  },
  {
    "path": "android/walletsdk/src/test/resources/personal_sign.json",
    "content": "{\n  \"#wsegue_type\": \"personal_sign\",\n  \"address\": \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n  \"message\": \"hello\"\n}"
  },
  {
    "path": "android/walletsdk/src/test/resources/send_transaction.json",
    "content": "{\n  \"#wsegue_type\": \"eth_sendTransaction\",\n  \"fromAddress\": \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n  \"toAddress\": \"0x571a6a108adb08f9ca54fe8605280f9ee0ed4af6\",\n  \"weiValue\": \"10000000000000\",\n  \"data\": \"0x\",\n  \"nonce\": null,\n  \"gasPriceInWei\": null,\n  \"maxFeePerGas\": null,\n  \"maxPriorityFeePerGas\": null,\n  \"gasLimit\": \"1000\",\n  \"chainId\": \"1\"\n}"
  },
  {
    "path": "android/walletsdk/src/test/resources/sign_transaction.json",
    "content": "{\n  \"#wsegue_type\": \"eth_signTransaction\",\n  \"fromAddress\": \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n  \"toAddress\": \"0x571a6a108adb08f9ca54fe8605280f9ee0ed4af6\",\n  \"weiValue\": \"10000000000000\",\n  \"data\": \"0x\",\n  \"nonce\": null,\n  \"gasPriceInWei\": null,\n  \"maxFeePerGas\": null,\n  \"maxPriorityFeePerGas\": null,\n  \"gasLimit\": \"1000\",\n  \"chainId\": \"1\"\n}"
  },
  {
    "path": "android/walletsdk/src/test/resources/sign_typed_data_v3.json",
    "content": "{\n  \"#wsegue_type\": \"eth_signTypedData_v3\",\n  \"address\": \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n  \"typedDataJson\": \"{\\\"types\\\":{\\\"EIP712Domain\\\":[{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"version\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"chainId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"verifyingContract\\\",\\\"type\\\":\\\"address\\\"},{\\\"name\\\":\\\"salt\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"Bid\\\":[{\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"bidder\\\",\\\"type\\\":\\\"Identity\\\"}],\\\"Identity\\\":[{\\\"name\\\":\\\"userId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"wallet\\\",\\\"type\\\":\\\"address\\\"}]},\\\"domain\\\":{\\\"name\\\":\\\"DApp Browser Test DApp\\\",\\\"version\\\":\\\"1\\\",\\\"chainId\\\":1,\\\"verifyingContract\\\":\\\"0x1C56346CD2A2Bf3202F771f50d3D14a367B48070\\\",\\\"salt\\\":\\\"0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558\\\"},\\\"primaryType\\\":\\\"Bid\\\",\\\"message\\\":{\\\"amount\\\":100,\\\"bidder\\\":{\\\"userId\\\":323,\\\"wallet\\\":\\\"0x3333333333333333333333333333333333333333\\\"}}}\"\n}"
  },
  {
    "path": "android/walletsdk/src/test/resources/sign_typed_data_v4.json",
    "content": "{\n  \"#wsegue_type\": \"eth_signTypedData_v4\",\n  \"address\": \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n  \"typedDataJson\": \"{\\\"types\\\":{\\\"EIP712Domain\\\":[{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"version\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"chainId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"verifyingContract\\\",\\\"type\\\":\\\"address\\\"},{\\\"name\\\":\\\"salt\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"Bid\\\":[{\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"bidder\\\",\\\"type\\\":\\\"Identity\\\"}],\\\"Identity\\\":[{\\\"name\\\":\\\"userId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"name\\\":\\\"wallet\\\",\\\"type\\\":\\\"address\\\"}]},\\\"domain\\\":{\\\"name\\\":\\\"DApp Browser Test DApp\\\",\\\"version\\\":\\\"1\\\",\\\"chainId\\\":1,\\\"verifyingContract\\\":\\\"0x1C56346CD2A2Bf3202F771f50d3D14a367B48070\\\",\\\"salt\\\":\\\"0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558\\\"},\\\"primaryType\\\":\\\"Bid\\\",\\\"message\\\":{\\\"amount\\\":100,\\\"bidder\\\":{\\\"userId\\\":323,\\\"wallet\\\":\\\"0x3333333333333333333333333333333333333333\\\"}}}\"\n}"
  },
  {
    "path": "android/walletsdk/src/test/resources/watch_asset.json",
    "content": "{\n  \"#wsegue_type\": \"wallet_watchAsset\",\n  \"type\": \"type\",\n  \"options\": {\n    \"address\": \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n    \"symbol\": \"APE\",\n    \"decimals\": 3,\n    \"image\": \"image_site\"\n  }\n}"
  },
  {
    "path": "docs/.gitignore",
    "content": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "docs/babel.config.js",
    "content": "module.exports = {\n  presets: [require.resolve('@docusaurus/core/lib/babel/preset')],\n};\n"
  },
  {
    "path": "docs/docs/client-sdk/android-api-reference.md",
    "content": "---\ntitle: \"API Reference\"\nslug: \"android-api-reference\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\n# Actions\n\nThe `initiateHandshake` and `makeRequest` methods accept a list of actions to perform. An `Action` can be created using the `Web3JsonRPC` class.\n\nBelow is a list of supported actions for each method:\n\n| Action | RPC method | initiateHandshake | makeRequest |\n| :--- | :--- | :--- | :--- |\n| [RequestAccounts](doc:android-api-reference#requestaccounts) | [eth_requestAccounts](https://eips.ethereum.org/EIPS/eip-1102) | ✔️ Supported | ✔️ Supported |\n| [SignTransaction](doc:android-api-reference#signtransaction) | [eth_signTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction) | ❌ Not supported | ✔️ Supported |\n| [SendTransaction](doc:android-api-reference#sendtransaction) | [eth_sendTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction) | ❌ Not supported | ✔️ Supported |\n| - | [eth_sign](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign) | ❌ Not supported | ❌ Not supported |\n| [PersonalSign](doc:android-api-reference#personalsign) | [personal_sign](https://eips.ethereum.org/EIPS/eip-191) | ✔️ Supported | ✔️ Supported |\n| [SignTypedDataV3](doc:android-api-reference#signtypeddatav3) | [eth_signTypedData_v3](https://eips.ethereum.org/EIPS/eip-712) | ✔️ Supported | ✔️ Supported |\n| [SignTypedDataV4](doc:android-api-reference#signtypeddatav4) | [eth_signTypedData_v4](https://eips.ethereum.org/EIPS/eip-712) | ✔️ Supported | ✔️ Supported |\n| [SwitchEthereumChain](doc:android-api-reference#switchethereumchain) | [wallet_switchEthereumChain](https://eips.ethereum.org/EIPS/eip-3326) | ✔️ Supported | ✔️ Supported |\n| [AddEthereumChain](doc:android-api-reference#addethereumchain) | [wallet_addEthereumChain](https://eips.ethereum.org/EIPS/eip-3085) | ✔️ Supported | ✔️ Supported |\n| [WatchAsset](doc:android-api-reference#watchasset) | [wallet_watchAsset](https://eips.ethereum.org/EIPS/eip-747) | ✔️ Supported | ✔️ Supported |\n\n## RequestAccounts\n\nRequest that the user provides an account in the form of an Ethereum address.\n\n### Parameters\n\nNone.\n\n### Example\n\n```kotlin Kotlin\nval requestAccounts = Web3JsonRPC.RequestAccounts().action()\n```\n```java Java\nAction requestAccounts = new Web3JsonRPC.RequestAccounts().action(false);\n```\n\n## PersonalSign\n\nSign a message by calculating an Ethereum specific signature with: `sign(keccak256(\"\\x19Ethereum Signed Message:\\n\" + len(message) + message))`.\n\nAdding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.\n\nSee [personal_sign](https://eips.ethereum.org/EIPS/eip-191).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Address to sign data with. |\n| message | `String` | Message data to sign. |\n\n### Example\n\n```kotlin Kotlin\nval personalSign = Web3JsonRPC.PersonalSign(\n   address = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"\n   message = \"0xdeadbeaf\"\n).action()\n```\n```java Java\nAction personalSign = new Web3JsonRPC.PersonalSign(\n       \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n       \"0xdeadbeaf\")\n       .action(false);\n```\n\n## SignTypedDataV3\n\nSign typed structured data.\n\nSee [eth_signTypedData_v3](https://eips.ethereum.org/EIPS/eip-712).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Address to sign data with. |\n| typedDataJson | `String` | Typed data to sign. Structured according to the JSON-Schema specified in [EIP-712](https://eips.ethereum.org/EIPS/eip-712). |\n\n### Example\n\n```kotlin Kotlin\nval signTypedDataV3 = Web3JsonRPC.SignTypedDataV3(\n   address = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n   typedDataJson = typedData\n).action()\n```\n```java Java\nAction signTypedDataV3 = new Web3JsonRPC.SignTypedDataV3(\n       \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n       typedData)\n       .action(false);\n```\n\n## SignTypedDataV4\n\nSign typed structured data.\n\nSee [eth_signTypedData_v4](https://eips.ethereum.org/EIPS/eip-712).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Address to sign data with. |\n| typedDataJson | `String` | Typed data to sign. Structured according to the JSON-Schema specified in [EIP-712](https://eips.ethereum.org/EIPS/eip-712). |\n\n### Example\n\n```kotlin Kotlin\nval signTypedDataV4 = Web3JsonRPC.SignTypedDataV4(\n   address = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n   typedDataJson = typedData\n).action()\n```\n```java Java\nAction signTypedDataV4 = new Web3JsonRPC.SignTypedDataV4(\n       \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n       typedData)\n       .action(false);\n```\n\n## SignTransaction\n\nSign a transaction that can be submitted to the network at a later time.\n\nSee [eth_signTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| fromAddress | `String` | Address the transaction is sent from. |\n| toAddress | `String` | **Optional**. Address the transaction is sent to. |\n| weiValue | `BigInt` | Value for the transaction, in Wei. |\n| data | `String` | Compiled code of a contract or the hash of the invoked method signature and encoded parameters. |\n| nonce | `Int` | **Optional**. Nonce of the transaction. Allows for overwriting pending transactions that use an identical nonce. |\n| gasPriceInWei | `BigInt` | **Optional**. Gas price for the transaction, in Wei. |\n| maxFeePerGas | `BigInt` | **Optional**. Maximum fee per unit of gas for the transaction. |\n| maxPriorityFeePerGas | `BigInt` | **Optional**. Maximum priority fee per unit of gas for the transaction. |\n| gasLimit | `BigInt` | **Optional**. Gas limit for the transaction. |\n| chainId | `String` | Chain ID for the transaction, as an integer string. |\n\n### Example\n\n```kotlin Kotlin\nval signTransaction = Web3JsonRPC.SignTransaction(\n   fromAddress = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n   toAddress = \"0x000000000000000000000000000000000000dEaD\",\n   weiValue = \"10000000000000\",\n   data = \"0x\",\n   nonce = 1,\n   gasPriceInWei = \"30000000000\",\n   maxFeePerGas = \"60000000000\",\n   maxPriorityFeePerGas = \"2500000000\",\n   gasLimit = \"1000\",\n   chainId = \"1\"\n).action()\n```\n```java Java\nAction signTransaction = new Web3JsonRPC.SignTransaction(\n       \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", // fromAddress\n       \"0x000000000000000000000000000000000000dEaD\", // toAddress\n       \"10000000000000\", // weiValue\n       \"0x\", // data\n       1, // nonce\n       \"30000000000\", // gasPriceInWei\n       \"60000000000\", // maxFeePerGas\n       \"2500000000\", // maxPriorityFeePerGas\n       \"1000\", // gasLimit\n       \"1\") // chainId\n       .action(false);\n```\n\n## SendTransaction\n\nSend a transaction, or create a contract if the `data` field contains code.\n\nSee [eth_sendTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| fromAddress | `String` | Address the transaction is sent from. |\n| toAddress | `String` | **Optional**. Address the transaction is sent to. |\n| weiValue | `BigInt` | Value for the transaction, in Wei. |\n| data | `String` | Compiled code of a contract or the hash of the invoked method signature and encoded parameters. |\n| nonce | `Int` | **Optional**. Nonce of the transaction. Allows for overwriting pending transactions that use an identical nonce. |\n| gasPriceInWei | `BigInt` | **Optional**. Gas price for the transaction, in Wei. |\n| maxFeePerGas | `BigInt` | **Optional**. Maximum fee per unit of gas for the transaction. |\n| maxPriorityFeePerGas | `BigInt` | **Optional**. Maximum priority fee per unit of gas for the transaction. |\n| gasLimit | `BigInt` | **Optional**. Gas limit for the transaction. |\n| chainId | `String` | Chain ID for the transaction, as an integer string. |\n\n### Example\n\n```kotlin Kotlin\nval sendTransaction = Web3JsonRPC.SendTransaction(\n   fromAddress = \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n   toAddress = \"0x000000000000000000000000000000000000dEaD\",\n   weiValue = \"10000000000000\",\n   data = \"0x\",\n   nonce = 1,\n   gasPriceInWei = \"30000000000\",\n   maxFeePerGas = \"60000000000\",\n   maxPriorityFeePerGas = \"2500000000\",\n   gasLimit = \"1000\",\n   chainId = \"1\"\n).action()\n```\n```java Java\nAction sendTransaction = new Web3JsonRPC.SendTransaction(\n       \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", // fromAddress\n       \"0x000000000000000000000000000000000000dEaD\", // toAddress\n       \"10000000000000\", // weiValue\n       \"0x\", // data\n       1, // nonce\n       \"30000000000\", // gasPriceInWei\n       \"60000000000\", // maxFeePerGas\n       \"2500000000\", // maxPriorityFeePerGas\n       \"1000\", // gasLimit\n       \"1\") // chainId\n       .action(false);\n```\n\n## SwitchEthereumChain\n\nSwitch a wallet’s currently active chain.\n\nSee [wallet_switchEthereumChain](https://eips.ethereum.org/EIPS/eip-3326).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| chainId | `String` | ID of the chain to switch to, as an integer string. |\n\n### Example\n\n```kotlin Kotlin\nval switchEthereumChain = Web3JsonRPC.SwitchEthereumChain(\n   chainId = \"1666600000\"\n).action()\n```\n```java Java\nAction switchEthereumChain = new Web3JsonRPC.SwitchEthereumChain(\n       \"1666600000\") // chainId\n       .action(false);\n```\n\n## AddEthereumChain\n\nAdd a chain to a wallet.\n\nSee [wallet_addEthereumChain](https://eips.ethereum.org/EIPS/eip-3085).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| chainId | `String` | ID of the chain to add, as an integer string. |\n| blockExplorerUrls | `List<String>` | **Optional**. List of block explorer URL strings. |\n| chainName | `String` | **Optional**. Name of the chain to add. |\n| iconUrls | `List<String>` | **Optional**. List of image icons URL strings. |\n| nativeCurrency | [`AddChainNativeCurrency`](doc:android-api-reference#addchainnativecurrency) | **Optional**. Data for the chain’s native currency. |\n| rpcUrls | `List<String>` | List of RPC URL strings. Defaults to an empty list. |\n\n### Example\n\n```kotlin Kotlin\nval addEthereumChain = Web3JsonRPC.AddEthereumChain(\n   chainId = \"1666600000\",\n   blockExplorerUrls = listOf(\"https://explorer.harmony.one\"),\n   chainName = \"Harmony Mainnet\",\n   iconUrls = listOf(\"https://harmonynews.one/wp-content/uploads/2019/11/slfdjs.png\"),\n   nativeCurrency = AddChainNativeCurrency(\"ONE\", \"ONE\", 18)\n).action()\n```\n```java Java\nAction addEthereumChain = new Web3JsonRPC.AddEthereumChain(\n       \"1666600000\", // chainId\n       List.of(\"https://explorer.harmony.one\"), // blockExplorerUrls\n       \"Harmony Mainnet\", // chainName\n       List.of(\"https://harmonynews.one/wp-content/uploads/2019/11/slfdjs.png\"), // iconUrls\n       new AddChainNativeCurrency(\"ONE\", \"ONE\", 18)) // nativeCurrency\n       .action(false);\n```\n\n## WatchAsset\n\nAdd and track a new asset within a wallet.\n\nSee [wallet_watchAsset](https://eips.ethereum.org/EIPS/eip-747).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| type | `String` | Type of token asset. (i.e. `ERC20`, `ERC721`). |\n| options | [`WatchAssetOptions`](doc:android-api-reference#watchassetoptions) | Data of the asset to watch (i.e. contract address, name, icon, etc.) |\n\n### Example\n\n```kotlin Kotlin\nval watchAsset = Web3JsonRPC.WatchAsset(\n   type = \"ERC20\",\n   options = WatchAssetOptions(\n      \"0xcf664087a5bb0237a0bad6742852ec6c8d69a27a\",\n      \"WONE\",\n      18,\n      \"https://s2.coinmarketcap.com/static/img/coins/64x64/11696.png\"\n   )\n).action()\n```\n```java Java\nAction watchAsset = new Web3JsonRPC.WatchAsset(\n       \"ERC20\", // type\n       new WatchAssetOptions( // options\n               \"0xcf664087a5bb0237a0bad6742852ec6c8d69a27a\", // address\n               \"WONE\", // symbol\n               18, // decimals\n               \"https://s2.coinmarketcap.com/static/img/coins/64x64/11696.png\") // image\n       ).action(false);\n```\n\n# Types\n\n## AddChainNativeCurrency\n\nDefines a native currency to add when making a request to add a new Ethereum chain.\n\nSee [AddEthereumChain](doc:android-api-reference#addethereumchain).\n\n### Properties\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| name | `String` | Name of native currency for the chain. |\n| symbol | `String` | Symbol of native currency for the chain. |\n| decimals | `Int` | Decimals of precision, as an integer. |\n\n### Example\n\n```kotlin Kotlin\nval nativeCurrency = AddChainNativeCurrency(\"ONE\", \"ONE\", 18)\n```\n```java Java\nAddChainNativeCurrency nativeCurrency = new AddChainNativeCurrency(\"ONE\", \"ONE\", 18);\n```\n\n## WatchAssetOptions\n\nDefines options when making a request to watch a new asset.\n\nSee [WatchAsset](doc:android-api-reference#watchasset).\n\n### Properties\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Contract address for the token asset. |\n| symbol | `String` | **Optional**. Symbol for the token asset. |\n| decimals | `Int` | **Optional**. Decimals of precision, as an integer. |\n| image | `String` | **Optional**. Logo image for the token asset. |\n\n### Example\n\n```kotlin Kotlin\nval watchAssetOptions = WatchAssetOptions(\n      address = \"0xcf664087a5bb0237a0bad6742852ec6c8d69a27a\",\n      symbol = \"WONE\",\n      decimals = 18,\n      image = \"https://s2.coinmarketcap.com/static/img/coins/64x64/11696.png\"\n   )\n\n```\n```java Java\nWatchAssetOptions watchAssetOptions = new WatchAssetOptions(\n        \"0xcf664087a5bb0237a0bad6742852ec6c8d69a27a\", // address\n        \"WONE\", // symbol\n        18, // decimals\n        \"https://s2.coinmarketcap.com/static/img/coins/64x64/11696.png\") // image\n       );\n```\n"
  },
  {
    "path": "docs/docs/client-sdk/android-establishing-a-connection.md",
    "content": "---\ntitle: \"Establishing a connection\"\nslug: \"android-establishing-a-connection\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nA connection to Coinbase Wallet can be initiated by calling the `initiateHandshake` function provided by the SDK. The function also takes in an optional `initialActions` parameter which apps can use to take certain actions along with the initial handshake request.\n\n```kotlin Kotlin\nval requestAccount = Web3JsonRPC.RequestAccounts().action()\nval handShakeActions = listOf(requestAccount)\n\nclient.initiateHandshake(\n   initialActions = handShakeActions\n) { result: Result<List<ActionResult>>, account: Account? ->\n    result.onSuccess { actionResults: List<ActionResult> ->\n        actionResults.handleSuccess(\"Handshake\", handShakeActions, account)\n    }\n    result.onFailure { err ->\n        err.handleError(\"HandShake\")\n    }\n}\n```\n```java Java\n// requestAccounts request\nArrayList<Action> actions = new ArrayList<>();\nactions.add(\n   new Web3JsonRPC.RequestAccounts().action(false)\n);\n\n// Initiate handshake\nclient.initiateHandshake(\n   actions,\n   (results, account) -> {\n      for (ActionResult result : results) {\n         if (result instanceof ActionResult.Result) {\n            ((ActionResult.Result) result).getValue();\n         }\n\n         if (result instanceof ActionResult.Error) {\n            ((ActionResult.Error) result).getCode();\n            ((ActionResult.Error) result).getMessage();\n         }\n      }\n   },\n   error -> {\n   }\n);\n```\n\nAn example handshake request is provided in the [sample application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/android/example/src/main/java/com/coinbase/android/beta/MainActivity.kt#L52)."
  },
  {
    "path": "docs/docs/client-sdk/android-install.md",
    "content": "---\ntitle: \"Install\"\nslug: \"android-install\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nThe Coinbase Wallet Mobile SDK is available on [Maven Central](https://search.maven.org/artifact/com.coinbase/coinbase-wallet-sdk/0.1.0/aar).\n\n## Gradle\n\nAdd Coinbase Wallet SDK to your `build.gradle` file.\n\n```groovy\nrepositories {\n   mavenCentral()\n}\n\ndependencies {\n   implementation \"com.coinbase:coinbase-wallet-sdk:1.0.3\"\n}\n```\n\n## Maven\n\nAdd Coinbase Wallet SDK to your `pom.xml` file.\n\n```xml\n<dependency>\n\t<groupId>com.coinbase</groupId>\n\t<artifactId>coinbase-wallet-sdk</artifactId>\n\t<version>1.0.3</version>\n</dependency>\n```"
  },
  {
    "path": "docs/docs/client-sdk/android-making-requests.md",
    "content": "---\ntitle: \"Making requests\"\nslug: \"android-making-requests\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nRequests to Coinbase Wallet can be made by calling the `makeRequest` function provided by the SDK. This function also accepts a list of actions that can be taken in as a single batch request.\n\n```kotlin Kotlin\nval signTypedDataV3 = Web3JsonRPC.SignTypedDataV3(\n   \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\", // address\n   \"\" // typed data JSON\n).action()\nval requestActions = listOf(signTypedDataV3)\n\nclient.makeRequest(request = RequestContent.Request(actions = requestActions)) { result ->\n   result.fold(\n       onSuccess = { returnValues ->\n           returnValues.handleSuccess(\"Request\", requestActions)\n       },\n       onFailure = { err ->\n           err.handleError(\"Request\")\n       }\n   )\n}\n```"
  },
  {
    "path": "docs/docs/client-sdk/android-setup.md",
    "content": "---\ntitle: \"Setup\"\nslug: \"android-setup\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nIn order for your app to interact with Coinbase Wallet, you must add a [queries element](https://developer.android.com/guide/topics/manifest/queries-element) to your `AndroidManifest.xml` file, specifying the package name for Coinbase Wallet, `org.toshi`.\n\n```xml AndroidManifest.xml\n<queries>\n      <package android:name=\"org.toshi\" />\n</queries>\n```\n\nBefore the SDK can be used, it needs to be configured with an App Link to your application. This callback URL will be used by the Coinbase Wallet application to navigate back to your application.\n\n```kotlin Kotlin\nCoinbaseWalletSDK(\n    appContext = applicationContext,\n    domain = Uri.parse(\"https://www.myappxyz.com\"),\n    openIntent = { intent -> launcher.launch(intent) }\n)\n```\n```java Java\nnew CoinbaseWalletSDK(\n    Uri.parse(\"https://www.myappxyz.com\"),\n    getApplicationContext(),\n    CBW_PACKAGE_NAME,\n    intent -> {\n        startActivityForResult(intent, CBW_ACTIVITY_RESULT_CODE);\n    }\n);\n```\n\nWhen your application receives a response from Coinbase Wallet via App Links, this URL needs to be handed off to the SDK via the `handleResponse` function.\n\n```kotlin Kotlin\nlauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->\n   val uri = result.data?.data ?: return@registerForActivityResult\n   client.handleResponse(uri)\n}\n```\n```java Java\n@Override\nprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\n   super.onActivityResult(requestCode, resultCode, data);\n\n   if (requestCode != CBW_ACTIVITY_RESULT_CODE) {\n       return;\n   }\n\n   if (data == null) {\n       return;\n   }\n\n   Uri url = data.getData();\n   client.handleResponse(url);\n}\n```\n\nAn example is provided in our [sample application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/android/example/src/main/java/com/coinbase/android/beta/MainActivity.kt#L27)."
  },
  {
    "path": "docs/docs/client-sdk/ios-api-reference.md",
    "content": "---\ntitle: \"API Reference\"\nslug: \"ios-api-reference\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\n# Actions\n\nThe `initiateHandshake` and `makeRequest` methods accept a list of actions to perform. An `Action` can be created using the `Web3JsonRPC` class.\n\nBelow is a list of supported actions for each method:\n\n| Action | RPC method | initiateHandshake | makeRequest |\n| :--- | :--- | :--- | :--- |\n| [RequestAccounts](doc:ios-api-reference#requestaccounts) | [eth_requestAccounts](https://eips.ethereum.org/EIPS/eip-1102) | ✔️ Supported | ✔️ Supported |\n| [SignTransaction](doc:ios-api-reference#signtransaction) | [eth_signTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction) | ❌ Not supported | ✔️ Supported |\n| [SendTransaction](doc:ios-api-reference#sendtransaction) | [eth_sendTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction) | ❌ Not supported | ✔️ Supported |\n| - | [eth_sign](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign) | ❌ Not supported | ❌ Not supported |\n| [PersonalSign](doc:ios-api-reference#personalsign) | [personal_sign](https://eips.ethereum.org/EIPS/eip-191) | ✔️ Supported | ✔️ Supported |\n| [SignTypedDataV3](doc:ios-api-reference#signtypeddatav3) | [eth_signTypedData_v3](https://eips.ethereum.org/EIPS/eip-712) | ✔️ Supported | ✔️ Supported |\n| [SignTypedDataV4](doc:ios-api-reference#signtypeddatav4) | [eth_signTypedData_v4](https://eips.ethereum.org/EIPS/eip-712) | ✔️ Supported | ✔️ Supported |\n| [SwitchEthereumChain](doc:ios-api-reference#switchethereumchain) | [wallet_switchEthereumChain](https://eips.ethereum.org/EIPS/eip-3326) | ✔️ Supported | ✔️ Supported |\n| [AddEthereumChain](doc:ios-api-reference#addethereumchain) | [wallet_addEthereumChain](https://eips.ethereum.org/EIPS/eip-3085) | ✔️ Supported | ✔️ Supported |\n| [WatchAsset](doc:ios-api-reference#watchasset) | [wallet_watchAsset](https://eips.ethereum.org/EIPS/eip-747) | ✔️ Supported | ✔️ Supported |\n\n## RequestAccounts\n\nRequest that the user provides an account in the form of an Ethereum address.\n\n### Parameters\n\nNone.\n\n### Example\n\n```swift\nlet requestAccounts = Action(jsonRpc: .eth_requestAccounts)\n```\n\n## PersonalSign\n\nSign a message by calculating an Ethereum specific signature with: `sign(keccak256(\"\\x19Ethereum Signed Message:\\n\" + len(message) + message))`.\n\nAdding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.\n\nSee [personal_sign](https://eips.ethereum.org/EIPS/eip-191).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Address to sign data with. |\n| message | `String` | Message data to sign. |\n\n### Example\n\n```swift\nlet personalSign =\n      Action(jsonRpc: .personal_sign(\n            address: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            message: \"0xdeadbeaf\"))\n```\n\n## SignTypedDataV3\n\nSign typed structured data.\n\nSee [eth_signTypedData_v3](https://eips.ethereum.org/EIPS/eip-712).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Address to sign data with. |\n| typedDataJson | `String` | Typed data to sign. Structured according to the JSON-Schema specified in [EIP-712](https://eips.ethereum.org/EIPS/eip-712). |\n\n### Example\n\n```swift\nlet signTypedDataV3 =\n      Action(jsonRpc: .eth_signTypedData_v3(\n            address: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            typedDataJson: JSONString(encode: typedData)!))\n```\n\n## SignTypedDataV4\n\nSign typed structured data.\n\nSee [eth_signTypedData_v4](https://eips.ethereum.org/EIPS/eip-712).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Address to sign data with. |\n| typedDataJson | `String` | Typed data to sign. Structured according to the JSON-Schema specified in [EIP-712](https://eips.ethereum.org/EIPS/eip-712). |\n\n### Example\n\n```swift\nlet signTypedDataV4 =\n      Action(jsonRpc: .eth_signTypedData_v4(\n            address: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            typedDataJson: JSONString(encode: typedData)!))\n```\n\n## SignTransaction\n\nSign a transaction that can be submitted to the network at a later time.\n\nSee [eth_signTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| fromAddress | `String` | Address the transaction is sent from. |\n| toAddress | `String` | **Optional**. Address the transaction is sent to. |\n| weiValue | `BigInt` | Value for the transaction, in Wei. |\n| data | `String` | Compiled code of a contract or the hash of the invoked method signature and encoded parameters. |\n| nonce | `Int` | **Optional**. Nonce of the transaction. Allows for overwriting pending transactions that use an identical nonce. |\n| gasPriceInWei | `BigInt` | **Optional**. Gas price for the transaction, in Wei. |\n| maxFeePerGas | `BigInt` | **Optional**. Maximum fee per unit of gas for the transaction. |\n| maxPriorityFeePerGas | `BigInt` | **Optional**. Maximum priority fee per unit of gas for the transaction. |\n| gasLimit | `BigInt` | **Optional**. Gas limit for the transaction. |\n| chainId | `String` | Chain ID for the transaction, as an integer string. |\n\n### Example\n\n```swift\nlet signTransaction = \n      Action(jsonRpc: .eth_signTransaction(\n             fromAddress: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n             toAddress: \"0x000000000000000000000000000000000000dEaD\",\n             weiValue: \"10000000000000\",\n             data: \"0x\",\n             nonce: 1,\n             gasPriceInWei: \"30000000000\",\n             maxFeePerGas: \"60000000000\",\n             maxPriorityFeePerGas: \"2500000000\",\n             gasLimit: \"1000\",\n             chainId: \"1\"))\n```\n\n## SendTransaction\n\nSend a transaction, or create a contract if the `data` field contains code.\n\nSee [eth_sendTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| fromAddress | `String` | Address the transaction is sent from. |\n| toAddress | `String` | **Optional**. Address the transaction is sent to. |\n| weiValue | `BigInt` | Value for the transaction, in Wei. |\n| data | `String` | Compiled code of a contract or the hash of the invoked method signature and encoded parameters. |\n| nonce | `Int` | **Optional**. Nonce of the transaction. Allows for overwriting pending transactions that use an identical nonce. |\n| gasPriceInWei | `BigInt` | **Optional**. Gas price for the transaction, in Wei. |\n| maxFeePerGas | `BigInt` | **Optional**. Maximum fee per unit of gas for the transaction. |\n| maxPriorityFeePerGas | `BigInt` | **Optional**. Maximum priority fee per unit of gas for the transaction. |\n| gasLimit | `BigInt` | **Optional**. Gas limit for the transaction. |\n| chainId | `String` | Chain ID for the transaction, as an integer string. |\n\n### Example\n\n```swift\nlet sendTransaction = \n      Action(jsonRpc: .eth_sendTransaction(\n             fromAddress: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n             toAddress: \"0x000000000000000000000000000000000000dEaD\",\n             weiValue: \"10000000000000\",\n             data: \"0x\",\n             nonce: 1,\n             gasPriceInWei: \"30000000000\",\n             maxFeePerGas: \"60000000000\",\n             maxPriorityFeePerGas: \"2500000000\",\n             gasLimit: \"1000\",\n             chainId: \"1\"))\n```\n\n## SwitchEthereumChain\n\nSwitch a wallet’s currently active chain.\n\nSee [wallet_switchEthereumChain](https://eips.ethereum.org/EIPS/eip-3326).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| chainId | `String` | ID of the chain to switch to, as an integer string. |\n\n### Example\n\n```swift\nlet switchEthereumChain =\n      Action(jsonRpc: .wallet_switchEthereumChain(chainId: \"1666600000\"))\n```\n\n## AddEthereumChain\n\nAdd a chain to a wallet.\n\nSee [wallet_addEthereumChain](https://eips.ethereum.org/EIPS/eip-3085).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| chainId | `String` | ID of the chain to add, as an integer string. |\n| blockExplorerUrls | `List<String>` | **Optional**. List of block explorer URL strings. |\n| chainName | `String` | **Optional**. Name of the chain to add. |\n| iconUrls | `List<String>` | **Optional**. List of image icons URL strings. |\n| nativeCurrency | [`AddChainNativeCurrency`](doc:ios-api-reference#addchainnativecurrency) | **Optional**. Data for the chain’s native currency. |\n| rpcUrls | `List<String>` | List of RPC URL strings. Defaults to an empty list. |\n\n### Example\n\n```swift\nlet addEthereumChain = \n      Action(jsonRpc: .wallet_addEthereumChain(\n             chainId: \"1666600000\",\n              blockExplorerUrls: [\"https://explorer.harmony.one\"],\n              chainName: \"Harmony Mainnet\",\n              iconUrls: [\"https://harmonynews.one/wp-content/uploads/2019/11/slfdjs.png\"],\n              nativeCurrency: AddChainNativeCurrency(\n                    name: \"ONE\",\n                    symbol: \"ONE\",\n                    decimals: 18)\n             ))\n```\n\n## WatchAsset\n\nAdd and track a new asset within a wallet.\n\nSee [wallet_watchAsset](https://eips.ethereum.org/EIPS/eip-747).\n\n### Parameters\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| type | `String` | Type of token asset. (i.e. `ERC20`, `ERC721`). |\n| options | [`WatchAssetOptions`](doc:ios-api-reference#watchassetoptions) | Data of the asset to watch (i.e. contract address, name, icon, etc.) |\n\n### Example\n\n```swift\nlet watchAsset = \n      Action(jsonRpc: .wallet_watchAsset(\n             type: \"ERC20\",\n             options: WatchAssetOptions(\n                    address: \"0xcf664087a5bb0237a0bad6742852ec6c8d69a27a\",\n                    symbol: \"WONE\",\n                    decimals: 18,\n                    image: \"https://s2.coinmarketcap.com/static/img/coins/64x64/11696.png\")\n             ))\n```\n\n# Types\n\n## AddChainNativeCurrency\n\nDefines a native currency to add when making a request to add a new Ethereum chain.\n\nSee [AddEthereumChain](doc:ios-api-reference#addethereumchain).\n\n### Properties\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| name | `String` | Name of native currency for the chain. |\n| symbol | `String` | Symbol of native currency for the chain. |\n| decimals | `Int` | Decimals of precision, as an integer. |\n\n### Example\n\n```swift\nlet nativeCurrency =\n      AddChainNativeCurrency(name: \"ONE\", symbol: \"ONE\", decimals: 18)\n```\n\n## WatchAssetOptions\n\nDefines options when making a request to watch a new asset.\n\nSee [WatchAsset](doc:ios-api-reference#watchasset).\n\n### Properties\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| address | `String` | Contract address for the token asset. |\n| symbol | `String` | **Optional**. Symbol for the token asset. |\n| decimals | `Int` | **Optional**. Decimals of precision, as an integer. |\n| image | `String` | **Optional**. Logo image for the token asset. |\n\n### Example\n\n```swift\nlet watchAssetOptions = WatchAssetOptions(\n      address: \"0xcf664087a5bb0237a0bad6742852ec6c8d69a27a\",\n      symbol: \"WONE\",\n      decimals: 18,\n      image: \"https://s2.coinmarketcap.com/static/img/coins/64x64/11696.png\")\n```\n"
  },
  {
    "path": "docs/docs/client-sdk/ios-establishing-a-connection.md",
    "content": "---\ntitle: \"Establishing a connection\"\nslug: \"ios-establishing-a-connection\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nA connection to Coinbase Wallet can be initiated by calling the `initiateHandshake` function provided by the SDK. The function also takes in an optional `initialActions` parameter which apps can use to take certain actions along with the initial handshake request.\n\n```swift\nprivate let cbwallet = CoinbaseWalletSDK.shared\n\ncbwallet.initiateHandshake(\n    initialActions: [\n        Action(jsonRpc: .eth_requestAccounts)\n    ]\n) { result, account in\n    switch result {\n    case .success(let response):\n        self.logObject(label: \"Response:\\n\", response)\n\n        guard let account = account else { return }\n        self.logObject(label: \"Account:\\n\", account)\n        self.address = account.address\n    case .failure(let error):\n        self.log(\"\\(error)\")\n    }\n    self.updateSessionStatus()\n}\n```\n\nAn example handshake request is provided in our [sample application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/ios/example/SampleClient/ViewController.swift#L63)."
  },
  {
    "path": "docs/docs/client-sdk/ios-install.md",
    "content": "---\ntitle: \"Install\"\nslug: \"ios-install\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nThe Coinbase Wallet Mobile SDK is available on both [CocoaPods](https://cocoapods.org/) and [Swift Package Manager](https://swift.org/package-manager).\n\n## Cocoapods\n\nAdd Coinbase Wallet SDK to your `Podfile`.\n\n```ruby\nuse_frameworks!\n\ntarget 'YOUR_TARGET_NAME' do\n    pod 'CoinbaseWalletSDK', '1.0.3'\nend\n```\n\nReplace `YOUR_TARGET_NAME`, and then in the `Podfile` directory run:\n\n```bash\npod install\n```\n\n## Swift Package Manager\n\nAdd Coinbase Wallet SDK to your `Package.swift` file.\n\nUnder **File > Add packages…** enter the package url: [https://github.com/coinbase/wallet-mobile-sdk](https://github.com/coinbase/wallet-mobile-sdk)\n\n```swift\nimport PackageDescription\n\nlet package = Package(\n    name: \"YOUR_PROJECT_NAME\",\n    dependencies: [\n        .package(url: \"https://github.com/coinbase/wallet-mobile-sdk.git\", from: \"1.0.3\"),\n    ]\n)\n```\n\nReplace `YOUR_PROJECT_NAME`, and then run:\n\n```bash\nswift build\n```"
  },
  {
    "path": "docs/docs/client-sdk/ios-making-requests.md",
    "content": "---\ntitle: \"Making requests\"\nslug: \"ios-making-requests\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nRequests to Coinbase Wallet can be made by calling the `makeRequest` function provided by the SDK. This function also accepts a list of `actions` that can be taken in as a single batch request.\n\n```swift\ncbwallet.makeRequest(\n    Request(actions: [\n        Action(jsonRpc: .eth_signTypedData_v3(\n            address: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            message: Data()))\n    ])\n) { result in\n    self.log(\"\\(result)\")\n}\n```\n\nAn example request is provided in our [sample application](https://github.com/coinbase/coinbase-wallet-sdk/blob/master/examples/native-sdk-ios-client/SampleApp/ViewController.swift#L29)."
  },
  {
    "path": "docs/docs/client-sdk/ios-setup.md",
    "content": "---\ntitle: \"Setup\"\nslug: \"ios-setup\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\nCoinbase Wallet Mobile SDK uses [Universal Links](https://developer.apple.com/ios/universal-links/) to communicate between Coinbase Wallet and your application.\n\nBefore the SDK can be used, it needs to be configured with a Universal Link to your application. This callback URL will be used by the Coinbase Wallet application to navigate back to your application.\n\n```swift\nCoinbaseWalletSDK.configure(\n    callback: URL(string: \"https://myappxyz.com/mycallback\")!\n)\n```\n\nWhen your application receives a response from Coinbase Wallet via a Universal Link, this URL needs to be handed off to the SDK via the `handleResponse` function.\n\n```swift\nfunc application(_ app: UIApplication, open url: URL ...) -> Bool {\n    if (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n        return true\n    }\n    // handle other types of deep links\n    return false\n}\n```\n\nIt’s recommended to place this configuration logic in the AppDelegate as shown in this [example](https://github.com/coinbase/wallet-mobile-sdk/blob/master/ios/example/SampleClient/AppDelegate.swift#L19)."
  },
  {
    "path": "docs/docs/client-sdk/mobile-sdk-overview.md",
    "content": "---\ntitle: \"Overview\"\nslug: \"mobile-sdk-overview\"\ncategory: \"633d1d37bc7103008654c123\"\n---\n\n[Coinbase Wallet Mobile SDK](https://github.com/coinbase/wallet-mobile-sdk) is an open source SDK which allows you to connect your native mobile applications to millions of Coinbase Wallet users.\n\n## Platforms\n\nThe SDK is available for the following platforms:\n\n- [iOS](https://cocoapods.org/pods/CoinbaseWalletSDK)\n- [Android](https://mavenlibs.com/maven/dependency/com.coinbase/coinbase-wallet-sdk)\n\nWe also provide wrapper libraries and modules for [React Native](https://www.npmjs.com/package/@coinbase/wallet-mobile-sdk) and [Flutter](https://pub.dev/packages/coinbase_wallet_sdk) applications.\n\n## Features\n\n- **Easy**: Simplified and improved wallet integration for native mobile applications via deep-linking, without requiring a web application.\n- **Decentralized and reliable**: Doesn't depend on external services and relay servers for delivering messages and app-to-wallet communication. \n- **Secure**: Utilizes end-to-end encryption with secure key exchange and decentralized identity verification using the well-known URI standard for universal links.\n- **Efficient**: Reduces the number of hops between client applications and wallet via support for batch requests.\n- **Open-source**: All of the code for Coinbase Wallet Mobile SDK is open source and available on [GitHub](https://github.com/coinbase/wallet-mobile-sdk)."
  },
  {
    "path": "docs/docs/spec/batch.md",
    "content": "# Batch requests\n\nTo improve UX by minimizing app switches, \nMWP allows client apps to make requests with multiple actions at once. \nWallets should return results in a single response message as well.\nClient can specify whether each action is required or optional to customize the flow.\n\n## `Request` has `action`s\n- A `request` message contains an array of `action`s\n- Each `action` defines a single JSON RPC call with corresponding parameters in JSON format\n- `optional` boolean property to tell the host wallet to cancel the request if it fails to process non-optional action.\n\n### Example request message with three actions batched\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"AD6aqQNPr4/NRQymzqr14qjlnO9LN5JaEs/XEwEGTno=\",\n  \"content\": {\n    \"request\": {\n      \"actions\": [\n        {\n          \"paramsJson\": \"{\\\"chainId\\\":\\\"137\\\"}\",\n          \"method\": \"wallet_switchEthereumChain\",\n          \"optional\": false\n        },\n        {\n          \"paramsJson\": \"{\\\"address\\\":\\\"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\\\",\\\"message\\\":\\\"message\\\"}\",\n          \"method\": \"personal_sign\",\n          \"optional\": true\n        },\n        {\n          \"paramsJson\": \"{\\\"toAddress\\\":\\\"0\\\",\\\"fromAddress\\\":\\\"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\\\",\\\"chainId\\\":\\\"137\\\",\\\"weiValue\\\":\\\"0\\\",\\\"data\\\":\\\"\\\"}\",\n          \"method\": \"eth_sendTransaction\",\n          \"optional\": false\n        }\n      ]\n    }\n  },\n  \"timestamp\": 689616588.09238,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"84920218-ED92-4DF7-83BC-3CBFD1E5C7E3\"\n}\n```\n\n## `Response` has `value`s\n\n- A `response` message contains array of `value`s\n- `value` can be either\n    - `result`: JSON string\n    - `error`: error code and message\n\n### Example\n\ncoming soon\n"
  },
  {
    "path": "docs/docs/spec/encryption.md",
    "content": "# Encryption\n\nMWP uses deep links for direct communication between peers.\n\nTo ensure security, all messages in MWP after secure key exchange process are end-to-end encrypted.\n\n## Key generation\n\nBoth the client and the wallet generate their own key pair for each session via [Key-agreement protocol](https://en.wikipedia.org/wiki/Key-agreement_protocol) using [Elliptic-curve](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography).\n\nEach peer stores its private key in secure persistent storage\nand share its public key with the other party.\n\n## Key exchange to derive shared secret\n\nMWP uses [Diffie–Hellman key exchange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange) method to securely share cryptographic keys over deep links.\n\nThis method allows the two parties to derive the same shared secret offline using its own private key and the peer's public key.\n\n## Message `content` encryption\n\nAfter successful [handshake process](handshake) to exchange keys, subsequent messages ([`content` data](messages#content)) are encrypted with the common shared secret using a symmetric-key algorithm.\n\nIt uses [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)-[GCM](https://en.wikipedia.org/wiki/Galois/Counter_Mode) algorithm for cryptographic operations.\n\n### Example message after encryption\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"request\": {\n      \"data\": \"bgPGRoCBgH10b0IUhs8ZWRRPhFBGUlS3ESmB+xiGNb7n7oUdU9L9PGABmla/kCdnmES6iWXI7u5xzKm/CzPMGvlvlXLuRGlU4RjGJqbcQ55He3UcBXOgB0q489Vx2cx0fllrISuo87//kfcSolCWNSCHSBuSmojORG8YmO1L20724C8YKQrPxjmfWm5YyZxp/HyTnwX60eRJb819FZI4Zfc4RkTp4h+1A2lzBlERelr+MojfVBBBwxv4qQTAn7QRbUgoU+1CfblqcuB7bHUvfl+OwyZqIoxP68agkU9Na3aKDSM+oK6q9IBKG5X4Vz1+CBVchR5vggY+D7Omdaes6uDL443yV3uf8XHyv5ieWGgIS8bGgkdPvMrAtv78wdBr6iWLlh0pF7RyrPOWq/h8WiYerbAD9RFYhAxo1z3dymFgLamn/rf1LS+xu+sClKDrFx3DYkHEa/75CyQokBQiJFqO/sCTBLnXzV5I9bbjTTGuHi5tE/lKnsMsDz5tBpedavo9BT2bJNRUGh7yPMFybxV1hjyamlobBxyxik2GNjh09bINpZ4HVxe3mpmQWdg0NZiE5HG08HRHWooV+wQavMsWLqmOQtH30dy3+WMRSfURrrVdRXm0TZda6wCdU+sPbLPuvWucfdCTG62P8rGqklavjDQL8kkWAnsgMkCnAQJyoGqFHtGxjNd3rH5Pmkd7RC34fkEOsXxxKMzyOMlZjgr4a1MHO0URbrgA5k3IPdQ83Iq2GRpboshyHRyy27ClH6She9rQXUnbRI7WcGK/YCVu97rTxjWT8AzS8twI7egN6BhyricjMoUXNCewxWUBO4pp316mHtnPyktvFAZxF5Q/hbM2bcFQS2fdWooRUWlB405yv+magBC89GDbJHwBN73q3KTtYFVb5N7vDVIU71eGhL6ehve3NPcGxLKbRXWxWQnKNpIeWZ9W2mNWI5C6mbaasPbgGxW228OEs9FxjNmdA6XCScctgb8b31nM8xPOWeD+q33UIdNpQvkrZicPu7f5lGXGYibjsXnNWdO3tiOg6kuiHevt5Jqp35bO1Vn6y3UzZu6xwbUZQbE4NmR6j9BlGuNGS40Y91O/eCrFzSyayxPl6plRoekn2djBGHDyBZVwXfSKQef6gK9jV1RxQTjKbO6rDGR1hRgqWDvDeDLg03GBqwP93ZwqANK1jxpLOm0wbUycCl8grwAzTrZ0bJ68aUlT/Jmi3VAyV4QAwED8IZ0ipjLz7EmXkQWjuhChIiSwjkR6EEfctQhLK1+xvLsY796OSXG18qTAfjx2vgyGoxxrmEnufTIh4a9A+CTYQzNU137aRLXK/rN7Xs0d51xbis/FVm9ysgBNuWfxlOpVeahkvNSHzAM7Wn4WP/nlWp1yly/R/KrEE5iFi2dVxE9UMQFcbJ/xFDl+dj4hMJDFdCf1tyuP+ZCF6VSOjNUt6TCn2uXNTjIIJj2ZuH3O0YETcESMy+HwR8mmqn4DaFbbzRkZo7szOR3kGzKU8yk0fuW+McZtXfGd9YWG6wZEdMSV210jsmnDHklgHND87Zw0uZBdOWAYc6KzmTU1i2FxOEZaCjCGm9NDaVtgb1+gjrMUQN4KTuEWKaFpW74dZQymnfR9W/SYjH62DRLLEMDBV3xJDXl8fUgusnXMbLvf97fe/qZ7X1fgK70cWDJRTYSvziOC9knXQgOnr94bGaqWbzr7I2x6ODgTC6dczM9HJWOHjNvV8jouhgQIRldOaKA7ALLIEslhA6beJ/hnD2C2JpVwrcur/rCi2RZ5YOC3NKSvOv2sn4PG3++dpqHah1Zi4sdBKRxngSRCCcC1i123zmO3O4zSzI1i/Lo=\"\n    }\n  },\n  \"timestamp\": 689610765.957546,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"71BCE700-D717-4463-B4E4-4ECDCFC179A3\"\n}\n```\n\n### Example message before encryption (internal usage)\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"request\": {\n      \"actions\": [\n        {\n          \"paramsJson\": \"{\\\"address\\\":\\\"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\\\",\\\"message\\\":\\\"message\\\"}\",\n          \"method\": \"personal_sign\",\n          \"optional\": false\n        },\n        {\n          \"paramsJson\": \"{\\\"typedDataJson\\\":\\\"{\\\\\\\"types\\\\\\\":{\\\\\\\"Identity\\\\\\\":[{\\\\\\\"type\\\\\\\":\\\\\\\"uint256\\\\\\\",\\\\\\\"name\\\\\\\":\\\\\\\"userId\\\\\\\"},{\\\\\\\"type\\\\\\\":\\\\\\\"address\\\\\\\",\\\\\\\"name\\\\\\\":\\\\\\\"wallet\\\\\\\"}],\\\\\\\"Bid\\\\\\\":[{\\\\\\\"name\\\\\\\":\\\\\\\"amount\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"uint256\\\\\\\"},{\\\\\\\"name\\\\\\\":\\\\\\\"bidder\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"Identity\\\\\\\"}],\\\\\\\"EIP712Domain\\\\\\\":[{\\\\\\\"name\\\\\\\":\\\\\\\"name\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"string\\\\\\\"},{\\\\\\\"name\\\\\\\":\\\\\\\"version\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"string\\\\\\\"},{\\\\\\\"name\\\\\\\":\\\\\\\"chainId\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"uint256\\\\\\\"},{\\\\\\\"name\\\\\\\":\\\\\\\"verifyingContract\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"address\\\\\\\"},{\\\\\\\"type\\\\\\\":\\\\\\\"bytes32\\\\\\\",\\\\\\\"name\\\\\\\":\\\\\\\"salt\\\\\\\"}]},\\\\\\\"primaryType\\\\\\\":\\\\\\\"Bid\\\\\\\",\\\\\\\"message\\\\\\\":{\\\\\\\"bidder\\\\\\\":{\\\\\\\"userId\\\\\\\":323,\\\\\\\"wallet\\\\\\\":\\\\\\\"0x3333333333333333333333333333333333333333\\\\\\\"},\\\\\\\"amount\\\\\\\":100},\\\\\\\"domain\\\\\\\":{\\\\\\\"salt\\\\\\\":\\\\\\\"0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558\\\\\\\",\\\\\\\"name\\\\\\\":\\\\\\\"DApp Browser Test DApp\\\\\\\",\\\\\\\"chainId\\\\\\\":1,\\\\\\\"version\\\\\\\":\\\\\\\"1\\\\\\\",\\\\\\\"verifyingContract\\\\\\\":\\\\\\\"0x1C56346CD2A2Bf3202F771f50d3D14a367B48070\\\\\\\"}}\\\",\\\"address\\\":\\\"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\\\"}\",\n          \"method\": \"eth_signTypedData_v3\",\n          \"optional\": false\n        }\n      ]\n    }\n  },\n  \"timestamp\": 689610765.957546,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"71BCE700-D717-4463-B4E4-4ECDCFC179A3\"\n}\n```\n\n## Messages without encryption\n\nHowever, there are two exceptions where the content data are not encrypted:\n1. Handshake calls from the client in order to exchange keys with the wallet\n2. Failure responses from wallet to return errors happening during the handshake processes\n\n### Example handshake request message\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"handshake\": {\n      \"appId\": \"com.coinbase.SampleClient\",\n      \"callback\": \"myappxyz://mycallback/wsegue\",\n      \"initialActions\": [\n        {\n          \"paramsJson\": \"{}\",\n          \"method\": \"eth_requestAccounts\",\n          \"optional\": false\n        }\n      ]\n    }\n  },\n  \"timestamp\": 689587969.289106,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"451711FA-96B6-4955-B6EA-EFA78CEB89F5\"\n}\n```\n\n### Example failure response message\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"failure\": {\n      \"requestId\": \"B78F510E-DD5C-4477-8350-7550FAC7452E\",\n      \"description\": \"Request denied\"\n    }\n  },\n  \"timestamp\": 689611333.369556,\n  \"uuid\": \"E485820B-8F5E-4F8C-9A00-CE5B5B9C6F35\"\n}\n```\n\n## Implementation\n\nCoinbase's SDK is built with \n[Apple CryptoKit](https://developer.apple.com/documentation/cryptokit/) for iOS, \n[Google Tink](https://github.com/google/tink) and [androidx.security](https://developer.android.com/jetpack/androidx/releases/security) for Android.\n\n![](img/diffie-hellman.png)\n> source: https://commons.wikimedia.org/wiki/File:Public_key_shared_secret.svg\n"
  },
  {
    "path": "docs/docs/spec/handshake.md",
    "content": "# Handshake\n\nFor key exchange, client apps make `handshake` calls to ask wallets to generate and share a key to encrypt subsequent messages on the session.\n\n## Handshake request message from client\n\n`content` of a handshake message contains following:\n\n### `appId`\nBundle ID (iOS) or application/package ID (Android). \ne.g. \"com.coinbase.SampleClient\"\n\n### `callback`\nSender's URL to receive response from receiver.\nFor the best security measure, [universal links](https://developer.apple.com/ios/universal-links/) (or [app links](https://developer.android.com/training/app-links)) are recommended.\n\n### `initialActions`\n(optional) Actions to request after successful handshake process.\ne.g. `eth_requestAccounts` to get user's eth account info along with the handshake response\n\n### Example request message\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"handshake\": {\n      \"appId\": \"com.coinbase.SampleClient\",\n      \"callback\": \"myappxyz://mycallback/wsegue\",\n      \"initialActions\": [\n        {\n          \"paramsJson\": \"{}\",\n          \"method\": \"eth_requestAccounts\",\n          \"optional\": false\n        }\n      ]\n    }\n  },\n  \"timestamp\": 689587969.289106,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"451711FA-96B6-4955-B6EA-EFA78CEB89F5\"\n}\n```\n\n## Response from wallet\n\nOnce the host wallet [verifies the client app](verification) and gets approval from the user,\nit generates a key pair for the session and shares it with the caller.\n\n### Example response message (success)\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"EnX8x2D6lHzTg8YZCLybHPwivbCBRyFlP8aA235+MBg=\",\n  \"content\": {\n    \"response\": {\n      \"requestId\": \"5A920962-ECBE-42BC-A956-83A56F0D52F8\",\n      \"values\": [\n        {\n          \"result\": {\n            \"value\": \"{\\\"chain\\\":\\\"eth\\\",\\\"networkId\\\":1,\\\"address\\\":\\\"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\\\"}\"\n          }\n        }\n      ]\n    }\n  },\n  \"timestamp\": 689615011.030334,\n  \"uuid\": \"7446663A-685A-47E5-89E3-C1D37F085330\"\n}\n```\n\n### Example response message (failure)\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"failure\": {\n      \"requestId\": \"B78F510E-DD5C-4477-8350-7550FAC7452E\",\n      \"description\": \"Request denied\"\n    }\n  },\n  \"timestamp\": 689611333.369556,\n  \"uuid\": \"E485820B-8F5E-4F8C-9A00-CE5B5B9C6F35\"\n}\n```\n"
  },
  {
    "path": "docs/docs/spec/messages-example.md",
    "content": "# Example\n\n### handshake\n- URL\n`https://go.cb-w.com/wsegue?p=eyJ2ZXJzaW9uIjoiMS4wLjMiLCJzZW5kZXIiOiJsRUNcL1gzSzY4cmxnT29sZE1kazBENzc3MzhZN1cwbURiTU1WNVI2VnlDRT0iLCJjb250ZW50Ijp7ImhhbmRzaGFrZSI6eyJhcHBJZCI6ImNvbS5jb2luYmFzZS5TYW1wbGVDbGllbnQiLCJjYWxsYmFjayI6Im15YXBweHl6OlwvXC9teWNhbGxiYWNrXC93c2VndWUiLCJpbml0aWFsQWN0aW9ucyI6W3sicGFyYW1zSnNvbiI6Int9IiwibWV0aG9kIjoiZXRoX3JlcXVlc3RBY2NvdW50cyIsIm9wdGlvbmFsIjpmYWxzZX1dfX0sInRpbWVzdGFtcCI6MTY2Nzg5NTE2OTI4OS4xMDYsImNhbGxiYWNrVXJsIjoibXlhcHB4eXo6XC9cL215Y2FsbGJhY2tcL3dzZWd1ZSIsInV1aWQiOiI0NTE3MTFGQS05NkI2LTQ5NTUtQjZFQS1FRkE3OENFQjg5RjUifQ%3D%3D`\n- JSON (decoded the URL above. handshake messages are not encrypted)\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"handshake\": {\n      \"appId\": \"com.coinbase.SampleClient\",\n      \"callback\": \"myappxyz://mycallback/wsegue\",\n      \"initialActions\": [\n        {\n          \"paramsJson\": \"{}\",\n          \"method\": \"eth_requestAccounts\",\n          \"optional\": false\n        }\n      ]\n    }\n  },\n  \"timestamp\": 689587969.289106,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"451711FA-96B6-4955-B6EA-EFA78CEB89F5\"\n}\n```\n\n### request\n- URL\n`https://go.cb-w.com/wsegue?p=eyJ2ZXJzaW9uIjoiMS4yLjMiLCJzZW5kZXIiOiJmbW5IZVh3OTNlY000QnFzSXpRTk5zb2FvS0ZxK3NOMHZRaWdvaVNQZ2dvPSIsImNvbnRlbnQiOnsicmVxdWVzdCI6eyJfMCI6IkdQYUwwTWJjbVhoVWU5eUprY0p5dnRJWVJUM3RXNEhcL1lBUmNKTXZGZlZWOWh6OXcya1h3YmxIMEJPcFN2UXI0RVhoV0FVUlwvZGFwWUVMZ2lvTkFXY3IxVlwvY1JoNDVUaFN2SFV1cHRlY0lJR0tLeGxKTWdwZ2RiMWNJRWhNWEdpVElBYkZTblJTOVlwOFowOHJcL3pkcjlBVytFQjRXSXBLcnhTTmVqQXRRTDJWTDByRWE2YzhvM0lodG5DQ1U1SzRpaVVZcTJkamd0eGRJZm1FbmhrTUFCQVwvSm5INFpBPT0ifX0sInV1aWQiOiJEMzg3MUYwRS03QkNFLTQxMjYtQjY1Ny05QjlGOEQ1NEU3N0YifQ%3D%3D`\n- encrypted JSON (decoded from the URL above)\n```json\n{\n  \"version\": \"1.2.3\",\n  \"sender\": \"oEC2AZndVwTcLs3ixQyxThlHrKBNdBczbWp9OjeglGY=\",\n  \"content\": {\n    \"request\": {\n      \"data\": \"/LzMCiGCpiYuUHp2vdlQM4V+f7hYygKI2qhX/ZWuFA6/aqZ/bmnWhROK14vtBH3sbrROqfefMXue3rbqLOg1s+xzh6iXoVavhIeCSevugp1ZlERG9q+CSuLXyRR3tou6wdsJ60jOTDjGzLCvcHp2ykglfDUr2qaVRo3i/RXsJRoPrW9CurSM9+TmNZ46aq1Y/K8lBcpq1aFUYSn7+kHHR8xBY+QoPE0yox+dZrvSi7Z16fX3uwZ3NQPmhPqQXpDFEHrZeKEzoIZAPA8NUlrajgY/1mxhbkH9tmM8X5vSG7w=\"\n    }\n  },\n  \"uuid\": \"3E445386-8CB3-4995-99EC-DCF06A60081C\"\n}\n```\n- decrypted JSON (to pass via RN - native bridge)\n```json\n{\n  \"version\": \"1.2.3\",\n  \"sender\": \"qSAE/fvQ1cnZvVnKDjiHRyzK6bVQ/qJ7W29DL2aMjns=\",\n  \"content\": {\n    \"request\": {\n      \"actions\": [\n        {\n          \"paramsJson\" : \"{}\",\n          \"method\" : \"eth_requestAccounts\",\n          \"optional\" : false\n        },\n        {\n          \"paramsJson\" : \"{\\\"fromAddress\\\":\\\"\\\",\\\"data\\\":\\\"bWVzc2FnZQ==\\\"}\",\n          \"method\" : \"personal_sign\",\n          \"optional\" : false\n        }\n      ],\n      \"account\": {\n        \"chain\": \"eth\",\n        \"networkId\": 17,\n        \"address\": \"0x12345678ABCD\"\n      }\n    }\n  },\n  \"uuid\": \"853BFBB5-A6F1-4FBA-B8C6-DC2BE3CCF6DF\"\n}\n```\n\n### response\n- plain response JSON (to pass via RN - native bridge)\n```json\n{\n  \"version\": \"7.13.1\",\n  \"sender\": \"u9IB3p8tN8P4U2LvYfaCphd8/bXRN34eTnuQPO4g6zQ=\",\n  \"content\": {\n    \"response\": {\n      \"requestId\": \"9D34C731-397B-473B-9850-C6F0261BC085\",\n      \"values\": [\n        {\n          \"result\": {\n            \"value\": \"return value 1\"\n          }\n        },\n        {\n          \"result\": {\n            \"value\": \"return value 2\"\n          }\n        },\n        {\n          \"error\": {\n            \"message\": \"error 1\",\n            \"code\": 1\n          }\n        },\n        {\n          \"error\": {\n            \"message\": \"error 2\",\n            \"code\": 2\n          }\n        }\n      ]\n    }\n  },\n  \"uuid\": \"C5CDDCF7-7A31-4185-BB6B-7A3B8F9B19BA\"\n}\n```\n- encrypted JSON (encrypted the JSON object above)\n```json\n{\n  \"version\": \"7.13.1\",\n  \"sender\": \"u9IB3p8tN8P4U2LvYfaCphd8/bXRN34eTnuQPO4g6zQ=\",\n  \"content\": {\n    \"response\": {\n      \"requestId\": \"9D34C731-397B-473B-9850-C6F0261BC085\",\n      \"data\": \"uXqgB78alErYBFXie8gP397igJ18dx+mcQcUV7K44W+96OQxNxJGm3WxEgsGMxeS8Wg1wiiRaXYRghFbwlnJuOLNpIvAiQYMOzJ1IAlFg452hwG7PrCCn6e9/xU5Hc+kzZYio355zSxSuXByo1bItCgNdjp5aocX1kUnZceV7dGjIGv66/z1k93hxGYooH0uCeI2wQ7qaZzJKfUJLgO0NFmj1fbTciv7CoVd8/mQAfHzlgaIhkHB+j4mAw==\"\n    }\n  },\n  \"uuid\": \"C5CDDCF7-7A31-4185-BB6B-7A3B8F9B19BA\"\n}\n```\n- URL\n`https://myapp.xyz/native-sdk?p=eyJ2ZXJzaW9uIjoiNy4xMy4xIiwic2VuZGVyIjoidTlJQjNwOHROOFA0VTJMdllmYUNwaGQ4XC9iWFJOMzRlVG51UVBPNGc2elE9IiwiY29udGVudCI6eyJyZXNwb25zZSI6eyJyZXF1ZXN0SWQiOiI5RDM0QzczMS0zOTdCLTQ3M0ItOTg1MC1DNkYwMjYxQkMwODUiLCJkYXRhIjoidVhxZ0I3OGFsRXJZQkZYaWU4Z1AzOTdpZ0oxOGR4K21jUWNVVjdLNDRXKzk2T1F4TnhKR20zV3hFZ3NHTXhlUzhXZzF3aWlSYVhZUmdoRmJ3bG5KdU9MTnBJdkFpUVlNT3pKMUlBbEZnNDUyaHdHN1ByQ0NuNmU5XC94VTVIYytrelpZaW8zNTV6U3hTdVhCeW8xYkl0Q2dOZGpwNWFvY1gxa1VuWmNlVjdkR2pJR3Y2NlwvejFrOTNoeEdZb29IMHVDZUkyd1E3cWFaekpLZlVKTGdPME5GbWoxZmJUY2l2N0NvVmQ4XC9tUUFmSHpsZ2FJaGtIQitqNG1Bdz09In19LCJ1dWlkIjoiQzVDRERDRjctN0EzMS00MTg1LUJCNkItN0EzQjhGOUIxOUJBIn0%3D`\n\n### error\n- JSON (error messages are not encrypted)\n```json\n{\n  \"version\": \"7.13.1\",\n  \"sender\": \"OzXg53x+wwIW1YCEbvP3sya7MmZT5yCQcArK3GbLmDo=\",\n  \"content\": {\n    \"failure\": {\n      \"requestId\": \"6C7706C2-B17F-4E96-8D52-C6876C09AECB\",\n      \"description\": \"error message from host\"\n    }\n  },\n  \"uuid\": \"C6900BD5-25EE-46F4-AB01-EBB8FAB1AC76\"\n}\n```\n- URL\n`https://myapp.xyz/native-sdk?p=eyJ2ZXJzaW9uIjoiNy4xMy4xIiwic2VuZGVyIjoiT3pYZzUzeCt3d0lXMVlDRWJ2UDNzeWE3TW1aVDV5Q1FjQXJLM0diTG1Ebz0iLCJjb250ZW50Ijp7ImZhaWx1cmUiOnsicmVxdWVzdElkIjoiNkM3NzA2QzItQjE3Ri00RTk2LThENTItQzY4NzZDMDlBRUNCIiwiZGVzY3JpcHRpb24iOiJlcnJvciBtZXNzYWdlIGZyb20gaG9zdCJ9fSwidXVpZCI6IkM2OTAwQkQ1LTI1RUUtNDZGNC1BQjAxLUVCQjhGQUIxQUM3NiJ9`\n"
  },
  {
    "path": "docs/docs/spec/messages-request.md",
    "content": "# Request content\n\nRequest message has `request` as its `content`, which contains following:\n\n## Properties\n\n### `actions`\nArray of actions. More details on [batch requests](batch).\n\n### `account`\nOptional property to specify the chain, network id, and/or address to run the `action`s. More details on [multi-chain](multi-chain).\n\n## Example\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"AD6aqQNPr4/NRQymzqr14qjlnO9LN5JaEs/XEwEGTno=\",\n  \"content\": {\n    \"request\": {\n      \"actions\": [\n        {\n          \"paramsJson\": \"{\\\"message\\\":\\\"message\\\",\\\"address\\\":\\\"\\\"}\",\n          \"method\": \"personal_sign\",\n          \"optional\": true\n        }\n      ],\n      \"account\": {\n        \"chain\": \"eth\",\n        \"networkId\": 137,\n        \"address\": \"\"\n      }\n    }\n  },\n  \"timestamp\": 689618032.540427,\n  \"callbackUrl\": \"myappxyz://mycallback/wsegue\",\n  \"uuid\": \"B454B12D-516D-4CDF-979F-B3B50C956DFC\"\n}\n```"
  },
  {
    "path": "docs/docs/spec/messages-response.md",
    "content": "# Response content\n\nResponse content can be either `response` or `failure`.\n\n## `response`\n\nAs long as the host wallet can derive a valid shared secret to decrypt the request from the sender and encrypt the response from itself, \nthe return message has `response` as its `content`.\n\nThe data of `response` content are encrypted. More details on [encryption](encryption).\n\n### Properties\n\n#### `requestId`\nID of the corresponding request\n\n#### `values`\nArray of `value`s. More details on [batch requests](batch).\n\n`Value` can be either:\n- `result` of JSON string type\n- `error` with `code` and `message`\n\n### Example\n\ncoming soon\n\n\n## `failure`\n\nIf the wallet fails to derive a valid shared secret, it returns a unencrypted failure message with following properties:\n\n### Properties\n\n#### `requestId`\nID of the corresponding request\n\n#### `description`\nError description\n\n### Example failure response message\n```json\n{\n  \"version\": \"1.0.3\",\n  \"sender\": \"lEC/X3K68rlgOoldMdk0D77738Y7W0mDbMMV5R6VyCE=\",\n  \"content\": {\n    \"failure\": {\n      \"requestId\": \"B78F510E-DD5C-4477-8350-7550FAC7452E\",\n      \"description\": \"Request denied\"\n    }\n  },\n  \"timestamp\": 689611333.369556,\n  \"uuid\": \"E485820B-8F5E-4F8C-9A00-CE5B5B9C6F35\"\n}\n```"
  },
  {
    "path": "docs/docs/spec/messages.md",
    "content": "# Messages\n\nCommunications between client and server (wallet host) in MWP are through exchanging discrete stateless messages.\n\nThe messages sent by the client app are called requests and the ones returned by the wallet host are called responses.\n\n## Forms\n\nMWP messages can be transformed between two forms according to their use cases.\n\n### Data form \n\nJSON object or corresponding data type in the language in use (e.g. Swift `struct`, Kotlin `data class`, or JavaScript object) for internal usage within the app\n\n```json\n{\n  \"uuid\" : \"634A5C15-0316-4FD1-86FB-4818DBD6C12D\",\n  \"sender\" : \"bwf9U+VbjmvfBr3p3aoJyOEKS6mq7sSrg56V6FDYMBs=\",\n  \"content\" : {...},\n  \"version\" : \"1.0.0\",\n  \"timestamp\" : \"1667475279\"\n}\n```\n\n### URL form\n\nDeep link URL specifying recipient's address and base64 encoded [JSON object](#data-form) as query parameter to send the data to other party\n\n`https://wallet.coinbase.com/wsegue?p=eyJ2ZXJzaW...U2RTMyQiJ9`\n\n\n## Properties\n\n### `uuid`\nUnique id of the message\n\n### `sender` \nPublic key of the sender in base64 encoded string\n\n### `content`\n[Message's content](encryption#message-encryption) which might be encrypted by the sender using the derived shared secret\n\n### `timestamp`\nUNIX millisecond timestamp\n\n### `version`\nVersion of the protocol used by the sender\n\n### `callback`\n(Optional) sender's callback URL\n"
  },
  {
    "path": "docs/docs/spec/multi-chain.md",
    "content": "# Multi-chain support\n\nMWP is chain-agnostic. \nAs long as the wallet supports the chain and is able to process the requested actions, apps can communicate using MWP.\n\n## `Account`\n\nMWP defines a dedicated type to specify `account`s.\nIt contains `chain` and `networkId` along with `address`.\n\n### `chain`\ne.g. `\"eth\"`\n\n### `networkId`\ne.g. `1`\n\n### `address`\ne.g. `\"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\"`\n\n\n## `Request` message with `account`\n\nSee [request content properties](messages-request#account).\n\n"
  },
  {
    "path": "docs/docs/spec/network.md",
    "content": "# Transport layer\n\nDeep linking through universal links on iOS.\nIntent + app links on android.\n"
  },
  {
    "path": "docs/docs/spec/verification.md",
    "content": "# Verification\n\nDecentralized verification of participating apps’ authenticity using [.well-known](https://en.wikipedia.org/wiki/Well-known_URI) data without centralized registry\n- [apple-app-site-association](https://developer.apple.com/documentation/xcode/supporting-associated-domains) \n- [assetlinks.json](https://developer.android.com/training/app-links/verify-site-associations )\n\n3rd party client apps make requests to the wallet through universal links, whose authenticity is verified by the OS.\n- Wallet sends responses through universal links as well.\n- Application ID passed by caller should match the information on their domain.\n\nMWP host wallets load metadata from the iOS App Store / Android package manager with the client app's `appId`.\n\n![](img/handshake.png)\n"
  },
  {
    "path": "docs/docs/spec-overview.md",
    "content": "---\ntitle: \"Overview\"\nslug: \"spec\"\n---\n\n# Overview\n\n## Mobile Wallet Protocol\n\n![](spec/img/overview.png)\n\nMWP is a protocol to allow mobile web3 apps to interact with wallet apps and access users' web3 accounts. \nIt creates a direct channel between client and wallet apps, removing the need for an intermediary bridge or relay server. \n\n- Simple: The messages sent by the client app are called requests and the ones returned by the wallet host are called responses.\n- Direct: The protocol uses deep links as its transport layer to let participating apps deliver messages directly to their peer without external entities such as a bridge server.\n- Secure: It provides an encrypted P2P communication channel between client and server (wallet host) to exchange discrete stateless messages.\n- Efficient: Reduces the number of hops between client applications and wallet via support for batch requests.\n- Decentralized and reliable: It defines a decentralized verification procedure to check authenticity of each other using well-known URI standard for univeral link without a centralized registry.\n"
  },
  {
    "path": "docs/docusaurus.config.js",
    "content": "// @ts-check\n// Note: type annotations allow type checking and IDEs autocompletion\n\nconst lightCodeTheme = require('prism-react-renderer/themes/github');\nconst darkCodeTheme = require('prism-react-renderer/themes/dracula');\n\n/** @type {import('@docusaurus/types').Config} */\nconst config = {\n  title: 'Mobile Wallet Protocol',\n  tagline: 'An open protocol for mobile web3 apps to interact with wallets',\n  url: 'https://coinbase.github.io',\n  baseUrl: '/wallet-mobile-sdk/',\n  onBrokenLinks: 'throw',\n  onBrokenMarkdownLinks: 'warn',\n  favicon: 'img/favicon.ico',\n\n  // GitHub pages deployment config.\n  // If you aren't using GitHub pages, you don't need these.\n  organizationName: 'coinbase', // Usually your GitHub org/user name.\n  projectName: 'wallet-mobile-sdk', // Usually your repo name.\n\n  // Even if you don't use internalization, you can use this field to set useful\n  // metadata like html lang. For example, if your site is Chinese, you may want\n  // to replace \"en\" with \"zh-Hans\".\n  i18n: {\n    defaultLocale: 'en',\n    locales: ['en'],\n  },\n\n  presets: [\n    [\n      'classic',\n      /** @type {import('@docusaurus/preset-classic').Options} */\n      ({\n        docs: {\n          sidebarPath: require.resolve('./sidebars.js'),\n          // // Please change this to your repo.\n          // // Remove this to remove the \"edit this page\" links.\n          // editUrl:\n          //   'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',\n        },\n        theme: {\n          customCss: require.resolve('./src/css/custom.css'),\n        },\n      }),\n    ],\n  ],\n\n  themeConfig:\n    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n    ({\n      navbar: {\n        title: 'Mobile Wallet Protocol',\n        logo: {\n          alt: 'My Site Logo',\n          src: 'img/logo.svg',\n        },\n        items: [\n          {\n            type: 'doc',\n            docId: 'spec-overview',\n            position: 'left',\n            label: 'Spec',\n          },\n          {\n            type: 'doc',\n            docId: 'client-sdk/mobile-sdk-overview',\n            position: 'left',\n            label: 'Client SDK',\n          },\n          {\n            href: 'https://github.com/coinbase/wallet-mobile-sdk',\n            label: 'GitHub',\n            position: 'right',\n          },\n        ],\n      },\n      footer: {\n        style: 'dark',\n        links: [\n          {\n            title: 'Docs',\n            items: [\n              {\n                label: 'Spec',\n                to: '/docs/spec',\n              },\n            ],\n          },\n          {\n            title: 'Community',\n            items: [\n              {\n                label: 'Stack Overflow',\n                href: 'https://stackoverflow.com/questions/tagged/coinbase-wallet-sdk',\n              },\n              {\n                label: 'Twitter',\n                href: 'https://twitter.com/CoinbaseWallet',\n              },\n            ],\n          },\n          {\n            title: 'More',\n            items: [\n              {\n                label: 'GitHub',\n                href: 'https://github.com/coinbase/wallet-mobile-sdk',\n              },\n            ],\n          },\n        ],\n        copyright: `Copyright © ${new Date().getFullYear()} Coinbase, Inc. Built with Docusaurus.`,\n      },\n      prism: {\n        theme: lightCodeTheme,\n        darkTheme: darkCodeTheme,\n      },\n    }),\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"mobile-wallet-protocol\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"start\": \"docusaurus start\",\n    \"build\": \"docusaurus build\",\n    \"swizzle\": \"docusaurus swizzle\",\n    \"deploy\": \"docusaurus deploy\",\n    \"clear\": \"docusaurus clear\",\n    \"serve\": \"docusaurus serve\",\n    \"write-translations\": \"docusaurus write-translations\",\n    \"write-heading-ids\": \"docusaurus write-heading-ids\",\n    \"typecheck\": \"tsc\"\n  },\n  \"dependencies\": {\n    \"@docusaurus/core\": \"2.2.0\",\n    \"@docusaurus/preset-classic\": \"2.2.0\",\n    \"@mdx-js/react\": \"^1.6.22\",\n    \"clsx\": \"^1.2.1\",\n    \"prism-react-renderer\": \"^1.3.5\",\n    \"react\": \"^17.0.2\",\n    \"react-dom\": \"^17.0.2\"\n  },\n  \"devDependencies\": {\n    \"@docusaurus/module-type-aliases\": \"2.2.0\",\n    \"@tsconfig/docusaurus\": \"^1.0.5\",\n    \"typescript\": \"^4.7.4\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.5%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=16.14\"\n  }\n}\n"
  },
  {
    "path": "docs/sidebars.js",
    "content": "/**\n * Creating a sidebar enables you to:\n - create an ordered group of docs\n - render a sidebar for each doc of that group\n - provide next/previous navigation\n\n The sidebars can be generated from the filesystem, or explicitly defined here.\n\n Create as many sidebars as you want.\n */\n\n// @ts-check\n\n/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */\nconst sidebars = {\n  spec: [\n    'spec-overview',\n    {\n      type: 'category',\n      label: 'Messages',\n      link: {\n        type: 'doc',\n        id: 'spec/messages',\n      },\n      items: [\n        'spec/messages-request',\n        'spec/messages-response'\n      ]\n    },\n    'spec/batch',\n    'spec/encryption',\n    'spec/handshake',\n    'spec/verification',\n    'spec/multi-chain',\n    'spec/network',\n  ],\n  clientSdk: [\n    \"client-sdk/mobile-sdk-overview\",\n    {\n      type: \"category\",\n      label: \"iOS\",\n      items: [\n        \"client-sdk/ios-install\",\n        \"client-sdk/ios-setup\",\n        \"client-sdk/ios-establishing-a-connection\",\n        \"client-sdk/ios-making-requests\",\n        \"client-sdk/ios-api-reference\"\n      ]\n    },\n    {\n      type: \"category\",\n      label: \"Android\",\n      items: [\n        \"client-sdk/android-install\",\n        \"client-sdk/android-setup\",\n        \"client-sdk/android-establishing-a-connection\",\n        \"client-sdk/android-making-requests\",\n        \"client-sdk/android-api-reference\"\n      ]\n    }\n  ],\n  \n};\n\nmodule.exports = sidebars;\n"
  },
  {
    "path": "docs/spec.md",
    "content": "---\nlayout: page\ntitle: \"Spec\"\npermalink: /spec\n---\n\n# Mobile Wallet Protocol (MWP)\n\nMWP is a protocol to allow mobile web3 apps to interact with wallet apps and access users' web3 accounts. \n"
  },
  {
    "path": "docs/src/components/HomepageFeatures/index.tsx",
    "content": "import React from 'react';\nimport clsx from 'clsx';\nimport styles from './styles.module.css';\n\ntype FeatureItem = {\n  title: string;\n  description: JSX.Element;\n};\n\nconst FeatureList: FeatureItem[] = [\n  {\n    title: 'Easy',\n    description: (\n      <>\n        Simplified and improved wallet integration for native mobile applications \n        via deep-linking, without requiring a web application.\n      </>\n    ),\n  },\n  {\n    title: 'Efficient',\n    description: (\n      <>\n        Reduces the number of hops between client applications \n        and wallet via support for batch requests.\n      </>\n    ),\n  },\n  {\n    title: 'Decentralized and reliable',\n    description: (\n      <>\n        Doesn't depend on external services and relay servers \n        for delivering messages and app-to-wallet communication. \n      </>\n    ),\n  },\n  {\n    title: 'Secure',\n    description: (\n      <>\n        Utilizes end-to-end encryption with secure key exchange \n        and decentralized identity verification using \n        the well-known URI standard for universal links.\n      </>\n    ),\n  },\n];\n\nfunction Feature({title, description}: FeatureItem) {\n  return (\n    <div className={clsx('col col--3')}>\n      <div className=\"text--center padding-horiz--md\">\n        <h3>{title}</h3>\n        <p>{description}</p>\n      </div>\n    </div>\n  );\n}\n\nexport default function HomepageFeatures(): JSX.Element {\n  return (\n    <section className={styles.features}>\n      <div className=\"container\">\n        <div className=\"row\">\n          {FeatureList.map((props, idx) => (\n            <Feature key={idx} {...props} />\n          ))}\n        </div>\n      </div>\n    </section>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/HomepageFeatures/styles.module.css",
    "content": ".features {\n  display: flex;\n  align-items: center;\n  padding: 2rem 0;\n  width: 100%;\n}\n\n.featureSvg {\n  height: 200px;\n  width: 200px;\n}\n"
  },
  {
    "path": "docs/src/css/custom.css",
    "content": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framework designed to\n * work well for content-centric websites.\n */\n\n/* You can override the default Infima variables here. */\n:root {\n  --ifm-color-primary: #1B53E4;\n  --ifm-color-primary-dark: #29784c;\n  --ifm-color-primary-darker: #277148;\n  --ifm-color-primary-darkest: #205d3b;\n  --ifm-color-primary-light: #33925d;\n  --ifm-color-primary-lighter: #359962;\n  --ifm-color-primary-lightest: #3cad6e;\n  --ifm-code-font-size: 95%;\n  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);\n}\n\n/* For readability concerns, you should choose a lighter palette in dark mode. */\n[data-theme='dark'] {\n  --ifm-color-primary: #1B53E4;\n  --ifm-color-primary-dark: #21af90;\n  --ifm-color-primary-darker: #1fa588;\n  --ifm-color-primary-darkest: #1a8870;\n  --ifm-color-primary-light: #29d5b0;\n  --ifm-color-primary-lighter: #32d8b4;\n  --ifm-color-primary-lightest: #4fddbf;\n  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);\n}\n"
  },
  {
    "path": "docs/src/pages/index.module.css",
    "content": "/**\n * CSS files with the .module.css suffix will be treated as CSS modules\n * and scoped locally.\n */\n\n.heroBanner {\n  padding: 4rem 0;\n  text-align: center;\n  position: relative;\n  overflow: hidden;\n  color: #e3e3e3;\n}\n\n@media screen and (max-width: 996px) {\n  .heroBanner {\n    padding: 2rem;\n  }\n}\n\n.buttons {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n"
  },
  {
    "path": "docs/src/pages/index.tsx",
    "content": "import React from 'react';\nimport clsx from 'clsx';\nimport Link from '@docusaurus/Link';\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport Layout from '@theme/Layout';\nimport HomepageFeatures from '@site/src/components/HomepageFeatures';\n\nimport styles from './index.module.css';\n\nfunction HomepageHeader() {\n  const {siteConfig} = useDocusaurusContext();\n  return (\n    <header className={clsx('hero hero--primary', styles.heroBanner)}>\n      <div className=\"container\">\n        <h1 className=\"hero__title\">{siteConfig.title}</h1>\n        <p className=\"hero__subtitle\">{siteConfig.tagline}</p>\n        <div className={styles.buttons}>\n          <Link\n            className=\"button button--secondary button--lg\"\n            to=\"/docs/spec\">\n            Protocol Specification\n          </Link>\n        </div>\n      </div>\n    </header>\n  );\n}\n\nexport default function Home(): JSX.Element {\n  const {siteConfig} = useDocusaurusContext();\n  return (\n    <Layout\n      title=\"\"\n      description=\"\">\n      <HomepageHeader />\n      <main>\n        <HomepageFeatures />\n      </main>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "docs/static/.nojekyll",
    "content": ""
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n  // This file is not used in compilation. It is here just for a nice editor experience.\n  \"extends\": \"@tsconfig/docusaurus/tsconfig.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\"\n  }\n}\n"
  },
  {
    "path": "flutter/.gitignore",
    "content": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\nmigrate_working_dir/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.iws\n.idea/\n\n# The .vscode folder contains launch configuration and tasks you configure in\n# VS Code which you may wish to be included in version control, so this line\n# is commented out by default.\n#.vscode/\n\n# Flutter/Dart/Pub related\n# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.\n/pubspec.lock\n**/doc/api/\n.dart_tool/\n.packages\nbuild/\n"
  },
  {
    "path": "flutter/.metadata",
    "content": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrades etc.\n#\n# This file should be version controlled.\n\nversion:\n  revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n  channel: stable\n\nproject_type: plugin\n\n# Tracks metadata for the flutter migrate command\nmigration:\n  platforms:\n    - platform: root\n      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n    - platform: android\n      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n    - platform: ios\n      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1\n\n  # User provided section\n\n  # List of Local paths (relative to this file) that should be\n  # ignored by the migrate tool.\n  #\n  # Files that are not part of the templates will be ignored by default.\n  unmanaged_files:\n    - 'lib/main.dart'\n    - 'ios/Runner.xcodeproj/project.pbxproj'\n"
  },
  {
    "path": "flutter/.pubignore",
    "content": "example\ntest\n"
  },
  {
    "path": "flutter/.vscode/settings.json",
    "content": "{\n  \"workbench.colorTheme\": \"Solarized Light\"\n}"
  },
  {
    "path": "flutter/CHANGELOG.md",
    "content": "## 1.0.0\n\n- iOS/Android Flutter support\n"
  },
  {
    "path": "flutter/README.md",
    "content": "# coinbase_wallet_sdk\n\nA flutter wrapper for CoinbaseWallet mobile SDK\n\nNote: This wrapper only supports iOS and Android.\n\n## Getting Started\n\n```dart\n  import 'package:coinbase_wallet_sdk/coinbase_wallet_sdk.dart';\n\n  // Configure SDK for each platform\n  await CoinbaseWalletSDK.shared.configure(\n    Configuration(\n      ios: IOSConfiguration(\n        host: Uri.parse('https://wallet.coinbase.com/wsegue'),\n        callback: Uri.parse('tribesxyz://mycallback'),\n      ),\n      android: AndroidConfiguration(\n        domain: Uri.parse('https://www.myappxyz.com'),\n      ),\n    ),\n  );\n```\n\n### iOS only\n\n```swift\n    override func application(\n      _ app: UIApplication,\n      open url: URL,\n      options: [UIApplication.OpenURLOptionsKey : Any] = [:]\n    ) -> Bool {\n        if (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n            return true\n        }\n        // handle other types of deep links\n        return false\n    }\n\n    override func application(\n      _ application: UIApplication,\n      continue userActivity: NSUserActivity,\n      restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void\n    ) -> Bool {\n        if let url = userActivity.webpageURL,\n           (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n            return true\n        }\n        // handle other types of deep links\n        return false\n    }\n```\n\n## Usage\n\n```dart\n  // To call web3's eth_requestAccounts\n  final response = await CoinbaseWalletSDK.shared.initiateHandshake([\n    const RequestAccounts(),\n  ]);\n\n  final walletAddress = response[0].value;\n\n  // to call web3's personalSign\n  final response = await CoinbaseWalletSDK.shared.makeRequest(\n    Request(\n      actions: [\n        PersonalSign(address: address.value, message: message),\n      ],\n    ),\n  );\n\n  final signature = response[0].value;\n```\n"
  },
  {
    "path": "flutter/analysis_options.yaml",
    "content": "include: package:flutter_lints/flutter.yaml\n\n# Additional information about this file can be found at\n# https://dart.dev/guides/language/analysis-options\n"
  },
  {
    "path": "flutter/android/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.cxx\n"
  },
  {
    "path": "flutter/android/build.gradle",
    "content": "group 'com.coinbase.coinbase_wallet_sdk'\nversion '1.0-SNAPSHOT'\n\nbuildscript {\n    ext.kotlin_version = '1.6.10'\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:7.1.2'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\nrootProject.allprojects {\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\napply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 31\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n\n    sourceSets {\n        main.java.srcDirs += 'src/main/kotlin'\n    }\n\n    defaultConfig {\n        minSdkVersion 23\n        consumerProguardFiles \"consumer-rules.pro\"\n        proguardFiles \"proguard-rules.pro\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n        }\n    }\n}\n\ndependencies {\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n    implementation \"com.coinbase:coinbase-wallet-sdk:1.0.4\"\n    implementation \"org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3\"\n}\n"
  },
  {
    "path": "flutter/android/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionUrl=https\\://services.gradle.org/distributions/gradle-7.4-all.zip"
  },
  {
    "path": "flutter/android/settings.gradle",
    "content": "rootProject.name = 'coinbase_wallet_sdk'\n"
  },
  {
    "path": "flutter/android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  package=\"com.coinbase.flutter.wallet_sdk\">\n</manifest>\n"
  },
  {
    "path": "flutter/android/src/main/kotlin/com/coinbase/flutter/wallet_sdk/CoinbaseWalletSdkFlutterPlugin.kt",
    "content": "package com.coinbase.flutter.wallet_sdk\n\nimport android.content.Context\nimport android.content.Intent\nimport android.net.Uri\nimport androidx.annotation.NonNull\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDK\nimport com.coinbase.android.nativesdk.message.request.Account\nimport com.coinbase.android.nativesdk.message.request.Action\nimport com.coinbase.android.nativesdk.message.request.RequestContent\nimport com.coinbase.android.nativesdk.message.response.ActionResult\nimport com.coinbase.android.nativesdk.message.response.ResponseResult\nimport io.flutter.embedding.engine.plugins.FlutterPlugin\nimport io.flutter.embedding.engine.plugins.activity.ActivityAware\nimport io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding\nimport io.flutter.plugin.common.MethodCall\nimport io.flutter.plugin.common.MethodChannel\nimport io.flutter.plugin.common.MethodChannel.MethodCallHandler\nimport io.flutter.plugin.common.MethodChannel.Result\nimport io.flutter.plugin.common.PluginRegistry\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport kotlinx.serialization.json.JsonPrimitive\nimport kotlinx.serialization.json.buildJsonObject\nimport kotlinx.serialization.json.encodeToJsonElement\n\n/** CoinbaseWalletSdkFlutterPlugin */\nclass CoinbaseWalletSdkFlutterPlugin : FlutterPlugin, MethodCallHandler,\n    ActivityAware, PluginRegistry.ActivityResultListener {\n    /// The MethodChannel that will the communication between Flutter and native Android\n    ///\n    /// This local reference serves to register the plugin with the Flutter Engine and unregister it\n    /// when the Flutter Engine is detached from the Activity\n    private lateinit var channel: MethodChannel\n\n    private lateinit var coinbase: CoinbaseWalletSDK\n\n    private lateinit var flutterApplicationContext: Context\n\n    private var act: android.app.Activity? = null\n\n    private val successJson = \"{ \\\"success\\\": true}\"\n\n    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {\n        flutterApplicationContext = flutterPluginBinding.applicationContext\n        coinbase = CoinbaseWalletSDK(\n            appContext = flutterPluginBinding.applicationContext,\n            // TODO: This should be changed, and passed in from client\n            domain = Uri.parse(\"https://www.coinbase.com\"),\n            openIntent = { intent -> act?.startActivityForResult(intent, 0) }\n        )\n        coinbase.appendVersionTag(\"flutter\")\n        channel = MethodChannel(flutterPluginBinding.binaryMessenger, \"coinbase_wallet_sdk\")\n        channel.setMethodCallHandler(this)\n    }\n\n    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {\n        try {\n            if (call.method == \"configure\") {\n                return configure(call, result)\n            }\n\n            if (call.method == \"initiateHandshake\") {\n                return initiateHandshake(call, result)\n            }\n\n            if (call.method == \"makeRequest\") {\n                return makeRequest(call, result)\n            }\n\n            if (call.method == \"resetSession\") {\n                return resetSession(result)\n            }\n\n            if (call.method == \"isAppInstalled\") {\n                return isAppInstalled(result)\n            }\n        } catch (e: Throwable) {\n            result.error(\"onMethodCall\", e.message, null)\n        }\n\n        result.notImplemented()\n    }\n\n    private fun isAppInstalled(@NonNull result: Result) {\n        result.success(coinbase.isCoinbaseWalletInstalled)\n    }\n\n    private fun configure(@NonNull call: MethodCall, @NonNull result: Result) {\n        val args = call.arguments\n        if (args !is Map<*, *>) {\n            return result.error(\"configure\", \"Missing arguments\", null)\n        }\n\n        val domain = args[\"domain\"] as String\n        coinbase = CoinbaseWalletSDK(\n            appContext = flutterApplicationContext,\n            domain = Uri.parse(domain),\n            openIntent = { intent -> act?.startActivityForResult(intent, 0) }\n        )\n\n        result.success(successJson)\n    }\n\n    private fun initiateHandshake(@NonNull call: MethodCall, @NonNull result: Result) {\n        val jsonString = call.arguments\n        if (jsonString !is String) {\n            return result.error(\"initiateHandshake\", \"Missing args\", null)\n        }\n\n        val actions = Json.decodeFromString<List<Action>>(jsonString)\n        coinbase.initiateHandshake(initialActions = actions) { responseResult, account ->\n            handleResponse(\"initiateHandshake\", responseResult, account, result)\n        }\n    }\n\n    private fun makeRequest(@NonNull call: MethodCall, @NonNull result: Result) {\n        val jsonString = call.arguments\n        if (jsonString !is String) {\n            return result.error(\"makeRequest\", \"Missing args\", null)\n        }\n\n        val request = Json.decodeFromString<RequestContent.Request>(jsonString)\n        coinbase.makeRequest(request) { responseResult ->\n            handleResponse(\"makeRequest\", responseResult, null, result)\n        }\n    }\n\n    private fun resetSession(@NonNull result: Result) {\n        coinbase.resetSession()\n        result.success(successJson)\n    }\n\n    private fun handleResponse(\n        code: String,\n        responseResult: ResponseResult,\n        account: Account?,\n        result: Result\n    ) {\n        if (responseResult.isFailure) {\n            return result.error(code, responseResult.exceptionOrNull()?.message, null)\n        }\n\n        val returnValues = responseResult.getOrNull() ?: emptyList()\n        val toFlutter = returnValues.map { actionResult ->\n            buildJsonObject {\n                if (account != null) {\n                    val accountJson = Json.encodeToJsonElement(account)\n                    put(\"account\", accountJson)\n                }\n\n                when (actionResult) {\n                    is ActionResult.Result -> {\n                        put(\"result\", JsonPrimitive(actionResult.value))\n                    }\n                    is ActionResult.Error -> {\n                        val errorJson = Json.encodeToJsonElement(actionResult)\n                        put(\"error\", errorJson)\n                    }\n                }\n            }\n        }\n\n        val jsonString = Json.encodeToString(toFlutter)\n        result.success(jsonString)\n    }\n\n    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {\n        channel.setMethodCallHandler(null)\n    }\n\n    override fun onAttachedToActivity(binding: ActivityPluginBinding) {\n        act = binding.activity\n        binding.addActivityResultListener(this)\n    }\n\n    override fun onDetachedFromActivityForConfigChanges() {\n        act = null\n    }\n\n    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {\n        // no-op\n    }\n\n    override fun onDetachedFromActivity() {\n        // no-op\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {\n        val uri = data?.data ?: return false\n        return coinbase.handleResponse(uri)\n    }\n}\n"
  },
  {
    "path": "flutter/example/.gitignore",
    "content": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\nmigrate_working_dir/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.iws\n.idea/\n\n# The .vscode folder contains launch configuration and tasks you configure in\n# VS Code which you may wish to be included in version control, so this line\n# is commented out by default.\n#.vscode/\n\n# Flutter/Dart/Pub related\n**/doc/api/\n**/ios/Flutter/.last_build_id\n.dart_tool/\n.flutter-plugins\n.flutter-plugins-dependencies\n.packages\n.pub-cache/\n.pub/\n/build/\n\n# Web related\nlib/generated_plugin_registrant.dart\n\n# Symbolication related\napp.*.symbols\n\n# Obfuscation related\napp.*.map.json\n\n# Android Studio will place build artifacts here\n/android/app/debug\n/android/app/profile\n/android/app/release\n"
  },
  {
    "path": "flutter/example/README.md",
    "content": "# coinbase_wallet_sdk_example\n\nDemonstrates how to use the coinbase_wallet_sdk plugin.\n\n## Getting Started\n\nThis project is a starting point for a Flutter application.\n\nA few resources to get you started if this is your first Flutter project:\n\n- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)\n- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)\n\nFor help getting started with Flutter development, view the\n[online documentation](https://docs.flutter.dev/), which offers tutorials,\nsamples, guidance on mobile development, and a full API reference.\n"
  },
  {
    "path": "flutter/example/analysis_options.yaml",
    "content": "# This file configures the analyzer, which statically analyzes Dart code to\n# check for errors, warnings, and lints.\n#\n# The issues identified by the analyzer are surfaced in the UI of Dart-enabled\n# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be\n# invoked from the command line by running `flutter analyze`.\n\n# The following line activates a set of recommended lints for Flutter apps,\n# packages, and plugins designed to encourage good coding practices.\ninclude: package:flutter_lints/flutter.yaml\n\nlinter:\n  # The lint rules applied to this project can be customized in the\n  # section below to disable rules from the `package:flutter_lints/flutter.yaml`\n  # included above or to enable additional rules. A list of all available lints\n  # and their documentation is published at\n  # https://dart-lang.github.io/linter/lints/index.html.\n  #\n  # Instead of disabling a lint rule for the entire project in the\n  # section below, it can also be suppressed for a single line of code\n  # or a specific dart file by using the `// ignore: name_of_lint` and\n  # `// ignore_for_file: name_of_lint` syntax on the line or in the file\n  # producing the lint.\n  rules:\n    # avoid_print: false  # Uncomment to disable the `avoid_print` rule\n    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule\n\n# Additional information about this file can be found at\n# https://dart.dev/guides/language/analysis-options\n"
  },
  {
    "path": "flutter/example/android/.gitignore",
    "content": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n\n# Remember to never publicly share your keystore.\n# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app\nkey.properties\n**/*.keystore\n**/*.jks\n"
  },
  {
    "path": "flutter/example/android/app/build.gradle",
    "content": "def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertiesFile.exists()) {\n    localPropertiesFile.withReader('UTF-8') { reader ->\n        localProperties.load(reader)\n    }\n}\n\ndef flutterRoot = localProperties.getProperty('flutter.sdk')\nif (flutterRoot == null) {\n    throw new GradleException(\"Flutter SDK not found. Define location with flutter.sdk in the local.properties file.\")\n}\n\ndef flutterVersionCode = localProperties.getProperty('flutter.versionCode')\nif (flutterVersionCode == null) {\n    flutterVersionCode = '1'\n}\n\ndef flutterVersionName = localProperties.getProperty('flutter.versionName')\nif (flutterVersionName == null) {\n    flutterVersionName = '1.0'\n}\n\napply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply from: \"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle\"\n\nandroid {\n    compileSdkVersion flutter.compileSdkVersion\n    ndkVersion flutter.ndkVersion\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n\n    sourceSets {\n        main.java.srcDirs += 'src/main/kotlin'\n    }\n\n    defaultConfig {\n        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).\n        applicationId \"xyz.tribes.coinbase.coinbase_wallet_sdk_example\"\n        // You can update the following values to match your application needs.\n        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.\n        minSdkVersion 23 // flutter.minSdkVersion\n        targetSdkVersion 32 // flutter.targetSdkVersion\n        versionCode flutterVersionCode.toInteger()\n        versionName flutterVersionName\n    }\n\n    buildTypes {\n        release {\n            // TODO: Add your own signing config for the release build.\n            // Signing with the debug keys for now, so `flutter run --release` works.\n            signingConfig signingConfigs.debug\n        }\n    }\n}\n\nflutter {\n    source '../..'\n}\n\ndependencies {\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n    implementation 'androidx.core:core-ktx:1.8.0'\n    implementation 'androidx.appcompat:appcompat:1.4.2'\n    implementation 'com.google.android.material:material:1.6.1'\n    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'\n    testImplementation 'junit:junit:4.13.2'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.3'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'\n    implementation \"com.coinbase:coinbase-wallet-sdk:1.0.1\"\n}\n"
  },
  {
    "path": "flutter/example/android/app/src/debug/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"xyz.tribes.coinbase.coinbase_wallet_sdk_example\">\n    <!-- The INTERNET permission is required for development. Specifically,\n         the Flutter tool needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "flutter/example/android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"xyz.tribes.coinbase.coinbase_wallet_sdk_example\">\n   <application\n        android:label=\"coinbase_wallet_sdk_example\"\n        android:name=\"${applicationName}\"\n        android:icon=\"@mipmap/ic_launcher\">\n        <activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style/LaunchTheme\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode\"\n            android:hardwareAccelerated=\"true\"\n            android:windowSoftInputMode=\"adjustResize\">\n            <!-- Specifies an Android theme to apply to this Activity as soon as\n                 the Android process has started. This theme is visible to the user\n                 while the Flutter UI initializes. After that, this theme continues\n                 to determine the Window background behind the Flutter UI. -->\n            <meta-data\n              android:name=\"io.flutter.embedding.android.NormalTheme\"\n              android:resource=\"@style/NormalTheme\"\n              />\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n        <!-- Don't delete the meta-data below.\n             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->\n        <meta-data\n            android:name=\"flutterEmbedding\"\n            android:value=\"2\" />\n    </application>\n\n    <queries>\n        <package android:name=\"org.toshi\" />\n        <package android:name=\"org.toshi.alpha\" />\n    </queries>\n\n</manifest>\n"
  },
  {
    "path": "flutter/example/android/app/src/main/kotlin/xyz/tribes/coinbase/coinbase_wallet_sdk_flutter_example/MainActivity.kt",
    "content": "package xyz.tribes.coinbase.coinbase_wallet_sdk_example\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDK\nimport io.flutter.embedding.android.FlutterActivity\nimport androidx.activity.result.ActivityResultLauncher\n\nclass MainActivity: FlutterActivity() {\n    private lateinit var launcher: ActivityResultLauncher<Intent>\n\n    private val client by lazy {\n        CoinbaseWalletSDK(\n            appContext = applicationContext,\n            domain = Uri.parse(\"https://www.myappxyz.com\"),\n            openIntent = { intent -> launcher.launch(intent) }\n        )\n    }\n\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n    }\n\n}\n"
  },
  {
    "path": "flutter/example/android/app/src/main/res/drawable/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@android:color/white\" />\n\n    <!-- You can insert your own image assets here -->\n    <!-- <item>\n        <bitmap\n            android:gravity=\"center\"\n            android:src=\"@mipmap/launch_image\" />\n    </item> -->\n</layer-list>\n"
  },
  {
    "path": "flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"?android:colorBackground\" />\n\n    <!-- You can insert your own image assets here -->\n    <!-- <item>\n        <bitmap\n            android:gravity=\"center\"\n            android:src=\"@mipmap/launch_image\" />\n    </item> -->\n</layer-list>\n"
  },
  {
    "path": "flutter/example/android/app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Light.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             the Flutter engine draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n\n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Light.NoTitleBar\">\n        <item name=\"android:windowBackground\">?android:colorBackground</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "flutter/example/android/app/src/main/res/values-night/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             the Flutter engine draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n\n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <item name=\"android:windowBackground\">?android:colorBackground</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "flutter/example/android/app/src/profile/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"xyz.tribes.coinbase.coinbase_wallet_sdk_example\">\n    <!-- The INTERNET permission is required for development. Specifically,\n         the Flutter tool needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "flutter/example/android/build.gradle",
    "content": "buildscript {\n    ext.kotlin_version = '1.6.10'\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:7.2.1'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\nrootProject.buildDir = '../build'\nsubprojects {\n    project.buildDir = \"${rootProject.buildDir}/${project.name}\"\n}\nsubprojects {\n    project.evaluationDependsOn(':app')\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "flutter/example/android/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Jun 23 08:50:38 CEST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.4-all.zip\n"
  },
  {
    "path": "flutter/example/android/gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx1536M\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "flutter/example/android/settings.gradle",
    "content": "include ':app'\n\ndef localPropertiesFile = new File(rootProject.projectDir, \"local.properties\")\ndef properties = new Properties()\n\nassert localPropertiesFile.exists()\nlocalPropertiesFile.withReader(\"UTF-8\") { reader -> properties.load(reader) }\n\ndef flutterSdkPath = properties.getProperty(\"flutter.sdk\")\nassert flutterSdkPath != null, \"flutter.sdk not set in local.properties\"\napply from: \"$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle\"\n\n"
  },
  {
    "path": "flutter/example/ios/.gitignore",
    "content": "**/dgph\n*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/DerivedData/\nIcon?\n**/Pods/\n**/.symlinks/\nprofile\nxcuserdata\n**/.generated/\nFlutter/App.framework\nFlutter/Flutter.framework\nFlutter/Flutter.podspec\nFlutter/Generated.xcconfig\nFlutter/ephemeral/\nFlutter/app.flx\nFlutter/app.zip\nFlutter/flutter_assets/\nFlutter/flutter_export_environment.sh\nServiceDefinitions.json\nRunner/GeneratedPluginRegistrant.*\n\n# Exceptions to above rules.\n!default.mode1v3\n!default.mode2v3\n!default.pbxuser\n!default.perspectivev3\n"
  },
  {
    "path": "flutter/example/ios/Flutter/AppFrameworkInfo.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>CFBundleDevelopmentRegion</key>\n  <string>en</string>\n  <key>CFBundleExecutable</key>\n  <string>App</string>\n  <key>CFBundleIdentifier</key>\n  <string>io.flutter.flutter.app</string>\n  <key>CFBundleInfoDictionaryVersion</key>\n  <string>6.0</string>\n  <key>CFBundleName</key>\n  <string>App</string>\n  <key>CFBundlePackageType</key>\n  <string>FMWK</string>\n  <key>CFBundleShortVersionString</key>\n  <string>1.0</string>\n  <key>CFBundleSignature</key>\n  <string>????</string>\n  <key>CFBundleVersion</key>\n  <string>1.0</string>\n  <key>MinimumOSVersion</key>\n  <string>11.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "flutter/example/ios/Flutter/Debug.xcconfig",
    "content": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "flutter/example/ios/Flutter/Release.xcconfig",
    "content": "#include? \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "flutter/example/ios/Podfile",
    "content": "platform :ios, '13.0'\n\n# CocoaPods analytics sends network stats synchronously affecting flutter build latency.\nENV['COCOAPODS_DISABLE_STATS'] = 'true'\n\nproject 'Runner', {\n  'Debug' => :debug,\n  'Profile' => :release,\n  'Release' => :release,\n}\n\ndef flutter_root\n  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)\n  unless File.exist?(generated_xcode_build_settings_path)\n    raise \"#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first\"\n  end\n\n  File.foreach(generated_xcode_build_settings_path) do |line|\n    matches = line.match(/FLUTTER_ROOT\\=(.*)/)\n    return matches[1].strip if matches\n  end\n  raise \"FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get\"\nend\n\nrequire File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)\n\nflutter_ios_podfile_setup\n\ntarget 'Runner' do\n  use_frameworks!\n  use_modular_headers!\n\n  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))\n  pod 'CoinbaseWalletSDK/CrossPlatform', :path => '../../../'\nend\n\npost_install do |installer|\n  installer.pods_project.targets.each do |target|\n    flutter_additional_ios_build_settings(target)\n  end\nend\n"
  },
  {
    "path": "flutter/example/ios/Runner/AppDelegate.swift",
    "content": "import UIKit\nimport Flutter\nimport CoinbaseWalletSDK\n\n@UIApplicationMain\n@objc class AppDelegate: FlutterAppDelegate {\n  override func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n  ) -> Bool {\n      GeneratedPluginRegistrant.register(with: self)\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n    \n    override func application(\n      _ app: UIApplication, \n      open url: URL, \n      options: [UIApplication.OpenURLOptionsKey : Any] = [:]\n    ) -> Bool {\n        if (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n            return true\n        }\n        // handle other types of deep links\n        return false\n    }\n    \n    override func application(\n      _ application: UIApplication, \n      continue userActivity: NSUserActivity, \n      restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void\n    ) -> Bool {\n        if let url = userActivity.webpageURL,\n           (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n            return true\n        }\n        // handle other types of deep links\n        return false\n    }\n}\n"
  },
  {
    "path": "flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"83.5x83.5\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-83.5x83.5@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"1024x1024\",\n      \"idiom\" : \"ios-marketing\",\n      \"filename\" : \"Icon-App-1024x1024@1x.png\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "content": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in this directory.\n\nYou 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."
  },
  {
    "path": "flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"12121\" systemVersion=\"16G29\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"12089\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ydg-fD-yQy\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xbc-2k-c8Z\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" image=\"LaunchImage\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YRO-k0-Ey4\">\n                            </imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerX\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerX\" id=\"1a2-6s-vTC\"/>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerY\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerY\" id=\"4X2-HB-R7a\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"LaunchImage\" width=\"168\" height=\"185\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "flutter/example/ios/Runner/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15F34\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10085\"/>\n    </dependencies>\n    <scenes>\n        <!--Flutter View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"FlutterViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "flutter/example/ios/Runner/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>Coinbase Wallet Sdk Flutter</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>coinbase_wallet_sdk_example</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(FLUTTER_BUILD_NAME)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(FLUTTER_BUILD_NUMBER)</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n\t<key>CADisableMinimumFrameDurationOnPhone</key>\n\t<true/>\n  <key>LSApplicationQueriesSchemes</key>\n  <array>\n    <string>cbwallet</string>\n  </array>\n  <key>CFBundleURLTypes</key>\n  <array>\n      <dict>\n          <key>CFBundleTypeRole</key>\n          <string>Editor</string>\n          <key>CFBundleURLName</key>\n          <string>xyz.myapp</string>\n          <key>CFBundleURLSchemes</key>\n          <array>\n              <string>tribesxyzsample</string>\n          </array>\n      </dict>\n  </array>\n</dict>\n</plist>\n"
  },
  {
    "path": "flutter/example/ios/Runner/Runner-Bridging-Header.h",
    "content": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "flutter/example/ios/Runner.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 51;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };\n\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };\n\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };\n\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };\n\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };\n\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };\n\t\tA801D991D2C0347E18E774F2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 632977FC36B713376CA20149 /* Pods_Runner.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t9705A1C41CF9048500538489 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1231562487A9E69F0695A637 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.release.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = \"<group>\"; };\n\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = \"<group>\"; };\n\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = \"<group>\"; };\n\t\t632977FC36B713376CA20149 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"Runner-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = \"<group>\"; };\n\t\t97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t9B9F6ED6A5104AB32086D219 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.debug.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tCDE608CC9346B2F30C39D2F9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-Runner.profile.xcconfig\"; path = \"Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t97C146EB1CF9000F007C117D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tA801D991D2C0347E18E774F2 /* Pods_Runner.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t6E7600A0553582F9BBF745AC /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t632977FC36B713376CA20149 /* Pods_Runner.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9740EEB11CF90186004384FC /* Flutter */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,\n\t\t\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */,\n\t\t\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */,\n\t\t\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */,\n\t\t\t);\n\t\t\tname = Flutter;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146E51CF9000F007C117D = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9740EEB11CF90186004384FC /* Flutter */,\n\t\t\t\t97C146F01CF9000F007C117D /* Runner */,\n\t\t\t\t97C146EF1CF9000F007C117D /* Products */,\n\t\t\t\tACA9B6DF8E133DCF23C189FC /* Pods */,\n\t\t\t\t6E7600A0553582F9BBF745AC /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146EF1CF9000F007C117D /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146EE1CF9000F007C117D /* Runner.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F01CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FA1CF9000F007C117D /* Main.storyboard */,\n\t\t\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */,\n\t\t\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,\n\t\t\t\t97C147021CF9000F007C117D /* Info.plist */,\n\t\t\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,\n\t\t\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,\n\t\t\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */,\n\t\t\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tACA9B6DF8E133DCF23C189FC /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9B9F6ED6A5104AB32086D219 /* Pods-Runner.debug.xcconfig */,\n\t\t\t\t1231562487A9E69F0695A637 /* Pods-Runner.release.xcconfig */,\n\t\t\t\tCDE608CC9346B2F30C39D2F9 /* Pods-Runner.profile.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t97C146ED1CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tEA14CAA479E7DE3ABA560117 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t9740EEB61CF901F6004384FC /* Run Script */,\n\t\t\t\t97C146EA1CF9000F007C117D /* Sources */,\n\t\t\t\t97C146EB1CF9000F007C117D /* Frameworks */,\n\t\t\t\t97C146EC1CF9000F007C117D /* Resources */,\n\t\t\t\t9705A1C41CF9048500538489 /* Embed Frameworks */,\n\t\t\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */,\n\t\t\t\tC9F10FB848EC932D8A5546BF /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Runner;\n\t\t\tproductName = Runner;\n\t\t\tproductReference = 97C146EE1CF9000F007C117D /* Runner.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t97C146E61CF9000F007C117D /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1300;\n\t\t\t\tORGANIZATIONNAME = \"\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t97C146ED1CF9000F007C117D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t\tLastSwiftMigration = 1100;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */;\n\t\t\tcompatibilityVersion = \"Xcode 9.3\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 97C146E51CF9000F007C117D;\n\t\t\tproductRefGroup = 97C146EF1CF9000F007C117D /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t97C146ED1CF9000F007C117D /* Runner */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t97C146EC1CF9000F007C117D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,\n\t\t\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,\n\t\t\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Thin Binary\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" embed_and_thin\";\n\t\t};\n\t\t9740EEB61CF901F6004384FC /* Run Script */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" build\";\n\t\t};\n\t\tC9F10FB848EC932D8A5546BF /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tEA14CAA479E7DE3ABA560117 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t97C146EA1CF9000F007C117D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,\n\t\t\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t97C146FA1CF9000F007C117D /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FB1CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C147001CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t249021D3217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 13.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t249021D4217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = K9PRP53827;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = xyz.tribes.coinbase.coinbaseWalletSdkFlutterExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t97C147031CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 13.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147041CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 13.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t97C147061CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = K9PRP53827;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = xyz.tribes.coinbase.coinbaseWalletSdkFlutterExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147071CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = K9PRP53827;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = xyz.tribes.coinbase.coinbaseWalletSdkFlutterExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147031CF9000F007C117D /* Debug */,\n\t\t\t\t97C147041CF9000F007C117D /* Release */,\n\t\t\t\t249021D3217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147061CF9000F007C117D /* Debug */,\n\t\t\t\t97C147071CF9000F007C117D /* Release */,\n\t\t\t\t249021D4217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 97C146E61CF9000F007C117D /* Project object */;\n}\n"
  },
  {
    "path": "flutter/example/lib/main.dart",
    "content": "import 'dart:async';\n\nimport 'package:coinbase_wallet_sdk/coinbase_wallet_sdk.dart';\nimport 'package:coinbase_wallet_sdk/configuration.dart';\nimport 'package:coinbase_wallet_sdk/eth_web3_rpc.dart';\nimport 'package:coinbase_wallet_sdk/request.dart';\nimport 'package:flutter/material.dart';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatefulWidget {\n  const MyApp({Key? key}) : super(key: key);\n\n  @override\n  State<MyApp> createState() => _MyAppState();\n}\n\nclass _MyAppState extends State<MyApp> {\n  String _addy = \"\";\n  String _signed = \"\";\n  String _sessionCleared = \"\";\n\n  @override\n  void initState() {\n    CoinbaseWalletSDK.shared.configure(\n      Configuration(\n        ios: IOSConfiguration(\n          host: Uri.parse('cbwallet://wsegue'),\n          callback: Uri.parse('tribesxyzsample://mycallback'),\n        ),\n        android: AndroidConfiguration(\n          domain: Uri.parse('https://www.myappxyz.com'),\n        ),\n      ),\n    );\n    super.initState();\n  }\n\n  // Platform messages are asynchronous, so we initialize in an async method.\n  Future<void> _requestAccount() async {\n    String addy;\n    try {\n      final results = await CoinbaseWalletSDK.shared.initiateHandshake([\n        const RequestAccounts(),\n      ]);\n      addy = results[0].account?.address ?? \"<no address>\";\n    } catch (e) {\n      addy = 'Failed to get address. => $e';\n    }\n\n    // If the widget was removed from the tree while the asynchronous platform\n    // message was in flight, we want to discard the reply rather than calling\n    // setState to update our non-existent appearance.\n    if (!mounted) return;\n\n    setState(() {\n      _addy = addy;\n    });\n  }\n\n  Future<void> _personalSign() async {\n    String message = \"Hello, world!\";\n    String signed;\n    try {\n      final request = Request(\n        actions: [PersonalSign(address: _addy, message: message)],\n      );\n      final results = await CoinbaseWalletSDK.shared.makeRequest(request);\n\n      signed = results[0].value ?? \"<no signature>\";\n    } catch (e) {\n      debugPrint('error --> $e');\n      signed = \"Failed to sign message.\";\n    }\n\n    // If the widget was removed from the tree while the asynchronous platform\n    // message was in flight, we want to discard the reply rather than calling\n    // setState to update our non-existent appearance.\n    if (!mounted) return;\n\n    setState(() {\n      _signed = signed;\n    });\n  }\n\n  Future<void> _resetSession() async {\n    try {\n      await CoinbaseWalletSDK.shared.resetSession();\n      setState(() {\n        _sessionCleared = \"SEssion Cleared!\";\n      });\n    } catch (e) {\n      setState(() {\n        _sessionCleared = \"Failed to reset session\";\n      });\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: Scaffold(\n        appBar: AppBar(\n          title: const Text('Coinbase Flutter SDK'),\n        ),\n        body: Center(\n          child: Column(\n            mainAxisAlignment: MainAxisAlignment.center,\n            children: [\n              FutureBuilder<bool>(\n                future: CoinbaseWalletSDK.shared.isAppInstalled(),\n                builder: ((context, snapshot) {\n                  return Text(\n                    'Is installed? ${snapshot.data}',\n                  );\n                }),\n              ),\n              TextButton(\n                onPressed: () => _requestAccount(),\n                child: const Text(\"Request Account\"),\n              ),\n              Text('address is\\n\\n $_addy'),\n              const SizedBox(height: 50),\n              TextButton(\n                onPressed: () => _personalSign(),\n                child: const Text(\"personalSign\"),\n              ),\n              Text('signed message is\\n\\n $_signed'),\n              const SizedBox(height: 50),\n              TextButton(\n                onPressed: () => _resetSession(),\n                child: const Text(\"Reset Session\"),\n              ),\n              Text('is reset\\n\\n $_sessionCleared'),\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "flutter/example/pubspec.yaml",
    "content": "name: coinbase_wallet_sdk_example\ndescription: Demonstrates how to use the coinbase_wallet_sdk plugin.\n\n# The following line prevents the package from being accidentally published to\n# pub.dev using `flutter pub publish`. This is preferred for private packages.\npublish_to: 'none' # Remove this line if you wish to publish to pub.dev\n\nenvironment:\n  sdk: \">=2.17.6 <3.0.0\"\n\n# Dependencies specify other packages that your package needs in order to work.\n# To automatically upgrade your package dependencies to the latest versions\n# consider running `flutter pub upgrade --major-versions`. Alternatively,\n# dependencies can be manually updated by changing the version numbers below to\n# the latest version available on pub.dev. To see which dependencies have newer\n# versions available, run `flutter pub outdated`.\ndependencies:\n  flutter:\n    sdk: flutter\n\n  coinbase_wallet_sdk:\n    # When depending on this package from a real application you should use:\n    #   coinbase_wallet_sdk: ^x.y.z\n    # See https://dart.dev/tools/pub/dependencies#version-constraints\n    # The example app is bundled with the plugin so we use a path dependency on\n    # the parent directory to use the current plugin's version.\n    path: ../\n\n  # The following adds the Cupertino Icons font to your application.\n  # Use with the CupertinoIcons class for iOS style icons.\n  cupertino_icons: ^1.0.2\n\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n\n  # The \"flutter_lints\" package below contains a set of recommended lints to\n  # encourage good coding practices. The lint set provided by the package is\n  # activated in the `analysis_options.yaml` file located at the root of your\n  # package. See that file for information about deactivating specific lint\n  # rules and activating additional ones.\n  flutter_lints: ^2.0.0\n\n# For information on the generic Dart part of this file, see the\n# following page: https://dart.dev/tools/pub/pubspec\n\n# The following section is specific to Flutter packages.\nflutter:\n\n  # The following line ensures that the Material Icons font is\n  # included with your application, so that you can use the icons in\n  # the material Icons class.\n  uses-material-design: true\n\n  # To add assets to your application, add an assets section, like this:\n  # assets:\n  #   - images/a_dot_burr.jpeg\n  #   - images/a_dot_ham.jpeg\n\n  # An image asset can refer to one or more resolution-specific \"variants\", see\n  # https://flutter.dev/assets-and-images/#resolution-aware\n\n  # For details regarding adding assets from package dependencies, see\n  # https://flutter.dev/assets-and-images/#from-packages\n\n  # To add custom fonts to your application, add a fonts section here,\n  # in this \"flutter\" section. Each entry in this list should have a\n  # \"family\" key with the font family name, and a \"fonts\" key with a\n  # list giving the asset and other descriptors for the font. For\n  # example:\n  # fonts:\n  #   - family: Schyler\n  #     fonts:\n  #       - asset: fonts/Schyler-Regular.ttf\n  #       - asset: fonts/Schyler-Italic.ttf\n  #         style: italic\n  #   - family: Trajan Pro\n  #     fonts:\n  #       - asset: fonts/TrajanPro.ttf\n  #       - asset: fonts/TrajanPro_Bold.ttf\n  #         weight: 700\n  #\n  # For details regarding fonts from package dependencies,\n  # see https://flutter.dev/custom-fonts/#from-packages\n"
  },
  {
    "path": "flutter/example/test/widget_test.dart",
    "content": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester\n// utility in the flutter_test package. For example, you can send tap and scroll\n// gestures. You can also use WidgetTester to find child widgets in the widget\n// tree, read text, and verify that the values of widget properties are correct.\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nimport 'package:coinbase_wallet_sdk_example/main.dart';\n\nvoid main() {\n  testWidgets('Verify Platform version', (WidgetTester tester) async {\n    // Build our app and trigger a frame.\n    await tester.pumpWidget(const MyApp());\n\n    // Verify that platform version is retrieved.\n    expect(\n      find.byWidgetPredicate(\n        (Widget widget) => widget is Text &&\n                           widget.data!.startsWith('Running on:'),\n      ),\n      findsOneWidget,\n    );\n  });\n}\n"
  },
  {
    "path": "flutter/ios/.gitignore",
    "content": ".idea/\n.vagrant/\n.sconsign.dblite\n.svn/\n\n.DS_Store\n*.swp\nprofile\n\nDerivedData/\nbuild/\nGeneratedPluginRegistrant.h\nGeneratedPluginRegistrant.m\n\n.generated/\n\n*.pbxuser\n*.mode1v3\n*.mode2v3\n*.perspectivev3\n\n!default.pbxuser\n!default.mode1v3\n!default.mode2v3\n!default.perspectivev3\n\nxcuserdata\n\n*.moved-aside\n\n*.pyc\n*sync/\nIcon?\n.tags*\n\n/Flutter/Generated.xcconfig\n/Flutter/ephemeral/\n/Flutter/flutter_export_environment.sh"
  },
  {
    "path": "flutter/ios/Assets/.gitkeep",
    "content": ""
  },
  {
    "path": "flutter/ios/Classes/CoinbaseWalletSdkFlutterPlugin.h",
    "content": "#import <Flutter/Flutter.h>\n\n@interface CoinbaseWalletSdkFlutterPlugin : NSObject<FlutterPlugin>\n@end\n"
  },
  {
    "path": "flutter/ios/Classes/CoinbaseWalletSdkFlutterPlugin.m",
    "content": "#import \"CoinbaseWalletSdkFlutterPlugin.h\"\n#if __has_include(<coinbase_wallet_sdk/coinbase_wallet_sdk-Swift.h>)\n#import <coinbase_wallet_sdk/coinbase_wallet_sdk-Swift.h>\n#else\n// Support project import fallback if the generated compatibility header\n// is not copied when this plugin is created as a library.\n// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816\n#import \"coinbase_wallet_sdk-Swift.h\"\n#endif\n\n@implementation CoinbaseWalletSdkFlutterPlugin\n+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {\n  [SwiftCoinbaseWalletSdkFlutterPlugin registerWithRegistrar:registrar];\n}\n@end\n"
  },
  {
    "path": "flutter/ios/Classes/SwiftCoinbaseWalletSdkFlutterPlugin.swift",
    "content": "import Flutter\nimport UIKit\nimport CoinbaseWalletSDK\n\npublic class SwiftCoinbaseWalletSdkFlutterPlugin: NSObject, FlutterPlugin {\n    private static let success = \"{ \\\"success\\\": true}\"\n    \n    public override init() {}\n    \n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let channel = FlutterMethodChannel(name: \"coinbase_wallet_sdk\", binaryMessenger: registrar.messenger())\n        let instance = SwiftCoinbaseWalletSdkFlutterPlugin()\n        registrar.addMethodCallDelegate(instance, channel: channel)\n    }\n    \n    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {\n        do {\n            if (call.method == \"configure\") {\n                return configure(call: call, result: result)\n            }\n            \n            if (call.method == \"initiateHandshake\") {\n                return try initiateHandshake(call: call, result: result)\n            }\n            \n            if (call.method == \"makeRequest\") {\n                return try makeRequest(call: call, result: result)\n            }\n            \n            if (call.method == \"resetSession\") {\n                return resetSession(call: call, result: result)\n            }\n\n            if (call.method == \"isAppInstalled\") {\n                return isAppInstalled(result: result)\n            }\n        } catch {\n            result(FlutterError(code: \"handle\", message: error.localizedDescription, details: nil))\n            return\n        }\n        \n        result(FlutterMethodNotImplemented)\n    }\n\n    private func isAppInstalled(result: @escaping FlutterResult) {\n        result(CoinbaseWalletSDK.isCoinbaseWalletInstalled())\n    }\n    \n    private func configure(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        guard\n            let args = call.arguments as? [String: Any],\n            let host = args[\"host\"] as? String,\n            let callback = args[\"callback\"] as? String,\n            let hostURL = URL(string: host),\n            let callbackURL = URL(string: callback)\n        else {\n            result(FlutterError(code: \"configure\", message: \"Invalid arguments\", details: nil))\n            return\n        }\n        \n        CoinbaseWalletSDK.configure(host: hostURL,callback: callbackURL)\n        CoinbaseWalletSDK.appendVersionTag(\"flutter\")\n        \n        result(SwiftCoinbaseWalletSdkFlutterPlugin.success)\n    }\n    \n    private func initiateHandshake(call: FlutterMethodCall, result: @escaping FlutterResult) throws {\n        var actions = [Action]()\n        \n        if let args = call.arguments as? String, let jsonData = args.data(using: .utf8) {\n            actions = try JSONDecoder().decode([Action].self, from: jsonData)\n        }\n        \n        CoinbaseWalletSDK.shared.initiateHandshake(initialActions: actions) { responseResult, account in\n            self.handleResponse(\n                code: \"initiateHandshake\",\n                responseResult: responseResult,\n                account: account,\n                result: result\n            )\n        }\n    }\n    \n    private func makeRequest(call: FlutterMethodCall, result: @escaping FlutterResult) throws {\n        guard\n            let args = call.arguments as? String,\n            let jsonData = args.data(using: .utf8)\n        else {\n            result(FlutterError(code: \"makeRequest\", message: \"Invalid arguments\", details: nil))\n            return\n        }\n        \n        let request = try JSONDecoder().decode(Request.self, from: jsonData)\n        \n        CoinbaseWalletSDK.shared.makeRequest(request) { responseResult in\n            self.handleResponse(\n                code: \"makeRequest\",\n                responseResult: responseResult,\n                account: nil,\n                result: result\n            )\n        }\n    }\n    \n    private func resetSession(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let responseResult = CoinbaseWalletSDK.shared.resetSession()\n        \n        switch responseResult {\n        case .success:\n            result(SwiftCoinbaseWalletSdkFlutterPlugin.success)\n        case .failure(let error):\n            result(FlutterError(code: \"resetSession\", message: error.localizedDescription, details: nil))\n        }\n    }\n    \n    private func handleResponse(\n        code: String,\n        responseResult: ResponseResult,\n        account: Account?,\n        result: @escaping FlutterResult\n    ) {\n        do {\n            switch responseResult {\n            case .success(let returnValues):\n                var toFlutter = [[String: Any]]()\n                \n                returnValues.content.forEach { it in\n                    var response = [String: Any]()\n                    \n                    if let account = account {\n                        response[\"account\"] = [\n                            \"chain\": account.chain,\n                            \"networkId\": account.networkId,\n                            \"address\": account.address\n                        ]\n                    }\n                    switch it {\n                    case .success(let value):\n                        response[\"result\"] = value.rawValue\n                    case .failure(let error):\n                        response[\"error\"] = [\"code\": error.code, \"message\": error.message]\n                    }\n                    \n                    toFlutter.append(response)\n                }\n                \n                let data = try JSONSerialization.data(withJSONObject: toFlutter, options: [])\n                let jsonString = String(data: data, encoding: .utf8)!\n                \n                result(jsonString)\n            case .failure(let error):\n                result(FlutterError(code: code, message: error.localizedDescription, details: nil))\n            }\n        } catch {\n            result(FlutterError(code: code, message: error.localizedDescription, details: nil))\n        }\n    }\n}\n"
  },
  {
    "path": "flutter/ios/coinbase_wallet_sdk.podspec",
    "content": "#\n# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.\n# Run `pod lib lint coinbase_wallet_sdk.podspec` to validate before publishing.\n#\nPod::Spec.new do |s|\n  s.name             = 'coinbase_wallet_sdk'\n  s.version          = '0.0.1'\n  s.summary          = 'A new Flutter plugin project.'\n  s.description      = <<-DESC\nA new Flutter plugin project.\n                       DESC\n  s.homepage         = 'http://example.com'\n  s.license          = { :file => '../LICENSE' }\n  s.author           = { 'Hish Bouabdallah' => 'hish@tribes.xyz' }\n  s.source           = { :path => '.' }\n  s.source_files = 'Classes/**/*'\n  s.dependency 'Flutter'\n  s.dependency 'CoinbaseWalletSDK/CrossPlatform', '1.0.4'\n  s.ios.deployment_target = '13.0'\n  s.swift_version = '5.0'\n\n  # Flutter.framework does not contain a i386 slice.\n  s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }\nend\n"
  },
  {
    "path": "flutter/lib/account.dart",
    "content": "class Account {\n  final String chain;\n  final int networkId;\n  final String address;\n\n  const Account({\n    required this.chain,\n    required this.networkId,\n    required this.address,\n  });\n\n  Map<String, dynamic> toJson() {\n    return <String, dynamic>{\n      'chain': chain,\n      'networkId': networkId,\n      'address': address,\n    };\n  }\n\n  factory Account.fromJson(Map<String, dynamic> json) {\n    return Account(\n      chain: json['chain'] as String,\n      networkId: json['networkId'] as int,\n      address: json['address'] as String,\n    );\n  }\n}\n"
  },
  {
    "path": "flutter/lib/action.dart",
    "content": "import 'dart:convert';\n\nclass Action {\n  final String method;\n  final String paramsJson;\n  final bool optional;\n\n  const Action({\n    required this.method,\n    required this.paramsJson,\n    this.optional = false,\n  });\n\n  factory Action.create({\n    required String method,\n    required Map<String, dynamic> params,\n    bool optional = false,\n  }) {\n    return Action(\n      method: method,\n      paramsJson: jsonEncode(params),\n      optional: optional,\n    );\n  }\n\n  Map<String, dynamic> toJson() {\n    return <String, dynamic>{\n      'method': method,\n      'paramsJson': paramsJson,\n      'optional': optional,\n    };\n  }\n}\n"
  },
  {
    "path": "flutter/lib/coinbase_wallet_sdk.dart",
    "content": "import 'dart:convert';\n\nimport 'package:coinbase_wallet_sdk/account.dart';\nimport 'package:coinbase_wallet_sdk/action.dart';\nimport 'package:coinbase_wallet_sdk/coinbase_wallet_sdk_platform_interface.dart';\nimport 'package:coinbase_wallet_sdk/configuration.dart';\nimport 'package:coinbase_wallet_sdk/request.dart';\nimport 'package:coinbase_wallet_sdk/return_value.dart';\nimport 'package:flutter/foundation.dart'\n    show defaultTargetPlatform, TargetPlatform;\n\nclass CoinbaseWalletSDK {\n  static const CoinbaseWalletSDK shared = CoinbaseWalletSDK._();\n\n  const CoinbaseWalletSDK._();\n\n  /// Setup the SDK\n  Future<void> configure(Configuration configuration) async {\n    if (defaultTargetPlatform == TargetPlatform.iOS) {\n      await _configureIOS(configuration.ios);\n    } else if (defaultTargetPlatform == TargetPlatform.android) {\n      await _configureAndroid(configuration.android);\n    } else {\n      throw UnsupportedError(\n        'Unsupported platform: ${defaultTargetPlatform.toString()}',\n      );\n    }\n  }\n\n  /// Initiate the handshake with Coinbase Wallet app\n  Future<List<ReturnValueWithAccount>> initiateHandshake(\n    List<Action>? initialActions,\n  ) async {\n    final actionsJson =\n        (initialActions ?? []).map((action) => action.toJson()).toList();\n\n    final result = await CoinbaseWalletSdkFlutterPlatform.instance\n        .call('initiateHandshake', jsonEncode(actionsJson));\n\n    final returnValuesWithAccounts = (result ?? [])\n        .map(\n          (e) {\n            final map = Map<String, dynamic>.from(e);\n            return ReturnValueWithAccount.fromJson(map);\n          },\n        )\n        .cast<ReturnValueWithAccount>()\n        .toList();\n\n    return returnValuesWithAccounts;\n  }\n\n  /// Send a web3 request to Coinbase Wallet app\n  Future<List<ReturnValue>> makeRequest(Request request) async {\n    final result = await CoinbaseWalletSdkFlutterPlatform.instance\n        .call('makeRequest', jsonEncode(request.toJson()));\n\n    return (result ?? [])\n        .map((e) => ReturnValue.fromJson(e))\n        .cast<ReturnValue>()\n        .toList();\n  }\n\n  /// Disconnect any active session\n  Future<void> resetSession() async {\n    await CoinbaseWalletSdkFlutterPlatform.instance.call('resetSession');\n  }\n\n  /// Check whether CoinbaseWallet app is installed\n  Future<bool> isAppInstalled() async {\n    final result =\n        await CoinbaseWalletSdkFlutterPlatform.instance.call('isAppInstalled');\n    return result ?? false;\n  }\n\n  // private helper methods\n\n  Future<void> _configureIOS(IOSConfiguration? configuration) async {\n    if (configuration == null) {\n      throw ArgumentError('iOS configuration is missing.');\n    }\n    await CoinbaseWalletSdkFlutterPlatform.instance\n        .call('configure', configuration.toJson());\n  }\n\n  Future<void> _configureAndroid(AndroidConfiguration? configuration) async {\n    if (configuration == null) {\n      throw ArgumentError('Android configuration is missing.');\n    }\n    await CoinbaseWalletSdkFlutterPlatform.instance\n        .call('configure', configuration.toJson());\n  }\n}\n\nclass ReturnValueWithAccount {\n  final String? value;\n  final ReturnValueError? error;\n  final Account? account;\n\n  ReturnValueWithAccount(ReturnValue returnValue, this.account)\n      : value = returnValue.value,\n        error = returnValue.error;\n\n  factory ReturnValueWithAccount.fromJson(Map<String, dynamic> json) {\n    final account = json['account'];\n    return ReturnValueWithAccount(\n      ReturnValue.fromJson(json),\n      account == null\n          ? null\n          : Account.fromJson(Map<String, dynamic>.from(account)),\n    );\n  }\n}\n"
  },
  {
    "path": "flutter/lib/coinbase_wallet_sdk_method_channel.dart",
    "content": "import 'dart:convert';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/services.dart';\n\nimport 'coinbase_wallet_sdk_platform_interface.dart';\n\n/// An implementation of [CoinbaseWalletSdkFlutterPlatform] that uses method channels.\nclass MethodChannelCoinbaseWalletSdkFlutter\n    extends CoinbaseWalletSdkFlutterPlatform {\n  /// The method channel used to interact with the native platform.\n  @visibleForTesting\n  final methodChannel = const MethodChannel('coinbase_wallet_sdk');\n\n  @override\n  Future<dynamic> call(String method, [arguments]) async {\n    final result = await methodChannel.invokeMethod<dynamic>(method, arguments);\n    if (result is bool) {\n      return result;\n    }\n\n    return result != null ? jsonDecode(result as String) : null;\n  }\n}\n"
  },
  {
    "path": "flutter/lib/coinbase_wallet_sdk_platform_interface.dart",
    "content": "import 'package:plugin_platform_interface/plugin_platform_interface.dart';\n\nimport 'coinbase_wallet_sdk_method_channel.dart';\n\nabstract class CoinbaseWalletSdkFlutterPlatform extends PlatformInterface {\n  /// Constructs a CoinbaseWalletSdkFlutterPlatform.\n  CoinbaseWalletSdkFlutterPlatform() : super(token: _token);\n\n  static final Object _token = Object();\n\n  static CoinbaseWalletSdkFlutterPlatform _instance =\n      MethodChannelCoinbaseWalletSdkFlutter();\n\n  /// The default instance of [CoinbaseWalletSdkFlutterPlatform] to use.\n  ///\n  /// Defaults to [MethodChannelCoinbaseWalletSdkFlutter].\n  static CoinbaseWalletSdkFlutterPlatform get instance => _instance;\n\n  /// Platform-specific implementations should set this with their own\n  /// platform-specific class that extends [CoinbaseWalletSdkFlutterPlatform] when\n  /// they register themselves.\n  static set instance(CoinbaseWalletSdkFlutterPlatform instance) {\n    PlatformInterface.verifyToken(instance, _token);\n    _instance = instance;\n  }\n\n  Future<dynamic> call(String method, [dynamic arguments]);\n}\n\nclass PlatformError implements Exception {\n  final int code;\n  final String message;\n\n  PlatformError(this.code, this.message);\n\n  @override\n  String toString() {\n    return \"PlatformError(code: $code, message: $message)\";\n  }\n}\n\nclass PlatformResult {\n  final String? value;\n  final PlatformError? error;\n\n  PlatformResult(this.value, this.error);\n}\n"
  },
  {
    "path": "flutter/lib/configuration.dart",
    "content": "class Configuration {\n  final IOSConfiguration? ios;\n  final AndroidConfiguration? android;\n\n  Configuration({\n    required this.ios,\n    required this.android,\n  });\n}\n\nclass IOSConfiguration {\n  final Uri host;\n  final Uri callback;\n\n  const IOSConfiguration({\n    required this.host,\n    required this.callback,\n  });\n\n  Map<String, dynamic> toJson() {\n    return {\n      'host': host.toString(),\n      'callback': callback.toString(),\n    };\n  }\n}\n\nclass AndroidConfiguration {\n  final Uri domain;\n\n  const AndroidConfiguration({\n    required this.domain,\n  });\n\n  Map<String, dynamic> toJson() {\n    return <String, dynamic>{\n      'domain': domain.toString(),\n    };\n  }\n}\n"
  },
  {
    "path": "flutter/lib/eth_web3_rpc.dart",
    "content": "import 'dart:convert';\n\nimport 'package:coinbase_wallet_sdk/action.dart';\n\nclass RequestAccounts extends Action {\n  const RequestAccounts()\n      : super(\n          method: 'eth_requestAccounts',\n          paramsJson: '{}',\n        );\n}\n\nclass PersonalSign extends Action {\n  PersonalSign({\n    required String address,\n    required String message,\n    bool optional = false,\n  }) : super(\n          method: 'personal_sign',\n          paramsJson: jsonEncode({\n            'address': address,\n            'message': message,\n          }),\n          optional: optional,\n        );\n}\n\nclass SignTypedDataV3 extends Action {\n  final String address;\n  final String typedDataJson;\n\n  SignTypedDataV3({\n    required this.address,\n    required this.typedDataJson,\n    bool optional = false,\n  }) : super(\n          method: 'eth_signTypedData_v3',\n          paramsJson: jsonEncode({\n            'address': address,\n            'typedDataJson': typedDataJson,\n          }),\n          optional: optional,\n        );\n}\n\nclass SignTypedDataV4 extends Action {\n  final String address;\n  final String typedDataJson;\n\n  SignTypedDataV4({\n    required this.address,\n    required this.typedDataJson,\n    bool optional = false,\n  }) : super(\n          method: 'eth_signTypedData_v4',\n          paramsJson: jsonEncode({\n            'address': address,\n            'typedDataJson': typedDataJson,\n          }),\n          optional: optional,\n        );\n}\n\nclass SignTransaction extends Action {\n  SignTransaction({\n    required String fromAddress,\n    required String? toAddress,\n    required BigInt weiValue,\n    required String data,\n    required int? nonce,\n    required BigInt? gasPriceInWei,\n    required BigInt? maxFeePerGas,\n    required BigInt? maxPriorityFeePerGas,\n    required BigInt? gasLimit,\n    required String chainId,\n  }) : super(\n          method: 'eth_signTransaction',\n          paramsJson: jsonEncode({\n            'fromAddress': fromAddress,\n            'toAddress': toAddress,\n            'weiValue': weiValue.toString(),\n            'data': data,\n            'nonce': nonce,\n            'gasPriceInWei': gasPriceInWei?.toString(),\n            'maxFeePerGas': maxFeePerGas?.toString(),\n            'maxPriorityFeePerGas': maxPriorityFeePerGas?.toString(),\n            'gasLimit': gasLimit?.toString(),\n            'chainId': chainId,\n          }),\n        );\n}\n\nclass SendTransaction extends Action {\n  SendTransaction({\n    required String fromAddress,\n    required String? toAddress,\n    required BigInt weiValue,\n    required String data,\n    required int? nonce,\n    required BigInt? gasPriceInWei,\n    required BigInt? maxFeePerGas,\n    required BigInt? maxPriorityFeePerGas,\n    required BigInt? gasLimit,\n    required String chainId,\n  }) : super(\n          method: 'eth_signTransaction',\n          paramsJson: jsonEncode({\n            'fromAddress': fromAddress,\n            'toAddress': toAddress,\n            'weiValue': weiValue.toString(),\n            'data': data,\n            'nonce': nonce,\n            'gasPriceInWei': gasPriceInWei?.toString(),\n            'maxFeePerGas': maxFeePerGas?.toString(),\n            'maxPriorityFeePerGas': maxPriorityFeePerGas?.toString(),\n            'gasLimit': gasLimit?.toString(),\n            'chainId': chainId,\n          }),\n        );\n}\n\nclass SwitchEthereumChain extends Action {\n  SwitchEthereumChain({\n    required int chainId,\n  }) : super(\n          method: 'wallet_switchEthereumChain',\n          paramsJson: jsonEncode({\n            'chainId': chainId,\n          }),\n        );\n}\n"
  },
  {
    "path": "flutter/lib/request.dart",
    "content": "import 'package:coinbase_wallet_sdk/account.dart';\nimport 'package:coinbase_wallet_sdk/action.dart';\n\nclass Request {\n  final List<Action> actions;\n  final Account? account;\n\n  const Request({\n    required this.actions,\n    this.account,\n  });\n\n  Map<String, dynamic> toJson() {\n    return <String, dynamic>{\n      'actions': actions.map((action) => action.toJson()).toList(),\n      'account': account?.toJson(),\n    };\n  }\n}\n"
  },
  {
    "path": "flutter/lib/return_value.dart",
    "content": "class ReturnValue {\n  final String? value;\n  final ReturnValueError? error;\n\n  const ReturnValue({\n    this.value,\n    this.error,\n  });\n\n  factory ReturnValue.fromJson(Map<String, dynamic> json) {\n    final error = json['error'];\n    return ReturnValue(\n      value: json['result'] as String?,\n      error: error == null\n          ? null\n          : ReturnValueError.fromJson(Map<String, dynamic>.from(error)),\n    );\n  }\n}\n\nclass ReturnValueError {\n  final int code;\n  final String message;\n\n  const ReturnValueError(this.code, this.message);\n\n  factory ReturnValueError.fromJson(Map<String, dynamic> json) {\n    return ReturnValueError(\n      json['code'] as int,\n      json['message'] as String,\n    );\n  }\n}\n"
  },
  {
    "path": "flutter/pubspec.yaml",
    "content": "name: coinbase_wallet_sdk\ndescription: Fluter implementation of Coinbase Wallet SDK.\nversion: 1.0.4\nhomepage: https://wallet.coinbase.com\n\nenvironment:\n  sdk: \">=2.17.6 <3.0.0\"\n  flutter: \">=2.5.0\"\n\ndependencies:\n  flutter:\n    sdk: flutter\n  plugin_platform_interface: ^2.0.2\n\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n  flutter_lints: ^2.0.0\n\n# For information on the generic Dart part of this file, see the\n# following page: https://dart.dev/tools/pub/pubspec\n\n# The following section is specific to Flutter packages.\nflutter:\n  plugin:\n    platforms:\n      android:\n        package: com.coinbase.flutter.wallet_sdk\n        pluginClass: CoinbaseWalletSdkFlutterPlugin\n      ios:\n        pluginClass: CoinbaseWalletSdkFlutterPlugin\n"
  },
  {
    "path": "flutter/test/coinbase_wallet_sdk_method_channel_test.dart",
    "content": "import 'package:coinbase_wallet_sdk/coinbase_wallet_sdk_method_channel.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nvoid main() {\n  MethodChannelCoinbaseWalletSdkFlutter platform =\n      MethodChannelCoinbaseWalletSdkFlutter();\n  const MethodChannel channel = MethodChannel('coinbase_wallet_sdk');\n\n  TestWidgetsFlutterBinding.ensureInitialized();\n\n  setUp(() {\n    channel.setMockMethodCallHandler((MethodCall methodCall) async {\n      return '42';\n    });\n  });\n\n  tearDown(() {\n    channel.setMockMethodCallHandler(null);\n  });\n\n  test('getPlatformVersion', () async {\n    // expect(await platform.getPlatformVersion(), '42');\n  });\n}\n"
  },
  {
    "path": "flutter/test/coinbase_wallet_sdk_test.dart",
    "content": "import 'package:coinbase_wallet_sdk/coinbase_wallet_sdk_method_channel.dart';\nimport 'package:coinbase_wallet_sdk/coinbase_wallet_sdk_platform_interface.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\n// class MockCoinbaseWalletSdkFlutterPlatform\n//     with MockPlatformInterfaceMixin\n//     implements CoinbaseWalletSdkFlutterPlatform {\n//   @override\n//   Future<String?> getPlatformVersion() => Future.value('42');\n\n//   @override\n//   Future<String> initiateHandshake() async {\n//     return _addy;\n//   }\n\n//   @override\n//   Future<String> personalSign(String address, String message) async {\n//     if (address == _addy) {\n//       return '0x0';\n//     } else {\n//       throw PlatformError(1, 'Invalid address');\n//     }\n//   }\n// }\n\nvoid main() {\n  final CoinbaseWalletSdkFlutterPlatform initialPlatform =\n      CoinbaseWalletSdkFlutterPlatform.instance;\n\n  test('$MethodChannelCoinbaseWalletSdkFlutter is the default instance', () {\n    expect(\n        initialPlatform, isInstanceOf<MethodChannelCoinbaseWalletSdkFlutter>());\n  });\n\n  test('getPlatformVersion', () async {\n    // CoinbaseWalletSdkFlutter coinbaseWalletSdkFlutterPlugin =\n    //     CoinbaseWalletSdkFlutter();\n    // MockCoinbaseWalletSdkFlutterPlatform fakePlatform =\n    //     MockCoinbaseWalletSdkFlutterPlatform();\n    // CoinbaseWalletSdkFlutterPlatform.instance = fakePlatform;\n\n    // expect(await coinbaseWalletSdkFlutterPlugin.getPlatformVersion(), '42');\n  });\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/CoinbaseWalletSDK.swift",
    "content": "//\n//  CoinbaseWalletSDK.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 5/20/22.\n//\n\nimport Foundation\nimport CryptoKit\nimport UIKit\n\npublic final class CoinbaseWalletSDK {\n    \n    static public func isCoinbaseWalletInstalled() -> Bool {\n        return UIApplication.shared.canOpenURL(URL(string: \"cbwallet://\")!)\n    }\n    \n    static public func getCoinbaseWalletMWPVersion() -> String? {\n        if UIApplication.shared.canOpenURL(URL(string: \"mwp+1.1://\")!) {\n            return \"1.1\"\n        } else if isCoinbaseWalletInstalled() {\n            return \"1.0\"\n        } else {\n            return nil\n        }\n    }\n    \n    // MARK: - Constructor\n    \n    static private var host: URL?\n    static private var callback: URL?\n    static public var isConfigured: Bool {\n        return host != nil && callback != nil\n    }\n    \n    static public func configure(\n        host: URL = URL(string: \"https://wallet.coinbase.com/wsegue\")!,\n        callback: URL\n    ) {\n        guard isConfigured == false else {\n            assertionFailure(\"`CoinbaseWalletSDK.configure` should be called only once.\")\n            return\n        }\n        \n        self.host = host\n        if callback.pathComponents.count < 2 { // [] or [\"/\"]\n            self.callback = callback.appendingPathComponent(\"wsegue\")\n        } else {\n            self.callback = callback\n        }\n    }\n    \n    static public var shared: CoinbaseWalletSDK = {\n        guard let host = CoinbaseWalletSDK.host,\n              let callback = CoinbaseWalletSDK.callback else {\n            preconditionFailure(\"Missing configuration: call `CoinbaseWalletSDK.configure` before accessing the `shared` instance.\")\n        }\n        \n        return CoinbaseWalletSDK(host: host, callback: callback)\n    }()\n    \n    // MARK: - Properties\n    \n    private let appId: String\n    private let host: URL\n    private let callback: URL\n    \n    private lazy var keyManager: KeyManager = {\n        KeyManager(host: self.host)\n    }()\n    private lazy var taskManager: TaskManager = {\n        TaskManager()\n    }()\n    \n    private init(\n        host: URL,\n        callback: URL\n    ) {\n        self.host = host\n        self.callback = callback\n        \n        self.appId = Bundle.main.bundleIdentifier!\n    }\n    \n    // MARK: - Send message\n    \n    /// Make handshake request to get session key from wallet\n    /// - Parameters:\n    ///   - initialActions: Batch of actions that you'd want to execute after successful handshake. `eth_requestAccounts` by default.\n    ///   - onResponse: Response callback with regular response result and optional parsed `Account` object.\n    public func initiateHandshake(\n        initialActions: [Action]? = [Action(jsonRpc: .eth_requestAccounts)],\n        onResponse: @escaping (ResponseResult, Account?) -> Void\n    ) {\n        let hasUnsupportedAction = initialActions?.contains { action in\n            [\"eth_signTransaction\", \"eth_sendTransaction\"].contains(where: { action.method == $0 })\n        }\n        \n        guard hasUnsupportedAction != true else {\n            onResponse(.failure(Error.invalidHandshakeRequest), nil)\n            return\n        }\n        \n        try? keyManager.resetOwnPrivateKey()\n        let message = RequestMessage(\n            uuid: UUID(),\n            sender: keyManager.ownPublicKey,\n            content: .handshake(\n                appId: appId,\n                callback: callback,\n                initialActions: initialActions\n            ),\n            version: CoinbaseWalletSDK.version,\n            timestamp: Date(),\n            callbackUrl: callback.absoluteString\n        )\n        self.send(message) { result in\n            guard\n                let requestAccountsIndex = initialActions?.firstIndex(where: { $0.method == \"eth_requestAccounts\" }),\n                let content = try? result.get().content,\n                content.indices.contains(requestAccountsIndex),\n                case .success(let accountJson) = content[requestAccountsIndex],\n                let account = try? accountJson.decode(as: Account.self)\n            else {\n                onResponse(result, nil)\n                return\n            }\n            \n            onResponse(result, account)\n        }\n    }\n    \n    /// Make regular requests. It requires session key you get after successful handshake.\n    public func makeRequest(_ request: Request, onResponse: @escaping ResponseHandler) {\n        let message = RequestMessage(\n            uuid: UUID(),\n            sender: keyManager.ownPublicKey,\n            content: .request(actions: request.actions, account: request.account),\n            version: CoinbaseWalletSDK.version,\n            timestamp: Date(),\n            callbackUrl: callback.absoluteString\n        )\n        return self.send(message, onResponse)\n    }\n    \n    private func send(_ request: RequestMessage, _ onResponse: @escaping ResponseHandler) {\n        let url: URL\n        do {\n            url = try MessageConverter.encode(request, to: host, with: keyManager.symmetricKey)\n        } catch {\n            onResponse(.failure(error))\n            return\n        }\n        \n        UIApplication.shared.open(url) { result in\n            guard result == true else {\n                onResponse(.failure(Error.openUrlFailed))\n                return\n            }\n            \n            self.taskManager.registerResponseHandler(for: request, onResponse)\n        }\n    }\n    \n    // MARK: - Receive message\n    \n    private func isWalletSegueMessage(_ url: URL) -> Bool {\n        return url.host == callback.host && url.path == callback.path\n    }\n\n    /// Handle incoming deep links\n    /// - Parameter url: deep link url\n    /// - Returns: `false` if the input was not response message type, `true` if SDK handled the input, or throws error if it failed to decode response.\n    @discardableResult\n    public func handleResponse(_ url: URL) throws -> Bool {\n        guard isWalletSegueMessage(url) else {\n            return false\n        }\n        \n        let response = try decodeResponse(url)\n        taskManager.runResponseHandler(with: response)\n        return true\n    }\n    \n    private func decodeResponse(_ url: URL) throws -> ResponseMessage {\n        if let symmetricKey = keyManager.symmetricKey {\n            return try MessageConverter.decode(url, with: symmetricKey)\n        }\n        \n        // no symmetric key yet\n        let encryptedResponse: EncryptedResponseMessage = try MessageConverter.decodeWithoutDecryption(url)\n        let request = taskManager.findRequest(for: encryptedResponse)\n        guard case .handshake = request?.content else {\n            throw Error.missingSymmetricKey\n        }\n        \n        try handleHandshakeResponse(encryptedResponse)\n        \n        return try encryptedResponse.decrypt(with: keyManager.symmetricKey)\n    }\n    \n    // MARK: - Session\n    \n    public func isConnected() -> Bool {\n        return keyManager.symmetricKey != nil\n    }\n    \n    public var ownPublicKey: PublicKey {\n        return keyManager.ownPublicKey\n    }\n    \n    public var peerPublicKey: PublicKey? {\n        return keyManager.peerPublicKey\n    }\n    \n    @discardableResult\n    public func resetSession() -> Result<Void, Swift.Error> {\n        do {\n            taskManager.reset()\n            try keyManager.resetOwnPrivateKey()\n            return .success(())\n        } catch {\n            return .failure(error)\n        }\n    }\n    \n    private func handleHandshakeResponse(_ response: EncryptedResponseMessage) throws {\n        if case .failure = response.content {\n            return\n        }\n        \n        try keyManager.storePeerPublicKey(response.sender)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Error.swift",
    "content": "//\n//  Error.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/16/22.\n//\n\nimport Foundation\n\nextension CoinbaseWalletSDK {\n    public enum Error: Swift.Error {\n        case encodingFailed\n        case decodingFailed\n        case missingSymmetricKey\n        case invalidHandshakeRequest\n        case openUrlFailed\n        case walletReturnedError(String)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Host/CoinbaseWalletHostSDK.swift",
    "content": "//\n//  CoinbaseWalletHostSDK.swift\n//  CoinbaseWalletSDK\n//\n//  Created by Jungho Bang on 9/2/22.\n//\n\nimport Foundation\nimport CryptoKit\n\npublic final class CoinbaseWalletHostSDK {\n    public static func deriveSymmetricKey(\n        with ownPrivateKey: CoinbaseWalletSDK.PrivateKey,\n        _ peerPublicKey: CoinbaseWalletSDK.PublicKey\n    ) throws -> SymmetricKey {\n        return try Cipher.deriveSymmetricKey(with: ownPrivateKey, peerPublicKey)\n    }\n    \n    public static func encode<C>(\n        _ message: Message<C>,\n        to recipient: URL,\n        with symmetricKey: SymmetricKey?\n    ) throws -> URL {\n        return try MessageConverter.encode(message, to: recipient, with: symmetricKey)\n    }\n    \n    public static func decode<C>(\n        _ url: URL,\n        with symmetricKey: SymmetricKey?\n    ) throws -> Message<C> {\n        return try MessageConverter.decode(url, with: symmetricKey)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Host/ResponseMessage+init.swift",
    "content": "//\n//  ResponseMessage+init.swift\n//  CoinbaseWalletSDK\n//\n//  Created by Jungho Bang on 9/2/22.\n//\n\nimport Foundation\n\nextension ResponseMessage {\n    public init(\n        uuid: UUID = UUID(),\n        sender: CoinbaseWalletSDK.PublicKey,\n        content: ResponseContent,\n        timestamp: Date = Date()\n    ) {\n        self.uuid = uuid\n        self.sender = sender\n        self.content = content\n        self.version = CoinbaseWalletSDK.version\n        self.timestamp = timestamp\n        self.callbackUrl = nil\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Key/Key+RawRepresentable.swift",
    "content": "//\n//  Key+RawRepresentable.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/13/22.\n//\n\nimport Foundation\n\npublic protocol RawRepresentableKey: Codable {\n    init<D>(rawRepresentation data: D) throws where D: ContiguousBytes\n    var rawRepresentation: Data { get }\n}\n\nextension CoinbaseWalletSDK.PrivateKey: RawRepresentableKey {}\nextension CoinbaseWalletSDK.PublicKey: RawRepresentableKey {}\n\nextension RawRepresentableKey {\n    public init(from decoder: Decoder) throws {\n        let container = try decoder.singleValueContainer()\n        let data = try container.decode(Data.self)\n        try self.init(rawRepresentation: data)\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        try container.encode(self.rawRepresentation)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Key/KeyManager.swift",
    "content": "//\n//  KeyManager.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/9/22.\n//\n\nimport Foundation\nimport CryptoKit\n\nextension CoinbaseWalletSDK {\n    public typealias PrivateKey = Curve25519.KeyAgreement.PrivateKey\n    public typealias PublicKey = Curve25519.KeyAgreement.PublicKey\n}\n\nfinal class KeyManager {\n    private(set) var ownPrivateKey: CoinbaseWalletSDK.PrivateKey\n    var ownPublicKey: CoinbaseWalletSDK.PublicKey {\n        return ownPrivateKey.publicKey\n    }\n    \n    private(set) var peerPublicKey: CoinbaseWalletSDK.PublicKey?\n    \n    private(set) var symmetricKey: SymmetricKey?\n    \n    // MARK: - methods\n    \n    private let storage: KeyStorage\n    \n    init(host: URL) {\n        self.storage = KeyStorage(host: host)\n        \n        guard let storedKey = try? storage.read(.ownPrivateKey) else {\n            // generate new private key\n            self.ownPrivateKey = CoinbaseWalletSDK.PrivateKey()\n            try? self.resetOwnPrivateKey(with: ownPrivateKey)\n            return\n        }\n        self.ownPrivateKey = storedKey\n        \n        self.peerPublicKey = try? storage.read(.peerPublicKey)\n        \n        if let peerPublicKey = self.peerPublicKey {\n            self.symmetricKey = try? Cipher.deriveSymmetricKey(with: ownPrivateKey, peerPublicKey)\n        }\n    }\n    \n    func resetOwnPrivateKey(with key: CoinbaseWalletSDK.PrivateKey = CoinbaseWalletSDK.PrivateKey()) throws {\n        self.symmetricKey = nil\n        self.peerPublicKey = nil\n        self.ownPrivateKey = key\n        \n        try storage.store(key, at: .ownPrivateKey)\n        \n        try storage.delete(.peerPublicKey)\n    }\n    \n    func storePeerPublicKey(_ key: CoinbaseWalletSDK.PublicKey) throws {\n        self.peerPublicKey = key\n        self.symmetricKey = try Cipher.deriveSymmetricKey(with: ownPrivateKey, key)\n        \n        try storage.store(key, at: .peerPublicKey)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Key/KeyStorage.swift",
    "content": "//\n//  KeyStorage.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/17/22.\n//\n\nimport Foundation\n\nfinal class KeyStorage {\n    \n    init(host: URL) {\n        let service = \"wsegue.keystorage.\\((host.isHttp ? host.host : host.scheme) ?? host.absoluteString)\"\n        \n        self.defaultQuery = [\n            kSecAttrService: service,\n            kSecClass: kSecClassGenericPassword,\n            kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,\n            kSecUseDataProtectionKeychain: true\n        ]\n        \n        let isInitializedKey = \"\\(service)-initialized\"\n        if UserDefaults.standard.bool(forKey: isInitializedKey) != true {\n            SecItemDelete(self.defaultQuery as CFDictionary)\n            UserDefaults.standard.set(true, forKey: isInitializedKey)\n        }\n    }\n    \n    private let defaultQuery: [CFString: Any]\n    \n    private func query<K>(\n        for item: KeyStorageItem<K>,\n        with other: [CFString: Any] = [:]\n    ) -> CFDictionary {\n        var query = self.defaultQuery\n        query[kSecAttrAccount] = item.name\n        return query.merging(other, uniquingKeysWith: { $1 }) as CFDictionary\n    }\n    \n    func store<K>(_ data: K, at item: KeyStorageItem<K>) throws {\n        try? self.delete(item)\n        \n        let query = query(for: item, with: [\n            kSecValueData: data.rawRepresentation\n        ])\n        \n        let status = SecItemAdd(query, nil)\n        guard status == errSecSuccess else {\n            throw KeyStorage.Error.storeFailed(status.message)\n        }\n    }\n    \n    func read<K>(_ item: KeyStorageItem<K>) throws -> K? {\n        let query = query(for: item, with: [\n            kSecReturnData: true\n        ])\n        \n        var item: CFTypeRef?\n        switch SecItemCopyMatching(query, &item) {\n        case errSecSuccess:\n            guard let data = item as? Data else { return nil }\n            return try K(rawRepresentation: data)  // Convert back to a key.\n        case errSecItemNotFound:\n            return nil\n        case let status:\n            throw KeyStorage.Error.readFailed(status.message)\n        }\n    }\n    \n    func delete<K>(_ item: KeyStorageItem<K>) throws {\n        let query = query(for: item)\n        \n        switch SecItemDelete(query) {\n        case errSecItemNotFound, errSecSuccess:\n            break // Okay to ignore\n        case let status:\n            throw KeyStorage.Error.deleteFailed(status.message)\n        }\n    }\n}\n\nextension KeyStorage {\n    enum Error: Swift.Error {\n        case storeFailed(String)\n        case readFailed(String)\n        case deleteFailed(String)\n    }\n}\n\nextension OSStatus {\n    var message: String {\n        return (SecCopyErrorMessageString(self, nil) as String?) ?? String(self)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Key/KeyStorageItem.swift",
    "content": "//\n//  KeyStorageItem.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/17/22.\n//\n\nimport Foundation\n\nstruct KeyStorageItem<K: RawRepresentableKey> {\n    let name: String\n    \n    init(_ name: String) {\n        self.name = name\n    }\n\n    static var ownPrivateKey: KeyStorageItem<CoinbaseWalletSDK.PrivateKey> {\n        return KeyStorageItem<CoinbaseWalletSDK.PrivateKey>(\"wsegue.ownPrivateKey\")\n    }\n    \n    static var peerPublicKey: KeyStorageItem<CoinbaseWalletSDK.PublicKey> {\n        return KeyStorageItem<CoinbaseWalletSDK.PublicKey>(\"wsegue.peerPublicKey\")\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Cipher.swift",
    "content": "//\n//  Cryptography.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/17/22.\n//\n\nimport Foundation\nimport CryptoKit\n\nfinal class Cipher {\n    static func encrypt<C: Encodable>(\n        _ content: C,\n        with symmetricKey: SymmetricKey\n    ) throws -> Data {\n        let jsonData = try JSONEncoder().encode(content)\n        let encrypted = try AES.GCM.seal(jsonData, using: symmetricKey).combined!\n        \n        return encrypted\n    }\n    \n    static func decrypt<C: Decodable>(\n        _ data: Data,\n        with symmetricKey: SymmetricKey\n    ) throws -> C {\n        let sealedBox = try AES.GCM.SealedBox(combined: data)\n        let decrypted = try AES.GCM.open(sealedBox, using: symmetricKey)\n        \n        return try JSONDecoder().decode(C.self, from: decrypted)\n    }\n    \n    static func deriveSymmetricKey(\n        with ownPrivateKey: CoinbaseWalletSDK.PrivateKey,\n        _ peerPublicKey: CoinbaseWalletSDK.PublicKey\n    ) throws -> SymmetricKey {\n        let sharedSecret = try ownPrivateKey.sharedSecretFromKeyAgreement(with: peerPublicKey)\n        return sharedSecret.hkdfDerivedSymmetricKey(\n            using: SHA256.self,\n            salt: Data(),\n            sharedInfo: Data(),\n            outputByteCount: 32\n        )\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/EncryptedMessage.swift",
    "content": "//\n//  EncryptedMessage.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/23/22.\n//\n\nimport Foundation\nimport CryptoKit\n\npublic protocol EncryptedContent: CodableContent {\n    associatedtype Unencrypted: UnencryptedContent where Unencrypted.Encrypted == Self\n    \n    func decrypt(with symmetricKey: SymmetricKey?) throws -> Unencrypted\n}\n\ntypealias EncryptedMessage<C> = CodableMessage<C> where C: EncryptedContent\n\nextension EncryptedMessage {\n    func decrypt(with symmetricKey: SymmetricKey?) throws -> Message<C.Unencrypted> {\n        return Message<C.Unencrypted>.copy(\n            self,\n            replaceContentWith: try self.content.decrypt(with: symmetricKey)\n        )\n    }\n}\n\nextension Message {\n    func encrypt(with symmetricKey: SymmetricKey?) throws -> EncryptedMessage<C.Encrypted> {\n        return EncryptedMessage<C.Encrypted>.copy(\n            self,\n            replaceContentWith: try self.content.encrypt(with: symmetricKey)\n        )\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/JSONString.swift",
    "content": "//\n//  JSONString.swift\n//  CoinbaseWalletSDK\n//\n//  Created by Jungho Bang on 8/19/22.\n//\n\nimport Foundation\n\npublic struct JSONString {\n    public let rawValue: String\n    \n    // MARK: Encode\n    \n    public init?<T: Encodable>(encode value: T) {\n        guard let encoded = try? JSONEncoder().encode(value) else { return nil }\n        self.init(encodedData: encoded)\n    }\n    \n    public init?(encode value: [String: Any]) {\n        guard let encoded = try? JSONSerialization.data(withJSONObject: value, options: .fragmentsAllowed) else { return nil }\n        self.init(encodedData: encoded)\n    }\n    \n    private init?(encodedData: Data) {\n        guard let string = String(data: encodedData, encoding: .utf8) else { return nil }\n        self.rawValue = string\n    }\n    \n    // MARK: Decode\n    \n    private var data: Data? { self.rawValue.data(using: .utf8) }\n    \n    public func decode() -> Any? {\n        guard\n            let data = self.data,\n            let object = try? JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)\n        else {\n            return nil\n        }\n        return object\n    }\n    \n    public func decode<T: Decodable>(as type: T.Type) throws -> T? {\n        guard let data = self.data else { return nil }\n        return try JSONDecoder().decode(type, from: data)\n    }\n}\n\nextension JSONString: RawRepresentable, Codable, CustomStringConvertible {\n    public init?(rawValue: String) {\n        self.rawValue = rawValue\n    }\n    \n    public var description: String {\n        self.rawValue\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Message.swift",
    "content": "//\n//  Message.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/13/22.\n//\n\nimport Foundation\nimport CryptoKit\n\npublic typealias Message<C> = CodableMessage<C> where C: UnencryptedContent\n\npublic protocol UnencryptedContent: CodableContent {\n    associatedtype Encrypted: EncryptedContent where Encrypted.Unencrypted == Self\n    \n    func encrypt(with symmetricKey: SymmetricKey?) throws -> Encrypted\n}\n\n// MARK: - base types\n\npublic protocol BaseContent {}\nextension Array: BaseContent where Element: BaseContent {}\n\npublic struct BaseMessage<C: BaseContent> {\n    public let uuid: UUID\n    public let sender: CoinbaseWalletSDK.PublicKey\n    public let content: C\n    public let version: String\n    public let timestamp: Date\n    public let callbackUrl: String?\n\n    static func copy<T>(_ orig: BaseMessage<T>, replaceContentWith content: C) -> BaseMessage<C> {\n        return BaseMessage<C>.init(\n            uuid: orig.uuid,\n            sender: orig.sender,\n            content: content,\n            version: orig.version,\n            timestamp: orig.timestamp,\n            callbackUrl: orig.callbackUrl\n        )\n    }\n}\n\n// MARK: - codable types\nextension BaseMessage: Codable where C: Codable {}\n\npublic protocol CodableContent: BaseContent, Codable {}\nextension Array: CodableContent where Element: CodableContent {}\n\npublic typealias CodableMessage<C> = BaseMessage<C> where C: CodableContent\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/MessageConverter.swift",
    "content": "//\n//  MessageRenderer.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/14/22.\n//\n\nimport Foundation\nimport CryptoKit\n\nfinal class MessageConverter {\n    static func encode<C>(\n        _ message: Message<C>,\n        to recipient: URL,\n        with symmetricKey: SymmetricKey?\n    ) throws -> URL {\n        let encrypted = try message.encrypt(with: symmetricKey)\n        \n        let encoder = JSONEncoder()\n        encoder.dateEncodingStrategy = .millisecondsSince1970\n        let data = try encoder.encode(encrypted)\n        let encodedString = data.base64EncodedString()\n        \n        var urlComponents = URLComponents(url: recipient, resolvingAgainstBaseURL: true)\n        urlComponents?.queryItems = [URLQueryItem(name: \"p\", value: encodedString)]\n        \n        guard let url = urlComponents?.url else {\n            throw CoinbaseWalletSDK.Error.encodingFailed\n        }\n        \n        return url\n    }\n    \n    static func decode<C>(\n        _ url: URL,\n        with symmetricKey: SymmetricKey?\n    ) throws -> Message<C> {\n        let encrypted: EncryptedMessage<C.Encrypted> = try self.decodeWithoutDecryption(url)\n        \n        return try encrypted.decrypt(with: symmetricKey)\n    }\n    \n    static func decodeWithoutDecryption<C>(\n        _ url: URL\n    ) throws -> EncryptedMessage<C> {\n        guard\n            let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false),\n            let queryItem = urlComponents.queryItems?.first(where: { $0.name == \"p\" }),\n            let encodedString = queryItem.value\n        else {\n            throw CoinbaseWalletSDK.Error.decodingFailed\n        }\n        \n        guard let data = Data(base64Encoded: encodedString) else {\n            throw CoinbaseWalletSDK.Error.decodingFailed\n        }\n        \n        let decoder = JSONDecoder()\n        decoder.dateDecodingStrategy = .millisecondsSince1970\n        return try decoder.decode(EncryptedMessage<C>.self, from: data)\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Request/Account.swift",
    "content": "//\n//  Account.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/13/22.\n//\n\nimport Foundation\n\npublic struct Account: Codable {\n    public let chain: String\n    public let networkId: UInt\n    public let address: String\n    \n    public init(chain: String, networkId: UInt, address: String) {\n        self.chain = chain\n        self.networkId = networkId\n        self.address = address\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Request/Action.swift",
    "content": "//\n//  Action.swift\n//  WalletSegueHost\n//\n//  Created by Jungho Bang on 6/21/22.\n//\n\nimport Foundation\n\npublic struct Action: Codable {\n    let method: String\n    let paramsJson: String\n    let optional: Bool\n    \n    public init(method: String, params: [String: Any], optional: Bool = false) {\n        self.method = method\n        self.paramsJson = String(data: try! JSONSerialization.data(withJSONObject: params), encoding: .utf8) ?? \"\"\n        self.optional = optional\n    }\n}\n\nextension Action {\n    public init(jsonRpc: Web3JSONRPC, optional: Bool = false) {\n        let (method, params) = jsonRpc.rawValues\n        self.init(\n            method: method,\n            params: params,\n            optional: optional\n        )\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Request/EncryptedRequestContent.swift",
    "content": "//\n//  EncryptedRequestContent.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/23/22.\n//\n\nimport Foundation\nimport CryptoKit\n\npublic enum EncryptedRequestContent: EncryptedContent {\n    case handshake(appId: String, callback: URL, initialActions: [Action]?)\n    case request(data: Data)\n    \n    public func decrypt(with symmetricKey: SymmetricKey?) throws -> RequestContent {\n        switch self {\n        case let .handshake(appId, callback, initialActions):\n            return .handshake(appId: appId, callback: callback, initialActions: initialActions)\n        case let .request(data):\n            guard let symmetricKey = symmetricKey else {\n                throw CoinbaseWalletSDK.Error.missingSymmetricKey\n            }\n            let request: Request = try Cipher.decrypt(data, with: symmetricKey)\n            return .request(actions: request.actions, account: request.account)\n        }\n    }\n}\n\nextension RequestContent {\n    public func encrypt(with symmetricKey: SymmetricKey?) throws -> EncryptedRequestContent {\n        switch self {\n        case let .handshake(appId, callback, initialActions):\n            return .handshake(appId: appId, callback: callback, initialActions: initialActions)\n        case let .request(actions, account):\n            guard let symmetricKey = symmetricKey else {\n                throw CoinbaseWalletSDK.Error.missingSymmetricKey\n            }\n            let request = Request(actions: actions, account: account)\n            return .request(data: try Cipher.encrypt(request, with: symmetricKey))\n        }\n    }\n}\n\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Request/Request.swift",
    "content": "//\n//  Request.swift\n//  WalletSegueHost\n//\n//  Created by Jungho Bang on 6/21/22.\n//\n\nimport Foundation\n\npublic struct Request: Codable {\n    public let actions: [Action]\n    public let account: Account?\n    \n    public init(actions: [Action], account: Account? = nil) {\n        self.actions = actions\n        self.account = account\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Request/RequestMessage.swift",
    "content": "//\n//  RequestMessage.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/9/22.\n//\n\nimport Foundation\n\npublic enum RequestContent: UnencryptedContent {\n    case handshake(appId: String, callback: URL, initialActions: [Action]?)\n    case request(actions: [Action], account: Account? = nil)\n}\n\npublic typealias RequestMessage = Message<RequestContent>\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Request/Web3JSONRPC.swift",
    "content": "//\n//  Web3JSONRPC.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/28/22.\n//\n\nimport Foundation\n\npublic typealias EthAddress = String\npublic typealias EthTxData = String\npublic typealias BigInt = String\n\npublic enum Web3JSONRPC: Codable {\n    case eth_requestAccounts\n    \n    case personal_sign(\n        address: EthAddress,\n        message: String\n    )\n    \n    case eth_signTypedData_v3(\n        address: EthAddress,\n        typedDataJson: JSONString\n    )\n\n    case eth_signTypedData_v4(\n        address: EthAddress,\n        typedDataJson: JSONString\n    )\n    \n    case eth_signTransaction(\n        fromAddress: EthAddress,\n        toAddress: EthAddress?,\n        weiValue: BigInt,\n        data: EthTxData,\n        nonce: Int?,\n        gasPriceInWei: BigInt?,\n        maxFeePerGas: BigInt?,\n        maxPriorityFeePerGas: BigInt?,\n        gasLimit: BigInt?,\n        chainId: BigInt\n    )\n    \n    case eth_sendTransaction(\n        fromAddress: EthAddress,\n        toAddress: EthAddress?,\n        weiValue: BigInt,\n        data: EthTxData,\n        nonce: Int?,\n        gasPriceInWei: BigInt?,\n        maxFeePerGas: BigInt?,\n        maxPriorityFeePerGas: BigInt?,\n        gasLimit: BigInt?,\n        chainId: BigInt,\n        actionSource: ActionSource?\n    )\n    \n    case wallet_switchEthereumChain(\n        chainId: BigInt\n    )\n    \n    case wallet_addEthereumChain(\n        chainId: BigInt,\n        blockExplorerUrls: [String]?,\n        chainName: String?,\n        iconUrls: [String]?,\n        nativeCurrency: AddChainNativeCurrency?,\n        rpcUrls: [String]\n    )\n    \n    case wallet_watchAsset(\n        type: String,\n        options: WatchAssetOptions\n    )\n    \n    var rawValues: (method: String, params: [String: Any]) {\n        let json = try! JSONEncoder().encode(self)\n        let dictionary = try! JSONSerialization.jsonObject(with: json) as! [String: [String: Any]]\n        \n        let method = dictionary.keys.first!\n        let params = dictionary[method]!\n        return (method, params)\n    }\n}\n\npublic struct AddChainNativeCurrency: Codable {\n    let name: String\n    let symbol: String\n    let decimals: Int\n    \n    public init(name: String, symbol: String, decimals: Int) {\n        self.name = name\n        self.symbol = symbol\n        self.decimals = decimals\n    }\n}\n\npublic struct WatchAssetOptions: Codable {\n    let address: String\n    let symbol: String?\n    let decimals: Int?\n    let image: String?\n    \n    public init(address: String, symbol: String?, decimals: Int?, image: String?) {\n        self.address = address\n        self.symbol = symbol\n        self.decimals = decimals\n        self.image = image\n    }\n}\n\npublic struct ActionSource: Codable {\n    let url: String\n    \n    public init(url: String) {\n        self.url = url\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Response/ActionResult.swift",
    "content": "//\n//  ActionResult.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/24/22.\n//\n\nimport Foundation\n\npublic typealias ActionResult = Result<JSONString, ActionError>\nextension ActionResult: BaseContent {}\n\npublic struct ActionError: Swift.Error {\n    public let code: Int\n    public let message: String\n}\n\npublic typealias ResponseResult = Result<BaseMessage<[ActionResult]>, Error>\n\nextension ResponseContent.Value {\n    var asActionResult: ActionResult {\n        switch self {\n        case let .result(value):\n            return .success(value)\n        case let .error(code, message):\n            return .failure(.init(code: code, message: message))\n        }\n    }\n}\n\npublic typealias ResponseHandler = (ResponseResult) -> Void\n\nextension ResponseMessage {\n    var result: ResponseResult {\n        switch self.content {\n        case .response(_, let values):\n            let results: [ActionResult] = values.map { $0.asActionResult }\n            return .success(\n                BaseMessage<[ActionResult]>.copy(self, replaceContentWith: results)\n            )\n        case .failure(_, let description):\n            return .failure(CoinbaseWalletSDK.Error.walletReturnedError(description))\n        }\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Response/EncryptedResponseContent.swift",
    "content": "//\n//  EncryptedResponseContent.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/23/22.\n//\n\nimport Foundation\nimport CryptoKit\n\npublic enum EncryptedResponseContent: EncryptedContent {\n    case response(requestId: UUID, data: Data)\n    case failure(requestId: UUID, description: String)\n    \n    public func decrypt(with symmetricKey: SymmetricKey?) throws -> ResponseContent {\n        switch self {\n        case let .response(requestId, encryptedResults):\n            guard let symmetricKey = symmetricKey else {\n                throw CoinbaseWalletSDK.Error.missingSymmetricKey\n            }\n            let values: [ResponseContent.Value] = try Cipher.decrypt(encryptedResults, with: symmetricKey)\n            return .response(requestId: requestId, values: values)\n        case let .failure(requestId, description):\n            return .failure(requestId: requestId, description: description)\n        }\n    }\n    \n    var requestId: UUID {\n        switch self {\n        case .response(let requestId, _),\n             .failure(let requestId, _):\n            return requestId\n        }\n    }\n}\n\nextension ResponseContent {\n    public func encrypt(with symmetricKey: SymmetricKey?) throws -> EncryptedResponseContent {\n        switch self {\n        case let .response(requestId, results):\n            guard let symmetricKey = symmetricKey else {\n                throw CoinbaseWalletSDK.Error.missingSymmetricKey\n            }\n            let encrypted = try Cipher.encrypt(results, with: symmetricKey)\n            return .response(requestId: requestId, data: encrypted)\n        case let .failure(requestId, description):\n            return .failure(requestId: requestId, description: description)\n        }\n    }\n}\n\ntypealias EncryptedResponseMessage = EncryptedMessage<EncryptedResponseContent>\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/Response/ResponseMessage.swift",
    "content": "//\n//  Response.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/13/22.\n//\n\nimport Foundation\n\npublic enum ResponseContent: UnencryptedContent {\n    case response(requestId: UUID, values: [Value])\n    case failure(requestId: UUID, description: String)\n    \n    public enum Value: Codable {\n        case result(value: JSONString)\n        case error(code: Int, message: String)\n    }\n    \n    var requestId: UUID {\n        switch self {\n        case .response(let requestId, _),\n             .failure(let requestId, _):\n            return requestId\n        }\n    }\n}\n\npublic typealias ResponseMessage = Message<ResponseContent>\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Message/URL+extension.swift",
    "content": "//\n//  URL+extension.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/29/22.\n//\n\nimport Foundation\n\nextension URL {\n    var isHttp: Bool {\n        return self.scheme?.lowercased().hasPrefix(\"http\") ?? false\n    }\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Resources/CoinbaseWalletSDK+version.swift",
    "content": "//\n//  CoinbaseWalletSDK+version.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 9/12/22.\n//\n\nimport Foundation\n\nextension CoinbaseWalletSDK {\n    // CFBundleShortVersionString doesn't exist if the SDK is built as a static library.\n    static private(set) var version = \"1.1.0\"\n    \n    #if CROSS_PLATFORM\n    static public func appendVersionTag(_ tag: String) {\n        self.version += \"/\\(tag)\"\n    }\n    #endif\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Task/Task.swift",
    "content": "//\n//  Task.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/14/22.\n//\n\nimport Foundation\n\nstruct Task {\n    let request: RequestMessage\n    let handler: ResponseHandler\n    let timestamp: Date\n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Task/TaskManager.swift",
    "content": "//\n//  TaskManager.swift\n//  WalletSegue\n//\n//  Created by Jungho Bang on 6/9/22.\n//\n\nimport Foundation\n\nclass TaskManager {\n    private var tasks = [UUID: Task]()\n    \n    func registerResponseHandler(\n        for request: RequestMessage,\n        _ handler: @escaping ResponseHandler\n    ) {\n        let uuid = request.uuid\n        tasks[uuid] = Task(\n            request: request,\n            handler: handler,\n            timestamp: Date()\n        )\n    }\n    \n    @discardableResult func runResponseHandler(with response: ResponseMessage) -> Bool {\n        let requestId = response.content.requestId\n \n        guard let task = tasks[requestId] else {\n            return false\n        }\n        \n        task.handler(response.result)\n        tasks.removeValue(forKey: requestId)\n        return true\n    }\n    \n    func findRequest(for response: EncryptedResponseMessage) -> RequestMessage? {\n        guard let task = tasks[response.content.requestId] else {\n            return nil\n        }\n    \n        return task.request\n    }\n    \n    func reset() {\n        tasks.removeAll()\n    }\n    \n}\n"
  },
  {
    "path": "ios/CoinbaseWalletSDK/Test/ExampleTest.swift",
    "content": "//\n//  ExampleTest.swift\n//  CoinbaseWalletSDK-Unit-Test\n//\n//  Created by Jungho Bang on 10/7/22.\n//\n\nimport XCTest\n@testable import CoinbaseWalletSDK\n\nclass ExampleTest: XCTestCase {\n\n    func testCoinbaseWalletSDKConfigure() {\n        XCTAssertFalse(CoinbaseWalletSDK.isConfigured)\n        \n        CoinbaseWalletSDK.configure(callback: URL(string: \"myappxyz://mycallback\")!)\n        XCTAssertTrue(CoinbaseWalletSDK.isConfigured)\n    }\n\n}\n"
  },
  {
    "path": "ios/README.md",
    "content": "# Coinbase Wallet Mobile SDK\n\n[![Cocoapods](https://img.shields.io/cocoapods/v/CoinbaseWalletSDK)](https://cocoapods.org/pods/CoinbaseWalletSDK)\n\nCoinbase Wallet Mobile SDK is an open source SDK which allows you to connect your native mobile applications to millions of Coinbase Wallet users.\n\n## Install\n\nThe Coinbase Wallet Mobile SDK is available on both [CocoaPods](https://cocoapods.org/) and [Swift Package Manager](https://swift.org/package-manager).\n\n### Cocoapods\n\nAdd Coinbase Wallet SDK to your `Podfile`.\n\n```ruby\nuse_frameworks!\n\ntarget 'YOUR_TARGET_NAME' do\n    pod 'CoinbaseWalletSDK', '1.1.2'\nend\n```\n\nReplace `YOUR_TARGET_NAME`, and then in the `Podfile` directory run:\n\n```bash\npod install\n```\n\n### Swift Package Manager\n\nAdd Coinbase Wallet SDK to your `Package.swift` file.\n\nUnder **File > Add packages…** enter the package url: [https://github.com/coinbase/wallet-mobile-sdk](https://github.com/coinbase/wallet-mobile-sdk)\n\n```swift\nimport PackageDescription\n\nlet package = Package(\n    name: \"YOUR_PROJECT_NAME\",\n    dependencies: [\n        .package(url: \"https://github.com/coinbase/wallet-mobile-sdk.git\", from: \"1.1.2\"),\n    ]\n)\n```\n\nReplace `YOUR_PROJECT_NAME`, and then run:\n\n```bash\nswift build\n```\n\n## Usage\n\n### Setup\n\nCoinbase Wallet Mobile SDK uses Universal Links to communicate between Coinbase Wallet and your application.\n\nBefore the SDK can be used, it needs to be configured with a Universal Link to your application. This callback URL will be used by the Coinbase Wallet application to navigate back to your application.\n\n```swift\nCoinbaseWalletSDK.configure(\n    callback: URL(string: \"https://myappxyz.com/mycallback\")!\n)\n```\n\nWhen your application receives a response from Coinbase Wallet via a Universal Link, this URL needs to be handed off to the SDK via the handleResponse function.\n\n```swift\nfunc application(_ app: UIApplication, open url: URL ...) -> Bool {\n    if (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n        return true\n    }\n    // handle other types of deep links\n    return false\n}\n```\n\nIt’s recommended to place this configuration logic in the AppDelegate as shown in this [example](https://github.com/coinbase/wallet-mobile-sdk/blob/master/ios/example/SampleClient/AppDelegate.swift#L19).\n\n### Establishing a connection\n\nA connection to Coinbase Wallet can be initiated by calling the `initiateHandshake` function provided by the SDK. The function also takes in an optional `initialActions` parameter which apps can use to take certain actions along with the initial handshake request.\n\n```swift\nprivate let cbwallet = CoinbaseWalletSDK.shared\n\ncbwallet.initiateHandshake(\n    initialActions: [\n        Action(jsonRpc: .eth_requestAccounts)\n    ]\n) { result, account in\n    switch result {\n    case .success(let response):\n        self.logObject(label: \"Response:\\n\", response)\n\n        guard let account = account else { return }\n        self.logObject(label: \"Account:\\n\", account)\n        self.address = account.address\n    case .failure(let error):\n        self.log(\"\\(error)\")\n    }\n    self.updateSessionStatus()\n}\n```\n\nAn example handshake request is provided in the sample [application](https://github.com/coinbase/wallet-mobile-sdk/blob/master/ios/example/SampleClient/ViewController.swift#L63).\n\n### Making requests\n\nRequests to Coinbase Wallet can be made by calling the `makeRequest` function provided by the SDK. This function also accepts a list of `actions` that can be taken in as a single batch request.\n\n```swift\ncbwallet.makeRequest(\n    Request(actions: [\n        Action(jsonRpc: .eth_signTypedData_v3(\n            address: \"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\n            message: Data()))\n    ])\n) { result in\n    self.log(\"\\(result)\")\n}\n```\n\nAn example request is provided in the sample [application](https://github.com/coinbase/coinbase-wallet-sdk/blob/master/examples/native-sdk-ios-client/SampleApp/ViewController.swift#L29).\n\nFor more information on the types of requests you can make, visit our [developer documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs/mobile-sdk-overview).\n\n## References\n- Coinbase Wallet [Developer Documentation](https://docs.cloud.coinbase.com/wallet-sdk/docs)\n- Questions? Visit our [Developer Forums](https://forums.coinbasecloud.dev/).\n- For bugs, please report an issue on Github.\n\n## License\n\n```\nCopyright © 2022 Coinbase, Inc. <https://www.coinbase.com/>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n"
  },
  {
    "path": "ios/example/Podfile",
    "content": "workspace 'Example.xcworkspace'\nplatform :ios, '13.0'\nuse_frameworks!\n\ntarget 'SampleClient' do\n  project 'SampleClient'\n  pod 'CoinbaseWalletSDK', path: '../../', :testspecs => ['Test']\nend\n\ntarget 'SampleWallet' do\n  project 'SampleWallet'\n  pod 'CoinbaseWalletSDK/Host', path: '../../'\nend\n"
  },
  {
    "path": "ios/example/README.md",
    "content": "![demo](./demo.gif)"
  },
  {
    "path": "ios/example/SampleClient/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  SampleWeb3App\n//\n//  Created by Jungho Bang on 6/27/22.\n//\n\nimport UIKit\nimport CoinbaseWalletSDK\n\n@main\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n    var window: UIWindow?\n    \n    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {\n        UIApplication.swizzleOpenURL()\n        \n        #warning(\"Should use universal links in production\")\n        CoinbaseWalletSDK.configure(\n//            host: URL(string: \"samplewallet://wsegue\")!,\n            callback: URL(string: \"myappxyz://mycallback\")!\n        )\n        \n        return true\n    }\n    \n    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {\n        if (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n            return true\n        }\n        // handle other types of deep links\n        return false\n    }\n    \n    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {\n        if let url = userActivity.webpageURL,\n           (try? CoinbaseWalletSDK.shared.handleResponse(url)) == true {\n            return true\n        }\n        // handle other types of deep links\n        return false\n    }\n\n}\n\nextension UIApplication {\n    static func swizzleOpenURL() {\n        guard\n            let original = class_getInstanceMethod(UIApplication.self, #selector(open(_:options:completionHandler:))),\n            let swizzled = class_getInstanceMethod(UIApplication.self, #selector(swizzledOpen(_:options:completionHandler:)))\n        else { return }\n        method_exchangeImplementations(original, swizzled)\n    }\n    \n    @objc func swizzledOpen(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey: Any], completionHandler completion: ((Bool) -> Void)?) {\n        logWalletSegueMessage(url: url)\n        \n        // it's not recursive. below is actually the original open(_:) method\n        self.swizzledOpen(url, options: options, completionHandler: completion)\n    }\n}\n\nfunc logWalletSegueMessage(url: URL, function: String = #function) {\n    let keyWindow = UIApplication.shared.connectedScenes\n            .filter({$0.activationState == .foregroundActive})\n            .compactMap({$0 as? UIWindowScene})\n            .first?.windows\n            .filter({$0.isKeyWindow}).first\n    if let vc = keyWindow?.rootViewController as? ViewController {\n        vc.logURL(url, function: function)\n    }\n}\n"
  },
  {
    "path": "ios/example/SampleClient/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"20037\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"N0H-g8-v1I\">\n    <device id=\"retina6_1\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"20020\"/>\n        <capability name=\"System colors in document resources\" minToolsVersion=\"11.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"zug-Ox-8lY\">\n            <objects>\n                <tableViewController id=\"N0H-g8-v1I\" customClass=\"ViewController\" customModule=\"NativeWeb3App\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <tableView key=\"view\" clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"static\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"-1\" estimatedRowHeight=\"-1\" sectionHeaderHeight=\"18\" estimatedSectionHeaderHeight=\"-1\" sectionFooterHeight=\"18\" estimatedSectionFooterHeight=\"-1\" id=\"fK4-3E-Da2\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"896\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\"/>\n                        <sections>\n                            <tableViewSection id=\"1cD-BP-bqt\">\n                                <cells>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" textLabel=\"XMs-AC-dDw\" detailTextLabel=\"crr-DB-0oO\" style=\"IBUITableViewCellStyleValue2\" id=\"TZr-pJ-2rz\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"18\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"TZr-pJ-2rz\" id=\"gRR-Nr-iUX\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"isCBWInstalled\" textAlignment=\"right\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"XMs-AC-dDw\">\n                                                    <rect key=\"frame\" x=\"20\" y=\"15\" width=\"91\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"bool\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"crr-DB-0oO\">\n                                                    <rect key=\"frame\" x=\"117\" y=\"15\" width=\"25\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                            </subviews>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" textLabel=\"bIA-Fa-7iI\" detailTextLabel=\"aQU-OY-KUj\" style=\"IBUITableViewCellStyleValue2\" id=\"oiO-9C-Bhr\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"61.5\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"oiO-9C-Bhr\" id=\"vlQ-II-7Nj\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"isConnected\" textAlignment=\"right\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"bIA-Fa-7iI\">\n                                                    <rect key=\"frame\" x=\"20\" y=\"15\" width=\"91\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"bool\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"aQU-OY-KUj\">\n                                                    <rect key=\"frame\" x=\"117\" y=\"15\" width=\"25\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                            </subviews>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" textLabel=\"Pah-Wo-mhl\" detailTextLabel=\"kmY-1i-sqZ\" style=\"IBUITableViewCellStyleValue2\" id=\"JIf-L3-HZ0\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"105\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"JIf-L3-HZ0\" id=\"Yy5-ga-LhL\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"ownPubKey\" textAlignment=\"right\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"Pah-Wo-mhl\">\n                                                    <rect key=\"frame\" x=\"20\" y=\"15\" width=\"91\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"string\" textAlignment=\"natural\" lineBreakMode=\"middleTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"kmY-1i-sqZ\">\n                                                    <rect key=\"frame\" x=\"117\" y=\"15\" width=\"32.5\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                            </subviews>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" textLabel=\"Zi0-rV-vVI\" detailTextLabel=\"Ax0-s5-kcP\" style=\"IBUITableViewCellStyleValue2\" id=\"yFs-wz-EUW\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"148.5\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"yFs-wz-EUW\" id=\"e9K-23-pZe\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"peerPubKey\" textAlignment=\"right\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"Zi0-rV-vVI\">\n                                                    <rect key=\"frame\" x=\"20\" y=\"15\" width=\"91\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                                <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"string\" textAlignment=\"natural\" lineBreakMode=\"middleTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"Ax0-s5-kcP\">\n                                                    <rect key=\"frame\" x=\"117\" y=\"15\" width=\"32.5\" height=\"14.5\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"0.0\"/>\n                                                    <nil key=\"textColor\"/>\n                                                    <nil key=\"highlightedColor\"/>\n                                                </label>\n                                            </subviews>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"none\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" id=\"MDv-N0-vVu\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"192\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"MDv-N0-vVu\" id=\"I60-ow-F4F\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" buttonType=\"system\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"f0g-3n-F8G\">\n                                                    <rect key=\"frame\" x=\"6\" y=\"6\" width=\"402\" height=\"31.5\"/>\n                                                    <state key=\"normal\" title=\"Button\"/>\n                                                    <buttonConfiguration key=\"configuration\" style=\"filled\" title=\"Initiate handshake\"/>\n                                                    <connections>\n                                                        <action selector=\"initiateHandshake\" destination=\"N0H-g8-v1I\" eventType=\"touchUpInside\" id=\"3SX-uc-nCS\"/>\n                                                    </connections>\n                                                </button>\n                                            </subviews>\n                                            <constraints>\n                                                <constraint firstItem=\"f0g-3n-F8G\" firstAttribute=\"centerX\" secondItem=\"I60-ow-F4F\" secondAttribute=\"centerX\" id=\"129-dN-ifQ\"/>\n                                                <constraint firstItem=\"f0g-3n-F8G\" firstAttribute=\"top\" secondItem=\"I60-ow-F4F\" secondAttribute=\"topMargin\" constant=\"-5\" id=\"YYh-Qh-kb4\"/>\n                                                <constraint firstItem=\"f0g-3n-F8G\" firstAttribute=\"centerY\" secondItem=\"I60-ow-F4F\" secondAttribute=\"centerY\" id=\"o19-K7-jVy\"/>\n                                                <constraint firstItem=\"f0g-3n-F8G\" firstAttribute=\"leading\" secondItem=\"I60-ow-F4F\" secondAttribute=\"leadingMargin\" constant=\"-14\" id=\"ug1-r0-wzn\"/>\n                                            </constraints>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"default\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" id=\"9Xf-Eq-qch\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"235.5\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"9Xf-Eq-qch\" id=\"Nvt-rd-Kzh\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" buttonType=\"system\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UFh-Jt-LEP\">\n                                                    <rect key=\"frame\" x=\"6\" y=\"6\" width=\"402\" height=\"31.5\"/>\n                                                    <state key=\"normal\" title=\"Button\"/>\n                                                    <buttonConfiguration key=\"configuration\" style=\"filled\" title=\"Reset connection\"/>\n                                                    <connections>\n                                                        <action selector=\"resetConnection\" destination=\"N0H-g8-v1I\" eventType=\"touchUpInside\" id=\"MrE-Td-fVn\"/>\n                                                    </connections>\n                                                </button>\n                                            </subviews>\n                                            <constraints>\n                                                <constraint firstItem=\"UFh-Jt-LEP\" firstAttribute=\"centerY\" secondItem=\"Nvt-rd-Kzh\" secondAttribute=\"centerY\" id=\"7dL-fu-KmW\"/>\n                                                <constraint firstItem=\"UFh-Jt-LEP\" firstAttribute=\"leading\" secondItem=\"Nvt-rd-Kzh\" secondAttribute=\"leadingMargin\" constant=\"-14\" id=\"Mbb-QD-ih0\"/>\n                                                <constraint firstItem=\"UFh-Jt-LEP\" firstAttribute=\"centerX\" secondItem=\"Nvt-rd-Kzh\" secondAttribute=\"centerX\" id=\"NOQ-Wx-Y2k\"/>\n                                                <constraint firstItem=\"UFh-Jt-LEP\" firstAttribute=\"top\" secondItem=\"Nvt-rd-Kzh\" secondAttribute=\"topMargin\" constant=\"-5\" id=\"pJ8-md-cTD\"/>\n                                            </constraints>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"default\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" id=\"TTq-yp-kei\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"279\" width=\"414\" height=\"43.5\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"TTq-yp-kei\" id=\"3Hl-hx-44M\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" buttonType=\"system\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dpB-W6-PM0\">\n                                                    <rect key=\"frame\" x=\"6\" y=\"6\" width=\"402\" height=\"31.5\"/>\n                                                    <state key=\"normal\" title=\"Button\"/>\n                                                    <buttonConfiguration key=\"configuration\" style=\"filled\" title=\"Make request\"/>\n                                                    <connections>\n                                                        <action selector=\"makeRequest\" destination=\"N0H-g8-v1I\" eventType=\"touchUpInside\" id=\"I8M-jS-DMV\"/>\n                                                    </connections>\n                                                </button>\n                                            </subviews>\n                                            <constraints>\n                                                <constraint firstItem=\"dpB-W6-PM0\" firstAttribute=\"centerX\" secondItem=\"3Hl-hx-44M\" secondAttribute=\"centerX\" id=\"I2F-d0-Dk9\"/>\n                                                <constraint firstItem=\"dpB-W6-PM0\" firstAttribute=\"top\" secondItem=\"3Hl-hx-44M\" secondAttribute=\"topMargin\" constant=\"-5\" id=\"MZ3-rN-ZWf\"/>\n                                                <constraint firstItem=\"dpB-W6-PM0\" firstAttribute=\"centerY\" secondItem=\"3Hl-hx-44M\" secondAttribute=\"centerY\" id=\"UXD-Mk-QxF\"/>\n                                                <constraint firstItem=\"dpB-W6-PM0\" firstAttribute=\"leading\" secondItem=\"3Hl-hx-44M\" secondAttribute=\"leadingMargin\" constant=\"-14\" id=\"sVN-if-X5P\"/>\n                                            </constraints>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                </cells>\n                            </tableViewSection>\n                            <tableViewSection headerTitle=\"log\" id=\"hdE-4l-6RU\">\n                                <cells>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" insetsLayoutMarginsFromSafeArea=\"NO\" selectionStyle=\"blue\" hidesAccessoryWhenEditing=\"NO\" indentationLevel=\"1\" indentationWidth=\"0.0\" rowHeight=\"400\" id=\"7Ix-hF-4f6\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"372.5\" width=\"414\" height=\"400\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"7Ix-hF-4f6\" id=\"hR3-G0-o2o\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"400\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                            <subviews>\n                                                <textView clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"scaleToFill\" editable=\"NO\" textAlignment=\"natural\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PlN-Ph-shZ\">\n                                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"400\"/>\n                                                    <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\"/>\n                                                    <color key=\"textColor\" systemColor=\"labelColor\"/>\n                                                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                                    <textInputTraits key=\"textInputTraits\" autocapitalizationType=\"sentences\"/>\n                                                </textView>\n                                            </subviews>\n                                            <constraints>\n                                                <constraint firstItem=\"PlN-Ph-shZ\" firstAttribute=\"top\" secondItem=\"hR3-G0-o2o\" secondAttribute=\"top\" id=\"FYk-FQ-Jq1\"/>\n                                                <constraint firstAttribute=\"bottom\" secondItem=\"PlN-Ph-shZ\" secondAttribute=\"bottom\" id=\"QKc-h9-7Yn\"/>\n                                                <constraint firstAttribute=\"trailing\" secondItem=\"PlN-Ph-shZ\" secondAttribute=\"trailing\" id=\"Qxs-hq-uaU\"/>\n                                                <constraint firstItem=\"PlN-Ph-shZ\" firstAttribute=\"leading\" secondItem=\"hR3-G0-o2o\" secondAttribute=\"leading\" id=\"c6s-Ww-A8k\"/>\n                                            </constraints>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                </cells>\n                            </tableViewSection>\n                        </sections>\n                        <connections>\n                            <outlet property=\"dataSource\" destination=\"N0H-g8-v1I\" id=\"4Ky-tr-Rnr\"/>\n                            <outlet property=\"delegate\" destination=\"N0H-g8-v1I\" id=\"TYV-RP-LAU\"/>\n                        </connections>\n                    </tableView>\n                    <connections>\n                        <outlet property=\"isCBWalletInstalledLabel\" destination=\"crr-DB-0oO\" id=\"OT3-0e-g8G\"/>\n                        <outlet property=\"isConnectedLabel\" destination=\"aQU-OY-KUj\" id=\"iPl-4X-Fjj\"/>\n                        <outlet property=\"logTextView\" destination=\"PlN-Ph-shZ\" id=\"BW2-a7-hgy\"/>\n                        <outlet property=\"ownPubKeyLabel\" destination=\"kmY-1i-sqZ\" id=\"R7K-YM-JdI\"/>\n                        <outlet property=\"peerPubKeyLabel\" destination=\"Ax0-s5-kcP\" id=\"Mlr-FA-CDT\"/>\n                    </connections>\n                </tableViewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"wdV-MQ-XPI\" userLabel=\"First Responder\" customClass=\"UIResponder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"142.02898550724638\" y=\"132.58928571428572\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <systemColor name=\"labelColor\">\n            <color white=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n        </systemColor>\n        <systemColor name=\"systemBackgroundColor\">\n            <color white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n        </systemColor>\n    </resources>\n</document>\n"
  },
  {
    "path": "ios/example/SampleClient/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Editor</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>xyz.myapp</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>myappxyz</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n\t<key>LSApplicationQueriesSchemes</key>\n\t<array>\n\t\t<string>cbwallet</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/example/SampleClient/ViewController.swift",
    "content": "//\n//  ViewController.swift\n//  SampleWeb3App\n//\n//  Created by Jungho Bang on 6/27/22.\n//\n\nimport UIKit\nimport CoinbaseWalletSDK\n\nclass ViewController: UITableViewController {\n    \n    @IBOutlet weak var isCBWalletInstalledLabel: UILabel!\n    @IBOutlet weak var isConnectedLabel: UILabel!\n    @IBOutlet weak var ownPubKeyLabel: UILabel!\n    @IBOutlet weak var peerPubKeyLabel: UILabel!\n    \n    @IBOutlet weak var logTextView: UITextView!\n    \n    private lazy var cbwallet = { CoinbaseWalletSDK.shared }()\n    private var address: String?\n    private let typedData = [\n        \"types\": [\n            \"EIP712Domain\": [\n                [\"name\": \"name\", \"type\": \"string\"],\n                [\"name\": \"version\", \"type\": \"string\"],\n                [\"name\": \"chainId\", \"type\": \"uint256\"],\n                [\"name\": \"verifyingContract\", \"type\": \"address\"],\n                [\"name\": \"salt\", \"type\": \"bytes32\"],\n            ],\n            \"Bid\": [\n                [\"name\": \"amount\", \"type\": \"uint256\"],\n                [\"name\": \"bidder\", \"type\": \"Identity\"],\n            ],\n            \"Identity\": [\n                [\"name\": \"userId\", \"type\": \"uint256\"],\n                [\"name\": \"wallet\", \"type\": \"address\"],\n            ],\n        ],\n        \"domain\": [\n            \"name\": \"DApp Browser Test DApp\",\n            \"version\": \"1\",\n            \"chainId\": 1,\n            \"verifyingContract\": \"0x1C56346CD2A2Bf3202F771f50d3D14a367B48070\",\n            \"salt\": \"0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558\",\n        ],\n        \"primaryType\": \"Bid\",\n        \"message\": [\n            \"amount\": 100,\n            \"bidder\": [\n                \"userId\": 323,\n                \"wallet\": \"0x3333333333333333333333333333333333333333\"\n            ],\n        ],\n    ] as [String: Any]\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        isCBWalletInstalledLabel.text = \"\\(CoinbaseWalletSDK.isCoinbaseWalletInstalled())\"\n        self.log(\"Available MWP Version: \\(CoinbaseWalletSDK.getCoinbaseWalletMWPVersion() ?? \"none\")\")\n        updateSessionStatus()\n    }\n    \n    @IBAction func initiateHandshake() {\n        cbwallet.initiateHandshake(\n            initialActions: [\n                Action(jsonRpc: .eth_requestAccounts)\n            ]\n        ) { result, account in\n            switch result {\n            case .success(let response):\n                self.log(\"Response: \\(response.content)\")\n                \n                guard let account = account else { return }\n                self.logObject(label: \"Account:\\n\", account)\n                self.address = account.address\n                \n            case .failure(let error):\n                self.log(\"\\(error)\")\n            }\n            self.updateSessionStatus()\n        }\n    }\n    \n    @IBAction func resetConnection() {\n        self.address = nil\n        \n        let result = cbwallet.resetSession()\n        self.log(\"\\(result)\")\n        \n        updateSessionStatus()\n    }\n    \n    @IBAction func makeRequest() {\n        let address = self.address ?? \"\"\n        if address.isEmpty {\n            self.log(\"address hasn't been set.\")\n        }\n        \n        cbwallet.makeRequest(\n            Request(actions: [\n                Action(jsonRpc: .personal_sign(address: address, message: \"message\")),\n                Action(jsonRpc: .eth_signTypedData_v3(\n                    address: address,\n                    typedDataJson: JSONString(encode: typedData)!\n                ))\n            ])\n        ) { result in\n            guard case .success(let response) = result else {\n                self.log(\"error: \\(result)\")\n                return\n            }\n            \n            for returnValue in response.content {\n                switch returnValue {\n                case .success(let value):\n                    self.log(\"result (raw JSON): \\(value)\")\n                    if let decoded = value.decode() {\n                        self.log(\"result (decoded): \\(decoded)\")\n                    }\n                case .failure(let error):\n                    self.log(\"error \\(error.code): \\(error.message)\")\n                }\n            }\n        }\n    }\n    \n    // i should have chosen SwiftUI template...\n    \n    private func updateSessionStatus() {\n        DispatchQueue.main.async {\n            let isConnected = self.cbwallet.isConnected()\n            self.isConnectedLabel.textColor = isConnected ? .green : .red\n            self.isConnectedLabel.text = \"\\(isConnected)\"\n            \n            self.ownPubKeyLabel.text = self.cbwallet.ownPublicKey.rawRepresentation.base64EncodedString()\n            self.peerPubKeyLabel.text = self.cbwallet.peerPublicKey?.rawRepresentation.base64EncodedString() ?? \"(nil)\"\n        }\n    }\n    \n    private func logObject<T: Encodable>(label: String = \"\", _ object: T, function: String = #function) {\n        do {\n            let encoder = JSONEncoder()\n            encoder.outputFormatting = .prettyPrinted\n            let data = try encoder.encode(object)\n            let jsonString = String(data: data, encoding: .utf8)!\n            self.log(\"\\(label)\\(jsonString)\", function: function)\n        } catch {\n            self.log(\"\\(error)\")\n        }\n    }\n    \n    func logURL(_ url: URL?, function: String = #function) {\n        guard let url = url else { return }\n        self.log(\"URL: \\(url)\", function: function)\n    }\n    \n    private func log(_ text: String, function: String = #function) {\n        DispatchQueue.main.async {\n            self.logTextView.text = \"\\(function): \\(text)\\n\\n\\(self.logTextView.text ?? \"\")\"\n            //  self.logTextView.text += \"\\(function): \\(text)\\n\\n\"\n            //  self.logTextView.scrollRangeToVisible(NSMakeRange(self.logTextView.text.count - 1, 1))\n        }\n    }\n}\n\n"
  },
  {
    "path": "ios/example/SampleClient.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 55;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t5DA9B3CF286A755E0089D6DB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA9B3CE286A755E0089D6DB /* AppDelegate.swift */; };\n\t\t5DA9B3D3286A755E0089D6DB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA9B3D2286A755E0089D6DB /* ViewController.swift */; };\n\t\t5DA9B3D6286A755E0089D6DB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5DA9B3D4286A755E0089D6DB /* Main.storyboard */; };\n\t\tD6752D43EA87EC720AB457B0 /* Pods_SampleClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D748670EFBABCFCAAF467051 /* Pods_SampleClient.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t5DA9B3CB286A755E0089D6DB /* SampleClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleClient.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t5DA9B3CE286A755E0089D6DB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t5DA9B3D2286A755E0089D6DB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = \"<group>\"; };\n\t\t5DA9B3D5286A755E0089D6DB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t5DA9B3DC286A755F0089D6DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t6AD987FC34FA605B42114137 /* Pods-SampleClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-SampleClient.release.xcconfig\"; path = \"Target Support Files/Pods-SampleClient/Pods-SampleClient.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tAD64CFD01D3AB9B726DF335B /* Pods-NativeWeb3App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NativeWeb3App.release.xcconfig\"; path = \"Target Support Files/Pods-NativeWeb3App/Pods-NativeWeb3App.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tBE1C572549E74BC10010E50C /* Pods-SampleClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-SampleClient.debug.xcconfig\"; path = \"Target Support Files/Pods-SampleClient/Pods-SampleClient.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tD748670EFBABCFCAAF467051 /* Pods_SampleClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tFC120F48CB37E5C1FAFE2CAE /* Pods-NativeWeb3App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-NativeWeb3App.debug.xcconfig\"; path = \"Target Support Files/Pods-NativeWeb3App/Pods-NativeWeb3App.debug.xcconfig\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t5DA9B3C8286A755E0089D6DB /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD6752D43EA87EC720AB457B0 /* Pods_SampleClient.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t3E18EF9C1E2A7D3BF660A5CD /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD748670EFBABCFCAAF467051 /* Pods_SampleClient.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51AC5D6DCCB61B979D9D716E /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFC120F48CB37E5C1FAFE2CAE /* Pods-NativeWeb3App.debug.xcconfig */,\n\t\t\t\tAD64CFD01D3AB9B726DF335B /* Pods-NativeWeb3App.release.xcconfig */,\n\t\t\t\tBE1C572549E74BC10010E50C /* Pods-SampleClient.debug.xcconfig */,\n\t\t\t\t6AD987FC34FA605B42114137 /* Pods-SampleClient.release.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5DA9B3C2286A755E0089D6DB = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5DA9B3CD286A755E0089D6DB /* SampleClient */,\n\t\t\t\t5DA9B3CC286A755E0089D6DB /* Products */,\n\t\t\t\t51AC5D6DCCB61B979D9D716E /* Pods */,\n\t\t\t\t3E18EF9C1E2A7D3BF660A5CD /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5DA9B3CC286A755E0089D6DB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5DA9B3CB286A755E0089D6DB /* SampleClient.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5DA9B3CD286A755E0089D6DB /* SampleClient */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5DA9B3CE286A755E0089D6DB /* AppDelegate.swift */,\n\t\t\t\t5DA9B3D2286A755E0089D6DB /* ViewController.swift */,\n\t\t\t\t5DA9B3D4286A755E0089D6DB /* Main.storyboard */,\n\t\t\t\t5DA9B3DC286A755F0089D6DB /* Info.plist */,\n\t\t\t);\n\t\t\tpath = SampleClient;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t5DA9B3CA286A755E0089D6DB /* SampleClient */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 5DA9B3DF286A755F0089D6DB /* Build configuration list for PBXNativeTarget \"SampleClient\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t29FDABA7E59E1339DA4167A7 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t5DA9B3C7286A755E0089D6DB /* Sources */,\n\t\t\t\t5DA9B3C8286A755E0089D6DB /* Frameworks */,\n\t\t\t\t5DA9B3C9286A755E0089D6DB /* Resources */,\n\t\t\t\t4A2E3B84F8F828F77205E15C /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = SampleClient;\n\t\t\tproductName = NativeWeb3App;\n\t\t\tproductReference = 5DA9B3CB286A755E0089D6DB /* SampleClient.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t5DA9B3C3286A755E0089D6DB /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = 1;\n\t\t\t\tLastSwiftUpdateCheck = 1330;\n\t\t\t\tLastUpgradeCheck = 1330;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t5DA9B3CA286A755E0089D6DB = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 13.3.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 5DA9B3C6286A755E0089D6DB /* Build configuration list for PBXProject \"SampleClient\" */;\n\t\t\tcompatibilityVersion = \"Xcode 13.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 5DA9B3C2286A755E0089D6DB;\n\t\t\tproductRefGroup = 5DA9B3CC286A755E0089D6DB /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t5DA9B3CA286A755E0089D6DB /* SampleClient */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t5DA9B3C9286A755E0089D6DB /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5DA9B3D6286A755E0089D6DB /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t29FDABA7E59E1339DA4167A7 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-SampleClient-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t4A2E3B84F8F828F77205E15C /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-SampleClient/Pods-SampleClient-frameworks-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-SampleClient/Pods-SampleClient-frameworks-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-SampleClient/Pods-SampleClient-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t5DA9B3C7286A755E0089D6DB /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5DA9B3D3286A755E0089D6DB /* ViewController.swift in Sources */,\n\t\t\t\t5DA9B3CF286A755E0089D6DB /* AppDelegate.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t5DA9B3D4286A755E0089D6DB /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t5DA9B3D5286A755E0089D6DB /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t5DA9B3DD286A755F0089D6DB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.4;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t5DA9B3DE286A755F0089D6DB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.4;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t5DA9B3E0286A755F0089D6DB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = BE1C572549E74BC10010E50C /* Pods-SampleClient.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = B7Y3D73M65;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = SampleClient/Info.plist;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchStoryboardName = Main;\n\t\t\t\tINFOPLIST_KEY_UIMainStoryboardFile = Main;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.coinbase.SampleClient;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t5DA9B3E1286A755F0089D6DB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 6AD987FC34FA605B42114137 /* Pods-SampleClient.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = B7Y3D73M65;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = SampleClient/Info.plist;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchStoryboardName = Main;\n\t\t\t\tINFOPLIST_KEY_UIMainStoryboardFile = Main;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.coinbase.SampleClient;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t5DA9B3C6286A755E0089D6DB /* Build configuration list for PBXProject \"SampleClient\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t5DA9B3DD286A755F0089D6DB /* Debug */,\n\t\t\t\t5DA9B3DE286A755F0089D6DB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t5DA9B3DF286A755F0089D6DB /* Build configuration list for PBXNativeTarget \"SampleClient\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t5DA9B3E0286A755F0089D6DB /* Debug */,\n\t\t\t\t5DA9B3E1286A755F0089D6DB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 5DA9B3C3286A755E0089D6DB /* Project object */;\n}\n"
  },
  {
    "path": "ios/example/SampleWallet/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  SampleWallet\n//\n//  Created by Jungho Bang on 7/1/22.\n//\n\nimport UIKit\nimport CoinbaseWalletSDK\nimport CryptoKit\n\n@main\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n    var window: UIWindow?\n    \n    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {\n        handleWalletSegue(url: url)\n        return true\n    }\n    \n    private var ownPrivateKey: CoinbaseWalletSDK.PrivateKey?\n    private var peerPublicKey: CoinbaseWalletSDK.PublicKey?\n    private var requestMessage: RequestMessage?\n    private var peerCallback: URL?\n}\n\nextension AppDelegate: UIAlertViewDelegate {\n    typealias AlertView = UIAlertView\n    \n    private var symmetricKey: SymmetricKey? {\n        guard let o = ownPrivateKey, let p = peerPublicKey else {\n            return nil\n        }\n        \n        return try? CoinbaseWalletHostSDK.deriveSymmetricKey(with: o, p)\n    }\n    \n    func handleWalletSegue(url: URL) {\n        guard let request: RequestMessage = try? CoinbaseWalletHostSDK.decode(url, with: symmetricKey) else { return }\n        \n        self.requestMessage = request\n        if case .handshake(_, let callback, _) = request.content {\n            self.peerCallback = callback\n        }\n        \n        let alert = AlertView(\n            title: \"Request\",\n            message: \"decrypted content: \\(request.content)\",\n            delegate: self,\n            cancelButtonTitle: \"Deny\",\n            otherButtonTitles: \"Confirm\"\n        )\n        alert.show()\n    }\n    \n    func alertView(_ alertView: AlertView, clickedButtonAt buttonIndex: Int) {\n        guard let requestMessage = requestMessage else { preconditionFailure() }\n        \n        let content: ResponseContent\n        let sender: CoinbaseWalletSDK.PublicKey\n        if buttonIndex == 0 { // cancel\n            content = .failure(\n                requestId: requestMessage.uuid,\n                description: \"Request denied\"\n            )\n            sender = self.peerPublicKey ?? requestMessage.sender\n        } else {\n            let returnValues: [ResponseContent.Value]\n            switch requestMessage.content {\n            case .handshake:\n                self.peerPublicKey = requestMessage.sender\n                self.ownPrivateKey = CoinbaseWalletSDK.PrivateKey()\n                let account = Account(chain: \"eth\", networkId: 0, address: \"0x571a6a108adb08f9ca54fe8605280F9EE0eD4AF6\")\n                returnValues = [\n                    .result(value: JSONString(encode: account)!)\n                ]\n            case let .request(actions, _):\n                let error: ResponseContent.Value = .error(code: 713, message: \"New CBWallet app will be able to actually handle those requests\")\n                returnValues = actions.map({ _ in error })\n            }\n            \n            content = .response(\n                requestId: requestMessage.uuid,\n                values: returnValues\n            )\n            sender = self.ownPrivateKey!.publicKey\n        }\n        \n        let response = ResponseMessage(\n            sender: sender,\n            content: content\n        )\n        \n        let url = try! CoinbaseWalletHostSDK.encode(\n            response,\n            to: peerCallback!,\n            with: symmetricKey\n        )\n        \n        UIApplication.shared.open(url)\n    }\n}\n"
  },
  {
    "path": "ios/example/SampleWallet/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"20037\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <device id=\"retina6_1\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"20020\"/>\n        <capability name=\"Safe area layout guides\" minToolsVersion=\"9.0\"/>\n        <capability name=\"System colors in document resources\" minToolsVersion=\"11.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"896\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Check out AppDelegate.swift\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jrF-FH-4bC\">\n                                <rect key=\"frame\" x=\"20\" y=\"44\" width=\"222\" height=\"21\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <nil key=\"textColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <viewLayoutGuide key=\"safeArea\" id=\"6Tk-OE-BBY\"/>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\"/>\n                        <constraints>\n                            <constraint firstItem=\"jrF-FH-4bC\" firstAttribute=\"top\" secondItem=\"6Tk-OE-BBY\" secondAttribute=\"top\" id=\"SSQ-nY-tR6\"/>\n                            <constraint firstItem=\"jrF-FH-4bC\" firstAttribute=\"leading\" secondItem=\"8bC-Xf-vdC\" secondAttribute=\"leadingMargin\" id=\"Xvc-cm-1xm\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"20\" y=\"98\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <systemColor name=\"systemBackgroundColor\">\n            <color white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n        </systemColor>\n    </resources>\n</document>\n"
  },
  {
    "path": "ios/example/SampleWallet/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>Editor</string>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>xyz.samplewallet</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>samplewallet</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/example/SampleWallet.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 55;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t5D3DD791286FB22000994152 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D3DD790286FB22000994152 /* AppDelegate.swift */; };\n\t\t5D3DD798286FB22000994152 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5D3DD796286FB22000994152 /* Main.storyboard */; };\n\t\tD6FF46E37F6C3795EE2EFC4E /* Pods_SampleWallet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FF03AF7C2BAC9156E0E106E /* Pods_SampleWallet.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t1372E29251AC61A1A0F6DD2E /* Pods-SampleWallet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-SampleWallet.release.xcconfig\"; path = \"Target Support Files/Pods-SampleWallet/Pods-SampleWallet.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t4515DD36563B470F9D13F93B /* Pods-SampleWallet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-SampleWallet.debug.xcconfig\"; path = \"Target Support Files/Pods-SampleWallet/Pods-SampleWallet.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t5D3DD78D286FB22000994152 /* SampleWallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleWallet.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t5D3DD790286FB22000994152 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t5D3DD797286FB22000994152 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t5D3DD79E286FB22100994152 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t5FF03AF7C2BAC9156E0E106E /* Pods_SampleWallet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleWallet.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t5D3DD78A286FB22000994152 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD6FF46E37F6C3795EE2EFC4E /* Pods_SampleWallet.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t17AE06C6CE18D005E138A0E7 /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t4515DD36563B470F9D13F93B /* Pods-SampleWallet.debug.xcconfig */,\n\t\t\t\t1372E29251AC61A1A0F6DD2E /* Pods-SampleWallet.release.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5D3DD784286FB22000994152 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5D3DD78F286FB22000994152 /* SampleWallet */,\n\t\t\t\t5D3DD78E286FB22000994152 /* Products */,\n\t\t\t\t17AE06C6CE18D005E138A0E7 /* Pods */,\n\t\t\t\t97A965865FD65B9253862A39 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5D3DD78E286FB22000994152 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5D3DD78D286FB22000994152 /* SampleWallet.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5D3DD78F286FB22000994152 /* SampleWallet */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5D3DD790286FB22000994152 /* AppDelegate.swift */,\n\t\t\t\t5D3DD796286FB22000994152 /* Main.storyboard */,\n\t\t\t\t5D3DD79E286FB22100994152 /* Info.plist */,\n\t\t\t);\n\t\t\tpath = SampleWallet;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97A965865FD65B9253862A39 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5FF03AF7C2BAC9156E0E106E /* Pods_SampleWallet.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t5D3DD78C286FB22000994152 /* SampleWallet */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 5D3DD7A1286FB22100994152 /* Build configuration list for PBXNativeTarget \"SampleWallet\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tB4EBEDD6894AC736F4478EC1 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t5D3DD789286FB22000994152 /* Sources */,\n\t\t\t\t5D3DD78A286FB22000994152 /* Frameworks */,\n\t\t\t\t5D3DD78B286FB22000994152 /* Resources */,\n\t\t\t\tA632CA3DEFDD6419D3331B57 /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = SampleWallet;\n\t\t\tproductName = SampleWallet;\n\t\t\tproductReference = 5D3DD78D286FB22000994152 /* SampleWallet.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t5D3DD785286FB22000994152 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = 1;\n\t\t\t\tLastSwiftUpdateCheck = 1330;\n\t\t\t\tLastUpgradeCheck = 1330;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t5D3DD78C286FB22000994152 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 13.3.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 5D3DD788286FB22000994152 /* Build configuration list for PBXProject \"SampleWallet\" */;\n\t\t\tcompatibilityVersion = \"Xcode 13.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 5D3DD784286FB22000994152;\n\t\t\tproductRefGroup = 5D3DD78E286FB22000994152 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t5D3DD78C286FB22000994152 /* SampleWallet */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t5D3DD78B286FB22000994152 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5D3DD798286FB22000994152 /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\tA632CA3DEFDD6419D3331B57 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-SampleWallet/Pods-SampleWallet-frameworks-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-SampleWallet/Pods-SampleWallet-frameworks-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-SampleWallet/Pods-SampleWallet-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tB4EBEDD6894AC736F4478EC1 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-SampleWallet-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t5D3DD789286FB22000994152 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5D3DD791286FB22000994152 /* AppDelegate.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t5D3DD796286FB22000994152 /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t5D3DD797286FB22000994152 /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t5D3DD79F286FB22100994152 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.4;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t5D3DD7A0286FB22100994152 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.4;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t5D3DD7A2286FB22100994152 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 4515DD36563B470F9D13F93B /* Pods-SampleWallet.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = B7Y3D73M65;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = SampleWallet/Info.plist;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UIMainStoryboardFile = Main;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.coinbase.SampleWallet;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t5D3DD7A3286FB22100994152 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1372E29251AC61A1A0F6DD2E /* Pods-SampleWallet.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = B7Y3D73M65;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_FILE = SampleWallet/Info.plist;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UIMainStoryboardFile = Main;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.coinbase.SampleWallet;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t5D3DD788286FB22000994152 /* Build configuration list for PBXProject \"SampleWallet\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t5D3DD79F286FB22100994152 /* Debug */,\n\t\t\t\t5D3DD7A0286FB22100994152 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t5D3DD7A1286FB22100994152 /* Build configuration list for PBXNativeTarget \"SampleWallet\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t5D3DD7A2286FB22100994152 /* Debug */,\n\t\t\t\t5D3DD7A3286FB22100994152 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 5D3DD785286FB22000994152 /* Project object */;\n}\n"
  },
  {
    "path": "react-native/.eslintrc.js",
    "content": "// @generated by expo-module-scripts\nmodule.exports = require('expo-module-scripts/eslintrc.base.js');\n"
  },
  {
    "path": "react-native/.npmignore",
    "content": "example\n"
  },
  {
    "path": "react-native/README.md",
    "content": "# @coinbase/wallet-mobile-sdk\n\nCoinbase Wallet Mobile SDK for React Native\n\n# Installation in bare React Native projects\n\nFor bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing.\n\n### Add the package to your npm dependencies\n\n```\nnpm install @coinbase/wallet-mobile-sdk\n```\n\n### Configure for iOS\n\nRun `npx pod-install` after installing the npm package.\n\n### Configure for Android\n\nNo additional setup necessary.\n"
  },
  {
    "path": "react-native/android/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'maven-publish'\n\ngroup = 'expo.modules.coinbasewalletsdkexpo'\nversion = '0.1.0'\n\nbuildscript {\n  def expoModulesCorePlugin = new File(project(\":expo-modules-core\").projectDir.absolutePath, \"ExpoModulesCorePlugin.gradle\")\n  if (expoModulesCorePlugin.exists()) {\n    apply from: expoModulesCorePlugin\n    applyKotlinExpoModulesCorePlugin()\n  }\n\n  // Simple helper that allows the root project to override versions declared by this library.\n  ext.safeExtGet = { prop, fallback ->\n    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback\n  }\n\n  // Ensures backward compatibility\n  ext.getKotlinVersion = {\n    if (ext.has(\"kotlinVersion\")) {\n      ext.kotlinVersion()\n    } else {\n      ext.safeExtGet(\"kotlinVersion\", \"1.8.10\")\n    }\n  }\n\n  repositories {\n    mavenCentral()\n  }\n\n  dependencies {\n    classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}\")\n  }\n}\n\nafterEvaluate {\n  publishing {\n    publications {\n      release(MavenPublication) {\n        from components.release\n      }\n    }\n    repositories {\n      maven {\n        url = mavenLocal().url\n      }\n    }\n  }\n}\n\nandroid {\n  compileSdkVersion safeExtGet(\"compileSdkVersion\", 33)\n\n  def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION\n  if (agpVersion.tokenize('.')[0].toInteger() < 8) {\n    compileOptions {\n      sourceCompatibility JavaVersion.VERSION_11\n      targetCompatibility JavaVersion.VERSION_11\n    }\n\n    kotlinOptions {\n      jvmTarget = JavaVersion.VERSION_11.majorVersion\n    }\n  }\n\n  namespace \"expo.modules.coinbasewalletsdkexpo\"\n  defaultConfig {\n    minSdkVersion safeExtGet(\"minSdkVersion\", 23)\n    targetSdkVersion safeExtGet(\"targetSdkVersion\", 31)\n    versionCode 1\n    versionName \"0.1.0\"\n    consumerProguardFiles 'proguard-rules.pro'\n  }\n  lintOptions {\n    abortOnError false\n  }\n  publishing {\n    singleVariant(\"release\") {\n      withSourcesJar()\n    }\n  }\n}\n\nrepositories {\n  mavenCentral()\n}\n\ndependencies {\n  implementation project(':expo-modules-core')\n  implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}\"\n  implementation \"com.coinbase:coinbase-wallet-sdk:1.1.1\"\n  implementation 'androidx.appcompat:appcompat:1.4.2'\n}\n"
  },
  {
    "path": "react-native/android/proguard-rules.pro",
    "content": "\n-keepclassmembers class expo.modules.coinbasewalletsdkexpo.* {\n    <fields>;\n    <init>();\n    <methods>;\n}"
  },
  {
    "path": "react-native/android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"expo.modules.coinbasewalletsdkexpo\">\n\n    <queries>\n        <package android:name=\"org.toshi\" />\n        <package android:name=\"org.toshi.alpha\" />\n    </queries>\n</manifest>\n"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/ActivityLifecycleListener.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo\n\nimport android.app.Activity\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport androidx.activity.result.ActivityResultLauncher\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.appcompat.app.AppCompatActivity\nimport expo.modules.core.interfaces.ReactActivityLifecycleListener\n\nobject IntentLauncher {\n    var launcher: ActivityResultLauncher<Intent>? = null\n    var onResult: ((Uri) -> Unit)? = null\n}\n\nclass ActivityLifecycleListener : ReactActivityLifecycleListener {\n    override fun onCreate(activity: Activity?, savedInstanceState: Bundle?) {\n        super.onCreate(activity, savedInstanceState)\n\n        val currentActivity = requireNotNull(activity as? AppCompatActivity) {\n            \"CoinbaseWalletSDK: activity must be AppCompatActivity\"\n        }\n\n        IntentLauncher.launcher =\n            currentActivity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->\n                val uri = result.data?.data ?: return@registerForActivityResult\n                IntentLauncher.onResult?.invoke(uri)\n            }\n    }\n}"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/CoinbaseWalletSDKModule.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo\n\nimport android.net.Uri\nimport android.util.Log\nimport com.coinbase.android.nativesdk.CoinbaseWalletSDK\nimport com.coinbase.android.nativesdk.message.request.Account\nimport com.coinbase.android.nativesdk.message.request.Action\nimport com.coinbase.android.nativesdk.message.request.RequestContent\nimport expo.modules.coinbasewalletsdkexpo.records.AccountRecord\nimport expo.modules.coinbasewalletsdkexpo.records.ActionRecord\nimport expo.modules.coinbasewalletsdkexpo.records.ActionResultRecord\nimport expo.modules.coinbasewalletsdkexpo.records.ConfigParamsRecord\nimport expo.modules.coinbasewalletsdkexpo.records.HandshakeParamsRecord\nimport expo.modules.coinbasewalletsdkexpo.records.RequestParamsRecord\nimport expo.modules.coinbasewalletsdkexpo.records.asAction\nimport expo.modules.coinbasewalletsdkexpo.records.asRecord\nimport expo.modules.kotlin.Promise\nimport expo.modules.kotlin.modules.Module\nimport expo.modules.kotlin.modules.ModuleDefinition\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass CoinbaseWalletSDKModule : Module() {\n    private var sdk: CoinbaseWalletSDK? = null\n\n    override fun definition() = ModuleDefinition {\n\n        Name(\"CoinbaseWalletSDK\")\n\n        Function(\"configure\") { params: ConfigParamsRecord ->\n            try {\n                IntentLauncher.onResult = { uri -> sdk?.handleResponse(uri) }\n\n                val context = requireNotNull(appContext.reactContext?.applicationContext) {\n                    \"CoinbaseWalletSDK: Application context must not be null\"\n                }\n\n                sdk = CoinbaseWalletSDK(\n                    domain = Uri.parse(params.callbackURL),\n                    appContext = context,\n                    hostPackageName = params.hostPackageName ?: \"org.toshi\",\n                    openIntent = { IntentLauncher.launcher?.launch(it) }\n                )\n                sdk?.appendVersionTag(\"rn\")\n            } catch (e: Exception) {\n                Log.e(\"CoinbaseWalletSDK\", \"Configuration error\", e)\n            }\n        }\n\n        AsyncFunction(\"initiateHandshake\") { params: HandshakeParamsRecord, promise: Promise ->\n            val sdk = sdk\n            if (sdk == null) {\n                promise.reject(\"configure-error\", \"configure must be called before handshake can be initiated\", null)\n                return@AsyncFunction\n            }\n\n            val handshakeActions = params.initialActions.map { it.asAction }\n\n            sdk.initiateHandshake(handshakeActions) { result, account ->\n                result\n                    .onSuccess { responses ->\n                        val results: List<ActionResultRecord> = responses.map { it.asRecord }\n                        val accountRecord = account?.asRecord\n                        promise.resolve(listOf(results, accountRecord))\n                    }\n                    .onFailure { error ->\n                        Log.e(\"CoinbaseWalletSDK\", \"Handshake error\", error)\n                        promise.reject(\"handshake-error\", error.message, error)\n                    }\n            }\n        }\n\n        AsyncFunction(\"makeRequest\") { params: RequestParamsRecord, promise: Promise ->\n            val sdk = sdk\n            if (sdk == null) {\n                promise.reject(\"configure-error\", \"configure must be called before request can be initiated\", null)\n                return@AsyncFunction\n            }\n\n            val requestActions = params.actions.map { it.asAction }\n\n            val requestAccount = params.account?.let { record ->\n                Account(\n                    chain = record.chain,\n                    networkId = record.networkId.toLong(),\n                    address = record.address\n                )\n            }\n\n            val request = RequestContent.Request(actions = requestActions, account = requestAccount)\n            sdk.makeRequest(request) { result ->\n                result\n                    .onSuccess { responses ->\n                        val results: List<ActionResultRecord> = responses.map { it.asRecord }\n                        promise.resolve(results)\n                    }\n                    .onFailure { error ->\n                        Log.e(\"CoinbaseWalletSDK\", \"Request error\", error)\n                        promise.reject(\"request-error\", error.message, error)\n                    }\n            }\n        }\n\n        Function(\"handleResponse\") { url: String ->\n            val responseURL = Uri.parse(url)\n\n            try {\n                return@Function sdk?.handleResponse(responseURL) ?: false\n            } catch (error: Exception) {\n                return@Function false\n            }\n        }\n\n        Function(\"isCoinbaseWalletInstalled\") {\n            return@Function sdk?.isCoinbaseWalletInstalled ?: false\n        }\n\n        Function(\"getCoinbaseWalletMWPVersion\") {\n            val context = requireNotNull(appContext.reactContext?.applicationContext) {\n                \"CoinbaseWalletSDK: Application context must not be null\"\n            }\n            return@Function CoinbaseWalletSDK.getCoinbaseWalletMWPVersion(context)\n        }\n\n        Function(\"isConnected\") {\n            return@Function sdk?.isConnected ?: false\n        }\n\n        Function(\"resetSession\") {\n            sdk?.resetSession()\n        }\n    }\n}\n"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/CoinbaseWalletSDKPackage.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo\n\nimport android.content.Context\nimport expo.modules.core.interfaces.Package\nimport expo.modules.core.interfaces.ReactActivityLifecycleListener\n\nclass CoinbaseWalletSDKPackage : Package {\n    override fun createReactActivityLifecycleListeners(activityContext: Context?): List<ReactActivityLifecycleListener> {\n        return listOf(ActivityLifecycleListener())\n    }\n}"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/records/AccountRecord.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo.records\n\nimport com.coinbase.android.nativesdk.message.request.Account\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass AccountRecord : Record {\n    @Field\n    var chain: String = \"\"\n\n    @Field\n    var networkId: Int = 1\n\n    @Field\n    var address: String = \"\"\n}\n\nval Account.asRecord: AccountRecord\n    get() {\n        val record = AccountRecord()\n        record.chain = chain\n        record.networkId = networkId.toInt()\n        record.address = address\n        return record\n    }\n"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/records/ActionRecord.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo.records\n\nimport com.coinbase.android.nativesdk.message.request.Action\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass ActionRecord : Record {\n    @Field\n    var method: String = \"\"\n\n    @Field\n    var paramsJson: String = \"{}\"\n\n    @Field\n    var optional: Boolean = false\n}\n\nval ActionRecord.asAction: Action\n    get() {\n        return Action(\n            method = this.method,\n            paramsJson = this.paramsJson,\n            optional = this.optional\n        )\n    }"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/records/ActionResultRecord.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo.records\n\nimport com.coinbase.android.nativesdk.message.response.ActionResult\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass ActionResultRecord : Record {\n    @Field\n    var result: String? = null\n\n    @Field\n    var errorMessage: String? = null\n\n    @Field\n    var errorCode: Int? = null\n}\n\nval ActionResult.asRecord: ActionResultRecord\n    get() {\n        val record = ActionResultRecord()\n        when (this) {\n            is ActionResult.Result -> record.result = value\n            is ActionResult.Error -> {\n                record.errorCode = code.toInt()\n                record.errorMessage = message\n            }\n        }\n\n        return record\n    }"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/records/ConfigParamsRecord.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo.records\n\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass ConfigParamsRecord : Record {\n    @Field\n    var callbackURL: String = \"\"\n\n    @Field\n    var hostURL: String? = null\n\n    @Field\n    var hostPackageName: String? = null\n}"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/records/HandshakeParamsRecord.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo.records\n\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass HandshakeParamsRecord : Record {\n    @Field\n    var initialActions: List<ActionRecord> = listOf()\n}"
  },
  {
    "path": "react-native/android/src/main/java/expo/modules/coinbasewalletsdkexpo/records/RequestParamsRecord.kt",
    "content": "package expo.modules.coinbasewalletsdkexpo.records\n\nimport expo.modules.kotlin.records.Field\nimport expo.modules.kotlin.records.Record\n\nclass RequestParamsRecord : Record {\n    @Field\n    var actions: List<ActionRecord> = listOf()\n\n    @Field\n    var account: AccountRecord? = null\n}"
  },
  {
    "path": "react-native/example/.buckconfig",
    "content": "\n[android]\n  target = Google Inc.:Google APIs:23\n\n[maven_repositories]\n  central = https://repo1.maven.org/maven2\n"
  },
  {
    "path": "react-native/example/.bundle/config",
    "content": "BUNDLE_PATH: \"vendor/bundle\"\nBUNDLE_FORCE_RUBY_PLATFORM: 1\n"
  },
  {
    "path": "react-native/example/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  extends: '@react-native-community',\n};\n"
  },
  {
    "path": "react-native/example/.flowconfig",
    "content": "[ignore]\n; We fork some components by platform\n.*/*[.]android.js\n\n; Ignore \"BUCK\" generated dirs\n<PROJECT_ROOT>/\\.buckd/\n\n; Ignore polyfills\nnode_modules/react-native/Libraries/polyfills/.*\n\n; Flow doesn't support platforms\n.*/Libraries/Utilities/LoadingView.js\n\n.*/node_modules/resolve/test/resolver/malformed_package_json/package\\.json$\n\n[untyped]\n.*/node_modules/@react-native-community/cli/.*/.*\n\n[include]\n\n[libs]\nnode_modules/react-native/interface.js\nnode_modules/react-native/flow/\n\n[options]\nemoji=true\n\nexact_by_default=true\n\nformat.bracket_spacing=false\n\nmodule.file_ext=.js\nmodule.file_ext=.json\nmodule.file_ext=.ios.js\n\nmunge_underscores=true\n\nmodule.name_mapper='^react-native/\\(.*\\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\\1'\nmodule.name_mapper='^@?[./a-zA-Z0-9$_-]+\\.\\(bmp\\|gif\\|jpg\\|jpeg\\|png\\|psd\\|svg\\|webp\\|m4v\\|mov\\|mp4\\|mpeg\\|mpg\\|webm\\|aac\\|aiff\\|caf\\|m4a\\|mp3\\|wav\\|html\\|pdf\\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'\n\nsuppress_type=$FlowIssue\nsuppress_type=$FlowFixMe\nsuppress_type=$FlowFixMeProps\nsuppress_type=$FlowFixMeState\n\n[lints]\nsketchy-null-number=warn\nsketchy-null-mixed=warn\nsketchy-number=warn\nuntyped-type-import=warn\nnonstrict-import=warn\ndeprecated-type=warn\nunsafe-getters-setters=warn\nunnecessary-invariant=warn\n\n[strict]\ndeprecated-type\nnonstrict-import\nsketchy-null\nunclear-type\nunsafe-getters-setters\nuntyped-import\nuntyped-type-import\n\n[version]\n^0.182.0\n"
  },
  {
    "path": "react-native/example/.gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nios/.xcode.env.local\n\n# Android/IntelliJ\n#\nbuild/\n.idea\n.gradle\nlocal.properties\n*.iml\n*.hprof\n.cxx/\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\nyarn-error.log\n\n# BUCK\nbuck-out/\n\\.buckd/\n*.keystore\n!debug.keystore\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the\n# screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/\n\n**/fastlane/report.xml\n**/fastlane/Preview.html\n**/fastlane/screenshots\n**/fastlane/test_output\n\n# Bundle artifact\n*.jsbundle\n\n# Ruby / CocoaPods\n/ios/Pods/\n/vendor/bundle/\n\n.expo/\n\n# Don't check in native directories\nandroid/\nios/\n"
  },
  {
    "path": "react-native/example/.prettierrc.js",
    "content": "module.exports = {\n  arrowParens: 'avoid',\n  bracketSameLine: true,\n  bracketSpacing: false,\n  singleQuote: true,\n  trailingComma: 'all',\n};\n"
  },
  {
    "path": "react-native/example/.watchmanconfig",
    "content": "{}"
  },
  {
    "path": "react-native/example/App.js",
    "content": "import React from 'react';\nimport {useState, useMemo, useEffect, useCallback} from 'react';\nimport {\n  Button,\n  Linking,\n  SafeAreaView,\n  ScrollView,\n  StatusBar,\n  StyleSheet,\n  Text,\n  View,\n} from 'react-native';\n\nimport {Colors} from 'react-native/Libraries/NewAppScreen';\n\nimport {\n  configure,\n  getCoinbaseWalletMWPVersion,\n  handleResponse,\n  isCoinbaseWalletInstalled,\n  WalletMobileSDKEVMProvider,\n} from '@coinbase/wallet-mobile-sdk';\nimport {MMKV} from 'react-native-mmkv';\n\n// Configure Mobile SDK\nconfigure({\n  hostURL: new URL('https://wallet.coinbase.com/wsegue'),\n  callbackURL: new URL('example.rn.dapp://'), // Your app's Universal Link\n  hostPackageName: 'org.toshi',\n});\n\nconst provider = new WalletMobileSDKEVMProvider();\nconst storage = new MMKV();\n\nconst App = function () {\n  const [log, setLog] = useState('');\n\n  const cachedAddress = useMemo(() => storage.getString('address'), []);\n  const [address, setAddress] = useState(cachedAddress);\n\n  const isConnected = address !== undefined;\n\n  useEffect(function setupDeeplinkHandling() {\n    // Pass incoming deeplinks into Mobile SDK\n    const subscription = Linking.addEventListener('url', ({url}) => {\n      console.log('-- handleResponse --', url);\n      handleResponse(url);\n    });\n\n    return function cleanup() {\n      subscription.remove();\n    };\n  }, []);\n\n  const logMessage = useCallback(message => {\n    setLog(prev => `${message}\\n${prev}`);\n  }, []);\n\n  useEffect(() => {\n    async function logVersion() {\n      logMessage(\n        `Coinbase Wallet Installed?: ${await isCoinbaseWalletInstalled()}`,\n      );\n      logMessage(\n        `Available MWP Version: ${await getCoinbaseWalletMWPVersion()}`,\n      );\n    }\n    logVersion();\n  }, [logMessage]);\n\n  // Initiate connection to Wallet\n  const connectWallet = useCallback(async () => {\n    logMessage('--> eth_requestAccounts\\n');\n\n    try {\n      const accounts = await provider.request({\n        method: 'eth_requestAccounts',\n        params: [],\n      });\n      setAddress(accounts[0]);\n      storage.set('address', accounts[0]);\n\n      logMessage(`<-- ${accounts}`);\n    } catch (e) {\n      console.error(e.message);\n      logMessage('<-- error connecting');\n    }\n  }, [logMessage]);\n\n  // Reset connection to Wallet\n  const resetConnection = useCallback(() => {\n    logMessage('--- Disconnect\\n');\n\n    provider.disconnect();\n    setAddress(undefined);\n    storage.delete('address');\n  }, [logMessage]);\n\n  const personalSign = useCallback(async () => {\n    logMessage('--> personal_sign\\n');\n\n    try {\n      const result = await provider.request({\n        method: 'personal_sign',\n        params: ['0x48656c6c6f20776f726c64', address],\n      });\n\n      logMessage(`<-- ${result}`);\n    } catch (e) {\n      logMessage(`<-- ${e.message}`);\n    }\n  }, [logMessage, address]);\n\n  const switchToEthereumChain = useCallback(async () => {\n    logMessage('--> wallet_switchEthereumChain: 0x1\\n');\n\n    try {\n      const result = await provider.request({\n        method: 'wallet_switchEthereumChain',\n        params: [{chainId: '0x1'}],\n      });\n\n      logMessage(`<-- ${result}`);\n    } catch (e) {\n      console.error(e.message);\n      logMessage('<-- error');\n    }\n  }, [logMessage]);\n\n  const switchToPolygonChain = useCallback(async () => {\n    logMessage('--> wallet_switchEthereumChain: 0x89\\n');\n\n    try {\n      const result = await provider.request({\n        method: 'wallet_switchEthereumChain',\n        params: [{chainId: '0x89'}],\n      });\n\n      logMessage(`<-- ${result}`);\n    } catch (e) {\n      console.error(e.message);\n      logMessage('<-- error');\n    }\n  }, [logMessage]);\n\n  const addMumbaiTestnet = useCallback(async () => {\n    logMessage('--> wallet_addEthereumChain: Mumbai Testnet\\n');\n\n    try {\n      const result = await provider.request({\n        method: 'wallet_addEthereumChain',\n        params: [\n          {\n            chainId: '0x13881',\n            chainName: 'Matic(Polygon) Mumbai Testnet',\n            nativeCurrency: {\n              name: 'tMATIC',\n              symbol: 'tMATIC',\n              decimals: 18,\n            },\n            rpcUrls: ['https://rpc-mumbai.maticvigil.com'],\n            blockExplorerUrls: ['https://mumbai.polygonscan.com/'],\n          },\n        ],\n      });\n\n      logMessage(`<-- ${result}`);\n    } catch (e) {\n      console.error(e.message);\n      logMessage('<-- error');\n    }\n  }, [logMessage]);\n\n  const backgroundStyle = {\n    backgroundColor: Colors.lighter,\n  };\n\n  return (\n    <SafeAreaView style={backgroundStyle}>\n      <StatusBar />\n      <ScrollView style={styles.scrollViewStyle}>\n        <Section title=\"Methods\">\n          {!isConnected ? (\n            <Button title=\"Connect Wallet\" onPress={connectWallet} />\n          ) : (\n            <>\n              <Button title=\"Reset Connection\" onPress={resetConnection} />\n              <Button title=\"Personal Sign\" onPress={personalSign} />\n              <Button\n                title=\"Switch Chain: Ethereum\"\n                onPress={switchToEthereumChain}\n              />\n              <Button\n                title=\"Switch Chain: Polygon\"\n                onPress={switchToPolygonChain}\n              />\n              <Button\n                title=\"Add Chain: Mumbai Testnet\"\n                onPress={addMumbaiTestnet}\n              />\n            </>\n          )}\n        </Section>\n      </ScrollView>\n      <ScrollView style={styles.scrollViewStyle}>\n        <Section title=\"Output\">\n          <Text style={{color: Colors.black}}>{log}</Text>\n        </Section>\n      </ScrollView>\n    </SafeAreaView>\n  );\n};\n\nconst Section = function ({children, title}) {\n  return (\n    <View style={[styles.sectionContainer]}>\n      <Text\n        style={[\n          styles.sectionTitle,\n          {\n            color: Colors.black,\n          },\n        ]}>\n        {title}\n      </Text>\n      {children}\n    </View>\n  );\n};\n\nconst styles = StyleSheet.create({\n  sectionContainer: {\n    marginTop: 24,\n    paddingHorizontal: 24,\n  },\n  sectionTitle: {\n    fontSize: 24,\n    fontWeight: '600',\n  },\n  sectionDescription: {\n    marginTop: 8,\n    fontSize: 18,\n    fontWeight: '400',\n  },\n  highlight: {\n    fontWeight: '700',\n  },\n  scrollViewStyle: {\n    height: '50%',\n  },\n});\n\nexport default App;\n"
  },
  {
    "path": "react-native/example/__tests__/App-test.js",
    "content": "/**\n * @format\n */\n\nimport 'react-native';\nimport React from 'react';\nimport App from '../App';\n\n// Note: test renderer must be required after react-native.\nimport renderer from 'react-test-renderer';\n\nit('renders correctly', () => {\n  renderer.create(<App />);\n});\n"
  },
  {
    "path": "react-native/example/_node-version",
    "content": "16\n"
  },
  {
    "path": "react-native/example/app.json",
    "content": "{\n  \"name\": \"example\",\n  \"displayName\": \"example\",\n  \"android\": {\n    \"package\": \"com.anonymous.example\"\n  },\n  \"ios\": {\n    \"bundleIdentifier\": \"com.anonymous.example\"\n  },\n  \"plugins\": [\n    [\n      \"expo-build-properties\",\n      {\n        \"android\": {\n          \"minSdkVersion\": 23\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "react-native/example/babel.config.js",
    "content": "const path = require('path');\nconst pak = require('../package.json');\n\nconst libraryIndex = path.join(__dirname, '..', 'src', 'CoinbaseWalletSDK.ts');\n\nmodule.exports = function (api) {\n  api.cache(true);\n  return {\n    presets: ['babel-preset-expo'],\n    plugins: [\n      [\n        'module-resolver',\n        {\n          extensions: ['.tsx', '.ts', '.js', '.json'],\n          alias: {\n            // For development, we want to alias the library to the source\n            [pak.name]: libraryIndex,\n          },\n        },\n      ],\n    ],\n  };\n};\n"
  },
  {
    "path": "react-native/example/index.js",
    "content": "import {registerRootComponent} from 'expo';\n\nimport App from './App';\n\n// registerRootComponent calls AppRegistry.registerComponent('main', () => App);\n// It also ensures that whether you load the app in Expo Go or in a native build,\n// the environment is set up appropriately\nregisterRootComponent(App);\n"
  },
  {
    "path": "react-native/example/metro.config.js",
    "content": "const {getDefaultConfig} = require('expo/metro-config');\nconst path = require('path');\n\nconst config = getDefaultConfig(__dirname);\n\nconfig.resolver.blockList = [\n  ...Array.from(config.resolver.blockList ?? []),\n  new RegExp(path.resolve('..', 'node_modules', 'react-native')),\n];\n\nconfig.resolver.nodeModulesPaths = [\n  path.resolve(__dirname, './node_modules'),\n  path.resolve(__dirname, '../node_modules'),\n];\n\nconfig.watchFolders = [path.resolve(__dirname, '..')];\n\nconfig.transformer.getTransformOptions = async () => ({\n  transform: {\n    experimentalImportSupport: false,\n    inlineRequires: true,\n  },\n});\n\nmodule.exports = config;\n"
  },
  {
    "path": "react-native/example/package.json",
    "content": "{\n  \"name\": \"example\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"expo start --dev-client\",\n    \"android\": \"expo run:android\",\n    \"ios\": \"expo run:ios\",\n    \"test\": \"jest\",\n    \"lint\": \"eslint .\"\n  },\n  \"dependencies\": {\n    \"expo\": \"50.0.3\",\n    \"expo-build-properties\": \"0.11.0\",\n    \"expo-splash-screen\": \"0.26.4\",\n    \"expo-status-bar\": \"~1.6.0\",\n    \"react\": \"18.2.0\",\n    \"react-native\": \"0.73.0\",\n    \"react-native-mmkv\": \"^2.11.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.12.9\",\n    \"@babel/runtime\": \"^7.12.5\",\n    \"@react-native-community/eslint-config\": \"^2.0.0\",\n    \"babel-jest\": \"^26.6.3\",\n    \"eslint\": \"^7.32.0\",\n    \"jest\": \"^29.2.1\",\n    \"metro-react-native-babel-preset\": \"^0.72.1\",\n    \"react-test-renderer\": \"18.1.0\"\n  },\n  \"jest\": {\n    \"preset\": \"react-native\"\n  },\n  \"resolutions\": {\n    \"expo/**/json5\": \"^2.2.2\"\n  },\n  \"expo\": {\n    \"autolinking\": {\n      \"nativeModulesDir\": \"..\"\n    }\n  }\n}\n"
  },
  {
    "path": "react-native/expo-module.config.json",
    "content": "{\n  \"platforms\": [\"ios\", \"android\"],\n  \"ios\": {\n    \"modules\": [\"CoinbaseWalletSDKModule\"]\n  },\n  \"android\": {\n    \"modules\": [\"expo.modules.coinbasewalletsdkexpo.CoinbaseWalletSDKModule\"]\n  }\n}\n"
  },
  {
    "path": "react-native/ios/CoinbaseWalletSDKExpo.podspec",
    "content": "require 'json'\n\npackage = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))\n\nPod::Spec.new do |s|\n  s.name           = 'CoinbaseWalletSDKExpo'\n  s.version        = package['version']\n  s.summary        = package['description']\n  s.description    = package['description']\n  s.license        = package['license']\n  s.author         = package['author']\n  s.homepage       = package['homepage']\n  s.platform       = :ios, '13.0'\n  s.swift_version  = '5.4'\n  s.source         = { git: 'https://github.com/coinbase/wallet-mobile-sdk' }\n  s.static_framework = true\n\n  s.dependency 'ExpoModulesCore'\n  s.dependency 'CoinbaseWalletSDK/CrossPlatform', '1.1.2'\n\n  # Swift/Objective-C compatibility\n  s.pod_target_xcconfig = {\n    'DEFINES_MODULE' => 'YES',\n    'SWIFT_COMPILATION_MODE' => 'wholemodule'\n  }\n\n  if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?(\"#{s.name}.xcframework\") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')\n    s.source_files = \"**/*.h\"\n    s.vendored_frameworks = \"#{s.name}.xcframework\"\n  else\n    s.source_files = \"**/*.{h,m,swift}\"\n  end\nend\n"
  },
  {
    "path": "react-native/ios/CoinbaseWalletSDKModule.swift",
    "content": "import ExpoModulesCore\nimport CoinbaseWalletSDK\nimport Foundation\n\npublic class CoinbaseWalletSDKModule: Module {\n\n    public func definition() -> ModuleDefinition {\n\n        Name(\"CoinbaseWalletSDK\")\n\n        Function(\"configure\") { (params: ConfigParamsRecord) in\n            guard !CoinbaseWalletSDK.isConfigured else {\n                return\n            }\n\n            let host: URL\n            if let hostURLStr = params.hostURL {\n                host = URL(string: hostURLStr)!\n            } else {\n                host = URL(string: \"https://wallet.coinbase.com/wsegue\")!\n            }\n\n            CoinbaseWalletSDK.configure(\n                host: host,\n                callback: URL(string: params.callbackURL)!\n            )\n            CoinbaseWalletSDK.appendVersionTag(\"rn\")\n        }\n\n        AsyncFunction(\"initiateHandshake\") { (params: HandshakeParamsRecord, promise: Promise) in\n            let actions: [Action] = params.initialActions.map { $0.asAction }\n\n            DispatchQueue.main.async {\n                CoinbaseWalletSDK.shared.initiateHandshake(initialActions: actions) { result, account in\n                    switch result {\n                    case .success(let response):\n                        let results: [ActionResultRecord.Dict] = response.content.map { $0.asRecord }\n                        let accountRecord = account?.asRecord\n                        promise.resolve([results, accountRecord])\n                    case .failure(let error):\n                        promise.reject(\"handshake-error\", \"\\(error)\");\n                    }\n                }\n            }\n        }\n\n        AsyncFunction(\"makeRequest\") { (params: RequestParamsRecord, promise: Promise) in\n            let requestActions: [Action] = params.actions.map { $0.asAction }\n\n            let requestAccount: Account?\n            if let account = params.account {\n                requestAccount = Account(\n                    chain: account.chain,\n                    networkId: UInt(account.networkId),\n                    address: account.address\n                )\n            } else {\n                requestAccount = nil\n            }\n            \n            DispatchQueue.main.async {\n                CoinbaseWalletSDK.shared.makeRequest(\n                    Request(actions: requestActions, account: requestAccount)\n                ) { result in\n                    switch result {\n                    case .success(let response):\n                        let results: [ActionResultRecord.Dict] = response.content.map { $0.asRecord }\n                        promise.resolve(results)\n                    case .failure(let error):\n                        promise.reject(\"request-error\", \"\\(error)\")\n                    }\n                }\n            }\n        }\n\n        Function(\"handleResponse\") { (url: String) -> Bool in\n            guard CoinbaseWalletSDK.isConfigured else {\n                return false\n            }\n\n            let responseURL = URL(string: url)!\n            if (try? CoinbaseWalletSDK.shared.handleResponse(responseURL)) == true {\n                return true\n            }\n\n            return false\n        }\n\n        AsyncFunction(\"isCoinbaseWalletInstalled\") { (promise: Promise) in\n            DispatchQueue.main.async {\n                promise.resolve(CoinbaseWalletSDK.isCoinbaseWalletInstalled())\n            }\n        }\n        \n        AsyncFunction(\"getCoinbaseWalletMWPVersion\") { (promise: Promise) in\n            DispatchQueue.main.async {\n                promise.resolve(CoinbaseWalletSDK.getCoinbaseWalletMWPVersion())\n            }\n        }\n\n        Function(\"isConnected\") { () -> Bool in\n            return CoinbaseWalletSDK.shared.isConnected()\n        }\n\n        Function(\"resetSession\") {\n            CoinbaseWalletSDK.shared.resetSession()\n        }\n    }\n}\n"
  },
  {
    "path": "react-native/ios/Records/AccountRecord.swift",
    "content": "import CoinbaseWalletSDK\nimport ExpoModulesCore\nimport Foundation\n\nstruct AccountRecord : Record {\n    @Field\n    var chain: String\n\n    @Field\n    var networkId: Int\n\n    @Field\n    var address: String\n}\n\nextension Account {\n    var asRecord: AccountRecord.Dict {\n        let record = AccountRecord()\n        record.chain = self.chain\n        record.networkId = Int(self.networkId)\n        record.address = self.address\n\n        return record.toDictionary()\n    }\n}\n"
  },
  {
    "path": "react-native/ios/Records/ActionRecord.swift",
    "content": "import ExpoModulesCore\nimport CoinbaseWalletSDK\nimport Foundation\n\nstruct ActionRecord : Record {\n    @Field\n    var method: String\n\n    @Field\n    var paramsJson: String\n\n    @Field\n    var optional: Bool\n}\n\nextension ActionRecord {\n    var asAction: Action {\n        let paramsJson = self.paramsJson.data(using: .utf8)!\n        let params = try! JSONSerialization.jsonObject(with: paramsJson) as! [String: Any]\n        return Action(method: self.method, params: params)\n    }\n}\n"
  },
  {
    "path": "react-native/ios/Records/ActionResultRecord.swift",
    "content": "import CoinbaseWalletSDK\nimport ExpoModulesCore\nimport Foundation\n\nstruct ActionResultRecord : Record {\n    @Field\n    var result: String?\n\n    @Field\n    var errorMessage: String?\n\n    @Field\n    var errorCode: Int?\n}\n\nextension ActionResult {\n    var asRecord: ActionResultRecord.Dict {\n        let record = ActionResultRecord()\n\n        switch self {\n        case .success(let value):\n            record.result = value.rawValue\n        case .failure(let error):\n            record.errorCode = error.code\n            record.errorMessage = error.message\n        }\n\n        return record.toDictionary()\n    }\n}\n"
  },
  {
    "path": "react-native/ios/Records/ConfigParamsRecord.swift",
    "content": "import ExpoModulesCore\nimport Foundation\n\nstruct ConfigParamsRecord : Record {\n    @Field\n    var callbackURL: String\n\n    @Field\n    var hostURL: String?\n\n    @Field\n    var hostPackageName: String?\n}\n"
  },
  {
    "path": "react-native/ios/Records/HandshakeParamsRecord.swift",
    "content": "import ExpoModulesCore\nimport Foundation\n\nstruct HandshakeParamsRecord : Record {\n    @Field\n    var initialActions: [ActionRecord]\n}\n"
  },
  {
    "path": "react-native/ios/Records/RequestParamsRecord.swift",
    "content": "import ExpoModulesCore\nimport Foundation\n\nstruct RequestParamsRecord : Record {\n    @Field\n    var actions: [ActionRecord]\n\n    @Field\n    var account: AccountRecord?\n}\n"
  },
  {
    "path": "react-native/package.json",
    "content": "{\n  \"name\": \"@coinbase/wallet-mobile-sdk\",\n  \"version\": \"1.1.2\",\n  \"description\": \"Coinbase Wallet Mobile SDK for React Native\",\n  \"main\": \"build/CoinbaseWalletSDK.js\",\n  \"types\": \"build/CoinbaseWalletSDK.d.ts\",\n  \"scripts\": {\n    \"build\": \"expo-module build\",\n    \"clean\": \"expo-module clean\",\n    \"lint\": \"expo-module lint\",\n    \"test\": \"expo-module test\",\n    \"prepare\": \"expo-module prepare\",\n    \"prepublishOnly\": \"expo-module prepublishOnly\",\n    \"expo-module\": \"expo-module\"\n  },\n  \"keywords\": [\n    \"react-native\",\n    \"expo\",\n    \"coinbase-wallet-sdk-expo\",\n    \"CoinbaseWalletSDK\"\n  ],\n  \"repository\": \"https://github.com/coinbase/wallet-mobile-sdk\",\n  \"bugs\": {\n    \"url\": \"https://github.com/coinbase/wallet-mobile-sdk/issues\"\n  },\n  \"author\": \"Coinbase, Inc.\",\n  \"license\": \"Apache-2.0\",\n  \"homepage\": \"https://github.com/coinbase/wallet-mobile-sdk#readme\",\n  \"dependencies\": {\n    \"@metamask/safe-event-emitter\": \"2.0.0\",\n    \"eth-rpc-errors\": \"4.0.3\",\n    \"buffer\": \"6.0.3\",\n    \"bn.js\": \"5.2.1\",\n    \"events\": \"^3.0.0\",\n    \"react-native-mmkv\": \"^2.11.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^18.0.25\",\n    \"@types/react-native\": \"^0.70.6\",\n    \"expo-module-scripts\": \"^3.0.4\",\n    \"expo-modules-core\": \"^1.1.0\"\n  },\n  \"peerDependencies\": {\n    \"expo\": \"*\",\n    \"react\": \"*\",\n    \"react-native\": \"*\"\n  },\n  \"resolutions\": {\n    \"expo-module-scripts/**/json5\": \"^2.2.2\",\n    \"expo-module-scripts/**/jsdom\": \"^16.5.0\"\n  }\n}\n"
  },
  {
    "path": "react-native/src/CoinbaseWalletSDK.ts",
    "content": "import CoinbaseWalletSDK from \"./CoinbaseWalletSDKModule\";\nimport {\n  Action,\n  Account,\n  ConfigurationParams,\n  Result,\n} from \"./CoinbaseWalletSDK.types\";\n\nexport {\n  Action,\n  Account,\n  ConfigurationParams,\n  Result,\n} from \"./CoinbaseWalletSDK.types\";\nexport { WalletMobileSDKEVMProvider } from \"./WalletMobileSDKEVMProvider\";\n\nexport function configure({\n  callbackURL,\n  hostURL,\n  hostPackageName,\n}: ConfigurationParams) {\n  CoinbaseWalletSDK.configure({\n    callbackURL: callbackURL.toString(),\n    hostURL: hostURL?.toString(),\n    hostPackageName,\n  });\n}\n\nexport async function initiateHandshake(\n  initialActions?: Action[]\n): Promise<[Result[], Account?]> {\n  const actions =\n    initialActions?.map((action) => {\n      return {\n        method: action.method,\n        paramsJson: JSON.stringify(action.params),\n        optional: action.optional ?? false,\n      };\n    }) ?? [];\n\n  return await CoinbaseWalletSDK.initiateHandshake({ initialActions: actions });\n}\n\nexport async function makeRequest(\n  actions: Action[],\n  account?: Account\n): Promise<Result[]> {\n  const requestActions = actions.map((action) => {\n    return {\n      method: action.method,\n      paramsJson: JSON.stringify(action.params),\n      optional: action.optional ?? false,\n    };\n  });\n\n  return await CoinbaseWalletSDK.makeRequest({\n    actions: requestActions,\n    account,\n  });\n}\n\nexport function handleResponse(url: URL): boolean {\n  return CoinbaseWalletSDK.handleResponse(url.toString());\n}\n\nexport async function isCoinbaseWalletInstalled(): Promise<boolean> {\n  return CoinbaseWalletSDK.isCoinbaseWalletInstalled();\n}\n\nexport async function getCoinbaseWalletMWPVersion(): Promise<string | undefined> {\n  return CoinbaseWalletSDK.getCoinbaseWalletMWPVersion();\n}\n\nexport function isConnected(): boolean {\n  return CoinbaseWalletSDK.isConnected();\n}\n\nexport function resetSession() {\n  CoinbaseWalletSDK.resetSession();\n}\n"
  },
  {
    "path": "react-native/src/CoinbaseWalletSDK.types.ts",
    "content": "export type ConfigurationParams = {\n  callbackURL: URL;\n  hostURL?: URL;\n  hostPackageName?: string;\n};\n\nexport type Action = {\n  method: string;\n  params: any;\n  optional?: boolean;\n};\n\nexport type Account = {\n  chain: string;\n  networkId: number;\n  address: string;\n};\n\nexport type Result = {\n  result: string | null;\n  errorCode: number | null;\n  errorMessage: string | null;\n};\n\nexport type ActionSource = {\n  url: string;\n}\n"
  },
  {
    "path": "react-native/src/CoinbaseWalletSDKModule.ts",
    "content": "import { requireNativeModule } from 'expo-modules-core';\n\n// It loads the native module object from the JSI or falls back to\n// the bridge module (from NativeModulesProxy) if the remote debugger is on.\nexport default requireNativeModule('CoinbaseWalletSDK');\n"
  },
  {
    "path": "react-native/src/WalletMobileSDKEVMProvider.ts",
    "content": "import {\n  RequestArguments,\n  Web3Provider,\n} from \"./types/provider/Web3Provider\";\nimport {\n  JSONRPCRequest,\n  JSONRPCResponse,\n} from \"./types/provider/JSONRPC\";\nimport {\n  AddressString,\n  Callback,\n  IntNumber,\n} from \"./types/core/type\";\nimport { ethErrors } from \"eth-rpc-errors\";\nimport {\n  initiateHandshake,\n  isConnected,\n  makeRequest,\n  resetSession,\n} from \"./CoinbaseWalletSDK\";\nimport { Account, Action, ActionSource, Result } from \"./CoinbaseWalletSDK.types\";\nimport {\n  bigIntStringFromBN,\n  ensureAddressString,\n  ensureBN,\n  ensureBuffer,\n  ensureIntNumber,\n  ensureParsedJSONObject,\n  hexStringFromBuffer,\n  hexStringFromIntNumber,\n  prepend0x,\n} from \"./types/core/util\";\nimport BN from \"bn.js\";\nimport { MMKV, NativeMMKV } from \"react-native-mmkv\";\nimport SafeEventEmitter from \"@metamask/safe-event-emitter\";\n\nglobal.Buffer = global.Buffer || require(\"buffer\").Buffer;\n\nconst CACHED_ADDRESSES_KEY = \"mobile_sdk.addresses\";\nconst CHAIN_ID_KEY = \"mobile_sdk.chain_id\";\n\nexport interface WalletMobileSDKProviderOptions {\n  chainId?: number;\n  storage?: KVStorage;\n  jsonRpcUrl?: string;\n  address?: string;\n}\n\nexport interface KVStorage\n  extends Pick<NativeMMKV, \"set\" | \"getString\" | \"delete\"> {}\n\ninterface AddEthereumChainParams {\n  chainId: string;\n  blockExplorerUrls?: string[];\n  chainName?: string;\n  iconUrls?: string[];\n  rpcUrls?: string[];\n  nativeCurrency?: {\n    name: string;\n    symbol: string;\n    decimals: number;\n  };\n}\n\ninterface SwitchEthereumChainParams {\n  chainId: string;\n}\n\ninterface WatchAssetParams {\n  type: string;\n  options: {\n    address: string;\n    symbol?: string;\n    decimals?: number;\n    image?: string;\n  };\n}\n\ninterface EthereumTransactionParams {\n  fromAddress: AddressString;\n  toAddress: AddressString | null;\n  weiValue: BN;\n  data: Buffer;\n  nonce: IntNumber | null;\n  gasPriceInWei: BN | null;\n  maxFeePerGas: BN | null; // in wei\n  maxPriorityFeePerGas: BN | null; // in wei\n  gasLimit: BN | null;\n  chainId: IntNumber;\n  actionSource?: ActionSource;\n}\n\nexport class WalletMobileSDKEVMProvider\n  extends SafeEventEmitter\n  implements Web3Provider\n{\n  private _chainId?: number;\n  private _jsonRpcUrl?: string;\n  private _addresses: AddressString[] = [];\n  private _storage: KVStorage;\n\n  constructor(opts?: WalletMobileSDKProviderOptions) {\n    super();\n\n    this.send = this.send.bind(this);\n    this.sendAsync = this.sendAsync.bind(this);\n    this.request = this.request.bind(this);\n    this._updateChainId = this._updateChainId.bind(this);\n    this._setAddresses = this._setAddresses.bind(this);\n    this._getChainId = this._getChainId.bind(this);\n\n    this._storage = opts?.storage ?? new MMKV({ id: \"mobile_sdk.store\" });\n    this._chainId = opts?.chainId;\n    this._jsonRpcUrl = opts?.jsonRpcUrl;\n\n    const chainId = this._chainId ?? this._getChainId();\n    const chainIdStr = prepend0x(chainId.toString(16));\n    this.emit(\"connect\", { chainId: chainIdStr });\n\n    const cachedAddresses =\n      opts?.address ?? this._storage.getString(CACHED_ADDRESSES_KEY);\n    if (cachedAddresses) {\n      const addresses = cachedAddresses.split(\" \") as AddressString[];\n      if (addresses[0] && addresses[0] !== \"\") {\n        this._setAddresses(addresses);\n      }\n    }\n  }\n\n  public get selectedAddress(): AddressString | undefined {\n    return this._addresses[0] || undefined;\n  }\n\n  public get networkVersion(): string {\n    return this._getChainId().toString(10);\n  }\n\n  public get host(): string {\n    if (this._jsonRpcUrl) {\n      return this._jsonRpcUrl;\n    } else {\n      throw new Error(\"No jsonRpcUrl provided\");\n    }\n  }\n\n  public get connected(): boolean {\n    return isConnected();\n  }\n\n  public get chainId(): string {\n    return prepend0x(this._getChainId().toString(16));\n  }\n\n  public supportsSubscriptions(): boolean {\n    return false;\n  }\n\n  public disconnect(): boolean {\n    resetSession();\n    this._addresses = [];\n    this._storage.delete(CACHED_ADDRESSES_KEY);\n    this.emit(\"disconnect\");\n    return true;\n  }\n\n  private _send = this.send.bind(this);\n  private _sendAsync = this.sendAsync.bind(this);\n\n  public send(request: JSONRPCRequest): JSONRPCResponse;\n  public send(request: JSONRPCRequest[]): JSONRPCResponse[];\n  public send(\n    request: JSONRPCRequest,\n    callback: Callback<JSONRPCResponse>\n  ): void;\n  public send(\n    request: JSONRPCRequest[],\n    callback: Callback<JSONRPCResponse[]>\n  ): void;\n  public send<T = any>(method: string, params?: any[] | any): Promise<T>;\n  public send(\n    requestOrMethod: JSONRPCRequest | JSONRPCRequest[] | string,\n    callbackOrParams?:\n      | Callback<JSONRPCResponse>\n      | Callback<JSONRPCResponse[]>\n      | any[]\n      | any\n  ): JSONRPCResponse | JSONRPCResponse[] | void | Promise<any> {\n    // send<T>(method, params): Promise<T>\n    if (typeof requestOrMethod === \"string\") {\n      const method = requestOrMethod;\n      const params = Array.isArray(callbackOrParams)\n        ? callbackOrParams\n        : callbackOrParams !== undefined\n        ? [callbackOrParams]\n        : [];\n      const request: JSONRPCRequest = {\n        jsonrpc: \"2.0\",\n        id: 0,\n        method,\n        params,\n      };\n      return this._sendRequestAsync(request).then((res) => res.result);\n    }\n\n    // send(JSONRPCRequest | JSONRPCRequest[], callback): void\n    if (typeof callbackOrParams === \"function\") {\n      const request = requestOrMethod as any;\n      const callback = callbackOrParams;\n      return this._sendAsync(request, callback);\n    }\n\n    // send(JSONRPCRequest[]): JSONRPCResponse[]\n    if (Array.isArray(requestOrMethod)) {\n      const requests = requestOrMethod;\n      return requests.map((r) => this._sendRequest(r));\n    }\n\n    // send(JSONRPCRequest): JSONRPCResponse\n    const req: JSONRPCRequest = requestOrMethod;\n    return this._sendRequest(req);\n  }\n\n  public sendAsync(\n    request: JSONRPCRequest,\n    callback: Callback<JSONRPCResponse>\n  ): void;\n  public sendAsync(\n    request: JSONRPCRequest[],\n    callback: Callback<JSONRPCResponse[]>\n  ): void;\n  public async sendAsync(\n    request: JSONRPCRequest | JSONRPCRequest[],\n    callback: Callback<JSONRPCResponse> | Callback<JSONRPCResponse[]>\n  ): Promise<void> {\n    if (typeof callback !== \"function\") {\n      throw new Error(\"callback is required\");\n    }\n\n    // send(JSONRPCRequest[], callback): void\n    if (Array.isArray(request)) {\n      const arrayCb = callback as Callback<JSONRPCResponse[]>;\n      this._sendMultipleRequestsAsync(request)\n        .then((responses) => arrayCb(null, responses))\n        .catch((err) => arrayCb(err, null));\n      return;\n    }\n\n    // send(JSONRPCRequest, callback): void\n    const cb = callback as Callback<JSONRPCResponse>;\n    return this._sendRequestAsync(request)\n      .then((response) => cb(null, response))\n      .catch((err) => cb(err, null));\n  }\n\n  // request\n  public async request<T>(args: RequestArguments): Promise<T> {\n    if (!args || typeof args !== \"object\" || Array.isArray(args)) {\n      throw ethErrors.rpc.invalidRequest({\n        message: \"Expected a single, non-array, object argument.\",\n        data: args,\n      });\n    }\n\n    const { method, params } = args;\n\n    if (typeof method !== \"string\" || method.length === 0) {\n      throw ethErrors.rpc.invalidRequest({\n        message: \"'args.method' must be a non-empty string.\",\n        data: args,\n      });\n    }\n\n    if (\n      params !== undefined &&\n      !Array.isArray(params) &&\n      (typeof params !== \"object\" || params === null)\n    ) {\n      throw ethErrors.rpc.invalidRequest({\n        message: \"'args.params' must be an object or array if provided.\",\n        data: args,\n      });\n    }\n\n    const newParams = params === undefined ? [] : params;\n\n    const id = 0;\n    const result = await this._sendRequestAsync({\n      method,\n      params: newParams,\n      jsonrpc: \"2.0\",\n      id,\n    });\n\n    return result.result as T;\n  }\n\n  private _sendRequest(request: JSONRPCRequest): JSONRPCResponse {\n    const result = this._handleSynchronousMethods(request);\n    if (result === undefined) {\n      throw ethErrors.provider.unsupportedMethod(\n        `Unsupported synchronous method: ${request.method}`\n      );\n    }\n\n    return {\n      jsonrpc: \"2.0\",\n      id: request.id,\n      result,\n    };\n  }\n\n  private _sendMultipleRequestsAsync(\n    requests: JSONRPCRequest[]\n  ): Promise<JSONRPCResponse[]> {\n    return Promise.all(requests.map((r) => this._sendRequestAsync(r))); // TODO: Request batching\n  }\n\n  private _sendRequestAsync(request: JSONRPCRequest): Promise<JSONRPCResponse> {\n    return new Promise<JSONRPCResponse>((resolve, reject) => {\n      try {\n        // Handle synchronous methods\n        const syncResult = this._handleSynchronousMethods(request);\n        if (syncResult !== undefined) {\n          return resolve({\n            jsonrpc: \"2.0\",\n            id: request.id,\n            result: syncResult,\n          });\n        }\n      } catch (error) {\n        return reject(error);\n      }\n\n      // Handle asynchronous methods\n      this._handleAsynchronouseMethods(request)\n        .then((res) => res && resolve({ ...res, id: request.id }))\n        .catch((error) => reject(error));\n    });\n  }\n\n  private _handleSynchronousMethods({ method }: JSONRPCRequest) {\n    switch (method) {\n      case \"eth_accounts\":\n        return this._eth_accounts();\n      case \"eth_coinbase\":\n        return this._eth_coinbase();\n      case \"net_version\":\n        return this._net_version();\n      case \"eth_chainId\":\n        return this._eth_chainId();\n      default:\n        return undefined;\n    }\n  }\n\n  private async _handleAsynchronouseMethods(\n    request: JSONRPCRequest\n  ): Promise<JSONRPCResponse | void> {\n    const method = request.method;\n    const params = request.params || [];\n\n    switch (method) {\n      case \"eth_requestAccounts\":\n        return this._eth_requestAccounts();\n      case \"personal_sign\":\n        return this._personal_sign(params);\n      case \"eth_signTypedData_v3\":\n        return this._eth_signTypedData(params, \"v3\");\n      case \"eth_signTypedData_v4\":\n        return this._eth_signTypedData(params, \"v4\");\n      case \"eth_signTransaction\":\n        return this._eth_signTransaction(params, false);\n      case \"eth_sendTransaction\":\n        return this._eth_signTransaction(params, true);\n      case \"wallet_switchEthereumChain\":\n        return this._wallet_switchEthereumChain(params);\n      case \"wallet_addEthereumChain\":\n        return this._wallet_addEthereumChain(params);\n      case \"wallet_watchAsset\":\n        return this._wallet_watchAsset(params);\n      default:\n        if (this._jsonRpcUrl) {\n          return this._makeEthereumJsonRpcRequest(request, this._jsonRpcUrl);\n        } else {\n          throw ethErrors.provider.unsupportedMethod({\n            message: `Unsupported method: ${method}`,\n          });\n        }\n    }\n  }\n\n  private _eth_accounts(): string[] {\n    return [...this._addresses];\n  }\n\n  private _eth_coinbase(): string | null {\n    return this.selectedAddress ?? null;\n  }\n\n  private _net_version(): string {\n    return this._getChainId().toString(10);\n  }\n\n  private _eth_chainId(): string {\n    return hexStringFromIntNumber(this._getChainId());\n  }\n\n  private async _eth_requestAccounts(): Promise<JSONRPCResponse> {\n    const action: Action = {\n      method: \"eth_requestAccounts\",\n      params: {},\n    };\n\n    const [, account] = await this._makeHandshakeRequest(action);\n    this._setAddresses([account.address]);\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: [account.address],\n    };\n  }\n\n  private async _personal_sign(params: unknown[]): Promise<JSONRPCResponse> {\n    this._requireAuthorization();\n    const message = ensureBuffer(params[0]);\n    const address = ensureAddressString(params[1]);\n\n    const action: Action = {\n      method: \"personal_sign\",\n      params: {\n        message,\n        address,\n      },\n    };\n\n    const res = await this._makeSDKRequest(action);\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: res,\n    };\n  }\n\n  private async _eth_signTypedData(\n    params: unknown[],\n    type: \"v3\" | \"v4\"\n  ): Promise<JSONRPCResponse> {\n    this._requireAuthorization();\n    const address = ensureAddressString(params[0]);\n    const typedDataJson = JSON.stringify(ensureParsedJSONObject(params[1]));\n\n    const action: Action = {\n      method:\n        type === \"v3\"\n          ? \"eth_signTypedData_v3\"\n          : \"eth_signTypedData_v4\",\n      params: {\n        address,\n        typedDataJson,\n      },\n    };\n\n    const res = await this._makeSDKRequest(action);\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: res,\n    };\n  }\n\n  private async _eth_signTransaction(\n    params: unknown[],\n    shouldSubmit: boolean\n  ): Promise<JSONRPCResponse> {\n    this._requireAuthorization();\n    const tx = this._prepareTransactionParams((params[0] as any) || {});\n    const action: Action = {\n      method: shouldSubmit\n        ? \"eth_sendTransaction\"\n        : \"eth_signTransaction\",\n      params: {\n        fromAddress: tx.fromAddress,\n        toAddress: tx.toAddress,\n        weiValue: bigIntStringFromBN(tx.weiValue),\n        data: hexStringFromBuffer(tx.data),\n        nonce: tx.nonce,\n        gasPriceInWei: tx.gasPriceInWei\n          ? bigIntStringFromBN(tx.gasPriceInWei)\n          : null,\n        maxFeePerGas: tx.maxFeePerGas\n          ? bigIntStringFromBN(tx.maxFeePerGas)\n          : null,\n        maxPriorityFeePerGas: tx.maxPriorityFeePerGas\n          ? bigIntStringFromBN(tx.maxPriorityFeePerGas)\n          : null,\n        gasLimit: tx.gasLimit ? bigIntStringFromBN(tx.gasLimit) : null,\n        chainId: tx.chainId.toString(),\n      },\n    };\n\n    const res = await this._makeSDKRequest(action);\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: res,\n    };\n  }\n\n  private _prepareTransactionParams(tx: {\n    from?: unknown;\n    to?: unknown;\n    gasPrice?: unknown;\n    maxFeePerGas?: unknown;\n    maxPriorityFeePerGas?: unknown;\n    gas?: unknown;\n    value?: unknown;\n    data?: unknown;\n    nonce?: unknown;\n    chainId?: unknown;\n  }): EthereumTransactionParams {\n    const fromAddress = tx.from ? ensureAddressString(tx.from) : null;\n    if (!fromAddress) {\n      throw new Error(\"Ethereum address is unavailable\");\n    }\n\n    const toAddress = tx.to ? ensureAddressString(tx.to) : null;\n    const weiValue = tx.value != null ? ensureBN(tx.value) : new BN(0);\n    const data = tx.data ? ensureBuffer(tx.data) : Buffer.alloc(0);\n    const nonce = tx.nonce != null ? ensureIntNumber(tx.nonce) : null;\n    const gasPriceInWei = tx.gasPrice != null ? ensureBN(tx.gasPrice) : null;\n    const maxFeePerGas =\n      tx.maxFeePerGas != null ? ensureBN(tx.maxFeePerGas) : null;\n    const maxPriorityFeePerGas =\n      tx.maxPriorityFeePerGas != null\n        ? ensureBN(tx.maxPriorityFeePerGas)\n        : null;\n    const gasLimit = tx.gas != null ? ensureBN(tx.gas) : null;\n    const chainId = tx.chainId ? ensureIntNumber(tx.chainId) : this._getChainId();\n\n    return {\n      fromAddress,\n      toAddress,\n      weiValue,\n      data,\n      nonce,\n      gasPriceInWei,\n      maxFeePerGas,\n      maxPriorityFeePerGas,\n      gasLimit,\n      chainId,\n    };\n  }\n\n  private async _wallet_switchEthereumChain(\n    params: unknown[]\n  ): Promise<JSONRPCResponse> {\n    this._requireAuthorization();\n    const request = params[0] as SwitchEthereumChainParams;\n    const chainId = parseInt(request.chainId, 16);\n\n    const successResponse: JSONRPCResponse = {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: null,\n    };\n\n    if (ensureIntNumber(chainId) === this._getChainId()) {\n      return successResponse;\n    }\n\n    const action: Action = {\n      method: \"wallet_switchEthereumChain\",\n      params: {\n        chainId: chainId.toString(),\n      },\n    };\n\n    const res = await this._makeSDKRequest(action);\n    if (res === null) {\n      this._updateChainId(chainId);\n    }\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: res,\n    };\n  }\n\n  private async _wallet_addEthereumChain(\n    params: unknown[]\n  ): Promise<JSONRPCResponse> {\n    this._requireAuthorization();\n    const request = params[0] as AddEthereumChainParams;\n\n    if (!request.rpcUrls || request.rpcUrls?.length === 0) {\n      throw ethErrors.rpc.invalidParams({\n        message: \"please pass in at least 1 rpcUrl\",\n      });\n    }\n\n    if (!request.chainName || request.chainName.trim() === \"\") {\n      throw ethErrors.rpc.invalidParams({\n        message: \"chainName is a required field\",\n      });\n    }\n\n    if (!request.nativeCurrency) {\n      throw ethErrors.rpc.invalidParams({\n        message: \"nativeCurrency is a required field\",\n      });\n    }\n\n    const chainIdNumber = parseInt(request.chainId, 16);\n\n    const action: Action = {\n      method: \"wallet_addEthereumChain\",\n      params: {\n        chainId: chainIdNumber.toString(),\n        blockExplorerUrls: request.blockExplorerUrls ?? null,\n        chainName: request.chainName ?? null,\n        iconUrls: request.iconUrls ?? null,\n        nativeCurrency: request.nativeCurrency ?? null,\n        rpcUrls: request.rpcUrls ?? [],\n      },\n    };\n\n    const res = await this._makeSDKRequest(action);\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: res,\n    };\n  }\n\n  private async _wallet_watchAsset(params: unknown): Promise<JSONRPCResponse> {\n    this._requireAuthorization();\n    const request = (\n      Array.isArray(params) ? params[0] : params\n    ) as WatchAssetParams;\n\n    if (!request.type) {\n      throw ethErrors.rpc.invalidParams({\n        message: \"Type is required\",\n      });\n    }\n\n    if (request?.type !== \"ERC20\") {\n      throw ethErrors.rpc.invalidParams({\n        message: `Asset of type '${request.type}' is not supported`,\n      });\n    }\n\n    if (!request?.options) {\n      throw ethErrors.rpc.invalidParams({\n        message: \"Options are required\",\n      });\n    }\n\n    if (!request?.options.address) {\n      throw ethErrors.rpc.invalidParams({\n        message: \"Address is required\",\n      });\n    }\n\n    const { address, symbol, image, decimals } = request.options;\n\n    const action: Action = {\n      method: \"wallet_watchAsset\",\n      params: {\n        type: request.type,\n        options: {\n          address,\n          symbol: symbol ?? null,\n          decimals: decimals ?? null,\n          image: image ?? null,\n        },\n      },\n    };\n\n    const res = await this._makeSDKRequest(action);\n    return {\n      jsonrpc: \"2.0\",\n      id: 0,\n      result: res,\n    };\n  }\n\n  private async _makeEthereumJsonRpcRequest(\n    request: JSONRPCRequest,\n    jsonRpcUrl: string\n  ): Promise<JSONRPCResponse> {\n    return fetch(jsonRpcUrl, {\n      method: \"POST\",\n      body: JSON.stringify(request),\n      mode: \"cors\",\n      headers: { \"Content-Type\": \"application/json\" },\n    })\n      .then((res) => res.json())\n      .then((json) => {\n        if (!json) {\n          throw ethErrors.rpc.parse();\n        }\n\n        const response = json as JSONRPCResponse;\n        if (response.error) {\n          throw ethErrors.provider.custom(response.error);\n        }\n\n        return response;\n      });\n  }\n\n  private async _makeHandshakeRequest(\n    action: Action\n  ): Promise<[unknown, Account]> {\n    try {\n      const [[res], account] = await initiateHandshake([action]);\n      if (!res.result || !account) {\n        throw this._getProviderError(res);\n      }\n      return [JSON.parse(res.result), account];\n    } catch (error) {\n      if (error.message.match(/(session not found|session expired)/i)) {\n        this.disconnect();\n        throw ethErrors.provider.disconnected(error.message);\n      }\n\n      if (error.message.match(/(denied|rejected)/i)) {\n        throw ethErrors.provider.userRejectedRequest();\n      }\n\n      throw error;\n    }\n  }\n\n  private async _makeSDKRequest(action: Action): Promise<unknown> {\n    try {\n      const [res] = await makeRequest([action]);\n      if (res.errorMessage || !res.result) {\n        throw this._getProviderError(res);\n      }\n      return JSON.parse(res.result);\n    } catch (error) {\n      if (error.message.match(/(session not found|session expired)/i)) {\n        this.disconnect();\n        throw ethErrors.provider.disconnected(error.message);\n      }\n\n      if (error.message.match(/(denied|rejected)/i)) {\n        throw ethErrors.provider.userRejectedRequest();\n      }\n\n      throw error;\n    }\n  }\n\n  private _getProviderError(result: Result) {\n    const errorMessage = result.errorMessage ?? \"\";\n    if (errorMessage.match(/(denied|rejected)/i)) {\n      return ethErrors.provider.userRejectedRequest();\n    } else {\n      return ethErrors.provider.custom({\n        code: result.errorCode ?? 1000,\n        message: errorMessage,\n      });\n    }\n  }\n\n  private _getChainId(): IntNumber {\n    const chainIdStr = this._storage.getString(CHAIN_ID_KEY) || \"1\";\n    const chainId = parseInt(chainIdStr, 10);\n    return ensureIntNumber(chainId);\n  }\n\n  private _updateChainId(chainId: number) {\n    const originalChainId = this._getChainId();\n    this._storage.set(CHAIN_ID_KEY, chainId.toString(10));\n    const chainChanged = ensureIntNumber(chainId) !== originalChainId;\n    if (chainChanged) {\n      this.emit(\"chainChanged\", prepend0x(this._getChainId().toString(16)));\n    }\n  }\n\n  private _setAddresses(addresses: string[]) {\n    const newAddresses = addresses.map((address) =>\n      ensureAddressString(address)\n    );\n\n    if (JSON.stringify(this._addresses) === JSON.stringify(newAddresses)) {\n      return;\n    }\n\n    this._addresses = newAddresses;\n    this._storage.set(CACHED_ADDRESSES_KEY, newAddresses.join(\" \"));\n    this.emit(\"accountsChanged\", this._addresses);\n  }\n\n  private _requireAuthorization() {\n    if (!this.connected) {\n      throw ethErrors.provider.unauthorized();\n    }\n  }\n}\n"
  },
  {
    "path": "react-native/src/types/core/type.ts",
    "content": "// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>\n// Licensed under the Apache License, version 2.0\n\ninterface Tag<T extends string, RealType> {\n  __tag__: T;\n  __realType__: RealType;\n}\n\nexport type OpaqueType<T extends string, U> = U & Tag<T, U>;\n\nexport function OpaqueType<T extends Tag<string, unknown>>() {\n  return (value: T extends Tag<string, infer U> ? U : never): T => value as T;\n}\n\nexport type HexString = OpaqueType<'HexString', string>;\nexport const HexString = OpaqueType<HexString>();\n\nexport type AddressString = OpaqueType<'AddressString', string>;\nexport const AddressString = OpaqueType<AddressString>();\n\nexport type BigIntString = OpaqueType<'BigIntString', string>;\nexport const BigIntString = OpaqueType<BigIntString>();\n\nexport type IntNumber = OpaqueType<'IntNumber', number>;\nexport function IntNumber(num: number): IntNumber {\n  return Math.floor(num) as IntNumber;\n}\n\nexport type Callback<T> = (err: Error | null, result: T | null) => void;\n"
  },
  {
    "path": "react-native/src/types/core/util.ts",
    "content": "// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>\n// Licensed under the Apache License, version 2.0\n\nimport BN from 'bn.js';\n\nimport { AddressString, BigIntString, HexString, IntNumber } from './type';\n\nconst INT_STRING_REGEX = /^[0-9]*$/;\nconst HEXADECIMAL_STRING_REGEX = /^[a-f0-9]*$/;\n\nexport function hexStringToUint8Array(hexString: string): Uint8Array {\n  return new Uint8Array(hexString.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)));\n}\n\nexport function hexStringFromBuffer(buf: Buffer, includePrefix = false): HexString {\n  const hex = buf.toString('hex');\n  return HexString(includePrefix ? `0x${hex}` : hex);\n}\n\nexport function bigIntStringFromBN(bn: BN): BigIntString {\n  return BigIntString(bn.toString(10));\n}\n\nexport function intNumberFromHexString(hex: HexString): IntNumber {\n  return IntNumber(new BN(ensureEvenLengthHexString(hex, false), 16).toNumber());\n}\n\nexport function hexStringFromIntNumber(num: IntNumber): HexString {\n  return HexString(`0x${new BN(num).toString(16)}`);\n}\n\nexport function has0xPrefix(str: string): boolean {\n  return str.startsWith('0x') || str.startsWith('0X');\n}\n\nexport function strip0x(hex: string): string {\n  if (has0xPrefix(hex)) {\n    return hex.slice(2);\n  }\n  return hex;\n}\n\nexport function prepend0x(hex: string): string {\n  if (has0xPrefix(hex)) {\n    return `0x${hex.slice(2)}`;\n  }\n  return `0x${hex}`;\n}\n\nexport function isHexString(hex: unknown): hex is HexString {\n  if (typeof hex !== 'string') {\n    return false;\n  }\n  const s = strip0x(hex).toLowerCase();\n  return HEXADECIMAL_STRING_REGEX.test(s);\n}\n\nclass InvalidParamsError extends Error {\n  code = -32602;\n  constructor(message: string) {\n    super(message);\n  }\n}\n\nexport function ensureHexString(hex: unknown, includePrefix = false): HexString {\n  if (typeof hex === 'string') {\n    const s = strip0x(hex).toLowerCase();\n    if (HEXADECIMAL_STRING_REGEX.test(s)) {\n      return HexString(includePrefix ? `0x${s}` : s);\n    }\n  }\n  throw new InvalidParamsError(`\"${String(hex)}\" is not a hexadecimal string`);\n}\n\nexport function ensureEvenLengthHexString(hex: unknown, includePrefix = false): HexString {\n  let h = ensureHexString(hex, false);\n  if (h.length % 2 === 1) {\n    h = HexString(`0${h}`);\n  }\n  return includePrefix ? HexString(`0x${h}`) : h;\n}\n\nexport function ensureAddressString(str: unknown): AddressString {\n  if (typeof str === 'string') {\n    const s = strip0x(str).toLowerCase();\n    if (isHexString(s) && s.length === 40) {\n      return AddressString(prepend0x(s));\n    }\n  }\n  throw new InvalidParamsError(`Invalid Ethereum address: ${String(str)}`);\n}\n\nexport function ensureBuffer(str: unknown): Buffer {\n  if (Buffer.isBuffer(str)) {\n    return str;\n  }\n  if (typeof str === 'string') {\n    if (isHexString(str)) {\n      const s = ensureEvenLengthHexString(str, false);\n      return Buffer.from(s, 'hex');\n    }\n    return Buffer.from(str, 'utf8');\n  }\n  throw new InvalidParamsError(`Not binary data: ${String(str)}`);\n}\n\nexport function ensureIntNumber(num: unknown): IntNumber {\n  if (typeof num === 'number' && Number.isInteger(num)) {\n    return IntNumber(num);\n  }\n  if (typeof num === 'string') {\n    if (INT_STRING_REGEX.test(num)) {\n      return IntNumber(Number(num));\n    }\n    if (isHexString(num)) {\n      return IntNumber(new BN(ensureEvenLengthHexString(num, false), 16).toNumber());\n    }\n  }\n  throw new InvalidParamsError(`Not an integer: ${String(num)}`);\n}\n\nexport function ensureBN(val: unknown): BN {\n  if (val !== null && (BN.isBN(val) || isBigNumber(val))) {\n    return new BN((val as any).toString(10), 10);\n  }\n  if (typeof val === 'number') {\n    return new BN(ensureIntNumber(val));\n  }\n  if (typeof val === 'string') {\n    if (INT_STRING_REGEX.test(val)) {\n      return new BN(val, 10);\n    }\n    if (isHexString(val)) {\n      return new BN(ensureEvenLengthHexString(val, false), 16);\n    }\n  }\n  throw new InvalidParamsError(`Not an integer: ${String(val)}`);\n}\n\nexport function ensureParsedJSONObject<T extends object>(val: unknown): T {\n  if (typeof val === 'string') {\n    return JSON.parse(val) as T;\n  }\n\n  if (typeof val === 'object') {\n    return val as T;\n  }\n\n  throw new InvalidParamsError(`Not a JSON string or an object: ${String(val)}`);\n}\n\nexport function isBigNumber(val: unknown): boolean {\n  if (val == null || typeof (val as any).constructor !== 'function') {\n    return false;\n  }\n  const { constructor } = val as any;\n  return typeof constructor.config === 'function' && typeof constructor.EUCLID === 'number';\n}\n"
  },
  {
    "path": "react-native/src/types/provider/JSONRPC.ts",
    "content": "// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>\n// Licensed under the Apache License, version 2.0\n\nexport type JSONRPCMethod =\n  // synchronous or asynchronous\n  | 'eth_accounts'\n  | 'eth_coinbase'\n  | 'net_version'\n  | 'eth_chainId'\n  | 'eth_uninstallFilter' // synchronous\n\n  // asynchronous only\n  | 'eth_requestAccounts'\n  | 'eth_sign'\n  | 'eth_ecRecover'\n  | 'personal_sign'\n  | 'personal_ecRecover'\n  | 'eth_signTransaction'\n  | 'eth_sendRawTransaction'\n  | 'eth_sendTransaction'\n  | 'eth_signTypedData_v1'\n  | 'eth_signTypedData_v2'\n  | 'eth_signTypedData_v3'\n  | 'eth_signTypedData_v4'\n  | 'eth_signTypedData'\n  | 'walletlink_arbitrary' // compatibility\n  | 'wallet_addEthereumChain'\n  | 'wallet_switchEthereumChain'\n  | 'wallet_watchAsset'\n\n  // asynchronous pub/sub\n  | 'eth_subscribe'\n  | 'eth_unsubscribe'\n\n  // asynchronous filter methods\n  | 'eth_newFilter'\n  | 'eth_newBlockFilter'\n  | 'eth_newPendingTransactionFilter'\n  | 'eth_getFilterChanges'\n  | 'eth_getFilterLogs';\n\nexport interface JSONRPCRequest<T = any> {\n  jsonrpc: '2.0';\n  id: number;\n  method: string;\n  params: T;\n}\n\nexport interface JSONRPCResponse<T = any, U = any> {\n  jsonrpc: '2.0';\n  id: number;\n  result?: T;\n  error?: {\n    code: number;\n    message: string;\n    data?: U;\n  } | null;\n}\n"
  },
  {
    "path": "react-native/src/types/provider/Web3Provider.ts",
    "content": "// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/>\n// Licensed under the Apache License, version 2.0\n\nimport { Callback } from '../core/type';\nimport { JSONRPCRequest, JSONRPCResponse } from './JSONRPC';\n\nexport interface Web3Provider {\n  send(request: JSONRPCRequest): JSONRPCResponse;\n  send(request: JSONRPCRequest[]): JSONRPCResponse[];\n  send(request: JSONRPCRequest, callback: Callback<JSONRPCResponse>): void;\n  send(request: JSONRPCRequest[], callback: Callback<JSONRPCResponse[]>): void;\n  send<T = unknown>(method: string, params?: unknown[] | unknown): Promise<T>;\n\n  sendAsync(request: JSONRPCRequest, callback: Callback<JSONRPCResponse>): void;\n  sendAsync(request: JSONRPCRequest[], callback: Callback<JSONRPCResponse[]>): void;\n\n  request<T>(args: RequestArguments): Promise<T>;\n\n  host: string;\n  connected: boolean;\n  chainId: string;\n  supportsSubscriptions(): boolean;\n  disconnect(): boolean;\n}\n\nexport interface RequestArguments {\n  /** The RPC method to request. */\n  method: string;\n\n  /** The params of the RPC method, if any. */\n  params?: unknown;\n}\n"
  },
  {
    "path": "react-native/tsconfig.json",
    "content": "// @generated by expo-module-scripts\n{\n  \"extends\": \"expo-module-scripts/tsconfig.base\",\n  \"compilerOptions\": {\n    \"outDir\": \"./build\"\n  },\n  \"include\": [\"./src\"],\n  \"exclude\": [\"**/__mocks__/*\", \"**/__tests__/*\", \"**/__stories__/*\"]\n}\n"
  }
]