├── .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 | [](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 |
--------------------------------------------------------------------------------