├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── build.gradle ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── kotlin │ └── com │ └── tangem │ └── tangem_sdk │ └── TangemSdkPlugin.kt ├── example ├── .gitignore ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── tangem │ │ │ │ │ └── tangem_sdk_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── Runner-Bridging-Header.h │ │ └── Runner.entitlements ├── lib │ ├── app_widgets.dart │ ├── main.dart │ └── source.dart ├── pubspec.yaml └── test │ └── widget_test.dart ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── SwiftTangemSdkPlugin.swift │ ├── TangemSdkPlugin.h │ └── TangemSdkPlugin.m └── tangem_sdk.podspec ├── lib ├── extension │ └── string.dart ├── model │ └── sdk.dart ├── tangem_sdk.dart ├── tangem_sdk_method_channel.dart ├── tangem_sdk_platform_interface.dart └── tangem_sdk_plugin.dart ├── pubspec.yaml └── test ├── tangem_sdk_method_channel_test.dart └── tangem_sdk_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea/ 4 | .vscode/ 5 | 6 | .packages 7 | .pub/ 8 | .dart_tool/ 9 | pubspec.lock 10 | flutter_export_environment.sh 11 | 12 | examples/all_plugins/pubspec.yaml 13 | 14 | Pods/ 15 | .symlinks/ 16 | **/Flutter/App.framework/ 17 | **/Flutter/ephemeral/ 18 | **/Flutter/Flutter.framework/ 19 | **/Flutter/Generated.xcconfig 20 | **/Flutter/flutter_assets/ 21 | 22 | ServiceDefinitions.json 23 | xcuserdata/ 24 | **/DerivedData/ 25 | 26 | local.properties 27 | keystore.properties 28 | .gradle/ 29 | gradlew 30 | gradlew.bat 31 | gradle-wrapper.jar 32 | .flutter-plugins-dependencies 33 | *.iml 34 | 35 | generated_plugin_registrant.dart 36 | GeneratedPluginRegistrant.h 37 | GeneratedPluginRegistrant.m 38 | GeneratedPluginRegistrant.java 39 | GeneratedPluginRegistrant.swift 40 | build/ 41 | .flutter-plugins 42 | 43 | .project 44 | .classpath 45 | .settings -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.7.0 2 | 3 | * Update with tangem-sdk-android 3.5.0 version 4 | 5 | ## 0.1.2 6 | 7 | * Fixed mapping of the firmwareVersion 8 | 9 | ## 0.1.1 10 | 11 | * Added canonization for the secp256k1 signature 12 | 13 | ## 0.1.0 14 | 15 | * The release contains all the necessary methods to get started with TangemSDK 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tangem 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Twitter](https://img.shields.io/twitter/follow/tangem?style=flat)](http://twitter.com/tangem) 2 | 3 | # Welcome to Tangem 4 | 5 | The Tangem card is a self-custodial hardware wallet that works via NFC. The main functions of Tangem cards are to securely create and store a private key and sign data. 6 | 7 | Tangem SDK is needed to facilitate support for Tangem cards in third-party applications. 8 | 9 | Supported platforms: [iOS](https://github.com/tangem/tangem-sdk-ios) | [Android](https://github.com/tangem/tangem-sdk-android) | [JVM](https://github.com/tangem/tangem-sdk-android) | **Flutter** | [React Native ](https://github.com/tangem/tangem-sdk-react-native) | [Cordova](https://github.com/tangem/tangem-sdk-cordova) | [Capacitor](https://github.com/tangem/tangem-sdk-cordova) 10 | 11 | # Documentation 12 | 13 | For exhaustive documentation, see [Tangem Developers Portal](https://developers.tangem.com). 14 | 15 | To kick off the development process you can start with [Getting started](https://developers.tangem.com/getting-started/flutter) page. 16 | 17 | # License 18 | 19 | Tangem SDK is available under the MIT license. See the [LICENSE](LICENSE) file for more info. -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .cxx 10 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.tangem.tangem_sdk' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.8.0' 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:7.1.2' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | maven {url 'https://jitpack.io'} 22 | } 23 | } 24 | 25 | apply plugin: 'com.android.library' 26 | apply plugin: 'kotlin-android' 27 | apply plugin: 'kotlin-kapt' 28 | 29 | android { 30 | compileSdkVersion 33 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = '1.8' 39 | } 40 | 41 | sourceSets { 42 | main.java.srcDirs += 'src/main/kotlin' 43 | } 44 | 45 | defaultConfig { 46 | minSdkVersion 21 47 | } 48 | } 49 | 50 | dependencies { 51 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" 52 | 53 | implementation "com.github.tangem.tangem-sdk-android:android:3.8.2" 54 | implementation "com.github.tangem.tangem-sdk-android:core:3.8.2" 55 | 56 | implementation 'com.squareup.moshi:moshi:1.12.0' 57 | implementation "com.squareup.moshi:moshi-kotlin:1.12.0" 58 | kapt("com.squareup.moshi:moshi-kotlin-codegen:1.12.0") 59 | 60 | implementation 'androidx.appcompat:appcompat:1.6.1' 61 | implementation 'androidx.core:core-ktx:1.10.1' 62 | } 63 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'tangem_sdk' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/kotlin/com/tangem/tangem_sdk/TangemSdkPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.tangem.tangem_sdk 2 | 3 | import android.app.Activity 4 | import android.os.Handler 5 | import android.os.Looper 6 | import android.util.Base64 7 | import com.tangem.* 8 | import com.tangem.common.biometric.BiometricManager 9 | import com.tangem.common.core.Config 10 | import com.tangem.common.core.ScanTagImage 11 | import com.tangem.common.core.ScanTagImage.GenericCard 12 | import com.tangem.common.extensions.hexToBytes 13 | import com.tangem.common.json.MoshiJsonConverter 14 | import com.tangem.common.services.secure.SecureStorage 15 | import com.tangem.crypto.bip39.Wordlist 16 | import com.tangem.sdk.DefaultSessionViewDelegate 17 | import com.tangem.sdk.NfcLifecycleObserver 18 | import com.tangem.sdk.extensions.getWordlist 19 | import com.tangem.sdk.extensions.initBiometricManager 20 | import com.tangem.sdk.nfc.NfcManager 21 | import com.tangem.sdk.storage.create 22 | import io.flutter.embedding.android.FlutterFragmentActivity 23 | import io.flutter.embedding.engine.plugins.FlutterPlugin 24 | import io.flutter.embedding.engine.plugins.activity.ActivityAware 25 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding 26 | import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference 27 | import io.flutter.plugin.common.MethodCall 28 | import io.flutter.plugin.common.MethodChannel 29 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler 30 | import io.flutter.plugin.common.MethodChannel.Result 31 | import java.lang.ref.WeakReference 32 | 33 | /** TangemSdkPlugin */ 34 | class TangemSdkPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { 35 | private lateinit var channel: MethodChannel 36 | 37 | private val handler = Handler(Looper.getMainLooper()) 38 | private lateinit var wActivity: WeakReference 39 | 40 | private lateinit var sdk: TangemSdk 41 | private lateinit var nfcManager: NfcManager 42 | private val converter = MoshiJsonConverter.default() 43 | 44 | private var replyAlreadySubmit = false 45 | 46 | override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { 47 | channel = MethodChannel(flutterPluginBinding.binaryMessenger, "tangem_sdk") 48 | channel.setMethodCallHandler(this) 49 | } 50 | 51 | override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { 52 | channel.setMethodCallHandler(null) 53 | } 54 | 55 | override fun onAttachedToActivity(pluginBinding: ActivityPluginBinding) { 56 | val activity = pluginBinding.activity as FlutterFragmentActivity 57 | wActivity = WeakReference(activity) 58 | 59 | nfcManager = createNfcManager(pluginBinding) 60 | val viewDelegate = createViewDelegate(activity, nfcManager) 61 | val storage = SecureStorage.create(activity) 62 | val config = Config() 63 | val biometricManager: BiometricManager = TangemSdk.initBiometricManager(activity, storage) 64 | val wordlist: Wordlist = Wordlist.getWordlist(activity) 65 | sdk = TangemSdk(nfcManager.reader, viewDelegate, storage, biometricManager, wordlist, config) 66 | nfcManager.onStart() 67 | } 68 | 69 | override fun onDetachedFromActivity() { 70 | } 71 | 72 | private fun createNfcManager(pluginBinding: ActivityPluginBinding): NfcManager { 73 | val hiddenLifecycleReference = pluginBinding.lifecycle as HiddenLifecycleReference 74 | return NfcManager().apply { 75 | setCurrentActivity(pluginBinding.activity) 76 | hiddenLifecycleReference.lifecycle.addObserver(NfcLifecycleObserver(this)) 77 | } 78 | } 79 | 80 | private fun createViewDelegate(activity: Activity, nfcManager: NfcManager): SessionViewDelegate { 81 | return DefaultSessionViewDelegate(nfcManager, nfcManager.reader, activity) 82 | } 83 | 84 | override fun onReattachedToActivityForConfigChanges(pluginBinding: ActivityPluginBinding) { 85 | wActivity = WeakReference(pluginBinding.activity) 86 | } 87 | 88 | override fun onDetachedFromActivityForConfigChanges() { 89 | wActivity = WeakReference(null) 90 | } 91 | 92 | override fun onMethodCall(call: MethodCall, result: Result) { 93 | replyAlreadySubmit = false 94 | when (call.method) { 95 | "runJSONRPCRequest" -> { 96 | runJSONRPCRequest(call, result) 97 | } 98 | "setScanImage" -> { 99 | setScanImage(call, result) 100 | } 101 | else -> result.notImplemented() 102 | } 103 | } 104 | 105 | private fun runJSONRPCRequest(call: MethodCall, result: Result) { 106 | try { 107 | sdk.startSessionWithJsonRequest( 108 | call.extract("JSONRPCRequest"), 109 | call.extractOptional("cardId"), 110 | call.extractOptional("initialMessage"), 111 | call.extractOptional("accessCode") 112 | ) { 113 | handleResult(it, result) 114 | } 115 | } catch (ex: Exception) { 116 | handleException(ex, result) 117 | } 118 | } 119 | 120 | /** 121 | * { 122 | * "base64": "encodedBase64ImageSource", 123 | * "verticalOffset": 0 // optional 124 | * } 125 | */ 126 | private fun setScanImage(call: MethodCall, callback: Result) { 127 | fun sendSuccessResult(callback: Result) { 128 | val successResult = "{ \"success\": true }" 129 | handleResult(successResult, callback) 130 | } 131 | 132 | try { 133 | val base64String: String? = call.extractOptional("base64") 134 | if (base64String == null) { 135 | sdk.setScanImage(GenericCard) 136 | sendSuccessResult(callback) 137 | } else { 138 | val base64Image: ByteArray = Base64.decode(base64String, Base64.DEFAULT) 139 | val verticalOffset: Int = call.extractOptional("verticalOffset") ?: 0 140 | val scanTagImage = ScanTagImage.Image(base64Image, verticalOffset) 141 | 142 | sdk.setScanImage(scanTagImage) 143 | sendSuccessResult(callback) 144 | } 145 | } catch (ex: Exception) { 146 | handleException(ex, callback) 147 | } 148 | } 149 | 150 | private fun handleResult(methodResul: String, callback: Result) { 151 | if (replyAlreadySubmit) return 152 | replyAlreadySubmit = true 153 | 154 | handler.post { 155 | callback.success(methodResul) 156 | } 157 | } 158 | 159 | private fun handleException(ex: Exception, result: Result) { 160 | if (replyAlreadySubmit) return 161 | replyAlreadySubmit = true 162 | 163 | handler.post { 164 | result.error("-1", converter.prettyPrint(ex, " "), null) 165 | } 166 | } 167 | 168 | @Throws(Exception::class) 169 | private inline fun MethodCall.extract(name: String): T { 170 | return this.extractOptional(name) ?: throw NoSuchFieldException(name) 171 | } 172 | 173 | private inline fun MethodCall.extractOptional(name: String): T? { 174 | if (!this.hasArgument(name)) return null 175 | val argument = this.argument(name) ?: return null 176 | 177 | if (argument is String && T::class.java == ByteArray::class.java) { 178 | return argument.hexToBytes() as T 179 | } 180 | 181 | return if (argument is String) { 182 | argument as T 183 | } else { 184 | val json = converter.toJson(argument) 185 | converter.fromJson(json)!! 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Symbolication related 36 | app.*.symbols 37 | 38 | # Obfuscation related 39 | app.*.map.json 40 | 41 | # Android Studio will place build artifacts here 42 | /android/app/debug 43 | /android/app/profile 44 | /android/app/release 45 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # tangem_sdk_example 2 | 3 | Demonstrates how to use the tangem_sdk plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | 18 | ## Running iOS example 19 | 20 | From the root of the project execute: 21 | 22 | - flutter pub get 23 | - find . -name "Podfile" -execdir pod install \; 24 | 25 | Open Runner.xcworkspace and launch the app 26 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | ndkVersion flutter.ndkVersion 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = '1.8' 39 | } 40 | 41 | sourceSets { 42 | main.java.srcDirs += 'src/main/kotlin' 43 | } 44 | 45 | defaultConfig { 46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 47 | applicationId "com.tangem.tangem_sdk_example" 48 | // You can update the following values to match your application needs. 49 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. 50 | minSdkVersion 21 51 | compileSdkVersion 33 52 | targetSdkVersion flutter.targetSdkVersion 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | } 56 | 57 | buildTypes { 58 | release { 59 | // TODO: Add your own signing config for the release build. 60 | shrinkResources false 61 | minifyEnabled false 62 | signingConfig signingConfigs.debug 63 | } 64 | } 65 | } 66 | 67 | flutter { 68 | source '../..' 69 | } 70 | 71 | dependencies { 72 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" 73 | } 74 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/tangem/tangem_sdk_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.tangem.tangem_sdk_example 2 | 3 | import io.flutter.embedding.android.FlutterFragmentActivity 4 | import io.flutter.embedding.engine.FlutterEngine 5 | import io.flutter.plugins.GeneratedPluginRegistrant 6 | 7 | class MainActivity: FlutterFragmentActivity() { 8 | override fun configureFlutterEngine(flutterEngine: FlutterEngine) { 9 | GeneratedPluginRegistrant.registerWith(flutterEngine) 10 | } 11 | } -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.8.0' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | maven {url 'https://jitpack.io'} 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 6 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - tangem_sdk (0.8.0): 4 | - Flutter 5 | - TangemSdk (~> 3.8.0) 6 | - TangemSdk (3.8.0) 7 | 8 | DEPENDENCIES: 9 | - Flutter (from `Flutter`) 10 | - tangem_sdk (from `.symlinks/plugins/tangem_sdk/ios`) 11 | 12 | SPEC REPOS: 13 | trunk: 14 | - TangemSdk 15 | 16 | EXTERNAL SOURCES: 17 | Flutter: 18 | :path: Flutter 19 | tangem_sdk: 20 | :path: ".symlinks/plugins/tangem_sdk/ios" 21 | 22 | SPEC CHECKSUMS: 23 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 24 | tangem_sdk: 062d151e7428527642134725e629835eb51f7d28 25 | TangemSdk: 34019108337b79c3afc5a7a4b7e67ccb78bf2e1c 26 | 27 | PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048 28 | 29 | COCOAPODS: 1.12.1 30 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | CBE4BA936ABAE965310BC704 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 737696E18EAFB9A02516B383 /* Pods_Runner.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = ""; 24 | dstSubfolderSpec = 10; 25 | files = ( 26 | ); 27 | name = "Embed Frameworks"; 28 | runOnlyForDeploymentPostprocessing = 0; 29 | }; 30 | /* End PBXCopyFilesBuildPhase section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 35 | 2B4E58270D1263479E384BC1 /* 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 = ""; }; 36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 37 | 41A9F2ADFD0DA2F178D44EA8 /* 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 = ""; }; 38 | 737696E18EAFB9A02516B383 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 40 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 41 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 42 | 96D1E8916F97AC440D74ED99 /* 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 = ""; }; 43 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 44 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 45 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 47 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | DA2C33472A38A43100D5BB6A /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | CBE4BA936ABAE965310BC704 /* Pods_Runner.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 54ED19D031E35BE9A2B01C27 /* Frameworks */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 737696E18EAFB9A02516B383 /* Pods_Runner.framework */, 69 | ); 70 | name = Frameworks; 71 | sourceTree = ""; 72 | }; 73 | 77C16E2064E170D406002462 /* Pods */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 96D1E8916F97AC440D74ED99 /* Pods-Runner.debug.xcconfig */, 77 | 41A9F2ADFD0DA2F178D44EA8 /* Pods-Runner.release.xcconfig */, 78 | 2B4E58270D1263479E384BC1 /* Pods-Runner.profile.xcconfig */, 79 | ); 80 | path = Pods; 81 | sourceTree = ""; 82 | }; 83 | 9740EEB11CF90186004384FC /* Flutter */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 87 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 88 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 89 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 90 | ); 91 | name = Flutter; 92 | sourceTree = ""; 93 | }; 94 | 97C146E51CF9000F007C117D = { 95 | isa = PBXGroup; 96 | children = ( 97 | 9740EEB11CF90186004384FC /* Flutter */, 98 | 97C146F01CF9000F007C117D /* Runner */, 99 | 97C146EF1CF9000F007C117D /* Products */, 100 | 77C16E2064E170D406002462 /* Pods */, 101 | 54ED19D031E35BE9A2B01C27 /* Frameworks */, 102 | ); 103 | sourceTree = ""; 104 | }; 105 | 97C146EF1CF9000F007C117D /* Products */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 97C146EE1CF9000F007C117D /* Runner.app */, 109 | ); 110 | name = Products; 111 | sourceTree = ""; 112 | }; 113 | 97C146F01CF9000F007C117D /* Runner */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | DA2C33472A38A43100D5BB6A /* Runner.entitlements */, 117 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 118 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 119 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 120 | 97C147021CF9000F007C117D /* Info.plist */, 121 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 122 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 123 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 124 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 125 | ); 126 | path = Runner; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | 97C146ED1CF9000F007C117D /* Runner */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 135 | buildPhases = ( 136 | 623A1C43164863C640DD0895 /* [CP] Check Pods Manifest.lock */, 137 | 9740EEB61CF901F6004384FC /* Run Script */, 138 | 97C146EA1CF9000F007C117D /* Sources */, 139 | 97C146EB1CF9000F007C117D /* Frameworks */, 140 | 97C146EC1CF9000F007C117D /* Resources */, 141 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 142 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 143 | 3AE6CAEC2041AA66F1BBEA0A /* [CP] Embed Pods Frameworks */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | ); 149 | name = Runner; 150 | productName = Runner; 151 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 152 | productType = "com.apple.product-type.application"; 153 | }; 154 | /* End PBXNativeTarget section */ 155 | 156 | /* Begin PBXProject section */ 157 | 97C146E61CF9000F007C117D /* Project object */ = { 158 | isa = PBXProject; 159 | attributes = { 160 | LastUpgradeCheck = 1300; 161 | ORGANIZATIONNAME = ""; 162 | TargetAttributes = { 163 | 97C146ED1CF9000F007C117D = { 164 | CreatedOnToolsVersion = 7.3.1; 165 | LastSwiftMigration = 1100; 166 | }; 167 | }; 168 | }; 169 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 170 | compatibilityVersion = "Xcode 9.3"; 171 | developmentRegion = en; 172 | hasScannedForEncodings = 0; 173 | knownRegions = ( 174 | en, 175 | Base, 176 | ); 177 | mainGroup = 97C146E51CF9000F007C117D; 178 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 179 | projectDirPath = ""; 180 | projectRoot = ""; 181 | targets = ( 182 | 97C146ED1CF9000F007C117D /* Runner */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXResourcesBuildPhase section */ 188 | 97C146EC1CF9000F007C117D /* Resources */ = { 189 | isa = PBXResourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 193 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 194 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 195 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | }; 199 | /* End PBXResourcesBuildPhase section */ 200 | 201 | /* Begin PBXShellScriptBuildPhase section */ 202 | 3AE6CAEC2041AA66F1BBEA0A /* [CP] Embed Pods Frameworks */ = { 203 | isa = PBXShellScriptBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | ); 207 | inputFileListPaths = ( 208 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", 209 | ); 210 | name = "[CP] Embed Pods Frameworks"; 211 | outputFileListPaths = ( 212 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | shellPath = /bin/sh; 216 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 217 | showEnvVarsInLog = 0; 218 | }; 219 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 220 | isa = PBXShellScriptBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | ); 224 | inputPaths = ( 225 | ); 226 | name = "Thin Binary"; 227 | outputPaths = ( 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | shellPath = /bin/sh; 231 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 232 | }; 233 | 623A1C43164863C640DD0895 /* [CP] Check Pods Manifest.lock */ = { 234 | isa = PBXShellScriptBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | ); 238 | inputFileListPaths = ( 239 | ); 240 | inputPaths = ( 241 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 242 | "${PODS_ROOT}/Manifest.lock", 243 | ); 244 | name = "[CP] Check Pods Manifest.lock"; 245 | outputFileListPaths = ( 246 | ); 247 | outputPaths = ( 248 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | shellPath = /bin/sh; 252 | shellScript = "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"; 253 | showEnvVarsInLog = 0; 254 | }; 255 | 9740EEB61CF901F6004384FC /* Run Script */ = { 256 | isa = PBXShellScriptBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | ); 260 | inputPaths = ( 261 | ); 262 | name = "Run Script"; 263 | outputPaths = ( 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | shellPath = /bin/sh; 267 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 268 | }; 269 | /* End PBXShellScriptBuildPhase section */ 270 | 271 | /* Begin PBXSourcesBuildPhase section */ 272 | 97C146EA1CF9000F007C117D /* Sources */ = { 273 | isa = PBXSourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 277 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | /* End PBXSourcesBuildPhase section */ 282 | 283 | /* Begin PBXVariantGroup section */ 284 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 285 | isa = PBXVariantGroup; 286 | children = ( 287 | 97C146FB1CF9000F007C117D /* Base */, 288 | ); 289 | name = Main.storyboard; 290 | sourceTree = ""; 291 | }; 292 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 293 | isa = PBXVariantGroup; 294 | children = ( 295 | 97C147001CF9000F007C117D /* Base */, 296 | ); 297 | name = LaunchScreen.storyboard; 298 | sourceTree = ""; 299 | }; 300 | /* End PBXVariantGroup section */ 301 | 302 | /* Begin XCBuildConfiguration section */ 303 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ALWAYS_SEARCH_USER_PATHS = NO; 307 | CLANG_ANALYZER_NONNULL = YES; 308 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 309 | CLANG_CXX_LIBRARY = "libc++"; 310 | CLANG_ENABLE_MODULES = YES; 311 | CLANG_ENABLE_OBJC_ARC = YES; 312 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_COMMA = YES; 315 | CLANG_WARN_CONSTANT_CONVERSION = YES; 316 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 317 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 318 | CLANG_WARN_EMPTY_BODY = YES; 319 | CLANG_WARN_ENUM_CONVERSION = YES; 320 | CLANG_WARN_INFINITE_RECURSION = YES; 321 | CLANG_WARN_INT_CONVERSION = YES; 322 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 323 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 324 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 325 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 326 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 327 | CLANG_WARN_STRICT_PROTOTYPES = YES; 328 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 332 | COPY_PHASE_STRIP = NO; 333 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 334 | ENABLE_NS_ASSERTIONS = NO; 335 | ENABLE_STRICT_OBJC_MSGSEND = YES; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_NO_COMMON_BLOCKS = YES; 338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 340 | GCC_WARN_UNDECLARED_SELECTOR = YES; 341 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 342 | GCC_WARN_UNUSED_FUNCTION = YES; 343 | GCC_WARN_UNUSED_VARIABLE = YES; 344 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 345 | MTL_ENABLE_DEBUG_INFO = NO; 346 | SDKROOT = iphoneos; 347 | SUPPORTED_PLATFORMS = iphoneos; 348 | TARGETED_DEVICE_FAMILY = "1,2"; 349 | VALIDATE_PRODUCT = YES; 350 | }; 351 | name = Profile; 352 | }; 353 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 354 | isa = XCBuildConfiguration; 355 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 356 | buildSettings = { 357 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 358 | CLANG_ENABLE_MODULES = YES; 359 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; 360 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 361 | DEVELOPMENT_TEAM = 4897UJ6D8C; 362 | ENABLE_BITCODE = NO; 363 | INFOPLIST_FILE = Runner/Info.plist; 364 | LD_RUNPATH_SEARCH_PATHS = ( 365 | "$(inherited)", 366 | "@executable_path/Frameworks", 367 | ); 368 | PRODUCT_BUNDLE_IDENTIFIER = com.tangem.flutter.plugin.tangemSdkExample1; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 371 | SWIFT_VERSION = 5.0; 372 | VERSIONING_SYSTEM = "apple-generic"; 373 | }; 374 | name = Profile; 375 | }; 376 | 97C147031CF9000F007C117D /* Debug */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | ALWAYS_SEARCH_USER_PATHS = NO; 380 | CLANG_ANALYZER_NONNULL = YES; 381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 382 | CLANG_CXX_LIBRARY = "libc++"; 383 | CLANG_ENABLE_MODULES = YES; 384 | CLANG_ENABLE_OBJC_ARC = YES; 385 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 386 | CLANG_WARN_BOOL_CONVERSION = YES; 387 | CLANG_WARN_COMMA = YES; 388 | CLANG_WARN_CONSTANT_CONVERSION = YES; 389 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 390 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 391 | CLANG_WARN_EMPTY_BODY = YES; 392 | CLANG_WARN_ENUM_CONVERSION = YES; 393 | CLANG_WARN_INFINITE_RECURSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNREACHABLE_CODE = YES; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | COPY_PHASE_STRIP = NO; 406 | DEBUG_INFORMATION_FORMAT = dwarf; 407 | ENABLE_STRICT_OBJC_MSGSEND = YES; 408 | ENABLE_TESTABILITY = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu99; 410 | GCC_DYNAMIC_NO_PIC = NO; 411 | GCC_NO_COMMON_BLOCKS = YES; 412 | GCC_OPTIMIZATION_LEVEL = 0; 413 | GCC_PREPROCESSOR_DEFINITIONS = ( 414 | "DEBUG=1", 415 | "$(inherited)", 416 | ); 417 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 418 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 419 | GCC_WARN_UNDECLARED_SELECTOR = YES; 420 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 421 | GCC_WARN_UNUSED_FUNCTION = YES; 422 | GCC_WARN_UNUSED_VARIABLE = YES; 423 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 424 | MTL_ENABLE_DEBUG_INFO = YES; 425 | ONLY_ACTIVE_ARCH = YES; 426 | SDKROOT = iphoneos; 427 | TARGETED_DEVICE_FAMILY = "1,2"; 428 | }; 429 | name = Debug; 430 | }; 431 | 97C147041CF9000F007C117D /* Release */ = { 432 | isa = XCBuildConfiguration; 433 | buildSettings = { 434 | ALWAYS_SEARCH_USER_PATHS = NO; 435 | CLANG_ANALYZER_NONNULL = YES; 436 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 437 | CLANG_CXX_LIBRARY = "libc++"; 438 | CLANG_ENABLE_MODULES = YES; 439 | CLANG_ENABLE_OBJC_ARC = YES; 440 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 441 | CLANG_WARN_BOOL_CONVERSION = YES; 442 | CLANG_WARN_COMMA = YES; 443 | CLANG_WARN_CONSTANT_CONVERSION = YES; 444 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 445 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 446 | CLANG_WARN_EMPTY_BODY = YES; 447 | CLANG_WARN_ENUM_CONVERSION = YES; 448 | CLANG_WARN_INFINITE_RECURSION = YES; 449 | CLANG_WARN_INT_CONVERSION = YES; 450 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 451 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 452 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 453 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 454 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 455 | CLANG_WARN_STRICT_PROTOTYPES = YES; 456 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 457 | CLANG_WARN_UNREACHABLE_CODE = YES; 458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 460 | COPY_PHASE_STRIP = NO; 461 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 462 | ENABLE_NS_ASSERTIONS = NO; 463 | ENABLE_STRICT_OBJC_MSGSEND = YES; 464 | GCC_C_LANGUAGE_STANDARD = gnu99; 465 | GCC_NO_COMMON_BLOCKS = YES; 466 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 467 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 468 | GCC_WARN_UNDECLARED_SELECTOR = YES; 469 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 470 | GCC_WARN_UNUSED_FUNCTION = YES; 471 | GCC_WARN_UNUSED_VARIABLE = YES; 472 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 473 | MTL_ENABLE_DEBUG_INFO = NO; 474 | SDKROOT = iphoneos; 475 | SUPPORTED_PLATFORMS = iphoneos; 476 | SWIFT_COMPILATION_MODE = wholemodule; 477 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 478 | TARGETED_DEVICE_FAMILY = "1,2"; 479 | VALIDATE_PRODUCT = YES; 480 | }; 481 | name = Release; 482 | }; 483 | 97C147061CF9000F007C117D /* Debug */ = { 484 | isa = XCBuildConfiguration; 485 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 486 | buildSettings = { 487 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 488 | CLANG_ENABLE_MODULES = YES; 489 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; 490 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 491 | DEVELOPMENT_TEAM = 4897UJ6D8C; 492 | ENABLE_BITCODE = NO; 493 | INFOPLIST_FILE = Runner/Info.plist; 494 | LD_RUNPATH_SEARCH_PATHS = ( 495 | "$(inherited)", 496 | "@executable_path/Frameworks", 497 | ); 498 | PRODUCT_BUNDLE_IDENTIFIER = com.tangem.flutter.plugin.tangemSdkExample1; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 501 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 502 | SWIFT_VERSION = 5.0; 503 | VERSIONING_SYSTEM = "apple-generic"; 504 | }; 505 | name = Debug; 506 | }; 507 | 97C147071CF9000F007C117D /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 510 | buildSettings = { 511 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 512 | CLANG_ENABLE_MODULES = YES; 513 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; 514 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 515 | DEVELOPMENT_TEAM = 4897UJ6D8C; 516 | ENABLE_BITCODE = NO; 517 | INFOPLIST_FILE = Runner/Info.plist; 518 | LD_RUNPATH_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "@executable_path/Frameworks", 521 | ); 522 | PRODUCT_BUNDLE_IDENTIFIER = com.tangem.flutter.plugin.tangemSdkExample1; 523 | PRODUCT_NAME = "$(TARGET_NAME)"; 524 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 525 | SWIFT_VERSION = 5.0; 526 | VERSIONING_SYSTEM = "apple-generic"; 527 | }; 528 | name = Release; 529 | }; 530 | /* End XCBuildConfiguration section */ 531 | 532 | /* Begin XCConfigurationList section */ 533 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | 97C147031CF9000F007C117D /* Debug */, 537 | 97C147041CF9000F007C117D /* Release */, 538 | 249021D3217E4FDB00AE95B9 /* Profile */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | 97C147061CF9000F007C117D /* Debug */, 547 | 97C147071CF9000F007C117D /* Release */, 548 | 249021D4217E4FDB00AE95B9 /* Profile */, 549 | ); 550 | defaultConfigurationIsVisible = 0; 551 | defaultConfigurationName = Release; 552 | }; 553 | /* End XCConfigurationList section */ 554 | }; 555 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 556 | } 557 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | Tangem Sdk 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | tangem_sdk_example 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(FLUTTER_BUILD_NAME) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSRequiresIPhoneOS 28 | 29 | NFCReaderUsageDescription 30 | To Scan Smart Card 31 | NSFaceIDUsageDescription 32 | To store access codes in a secure storage 33 | UIApplicationSupportsIndirectInputEvents 34 | 35 | UILaunchStoryboardName 36 | LaunchScreen 37 | UIMainStoryboardFile 38 | Main 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | UISupportedInterfaceOrientations~ipad 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationPortraitUpsideDown 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | com.apple.developer.nfc.readersession.iso7816.select-identifiers 55 | 56 | A000000812010208 57 | D2760000850101 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.nfc.readersession.formats 6 | 7 | TAG 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/lib/app_widgets.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class RowActions extends StatelessWidget { 4 | final List children; 5 | 6 | const RowActions(this.children, {Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | final spacer = SizedBox(width: 10); 11 | final wrappedChildren = []; 12 | wrappedChildren.add(spacer); 13 | children.forEach((e) { 14 | wrappedChildren.add(e); 15 | wrappedChildren.add(spacer); 16 | }); 17 | return Container( 18 | child: Row( 19 | mainAxisSize: MainAxisSize.max, 20 | mainAxisAlignment: MainAxisAlignment.center, 21 | children: wrappedChildren, 22 | ), 23 | ); 24 | } 25 | } 26 | 27 | class ActionType extends StatelessWidget { 28 | final String name; 29 | 30 | const ActionType(this.name, {Key? key}) : super(key: key); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return Column( 35 | children: [ 36 | SizedBox(height: 15), 37 | Center(child: Text(name)), 38 | SizedBox(height: 5), 39 | ], 40 | ); 41 | } 42 | } 43 | 44 | class ActionButton extends StatelessWidget { 45 | final String text; 46 | final VoidCallback action; 47 | 48 | const ActionButton(this.text, this.action, {Key? key}) : super(key: key); 49 | 50 | @override 51 | Widget build(BuildContext context) { 52 | return Container( 53 | child: ElevatedButton( 54 | child: Text(text), 55 | onPressed: action, 56 | ), 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | import 'package:tangem_sdk/tangem_sdk.dart'; 7 | import 'package:tangem_sdk_example/app_widgets.dart'; 8 | import 'package:tangem_sdk_example/source.dart'; 9 | 10 | void main() { 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | home: Scaffold( 19 | appBar: AppBar(title: const Text('Tangem SDK plugin example')), 20 | body: CommandListWidget(), 21 | ), 22 | ); 23 | } 24 | } 25 | 26 | class CommandListWidget extends StatefulWidget { 27 | @override 28 | _CommandListWidgetState createState() => _CommandListWidgetState(); 29 | } 30 | 31 | class _CommandListWidgetState extends State { 32 | final _jsonEncoder = JsonEncoder.withIndent(' '); 33 | 34 | static const int ID_UNDEFINED = -1; 35 | static const int ID_SCAN = 1; 36 | static const int ID_CREATE_WALLET = 2; 37 | static const int ID_PURGE_WALLET = 3; 38 | 39 | late TangemSdk _sdk; 40 | int _methodId = 10; 41 | 42 | String? _cardId; 43 | String? _walletPublicKey; 44 | String? _scanImage; 45 | String _response = ""; 46 | 47 | final _controller = TextEditingController(); 48 | 49 | @override 50 | void initState() { 51 | super.initState(); 52 | 53 | _sdk = TangemSdk(); 54 | _controller.addListener(() { 55 | setState(() {}); 56 | }); 57 | } 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | return SingleChildScrollView( 62 | child: Column( 63 | mainAxisSize: MainAxisSize.max, 64 | mainAxisAlignment: MainAxisAlignment.start, 65 | crossAxisAlignment: CrossAxisAlignment.stretch, 66 | children: [ 67 | SizedBox(height: 25), 68 | RowActions( 69 | [ 70 | ActionButton("Scan card", _handleScanCard), 71 | ActionButton("Sign hash", _handleSign), 72 | ], 73 | ), 74 | ActionType("Set scan image"), 75 | RowActions( 76 | [ 77 | ActionButton("Set", _handleSetScanImage), 78 | ActionButton("Remove", _handleRemoveScanImage), 79 | ], 80 | ), 81 | ActionType("Wallet"), 82 | RowActions( 83 | [ 84 | ActionButton("Create", _handleCreateWallet), 85 | ActionButton("Purge", _handlePurgeWallet), 86 | ], 87 | ), 88 | ActionType("Pins"), 89 | RowActions( 90 | [ 91 | ActionButton("Set access code", _handleSetAccessCode), 92 | ActionButton("Set passcode", _handleSetPasscode), 93 | ], 94 | ), 95 | SizedBox(height: 5), 96 | Divider(), 97 | ActionType("JSONRRPC"), 98 | Container( 99 | padding: EdgeInsets.symmetric(horizontal: 16), 100 | child: Column( 101 | mainAxisSize: MainAxisSize.min, 102 | children: [ 103 | SizedBox(height: 5), 104 | TextField( 105 | decoration: InputDecoration( 106 | contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 5), 107 | labelText: "Paste the configuration", 108 | isDense: true, 109 | ), 110 | minLines: 1, 111 | maxLines: 25, 112 | controller: _controller, 113 | ), 114 | SizedBox(height: 15), 115 | Row( 116 | children: [ 117 | OutlinedButton( 118 | onPressed: () async { 119 | final data = await Clipboard.getData(Clipboard.kTextPlain); 120 | final textData = data?.text ?? ""; 121 | if (textData.isEmpty) return; 122 | 123 | _controller.value = TextEditingValue(text: textData); 124 | }, 125 | child: Icon(Icons.paste)), 126 | SizedBox(width: 8), 127 | Expanded( 128 | child: OutlinedButton( 129 | child: Text("Launch"), 130 | onPressed: _controller.text.isEmpty ? null : () => _handleJsonRpc(_controller.text), 131 | ), 132 | ) 133 | ], 134 | ), 135 | ], 136 | ), 137 | ), 138 | Divider(), 139 | ActionType("RESULT"), 140 | Text(_response), 141 | ], 142 | ), 143 | ); 144 | } 145 | 146 | void _handleScanCard() { 147 | _execJsonRPCRequest(_makeJsonRpc(SdkMethod.scan)); 148 | } 149 | 150 | void _handleSign() { 151 | if (_cardId == null || _walletPublicKey == null) { 152 | _notify("Scan the card or create a wallet"); 153 | return; 154 | } 155 | 156 | final request = _makeJsonRpc(SdkMethod.sign_hash, { 157 | "walletPublicKey": _walletPublicKey, 158 | "hash": "f1642bb080e1f320924dde7238c1c5f8f1642bb080e1f320924dde7238c1c5f8ff", 159 | }); 160 | _execJsonRPCRequest(request, _cardId); 161 | } 162 | 163 | void _handleSetScanImage() { 164 | _sdk.setScanImage(ScanTagImage(base64Image, 0)).then((value) { 165 | _parseResponse(value); 166 | _printResponse(value); 167 | }).onError((error, stackTrace) { 168 | _printResponse(error); 169 | }); 170 | } 171 | 172 | void _handleRemoveScanImage() { 173 | _sdk.setScanImage(null).then((value) { 174 | _parseResponse(value); 175 | _printResponse(value); 176 | }).onError((error, stackTrace) { 177 | _printResponse(error); 178 | }); 179 | } 180 | 181 | void _handleCreateWallet() { 182 | if (_cardId == null) { 183 | _notify("Scan the card"); 184 | return; 185 | } 186 | 187 | final request = _makeJsonRpc(SdkMethod.create_wallet, { 188 | "curve": "Secp256k1", 189 | }); 190 | _execJsonRPCRequest(request, _cardId); 191 | } 192 | 193 | void _handlePurgeWallet() { 194 | if (_cardId == null || _walletPublicKey == null) { 195 | _notify("Scan the card or create a wallet"); 196 | return; 197 | } 198 | 199 | final request = _makeJsonRpc(SdkMethod.purge_wallet, { 200 | "walletPublicKey": _walletPublicKey, 201 | }); 202 | _execJsonRPCRequest(request, _cardId); 203 | } 204 | 205 | void _handleSetAccessCode() { 206 | if (_cardId == null) { 207 | _notify("Scan the card"); 208 | return; 209 | } 210 | 211 | final request = _makeJsonRpc(SdkMethod.set_accesscode, { 212 | "accessCode": "ABCDEFGH", 213 | }); 214 | _execJsonRPCRequest(request, _cardId); 215 | } 216 | 217 | void _handleSetPasscode() { 218 | if (_cardId == null) { 219 | _notify("Scan the card"); 220 | return; 221 | } 222 | 223 | final request = _makeJsonRpc(SdkMethod.set_passcode, { 224 | "passcode": "ABCDEFGH", 225 | }); 226 | _execJsonRPCRequest(request, _cardId); 227 | } 228 | 229 | void _handleJsonRpc(String text) { 230 | try { 231 | final jsonMap = jsonDecode(text.trim()); 232 | final request = JSONRPCRequest.fromJson(jsonMap); 233 | _execJsonRPCRequest(request, _cardId); 234 | } catch (ex) { 235 | _notify(ex.toString()); 236 | } 237 | } 238 | 239 | void _execJsonRPCRequest(JSONRPCRequest request, [String? cardId, Message? message, String? accessCode]) { 240 | final completeRequest = { 241 | "JSONRPCRequest": jsonEncode(request), 242 | "cardId": cardId, 243 | "initialMessage": message?.toJson(), 244 | "accessCode": accessCode, 245 | }; 246 | 247 | _sdk.runJSONRPCRequest(completeRequest).then((value) { 248 | _parseResponse(value); 249 | _printResponse(value); 250 | }).onError((error, stackTrace) { 251 | _printResponse(error); 252 | }); 253 | } 254 | 255 | void _printResponse(Object? decodedResponse) { 256 | if (decodedResponse == null) return; 257 | 258 | setState(() { 259 | _response = _reEncode(decodedResponse); 260 | }); 261 | } 262 | 263 | void _parseResponse(String response) { 264 | JSONRPCResponse jsonRpcResponse; 265 | try { 266 | jsonRpcResponse = JSONRPCResponse.fromJson(jsonDecode(response)); 267 | } catch (ex) { 268 | print(ex.toString()); 269 | return; 270 | } 271 | 272 | if (jsonRpcResponse.result != null) { 273 | switch (jsonRpcResponse.id) { 274 | case ID_SCAN: 275 | { 276 | _cardId = jsonRpcResponse.result["cardId"]; 277 | final wallets = jsonRpcResponse.result["wallets"]; 278 | if (wallets is List && wallets.isNotEmpty) { 279 | _walletPublicKey = wallets[0]["publicKey"]; 280 | } 281 | break; 282 | } 283 | case ID_CREATE_WALLET: 284 | { 285 | _walletPublicKey = jsonRpcResponse.result["wallet"]["publicKey"]; 286 | break; 287 | } 288 | case ID_PURGE_WALLET: 289 | { 290 | _walletPublicKey = null; 291 | break; 292 | } 293 | } 294 | } 295 | } 296 | 297 | JSONRPCRequest _makeJsonRpc(SdkMethod method, [Map params = const {}]) { 298 | return JSONRPCRequest(describeEnum(method), params, _getMethodId(method)); 299 | } 300 | 301 | int _getMethodId(SdkMethod method) { 302 | switch (method) { 303 | case SdkMethod.scan: 304 | return ID_SCAN; 305 | case SdkMethod.create_wallet: 306 | return ID_CREATE_WALLET; 307 | case SdkMethod.purge_wallet: 308 | return ID_PURGE_WALLET; 309 | default: 310 | return _methodId++; 311 | } 312 | } 313 | 314 | void _notify(String message) { 315 | setState(() { 316 | _response = message; 317 | }); 318 | } 319 | 320 | String _reEncode(Object value) { 321 | if (value is String) { 322 | return _jsonEncoder.convert(jsonDecode(value)); 323 | } else { 324 | return _jsonEncoder.convert(value); 325 | } 326 | } 327 | // describeEnum 328 | 329 | } 330 | 331 | enum SdkMethod { 332 | scan, 333 | sign_hash, 334 | sign_hashes, 335 | create_wallet, 336 | purge_wallet, 337 | set_accesscode, 338 | set_passcode, 339 | reset_usercodes, 340 | preflight_read, 341 | change_file_settings, 342 | delete_files, 343 | read_files, 344 | write_files, 345 | } 346 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: tangem_sdk_example 2 | description: Demonstrates how to use the tangem_sdk plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: '>=2.18.6 <3.0.0' 10 | 11 | # Dependencies specify other packages that your package needs in order to work. 12 | # To automatically upgrade your package dependencies to the latest versions 13 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 14 | # dependencies can be manually updated by changing the version numbers below to 15 | # the latest version available on pub.dev. To see which dependencies have newer 16 | # versions available, run `flutter pub outdated`. 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | 21 | tangem_sdk: 22 | # When depending on this package from a real application you should use: 23 | # tangem_sdk: ^x.y.z 24 | # See https://dart.dev/tools/pub/dependencies#version-constraints 25 | # The example app is bundled with the plugin so we use a path dependency on 26 | # the parent directory to use the current plugin's version. 27 | path: ../ 28 | 29 | # The following adds the Cupertino Icons font to your application. 30 | # Use with the CupertinoIcons class for iOS style icons. 31 | cupertino_icons: ^1.0.2 32 | 33 | dev_dependencies: 34 | flutter_test: 35 | sdk: flutter 36 | 37 | # For information on the generic Dart part of this file, see the 38 | # following page: https://dart.dev/tools/pub/pubspec 39 | 40 | # The following section is specific to Flutter packages. 41 | flutter: 42 | 43 | # The following line ensures that the Material Icons font is 44 | # included with your application, so that you can use the icons in 45 | # the material Icons class. 46 | uses-material-design: true 47 | 48 | # To add assets to your application, add an assets section, like this: 49 | # assets: 50 | # - images/a_dot_burr.jpeg 51 | # - images/a_dot_ham.jpeg 52 | 53 | # An image asset can refer to one or more resolution-specific "variants", see 54 | # https://flutter.dev/assets-and-images/#resolution-aware 55 | 56 | # For details regarding adding assets from package dependencies, see 57 | # https://flutter.dev/assets-and-images/#from-packages 58 | 59 | # To add custom fonts to your application, add a fonts section here, 60 | # in this "flutter" section. Each entry in this list should have a 61 | # "family" key with the font family name, and a "fonts" key with a 62 | # list giving the asset and other descriptors for the font. For 63 | # example: 64 | # fonts: 65 | # - family: Schyler 66 | # fonts: 67 | # - asset: fonts/Schyler-Regular.ttf 68 | # - asset: fonts/Schyler-Italic.ttf 69 | # style: italic 70 | # - family: Trajan Pro 71 | # fonts: 72 | # - asset: fonts/TrajanPro.ttf 73 | # - asset: fonts/TrajanPro_Bold.ttf 74 | # weight: 700 75 | # 76 | # For details regarding fonts from package dependencies, 77 | # see https://flutter.dev/custom-fonts/#from-packages 78 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:tangem_sdk_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && widget.data!.startsWith('Running on:'), 22 | ), 23 | findsOneWidget, 24 | ); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/ephemeral/ 38 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangem/tangem-sdk-flutter/ef4301ac51193b3496de461f37a935ce66bf7528/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/SwiftTangemSdkPlugin.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import TangemSdk 4 | 5 | public class SwiftTangemSdkPlugin: NSObject, FlutterPlugin { 6 | public static func register(with registrar: FlutterPluginRegistrar) { 7 | let channel = FlutterMethodChannel(name: "tangem_sdk", binaryMessenger: registrar.messenger()) 8 | let instance = SwiftTangemSdkPlugin() 9 | registrar.addMethodCallDelegate(instance, channel: channel) 10 | } 11 | 12 | private var _sdk: Any? 13 | 14 | @available(iOS 13, *) 15 | private var sdk: TangemSdk { 16 | if _sdk == nil { 17 | _sdk = TangemSdk() 18 | } 19 | return _sdk as! TangemSdk 20 | } 21 | 22 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 23 | do { 24 | switch call.method { 25 | case "runJSONRPCRequest": 26 | try runJSONRPCRequest(call.arguments, result) 27 | case "setScanImage": 28 | try setScanImage(call.arguments) 29 | default: 30 | result(FlutterMethodNotImplemented) 31 | } 32 | } catch { 33 | print(error) 34 | print(error.localizedDescription) 35 | result(error as? FlutterError ?? .underlyingError(error)) 36 | } 37 | } 38 | 39 | private func runJSONRPCRequest(_ args: Any?, _ completion: @escaping FlutterResult) throws { 40 | guard #available(iOS 13, *) else { 41 | throw FlutterError.iosTooOld 42 | } 43 | 44 | guard let request: String = getArg(for: .request, from: args) else { 45 | throw FlutterError.missingRequest 46 | } 47 | 48 | let cardId: String? = getArg(for: .cardId, from: args) 49 | let initialMessage: String? = getArg(for: .initialMessage, from: args) 50 | let accessCode: String? = getArg(for: .accessCode, from: args) 51 | 52 | sdk.startSession(with: request, 53 | cardId: cardId, 54 | initialMessage: initialMessage, 55 | accessCode: accessCode) { completion($0) } 56 | } 57 | 58 | public func setScanImage(_ args: Any?) throws { 59 | guard #available(iOS 13, *) else { 60 | return 61 | } 62 | 63 | let base64: String? = getArg(for: .base64, from: args) 64 | 65 | let scanTagImage: TangemSdkStyle.ScanTagImage 66 | if let base64, 67 | let data = Data(base64Encoded: base64.trimmingCharacters(in: .whitespacesAndNewlines)), 68 | let uiImage = UIImage(data: data) { 69 | let verticalOffset: Double = getArg(for: .verticalOffset, from: args) ?? 0 70 | scanTagImage = .image(uiImage: uiImage, verticalOffset: verticalOffset) 71 | } else { 72 | scanTagImage = .genericCard 73 | } 74 | sdk.config.style.scanTagImage = scanTagImage 75 | } 76 | 77 | private func getArg(for key: ArgKey, from arguments: Any?) -> T? { 78 | if let value = (arguments as? NSDictionary)?[key.rawValue] { 79 | return value as? T 80 | } 81 | 82 | return nil 83 | } 84 | } 85 | 86 | fileprivate enum ArgKey: String { 87 | case cardId 88 | case initialMessage 89 | case accessCode 90 | case request = "JSONRPCRequest" 91 | case base64 92 | case verticalOffset 93 | } 94 | 95 | extension FlutterError: Error {} 96 | 97 | fileprivate extension FlutterError { 98 | static let genericCode = "9999" 99 | 100 | static var missingRequest: FlutterError { 101 | FlutterError(code: genericCode, message: "Missing JSON RPC request", details: nil) 102 | } 103 | 104 | static func underlyingError(_ error: Error) -> FlutterError { 105 | FlutterError(code: genericCode, message: "Some error occured", details: error) 106 | } 107 | 108 | static var iosTooOld: FlutterError { 109 | FlutterError(code: genericCode, message: "Tangem SDK available from iOS 13", details: nil) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /ios/Classes/TangemSdkPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface TangemSdkPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/Classes/TangemSdkPlugin.m: -------------------------------------------------------------------------------- 1 | #import "TangemSdkPlugin.h" 2 | #if __has_include() 3 | #import 4 | #else 5 | // Support project import fallback if the generated compatibility header 6 | // is not copied when this plugin is created as a library. 7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 8 | #import "tangem_sdk-Swift.h" 9 | #endif 10 | 11 | @implementation TangemSdkPlugin 12 | + (void)registerWithRegistrar:(NSObject*)registrar { 13 | [SwiftTangemSdkPlugin registerWithRegistrar:registrar]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /ios/tangem_sdk.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint tangem_sdk.podspec` to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'tangem_sdk' 7 | s.version = '0.8.0' 8 | s.summary = 'TangemSdk flutter plugin.' 9 | s.description = <<-DESC 10 | TangemSdk plugin for integration into flutter projects 11 | DESC 12 | s.homepage = 'https://tangem.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.dependency 'Flutter' 18 | s.platform = :ios, '9.0' 19 | 20 | # Flutter.framework does not contain a i386 slice. 21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } 22 | s.swift_version = '5.0' 23 | s.dependency 'TangemSdk', '~> 3.8.0' 24 | end 25 | -------------------------------------------------------------------------------- /lib/extension/string.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:convert/convert.dart'; 4 | 5 | extension OnStringNullSafe on String { 6 | List hexToBytes() { 7 | final length = this.length ~/ 2; 8 | return List.generate(length, (index) => int.parse(this.substring(2 * index, 2 * index + 2), radix: 16)); 9 | } 10 | 11 | String hexToString() => utf8.decode(this.hexToBytes()); 12 | 13 | String toHexString() => hex.encode(this.toBytes()); 14 | 15 | List toBytes() => this.codeUnits; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lib/model/sdk.dart: -------------------------------------------------------------------------------- 1 | class Message { 2 | String? header; 3 | String? body; 4 | 5 | Message([this.header, this.body]); 6 | 7 | Map toJson() => { 8 | "header": header, 9 | "body": body, 10 | }; 11 | } 12 | 13 | class ScanTagImage { 14 | final String base64; 15 | final int verticalOffset; 16 | 17 | ScanTagImage(this.base64, [this.verticalOffset = 0]); 18 | 19 | Map toJson() => { 20 | "base64": base64, 21 | "verticalOffset": verticalOffset, 22 | }; 23 | } 24 | 25 | abstract class JSONRPC { 26 | final String jsonrpc = "2.0"; 27 | final dynamic id; 28 | 29 | JSONRPC([this.id]); 30 | } 31 | 32 | class JSONRPCRequest extends JSONRPC { 33 | final String method; 34 | final Map params; 35 | 36 | JSONRPCRequest(this.method, [this.params = const {}, dynamic id]) : super(id); 37 | 38 | Map toJson() => { 39 | 'method': method, 40 | 'params': params, 41 | 'id': id, 42 | 'jsonrpc': jsonrpc, 43 | }; 44 | 45 | factory JSONRPCRequest.fromJson(Map json) => JSONRPCRequest( 46 | json['method'] as String, 47 | json['params'] as Map, 48 | json['id'], 49 | ); 50 | } 51 | 52 | class JSONRPCResponse extends JSONRPC { 53 | final dynamic result; 54 | final dynamic error; 55 | 56 | JSONRPCResponse(this.result, this.error, [dynamic id]) : super(id); 57 | 58 | Map toJson() => { 59 | 'result': result, 60 | 'error': error, 61 | 'id': id, 62 | 'jsonrpc': jsonrpc, 63 | }; 64 | 65 | factory JSONRPCResponse.fromJson(Map json) => 66 | JSONRPCResponse( 67 | json['result'], 68 | json['error'], 69 | json['id'], 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /lib/tangem_sdk.dart: -------------------------------------------------------------------------------- 1 | export 'extension/string.dart'; 2 | export 'model/sdk.dart'; 3 | export 'tangem_sdk_plugin.dart'; 4 | -------------------------------------------------------------------------------- /lib/tangem_sdk_method_channel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'model/sdk.dart'; 5 | import 'tangem_sdk_platform_interface.dart'; 6 | 7 | /// An implementation of [TangemSdkPlatform] that uses method channels. 8 | class MethodChannelTangemSdk extends TangemSdkPlatform { 9 | /// The method channel used to interact with the native platform. 10 | @visibleForTesting 11 | final methodChannel = const MethodChannel('tangem_sdk'); 12 | 13 | @override 14 | Future getPlatformVersion() async { 15 | return await methodChannel.invokeMethod('getPlatformVersion'); 16 | } 17 | 18 | @override 19 | Future runJSONRPCRequest(Map request) async { 20 | return await methodChannel.invokeMethod("runJSONRPCRequest", request); 21 | } 22 | 23 | @override 24 | Future setScanImage(ScanTagImage? scanCardImage) async { 25 | Map args = {}; 26 | if (scanCardImage != null) { 27 | args = scanCardImage.toJson(); 28 | } 29 | return await methodChannel.invokeMethod("setScanImage", args); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/tangem_sdk_platform_interface.dart: -------------------------------------------------------------------------------- 1 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 2 | 3 | import 'model/sdk.dart'; 4 | import 'tangem_sdk_method_channel.dart'; 5 | 6 | abstract class TangemSdkPlatform extends PlatformInterface { 7 | static final Object _token = Object(); 8 | 9 | TangemSdkPlatform() : super(token: _token); 10 | 11 | static TangemSdkPlatform _instance = MethodChannelTangemSdk(); 12 | 13 | static TangemSdkPlatform get instance => _instance; 14 | 15 | /// Platform-specific implementations should set this with their own 16 | /// platform-specific class that extends [TangemSdkPlatform] when 17 | /// they register themselves. 18 | static set instance(TangemSdkPlatform instance) { 19 | PlatformInterface.verifyToken(instance, _token); 20 | _instance = instance; 21 | } 22 | 23 | Future getPlatformVersion() { 24 | throw UnimplementedError('platformVersion() has not been implemented.'); 25 | } 26 | 27 | Future runJSONRPCRequest(Map request) { 28 | throw UnimplementedError('runJSONRPCRequest has not been implemented.'); 29 | } 30 | 31 | Future setScanImage(ScanTagImage? scanCardImage) { 32 | throw UnimplementedError('setCardImage has not been implemented.'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/tangem_sdk_plugin.dart: -------------------------------------------------------------------------------- 1 | import 'model/sdk.dart'; 2 | import 'tangem_sdk_platform_interface.dart'; 3 | 4 | class TangemSdk { 5 | Future getPlatformVersion() { 6 | return TangemSdkPlatform.instance.getPlatformVersion(); 7 | } 8 | 9 | Future runJSONRPCRequest(Map request) { 10 | return TangemSdkPlatform.instance.runJSONRPCRequest(request); 11 | } 12 | 13 | Future setScanImage(ScanTagImage? scanCardImage) async { 14 | return TangemSdkPlatform.instance.setScanImage(scanCardImage); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: tangem_sdk 2 | description: TangemSdk flutter plugin. 3 | version: 0.8.0 4 | homepage: https://github.com/Tangem/tangem-sdk-flutter 5 | 6 | environment: 7 | sdk: '>=2.18.6 <3.0.0' 8 | flutter: ">=2.5.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | plugin_platform_interface: ^2.0.2 14 | convert: ^3.0.0 15 | json_annotation: ^4.0.1 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | build_runner: ^2.0.3 21 | json_serializable: ^6.6.1 22 | 23 | # generate files for json - https://github.com/dart-lang/json_serializable/tree/master/example 24 | # command for full generation 25 | # $ flutter pub get && flutter packages pub run build_runner build 26 | # command for update 27 | # $ flutter pub get && flutter packages pub run build_runner watch 28 | 29 | # For information on the generic Dart part of this file, see the 30 | # following page: https://dart.dev/tools/pub/pubspec 31 | 32 | # The following section is specific to Flutter packages. 33 | flutter: 34 | # This section identifies this Flutter project as a plugin project. 35 | # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) 36 | # which should be registered in the plugin registry. This is required for 37 | # using method channels. 38 | # The Android 'package' specifies package in which the registered class is. 39 | # This is required for using method channels on Android. 40 | # The 'ffiPlugin' specifies that native code should be built and bundled. 41 | # This is required for using `dart:ffi`. 42 | # All these are used by the tooling to maintain consistency when 43 | # adding or updating assets for this project. 44 | plugin: 45 | platforms: 46 | android: 47 | package: com.tangem.tangem_sdk 48 | pluginClass: TangemSdkPlugin 49 | ios: 50 | pluginClass: TangemSdkPlugin 51 | 52 | # To add assets to your plugin package, add an assets section, like this: 53 | # assets: 54 | # - images/a_dot_burr.jpeg 55 | # - images/a_dot_ham.jpeg 56 | # 57 | # For details regarding assets in packages, see 58 | # https://flutter.dev/assets-and-images/#from-packages 59 | # 60 | # An image asset can refer to one or more resolution-specific "variants", see 61 | # https://flutter.dev/assets-and-images/#resolution-aware 62 | 63 | # To add custom fonts to your plugin package, add a fonts section here, 64 | # in this "flutter" section. Each entry in this list should have a 65 | # "family" key with the font family name, and a "fonts" key with a 66 | # list giving the asset and other descriptors for the font. For 67 | # example: 68 | # fonts: 69 | # - family: Schyler 70 | # fonts: 71 | # - asset: fonts/Schyler-Regular.ttf 72 | # - asset: fonts/Schyler-Italic.ttf 73 | # style: italic 74 | # - family: Trajan Pro 75 | # fonts: 76 | # - asset: fonts/TrajanPro.ttf 77 | # - asset: fonts/TrajanPro_Bold.ttf 78 | # weight: 700 79 | # 80 | # For details regarding fonts in packages, see 81 | # https://flutter.dev/custom-fonts/#from-packages 82 | -------------------------------------------------------------------------------- /test/tangem_sdk_method_channel_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:tangem_sdk/tangem_sdk_method_channel.dart'; 4 | 5 | void main() { 6 | MethodChannelTangemSdk platform = MethodChannelTangemSdk(); 7 | const MethodChannel channel = MethodChannel('tangem_sdk'); 8 | 9 | TestWidgetsFlutterBinding.ensureInitialized(); 10 | 11 | setUp(() { 12 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 13 | return '42'; 14 | }); 15 | }); 16 | 17 | tearDown(() { 18 | channel.setMockMethodCallHandler(null); 19 | }); 20 | 21 | test('getPlatformVersion', () async { 22 | expect(await platform.getPlatformVersion(), '42'); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /test/tangem_sdk_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:tangem_sdk/model/sdk.dart'; 3 | import 'package:tangem_sdk/tangem_sdk_plugin.dart'; 4 | import 'package:tangem_sdk/tangem_sdk_platform_interface.dart'; 5 | import 'package:tangem_sdk/tangem_sdk_method_channel.dart'; 6 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 7 | 8 | class MockTangemSdkPlatform 9 | with MockPlatformInterfaceMixin 10 | implements TangemSdkPlatform { 11 | 12 | @override 13 | Future getPlatformVersion() => Future.value('42'); 14 | 15 | @override 16 | Future runJSONRPCRequest(Map request, [String? cardId, Message? initialMessage, String? accessCode]) { 17 | throw UnimplementedError(); 18 | } 19 | 20 | @override 21 | Future setScanImage(ScanTagImage? scanCardImage) { 22 | throw UnimplementedError(); 23 | } 24 | } 25 | 26 | void main() { 27 | final TangemSdkPlatform initialPlatform = TangemSdkPlatform.instance; 28 | 29 | test('$MethodChannelTangemSdk is the default instance', () { 30 | expect(initialPlatform, isInstanceOf()); 31 | }); 32 | 33 | test('getPlatformVersion', () async { 34 | TangemSdk tangemSdkPlugin = TangemSdk(); 35 | MockTangemSdkPlatform fakePlatform = MockTangemSdkPlatform(); 36 | TangemSdkPlatform.instance = fakePlatform; 37 | 38 | expect(await tangemSdkPlugin.getPlatformVersion(), '42'); 39 | }); 40 | } 41 | --------------------------------------------------------------------------------