mirror of
https://github.com/MAGICGrants/flutter_libsparkmobile.git
synced 2026-01-08 04:33:50 -05:00
migrate to ffi plugin
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -28,10 +28,6 @@ doc/api/
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
lib/git_versions.dart
|
|
||||||
|
|
||||||
# Ignore build artifacts.
|
# Ignore build artifacts.
|
||||||
scripts/*/cache/
|
src/build
|
||||||
scripts/*/sparkmobile
|
src/deps/sparkmobile
|
||||||
scripts/*/CMakeLists/sparkmobile/CMakeLists.txt
|
|
||||||
scripts/*/CMakeLists/secp256k1/CMakeLists.txt
|
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "sparkmobile"]
|
|
||||||
path = sparkmobile
|
|
||||||
url = https://github.com/firoorg/sparkmobile
|
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
|
// The Android Gradle Plugin builds the native code with the Android NDK.
|
||||||
|
|
||||||
group 'com.cypherstack.flutter_libsparkmobile'
|
group 'com.cypherstack.flutter_libsparkmobile'
|
||||||
version '1.0-SNAPSHOT'
|
version '1.0'
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.7.10'
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// The Android Gradle Plugin knows how to build native code with the NDK.
|
||||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
rootProject.allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -22,43 +23,37 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
// Bumping the plugin compileSdkVersion requires all clients of this plugin
|
||||||
|
// to bump the version in their app.
|
||||||
compileSdkVersion 31
|
compileSdkVersion 31
|
||||||
|
|
||||||
|
// Bumping the plugin ndkVersion requires all clients of this plugin to bump
|
||||||
|
// the version in their app and to download a newer version of the NDK.
|
||||||
|
ndkVersion "23.1.7779620"
|
||||||
|
|
||||||
|
// Invoke the shared CMake build with the Android Gradle Plugin.
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path "../src/CMakeLists.txt"
|
||||||
|
|
||||||
|
// The default CMake version for the Android Gradle Plugin is 3.10.2.
|
||||||
|
// https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
|
||||||
|
//
|
||||||
|
// The Flutter tooling requires that developers have CMake 3.10 or later
|
||||||
|
// installed. You should not increase this version, as doing so will cause
|
||||||
|
// the plugin to fail to compile for some customers of the plugin.
|
||||||
|
// version "3.10.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '1.8'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
|
||||||
test.java.srcDirs += 'src/test/kotlin'
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
testImplementation 'org.jetbrains.kotlin:kotlin-test'
|
|
||||||
testImplementation 'org.mockito:mockito-core:5.0.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
testOptions {
|
|
||||||
unitTests.all {
|
|
||||||
useJUnitPlatform()
|
|
||||||
|
|
||||||
testLogging {
|
|
||||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
|
||||||
outputs.upToDateWhen {false}
|
|
||||||
showStandardStreams = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.cypherstack.flutter_libsparkmobile
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull
|
|
||||||
|
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
|
||||||
import io.flutter.plugin.common.MethodCall
|
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
|
||||||
import io.flutter.plugin.common.MethodChannel.Result
|
|
||||||
|
|
||||||
/** FlutterLibsparkmobilePlugin */
|
|
||||||
class FlutterLibsparkmobilePlugin: FlutterPlugin, MethodCallHandler {
|
|
||||||
/// The MethodChannel that will the communication between Flutter and native Android
|
|
||||||
///
|
|
||||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
|
||||||
/// when the Flutter Engine is detached from the Activity
|
|
||||||
private lateinit var channel : MethodChannel
|
|
||||||
|
|
||||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
|
||||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_libsparkmobile")
|
|
||||||
channel.setMethodCallHandler(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
|
||||||
if (call.method == "getPlatformVersion") {
|
|
||||||
result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
|
||||||
} else {
|
|
||||||
result.notImplemented()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
|
||||||
channel.setMethodCallHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.cypherstack.flutter_libsparkmobile
|
|
||||||
|
|
||||||
import io.flutter.plugin.common.MethodCall
|
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
import kotlin.test.Test
|
|
||||||
import org.mockito.Mockito
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation.
|
|
||||||
*
|
|
||||||
* Once you have built the plugin's example app, you can run these tests from the command
|
|
||||||
* line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or
|
|
||||||
* you can run them directly from IDEs that support JUnit such as Android Studio.
|
|
||||||
*/
|
|
||||||
|
|
||||||
internal class FlutterLibsparkmobilePluginTest {
|
|
||||||
@Test
|
|
||||||
fun onMethodCall_getPlatformVersion_returnsExpectedValue() {
|
|
||||||
val plugin = FlutterLibsparkmobilePlugin()
|
|
||||||
|
|
||||||
val call = MethodCall("getPlatformVersion", null)
|
|
||||||
val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java)
|
|
||||||
plugin.onMethodCall(call, mockResult)
|
|
||||||
|
|
||||||
Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,25 +2,11 @@ import Flutter
|
|||||||
import UIKit
|
import UIKit
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
@testable import flutter_libsparkmobile
|
|
||||||
|
|
||||||
// This demonstrates a simple unit test of the Swift portion of this plugin's implementation.
|
|
||||||
//
|
|
||||||
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
|
||||||
|
|
||||||
class RunnerTests: XCTestCase {
|
class RunnerTests: XCTestCase {
|
||||||
|
|
||||||
func testGetPlatformVersion() {
|
func testExample() {
|
||||||
let plugin = FlutterLibsparkmobilePlugin()
|
// If you add code to the Runner application, consider adding tests here.
|
||||||
|
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||||
let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: [])
|
|
||||||
|
|
||||||
let resultExpectation = expectation(description: "result block must be called.")
|
|
||||||
plugin.handle(call) { result in
|
|
||||||
XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion)
|
|
||||||
resultExpectation.fulfill()
|
|
||||||
}
|
|
||||||
waitForExpectations(timeout: 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,8 +86,6 @@ set_target_properties(${BINARY_NAME}
|
|||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable the test target.
|
|
||||||
set(include_flutter_libsparkmobile_tests TRUE)
|
|
||||||
|
|
||||||
# Generated plugin build rules, which manage building the plugins and adding
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
# them to the application.
|
# them to the application.
|
||||||
@@ -119,10 +117,6 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}
|
|||||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/linux/build/libsparkmobile.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
# Must have ran build script(s) in order for this library to exist.
|
|
||||||
|
|
||||||
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||||
install(FILES "${bundled_library}"
|
install(FILES "${bundled_library}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
|||||||
@@ -6,10 +6,6 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <flutter_libsparkmobile/flutter_libsparkmobile_plugin.h>
|
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
g_autoptr(FlPluginRegistrar) flutter_libsparkmobile_registrar =
|
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibsparkmobilePlugin");
|
|
||||||
flutter_libsparkmobile_plugin_register_with_registrar(flutter_libsparkmobile_registrar);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
flutter_libsparkmobile
|
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
coinlib_flutter
|
coinlib_flutter
|
||||||
|
flutter_libsparkmobile
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import flutter_libsparkmobile
|
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
FlutterLibsparkmobilePlugin.register(with: registry.registrar(forPlugin: "FlutterLibsparkmobilePlugin"))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,11 @@ import FlutterMacOS
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
@testable import flutter_libsparkmobile
|
|
||||||
|
|
||||||
// This demonstrates a simple unit test of the Swift portion of this plugin's implementation.
|
|
||||||
//
|
|
||||||
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
|
||||||
|
|
||||||
class RunnerTests: XCTestCase {
|
class RunnerTests: XCTestCase {
|
||||||
|
|
||||||
func testGetPlatformVersion() {
|
func testExample() {
|
||||||
let plugin = FlutterLibsparkmobilePlugin()
|
// If you add code to the Runner application, consider adding tests here.
|
||||||
|
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||||
let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: [])
|
|
||||||
|
|
||||||
let resultExpectation = expectation(description: "result block must be called.")
|
|
||||||
plugin.handle(call) { result in
|
|
||||||
XCTAssertEqual(result as! String,
|
|
||||||
"macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
|
|
||||||
resultExpectation.fulfill()
|
|
||||||
}
|
|
||||||
waitForExpectations(timeout: 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,20 @@ description: Demonstrates how to use the flutter_libsparkmobile plugin.
|
|||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
|
# The following defines the version and build number for your application.
|
||||||
|
# A version number is three numbers separated by dots, like 1.2.43
|
||||||
|
# followed by an optional build number separated by a +.
|
||||||
|
# Both the version and the builder number may be overridden in flutter
|
||||||
|
# build by specifying --build-name and --build-number, respectively.
|
||||||
|
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||||
|
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||||
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
||||||
|
# Read more about iOS versioning at
|
||||||
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.6 <4.0.0'
|
sdk: '>=3.0.6 <4.0.0'
|
||||||
|
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ add_subdirectory(${FLUTTER_MANAGED_DIR})
|
|||||||
# Application build; see runner/CMakeLists.txt.
|
# Application build; see runner/CMakeLists.txt.
|
||||||
add_subdirectory("runner")
|
add_subdirectory("runner")
|
||||||
|
|
||||||
# Enable the test target.
|
|
||||||
set(include_flutter_libsparkmobile_tests TRUE)
|
|
||||||
|
|
||||||
# Generated plugin build rules, which manage building the plugins and adding
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
# them to the application.
|
# them to the application.
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <flutter_libsparkmobile/flutter_libsparkmobile_plugin_c_api.h>
|
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
FlutterLibsparkmobilePluginCApiRegisterWithRegistrar(
|
|
||||||
registry->GetRegistrarForPlugin("FlutterLibsparkmobilePluginCApi"));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
flutter_libsparkmobile
|
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
flutter_libsparkmobile
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
19
ffigen.yaml
Normal file
19
ffigen.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Run with `flutter pub run ffigen --config ffigen.yaml`.
|
||||||
|
name: FlutterLibsparkmobileBindings
|
||||||
|
description: |
|
||||||
|
Bindings for `src/flutter_libsparkmobile.h`.
|
||||||
|
|
||||||
|
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||||
|
output: 'lib/flutter_libsparkmobile_bindings_generated.dart'
|
||||||
|
headers:
|
||||||
|
entry-points:
|
||||||
|
- 'src/flutter_libsparkmobile.h'
|
||||||
|
include-directives:
|
||||||
|
- 'src/flutter_libsparkmobile.h'
|
||||||
|
preamble: |
|
||||||
|
// ignore_for_file: always_specify_types
|
||||||
|
// ignore_for_file: camel_case_types
|
||||||
|
// ignore_for_file: non_constant_identifier_names
|
||||||
|
comments:
|
||||||
|
style: any
|
||||||
|
length: full
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
|
<excludeFolder url="file://$MODULE_DIR$/example/.idea" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
|
<excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
|
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
|
||||||
|
|||||||
38
ios/.gitignore
vendored
38
ios/.gitignore
vendored
@@ -1,38 +0,0 @@
|
|||||||
.idea/
|
|
||||||
.vagrant/
|
|
||||||
.sconsign.dblite
|
|
||||||
.svn/
|
|
||||||
|
|
||||||
.DS_Store
|
|
||||||
*.swp
|
|
||||||
profile
|
|
||||||
|
|
||||||
DerivedData/
|
|
||||||
build/
|
|
||||||
GeneratedPluginRegistrant.h
|
|
||||||
GeneratedPluginRegistrant.m
|
|
||||||
|
|
||||||
.generated/
|
|
||||||
|
|
||||||
*.pbxuser
|
|
||||||
*.mode1v3
|
|
||||||
*.mode2v3
|
|
||||||
*.perspectivev3
|
|
||||||
|
|
||||||
!default.pbxuser
|
|
||||||
!default.mode1v3
|
|
||||||
!default.mode2v3
|
|
||||||
!default.perspectivev3
|
|
||||||
|
|
||||||
xcuserdata
|
|
||||||
|
|
||||||
*.moved-aside
|
|
||||||
|
|
||||||
*.pyc
|
|
||||||
*sync/
|
|
||||||
Icon?
|
|
||||||
.tags*
|
|
||||||
|
|
||||||
/Flutter/Generated.xcconfig
|
|
||||||
/Flutter/ephemeral/
|
|
||||||
/Flutter/flutter_export_environment.sh
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import Flutter
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
public class FlutterLibsparkmobilePlugin: NSObject, FlutterPlugin {
|
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
||||||
let channel = FlutterMethodChannel(name: "flutter_libsparkmobile", binaryMessenger: registrar.messenger())
|
|
||||||
let instance = FlutterLibsparkmobilePlugin()
|
|
||||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
||||||
switch call.method {
|
|
||||||
case "getPlatformVersion":
|
|
||||||
result("iOS " + UIDevice.current.systemVersion)
|
|
||||||
default:
|
|
||||||
result(FlutterMethodNotImplemented)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
ios/Classes/flutter_libsparkmobile.c
Normal file
3
ios/Classes/flutter_libsparkmobile.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Relative import to be able to reuse the C sources.
|
||||||
|
// See the comment in ../{projectName}}.podspec for more information.
|
||||||
|
#include flutter_libsparkmobile.cpp
|
||||||
@@ -5,13 +5,18 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'flutter_libsparkmobile'
|
s.name = 'flutter_libsparkmobile'
|
||||||
s.version = '0.0.1'
|
s.version = '0.0.1'
|
||||||
s.summary = 'A new Flutter plugin project.'
|
s.summary = 'A new Flutter project.'
|
||||||
s.description = <<-DESC
|
s.description = <<-DESC
|
||||||
A new Flutter plugin project.
|
A new Flutter project.
|
||||||
DESC
|
DESC
|
||||||
s.homepage = 'http://example.com'
|
s.homepage = 'http://example.com'
|
||||||
s.license = { :file => '../LICENSE' }
|
s.license = { :file => '../LICENSE' }
|
||||||
s.author = { 'Your Company' => 'email@example.com' }
|
s.author = { 'Your Company' => 'email@example.com' }
|
||||||
|
|
||||||
|
# This will ensure the source files in Classes/ are included in the native
|
||||||
|
# builds of apps using this FFI plugin. Podspec does not support relative
|
||||||
|
# paths, so Classes contains a forwarder C file that relatively imports
|
||||||
|
# `../src/*` so that the C sources can be shared among all target platforms.
|
||||||
s.source = { :path => '.' }
|
s.source = { :path => '.' }
|
||||||
s.source_files = 'Classes/**/*'
|
s.source_files = 'Classes/**/*'
|
||||||
s.dependency 'Flutter'
|
s.dependency 'Flutter'
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
@@ -5,46 +6,67 @@ import 'dart:typed_data';
|
|||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:flutter_libsparkmobile/extensions.dart';
|
import 'package:flutter_libsparkmobile/extensions.dart';
|
||||||
|
|
||||||
import 'flutter_libsparkmobile_bindings.dart';
|
import 'flutter_libsparkmobile_bindings_generated.dart';
|
||||||
|
|
||||||
const kSparkChain = 6;
|
const kSparkChain = 6;
|
||||||
const kSparkBaseDerivationPath = "m/44'/136'/0'/$kSparkChain/";
|
const kSparkBaseDerivationPath = "m/44'/136'/0'/$kSparkChain/";
|
||||||
|
|
||||||
|
const String _kLibName = 'flutter_libsparkmobile';
|
||||||
|
|
||||||
|
/// The dynamic library in which the symbols for [FlutterLibsparkmobileBindings] can be found.
|
||||||
|
final DynamicLibrary _dylib = () {
|
||||||
|
if (Platform.isMacOS || Platform.isIOS) {
|
||||||
|
return DynamicLibrary.open('$_kLibName.framework/$_kLibName');
|
||||||
|
}
|
||||||
|
if (Platform.isAndroid || Platform.isLinux) {
|
||||||
|
return DynamicLibrary.open('lib$_kLibName.so');
|
||||||
|
}
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
return DynamicLibrary.open('$_kLibName.dll');
|
||||||
|
}
|
||||||
|
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
|
||||||
|
}();
|
||||||
|
|
||||||
|
/// The bindings to the native functions in [_dylib].
|
||||||
|
final FlutterLibsparkmobileBindings _bindings =
|
||||||
|
FlutterLibsparkmobileBindings(_dylib);
|
||||||
|
|
||||||
abstract final class LibSpark {
|
abstract final class LibSpark {
|
||||||
static SparkMobileBindings? _bindings;
|
static final FlutterLibsparkmobileBindings _bindings =
|
||||||
|
FlutterLibsparkmobileBindings(_dylib);
|
||||||
static void _checkLoaded() {
|
//
|
||||||
_bindings ??= SparkMobileBindings(_loadLibrary());
|
// static void _checkLoaded() {
|
||||||
}
|
// _bindings ??= SparkMobileBindings(_loadLibrary());
|
||||||
|
// }
|
||||||
static DynamicLibrary _loadLibrary() {
|
//
|
||||||
// hack in prefix for test env
|
// static DynamicLibrary _loadLibrary() {
|
||||||
String testPrefix = "";
|
// // hack in prefix for test env
|
||||||
if (Platform.environment.containsKey('FLUTTER_TEST')) {
|
// String testPrefix = "";
|
||||||
if (Platform.isLinux) {
|
// if (Platform.environment.containsKey('FLUTTER_TEST')) {
|
||||||
testPrefix = 'scripts/linux/build/';
|
// if (Platform.isLinux) {
|
||||||
} else if (Platform.isMacOS) {
|
// testPrefix = 'scripts/linux/build/';
|
||||||
testPrefix = 'scripts/macos/build/';
|
// } else if (Platform.isMacOS) {
|
||||||
} else if (Platform.isWindows) {
|
// testPrefix = 'scripts/macos/build/';
|
||||||
testPrefix = 'scripts/windows/build/';
|
// } else if (Platform.isWindows) {
|
||||||
} else {
|
// testPrefix = 'scripts/windows/build/';
|
||||||
throw UnsupportedError('This platform is not supported');
|
// } else {
|
||||||
}
|
// throw UnsupportedError('This platform is not supported');
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
if (Platform.isLinux) {
|
//
|
||||||
return DynamicLibrary.open('${testPrefix}libsparkmobile.so');
|
// if (Platform.isLinux) {
|
||||||
} else if (Platform.isAndroid) {
|
// return DynamicLibrary.open('${testPrefix}libsparkmobile.so');
|
||||||
// return DynamicLibrary.open('${testPrefix}libsparkmobile.so');
|
// } else if (Platform.isAndroid) {
|
||||||
} else if (Platform.isIOS) {
|
// // return DynamicLibrary.open('${testPrefix}libsparkmobile.so');
|
||||||
// return DynamicLibrary.open('${testPrefix}libsparkmobile.dylib');
|
// } else if (Platform.isIOS) {
|
||||||
} else if (Platform.isMacOS) {
|
// // return DynamicLibrary.open('${testPrefix}libsparkmobile.dylib');
|
||||||
// return DynamicLibrary.open('${testPrefix}libsparkmobile.dylib');
|
// } else if (Platform.isMacOS) {
|
||||||
} else if (Platform.isWindows) {
|
// // return DynamicLibrary.open('${testPrefix}libsparkmobile.dylib');
|
||||||
// return DynamicLibrary.open('${testPrefix}sparkmobile.dll');
|
// } else if (Platform.isWindows) {
|
||||||
}
|
// // return DynamicLibrary.open('${testPrefix}sparkmobile.dll');
|
||||||
throw UnsupportedError('This platform is not supported');
|
// }
|
||||||
}
|
// throw UnsupportedError('This platform is not supported');
|
||||||
|
// }
|
||||||
|
|
||||||
// SparkMobileBindings methods:
|
// SparkMobileBindings methods:
|
||||||
|
|
||||||
@@ -55,7 +77,7 @@ abstract final class LibSpark {
|
|||||||
required int diversifier,
|
required int diversifier,
|
||||||
bool isTestNet = false,
|
bool isTestNet = false,
|
||||||
}) async {
|
}) async {
|
||||||
_checkLoaded();
|
// _checkLoaded();
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
throw Exception("Index must not be negative.");
|
throw Exception("Index must not be negative.");
|
||||||
@@ -75,7 +97,7 @@ abstract final class LibSpark {
|
|||||||
final keyDataPointer = privateKey.toHexString().toNativeUtf8().cast<Char>();
|
final keyDataPointer = privateKey.toHexString().toNativeUtf8().cast<Char>();
|
||||||
|
|
||||||
// Call the native method with the pointer.
|
// Call the native method with the pointer.
|
||||||
final addressPointer = _bindings!.getAddress(
|
final addressPointer = _bindings.getAddress(
|
||||||
keyDataPointer,
|
keyDataPointer,
|
||||||
index,
|
index,
|
||||||
diversifier,
|
diversifier,
|
||||||
@@ -92,3 +114,128 @@ abstract final class LibSpark {
|
|||||||
return addressString;
|
return addressString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// /// A very short-lived native function.
|
||||||
|
// ///
|
||||||
|
// /// For very short-lived functions, it is fine to call them on the main isolate.
|
||||||
|
// /// They will block the Dart execution while running the native function, so
|
||||||
|
// /// only do this for native functions which are guaranteed to be short-lived.
|
||||||
|
// int sum(int a, int b) => _bindings.sum(a, b);
|
||||||
|
//
|
||||||
|
// /// A longer lived native function, which occupies the thread calling it.
|
||||||
|
// ///
|
||||||
|
// /// Do not call these kind of native functions in the main isolate. They will
|
||||||
|
// /// block Dart execution. This will cause dropped frames in Flutter applications.
|
||||||
|
// /// Instead, call these native functions on a separate isolate.
|
||||||
|
// ///
|
||||||
|
// /// Modify this to suit your own use case. Example use cases:
|
||||||
|
// ///
|
||||||
|
// /// 1. Reuse a single isolate for various different kinds of requests.
|
||||||
|
// /// 2. Use multiple helper isolates for parallel execution.
|
||||||
|
// Future<int> sumAsync(int a, int b) async {
|
||||||
|
// final SendPort helperIsolateSendPort = await _helperIsolateSendPort;
|
||||||
|
// final int requestId = _nextSumRequestId++;
|
||||||
|
// final _SumRequest request = _SumRequest(requestId, a, b);
|
||||||
|
// final Completer<int> completer = Completer<int>();
|
||||||
|
// _sumRequests[requestId] = completer;
|
||||||
|
// helperIsolateSendPort.send(request);
|
||||||
|
// return completer.future;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const String _libName = 'flutter_libsparkmobile';
|
||||||
|
//
|
||||||
|
// /// The dynamic library in which the symbols for [FlutterLibsparkmobileBindings] can be found.
|
||||||
|
// final DynamicLibrary _dylib = () {
|
||||||
|
// if (Platform.isMacOS || Platform.isIOS) {
|
||||||
|
// return DynamicLibrary.open('$_libName.framework/$_libName');
|
||||||
|
// }
|
||||||
|
// if (Platform.isAndroid || Platform.isLinux) {
|
||||||
|
// return DynamicLibrary.open('lib$_libName.so');
|
||||||
|
// }
|
||||||
|
// if (Platform.isWindows) {
|
||||||
|
// return DynamicLibrary.open('$_libName.dll');
|
||||||
|
// }
|
||||||
|
// throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
|
||||||
|
// }();
|
||||||
|
//
|
||||||
|
// /// The bindings to the native functions in [_dylib].
|
||||||
|
// final FlutterLibsparkmobileBindings _bindings = FlutterLibsparkmobileBindings(_dylib);
|
||||||
|
|
||||||
|
//
|
||||||
|
// /// A request to compute `sum`.
|
||||||
|
// ///
|
||||||
|
// /// Typically sent from one isolate to another.
|
||||||
|
// class _SumRequest {
|
||||||
|
// final int id;
|
||||||
|
// final int a;
|
||||||
|
// final int b;
|
||||||
|
//
|
||||||
|
// const _SumRequest(this.id, this.a, this.b);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// A response with the result of `sum`.
|
||||||
|
// ///
|
||||||
|
// /// Typically sent from one isolate to another.
|
||||||
|
// class _SumResponse {
|
||||||
|
// final int id;
|
||||||
|
// final int result;
|
||||||
|
//
|
||||||
|
// const _SumResponse(this.id, this.result);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Counter to identify [_SumRequest]s and [_SumResponse]s.
|
||||||
|
// int _nextSumRequestId = 0;
|
||||||
|
//
|
||||||
|
// /// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request.
|
||||||
|
// final Map<int, Completer<int>> _sumRequests = <int, Completer<int>>{};
|
||||||
|
//
|
||||||
|
// /// The SendPort belonging to the helper isolate.
|
||||||
|
// Future<SendPort> _helperIsolateSendPort = () async {
|
||||||
|
// // The helper isolate is going to send us back a SendPort, which we want to
|
||||||
|
// // wait for.
|
||||||
|
// final Completer<SendPort> completer = Completer<SendPort>();
|
||||||
|
//
|
||||||
|
// // Receive port on the main isolate to receive messages from the helper.
|
||||||
|
// // We receive two types of messages:
|
||||||
|
// // 1. A port to send messages on.
|
||||||
|
// // 2. Responses to requests we sent.
|
||||||
|
// final ReceivePort receivePort = ReceivePort()
|
||||||
|
// ..listen((dynamic data) {
|
||||||
|
// if (data is SendPort) {
|
||||||
|
// // The helper isolate sent us the port on which we can sent it requests.
|
||||||
|
// completer.complete(data);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// if (data is _SumResponse) {
|
||||||
|
// // The helper isolate sent us a response to a request we sent.
|
||||||
|
// final Completer<int> completer = _sumRequests[data.id]!;
|
||||||
|
// _sumRequests.remove(data.id);
|
||||||
|
// completer.complete(data.result);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // Start the helper isolate.
|
||||||
|
// await Isolate.spawn((SendPort sendPort) async {
|
||||||
|
// final ReceivePort helperReceivePort = ReceivePort()
|
||||||
|
// ..listen((dynamic data) {
|
||||||
|
// // On the helper isolate listen to requests and respond to them.
|
||||||
|
// if (data is _SumRequest) {
|
||||||
|
// final int result = _bindings.sum_long_running(data.a, data.b);
|
||||||
|
// final _SumResponse response = _SumResponse(data.id, result);
|
||||||
|
// sendPort.send(response);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // Send the port to the main isolate on which we can receive requests.
|
||||||
|
// sendPort.send(helperReceivePort.sendPort);
|
||||||
|
// }, receivePort.sendPort);
|
||||||
|
//
|
||||||
|
// // Wait until the helper isolate has sent us back the SendPort on which we
|
||||||
|
// // can start sending requests.
|
||||||
|
// return completer.future;
|
||||||
|
// }();
|
||||||
|
|||||||
@@ -1,439 +0,0 @@
|
|||||||
// ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field, return_of_invalid_type, void_checks, annotate_overrides, no_leading_underscores_for_local_identifiers, library_private_types_in_public_api
|
|
||||||
|
|
||||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
|
||||||
//
|
|
||||||
// Generated by `package:ffigen`.
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
import 'dart:ffi' as ffi;
|
|
||||||
|
|
||||||
/// Bindings for sparkmobile.
|
|
||||||
class SparkMobileBindings {
|
|
||||||
/// Holds the symbol lookup function.
|
|
||||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
|
||||||
_lookup;
|
|
||||||
|
|
||||||
/// The symbols are looked up in [dynamicLibrary].
|
|
||||||
SparkMobileBindings(ffi.DynamicLibrary dynamicLibrary)
|
|
||||||
: _lookup = dynamicLibrary.lookup;
|
|
||||||
|
|
||||||
/// The symbols are looked up with [lookup].
|
|
||||||
SparkMobileBindings.fromLookup(
|
|
||||||
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
|
||||||
lookup)
|
|
||||||
: _lookup = lookup;
|
|
||||||
|
|
||||||
ffi.Pointer<ffi.Char> getAddress(
|
|
||||||
ffi.Pointer<ffi.Char> keyDataHex,
|
|
||||||
int index,
|
|
||||||
int diversifier,
|
|
||||||
int isTestNet,
|
|
||||||
) {
|
|
||||||
return _getAddress(
|
|
||||||
keyDataHex,
|
|
||||||
index,
|
|
||||||
diversifier,
|
|
||||||
isTestNet,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
late final _getAddressPtr = _lookup<
|
|
||||||
ffi.NativeFunction<
|
|
||||||
ffi.Pointer<ffi.Char> Function(
|
|
||||||
ffi.Pointer<ffi.Char>, ffi.Int, ffi.Int, ffi.Int)>>('getAddress');
|
|
||||||
late final _getAddress = _getAddressPtr.asFunction<
|
|
||||||
ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, int, int, int)>();
|
|
||||||
|
|
||||||
CIdentifiedCoinData identifyCoin(
|
|
||||||
CCoin c_struct,
|
|
||||||
ffi.Pointer<ffi.Char> keyDataHex,
|
|
||||||
int index,
|
|
||||||
) {
|
|
||||||
return _identifyCoin(
|
|
||||||
c_struct,
|
|
||||||
keyDataHex,
|
|
||||||
index,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
late final _identifyCoinPtr = _lookup<
|
|
||||||
ffi.NativeFunction<
|
|
||||||
CIdentifiedCoinData Function(
|
|
||||||
CCoin, ffi.Pointer<ffi.Char>, ffi.Int)>>('identifyCoin');
|
|
||||||
late final _identifyCoin = _identifyCoinPtr.asFunction<
|
|
||||||
CIdentifiedCoinData Function(CCoin, ffi.Pointer<ffi.Char>, int)>();
|
|
||||||
|
|
||||||
ffi.Pointer<CCRecipient> createSparkMintRecipients(
|
|
||||||
int numRecipients,
|
|
||||||
ffi.Pointer<PubKeyScript> pubKeyScripts,
|
|
||||||
ffi.Pointer<ffi.Uint64> amounts,
|
|
||||||
ffi.Pointer<ffi.Char> memo,
|
|
||||||
int subtractFee,
|
|
||||||
) {
|
|
||||||
return _createSparkMintRecipients(
|
|
||||||
numRecipients,
|
|
||||||
pubKeyScripts,
|
|
||||||
amounts,
|
|
||||||
memo,
|
|
||||||
subtractFee,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
late final _createSparkMintRecipientsPtr = _lookup<
|
|
||||||
ffi.NativeFunction<
|
|
||||||
ffi.Pointer<CCRecipient> Function(
|
|
||||||
ffi.Int,
|
|
||||||
ffi.Pointer<PubKeyScript>,
|
|
||||||
ffi.Pointer<ffi.Uint64>,
|
|
||||||
ffi.Pointer<ffi.Char>,
|
|
||||||
ffi.Int)>>('createSparkMintRecipients');
|
|
||||||
late final _createSparkMintRecipients =
|
|
||||||
_createSparkMintRecipientsPtr.asFunction<
|
|
||||||
ffi.Pointer<CCRecipient> Function(int, ffi.Pointer<PubKeyScript>,
|
|
||||||
ffi.Pointer<ffi.Uint64>, ffi.Pointer<ffi.Char>, int)>();
|
|
||||||
}
|
|
||||||
|
|
||||||
final class __fsid_t extends ffi.Struct {
|
|
||||||
@ffi.Array.multi([2])
|
|
||||||
external ffi.Array<ffi.Int> __val;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class CCoin extends ffi.Struct {
|
|
||||||
@ffi.Char()
|
|
||||||
external int type;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> k;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int kLength;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> address;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int v;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> memo;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int memoLength;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> serial_context;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int serial_contextLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class CIdentifiedCoinData extends ffi.Struct {
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int i;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> d;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int dLength;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int v;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> k;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int kLength;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> memo;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int memoLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class CCRecipient extends ffi.Struct {
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> pubKey;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int pubKeyLength;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int cAmount;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int subtractFee;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class CMintedCoinData extends ffi.Struct {
|
|
||||||
external ffi.Pointer<ffi.Char> address;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int value;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> memo;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class PubKeyScript extends ffi.Struct {
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> bytes;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int length;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class COutputCoinData extends ffi.Struct {
|
|
||||||
external ffi.Pointer<ffi.Char> address;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int value;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> memo;
|
|
||||||
}
|
|
||||||
|
|
||||||
final class CCSparkMintMeta extends ffi.Struct {
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int height;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> id;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int isUsed;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> txid;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int i;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> d;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int dLength;
|
|
||||||
|
|
||||||
@ffi.Uint64()
|
|
||||||
external int v;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> k;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int kLength;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.Char> memo;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int memoLength;
|
|
||||||
|
|
||||||
external ffi.Pointer<ffi.UnsignedChar> serial_context;
|
|
||||||
|
|
||||||
@ffi.Int()
|
|
||||||
external int serial_contextLength;
|
|
||||||
|
|
||||||
@ffi.Char()
|
|
||||||
external int type;
|
|
||||||
|
|
||||||
external CCoin coin;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int _STDINT_H = 1;
|
|
||||||
|
|
||||||
const int _FEATURES_H = 1;
|
|
||||||
|
|
||||||
const int _DEFAULT_SOURCE = 1;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_ISOC2X = 1;
|
|
||||||
|
|
||||||
const int __USE_ISOC11 = 1;
|
|
||||||
|
|
||||||
const int __USE_ISOC99 = 1;
|
|
||||||
|
|
||||||
const int __USE_ISOC95 = 1;
|
|
||||||
|
|
||||||
const int _POSIX_SOURCE = 1;
|
|
||||||
|
|
||||||
const int _POSIX_C_SOURCE = 200809;
|
|
||||||
|
|
||||||
const int __USE_POSIX = 1;
|
|
||||||
|
|
||||||
const int __USE_POSIX2 = 1;
|
|
||||||
|
|
||||||
const int __USE_POSIX199309 = 1;
|
|
||||||
|
|
||||||
const int __USE_POSIX199506 = 1;
|
|
||||||
|
|
||||||
const int __USE_XOPEN2K = 1;
|
|
||||||
|
|
||||||
const int __USE_XOPEN2K8 = 1;
|
|
||||||
|
|
||||||
const int _ATFILE_SOURCE = 1;
|
|
||||||
|
|
||||||
const int __USE_MISC = 1;
|
|
||||||
|
|
||||||
const int __USE_ATFILE = 1;
|
|
||||||
|
|
||||||
const int __USE_FORTIFY_LEVEL = 0;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_DEPRECATED_GETS = 0;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_DEPRECATED_SCANF = 0;
|
|
||||||
|
|
||||||
const int _STDC_PREDEF_H = 1;
|
|
||||||
|
|
||||||
const int __STDC_IEC_559__ = 1;
|
|
||||||
|
|
||||||
const int __STDC_IEC_559_COMPLEX__ = 1;
|
|
||||||
|
|
||||||
const int __STDC_ISO_10646__ = 201706;
|
|
||||||
|
|
||||||
const int __GNU_LIBRARY__ = 6;
|
|
||||||
|
|
||||||
const int __GLIBC__ = 2;
|
|
||||||
|
|
||||||
const int __GLIBC_MINOR__ = 31;
|
|
||||||
|
|
||||||
const int _SYS_CDEFS_H = 1;
|
|
||||||
|
|
||||||
const int __glibc_c99_flexarr_available = 1;
|
|
||||||
|
|
||||||
const int __WORDSIZE = 64;
|
|
||||||
|
|
||||||
const int __WORDSIZE_TIME64_COMPAT32 = 1;
|
|
||||||
|
|
||||||
const int __SYSCALL_WORDSIZE = 64;
|
|
||||||
|
|
||||||
const int __LONG_DOUBLE_USES_FLOAT128 = 0;
|
|
||||||
|
|
||||||
const int __HAVE_GENERIC_SELECTION = 0;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_LIB_EXT2 = 1;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_IEC_60559_BFP_EXT = 1;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_IEC_60559_BFP_EXT_C2X = 1;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_IEC_60559_FUNCS_EXT = 1;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X = 1;
|
|
||||||
|
|
||||||
const int __GLIBC_USE_IEC_60559_TYPES_EXT = 1;
|
|
||||||
|
|
||||||
const int _BITS_TYPES_H = 1;
|
|
||||||
|
|
||||||
const int __TIMESIZE = 64;
|
|
||||||
|
|
||||||
const int _BITS_TYPESIZES_H = 1;
|
|
||||||
|
|
||||||
const int __OFF_T_MATCHES_OFF64_T = 1;
|
|
||||||
|
|
||||||
const int __INO_T_MATCHES_INO64_T = 1;
|
|
||||||
|
|
||||||
const int __RLIM_T_MATCHES_RLIM64_T = 1;
|
|
||||||
|
|
||||||
const int __STATFS_MATCHES_STATFS64 = 1;
|
|
||||||
|
|
||||||
const int __FD_SETSIZE = 1024;
|
|
||||||
|
|
||||||
const int _BITS_TIME64_H = 1;
|
|
||||||
|
|
||||||
const int _BITS_WCHAR_H = 1;
|
|
||||||
|
|
||||||
const int __WCHAR_MAX = 2147483647;
|
|
||||||
|
|
||||||
const int __WCHAR_MIN = -2147483648;
|
|
||||||
|
|
||||||
const int _BITS_STDINT_INTN_H = 1;
|
|
||||||
|
|
||||||
const int _BITS_STDINT_UINTN_H = 1;
|
|
||||||
|
|
||||||
const int INT8_MIN = -128;
|
|
||||||
|
|
||||||
const int INT16_MIN = -32768;
|
|
||||||
|
|
||||||
const int INT32_MIN = -2147483648;
|
|
||||||
|
|
||||||
const int INT64_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INT8_MAX = 127;
|
|
||||||
|
|
||||||
const int INT16_MAX = 32767;
|
|
||||||
|
|
||||||
const int INT32_MAX = 2147483647;
|
|
||||||
|
|
||||||
const int INT64_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int UINT8_MAX = 255;
|
|
||||||
|
|
||||||
const int UINT16_MAX = 65535;
|
|
||||||
|
|
||||||
const int UINT32_MAX = 4294967295;
|
|
||||||
|
|
||||||
const int UINT64_MAX = -1;
|
|
||||||
|
|
||||||
const int INT_LEAST8_MIN = -128;
|
|
||||||
|
|
||||||
const int INT_LEAST16_MIN = -32768;
|
|
||||||
|
|
||||||
const int INT_LEAST32_MIN = -2147483648;
|
|
||||||
|
|
||||||
const int INT_LEAST64_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INT_LEAST8_MAX = 127;
|
|
||||||
|
|
||||||
const int INT_LEAST16_MAX = 32767;
|
|
||||||
|
|
||||||
const int INT_LEAST32_MAX = 2147483647;
|
|
||||||
|
|
||||||
const int INT_LEAST64_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int UINT_LEAST8_MAX = 255;
|
|
||||||
|
|
||||||
const int UINT_LEAST16_MAX = 65535;
|
|
||||||
|
|
||||||
const int UINT_LEAST32_MAX = 4294967295;
|
|
||||||
|
|
||||||
const int UINT_LEAST64_MAX = -1;
|
|
||||||
|
|
||||||
const int INT_FAST8_MIN = -128;
|
|
||||||
|
|
||||||
const int INT_FAST16_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INT_FAST32_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INT_FAST64_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INT_FAST8_MAX = 127;
|
|
||||||
|
|
||||||
const int INT_FAST16_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int INT_FAST32_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int INT_FAST64_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int UINT_FAST8_MAX = 255;
|
|
||||||
|
|
||||||
const int UINT_FAST16_MAX = -1;
|
|
||||||
|
|
||||||
const int UINT_FAST32_MAX = -1;
|
|
||||||
|
|
||||||
const int UINT_FAST64_MAX = -1;
|
|
||||||
|
|
||||||
const int INTPTR_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INTPTR_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int UINTPTR_MAX = -1;
|
|
||||||
|
|
||||||
const int INTMAX_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int INTMAX_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int UINTMAX_MAX = -1;
|
|
||||||
|
|
||||||
const int PTRDIFF_MIN = -9223372036854775808;
|
|
||||||
|
|
||||||
const int PTRDIFF_MAX = 9223372036854775807;
|
|
||||||
|
|
||||||
const int SIG_ATOMIC_MIN = -2147483648;
|
|
||||||
|
|
||||||
const int SIG_ATOMIC_MAX = 2147483647;
|
|
||||||
|
|
||||||
const int SIZE_MAX = -1;
|
|
||||||
|
|
||||||
const int WCHAR_MIN = -2147483648;
|
|
||||||
|
|
||||||
const int WCHAR_MAX = 2147483647;
|
|
||||||
|
|
||||||
const int WINT_MIN = 0;
|
|
||||||
|
|
||||||
const int WINT_MAX = 4294967295;
|
|
||||||
198
lib/flutter_libsparkmobile_bindings_generated.dart
Normal file
198
lib/flutter_libsparkmobile_bindings_generated.dart
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
// ignore_for_file: always_specify_types
|
||||||
|
// ignore_for_file: camel_case_types
|
||||||
|
// ignore_for_file: non_constant_identifier_names
|
||||||
|
|
||||||
|
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by `package:ffigen`.
|
||||||
|
import 'dart:ffi' as ffi;
|
||||||
|
|
||||||
|
/// Bindings for `src/flutter_libsparkmobile.h`.
|
||||||
|
///
|
||||||
|
/// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||||
|
///
|
||||||
|
class FlutterLibsparkmobileBindings {
|
||||||
|
/// Holds the symbol lookup function.
|
||||||
|
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||||
|
_lookup;
|
||||||
|
|
||||||
|
/// The symbols are looked up in [dynamicLibrary].
|
||||||
|
FlutterLibsparkmobileBindings(ffi.DynamicLibrary dynamicLibrary)
|
||||||
|
: _lookup = dynamicLibrary.lookup;
|
||||||
|
|
||||||
|
/// The symbols are looked up with [lookup].
|
||||||
|
FlutterLibsparkmobileBindings.fromLookup(
|
||||||
|
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||||
|
lookup)
|
||||||
|
: _lookup = lookup;
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for spark::getAddress.
|
||||||
|
ffi.Pointer<ffi.Char> getAddress(
|
||||||
|
ffi.Pointer<ffi.Char> keyDataHex,
|
||||||
|
int index,
|
||||||
|
int diversifier,
|
||||||
|
int isTestNet,
|
||||||
|
) {
|
||||||
|
return _getAddress(
|
||||||
|
keyDataHex,
|
||||||
|
index,
|
||||||
|
diversifier,
|
||||||
|
isTestNet,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _getAddressPtr = _lookup<
|
||||||
|
ffi.NativeFunction<
|
||||||
|
ffi.Pointer<ffi.Char> Function(
|
||||||
|
ffi.Pointer<ffi.Char>, ffi.Int, ffi.Int, ffi.Int)>>('getAddress');
|
||||||
|
late final _getAddress = _getAddressPtr.asFunction<
|
||||||
|
ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Char>, int, int, int)>();
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for spark::identifyCoin.
|
||||||
|
CIdentifiedCoinData identifyCoin(
|
||||||
|
CCoin c_struct,
|
||||||
|
ffi.Pointer<ffi.Char> keyDataHex,
|
||||||
|
int index,
|
||||||
|
) {
|
||||||
|
return _identifyCoin(
|
||||||
|
c_struct,
|
||||||
|
keyDataHex,
|
||||||
|
index,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _identifyCoinPtr = _lookup<
|
||||||
|
ffi.NativeFunction<
|
||||||
|
CIdentifiedCoinData Function(
|
||||||
|
CCoin, ffi.Pointer<ffi.Char>, ffi.Int)>>('identifyCoin');
|
||||||
|
late final _identifyCoin = _identifyCoinPtr.asFunction<
|
||||||
|
CIdentifiedCoinData Function(CCoin, ffi.Pointer<ffi.Char>, int)>();
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for spark::createSparkMintRecipients.
|
||||||
|
ffi.Pointer<CCRecipient> createSparkMintRecipients(
|
||||||
|
int numRecipients,
|
||||||
|
ffi.Pointer<PubKeyScript> pubKeyScripts,
|
||||||
|
ffi.Pointer<ffi.Uint64> amounts,
|
||||||
|
ffi.Pointer<ffi.Char> memo,
|
||||||
|
int subtractFee,
|
||||||
|
) {
|
||||||
|
return _createSparkMintRecipients(
|
||||||
|
numRecipients,
|
||||||
|
pubKeyScripts,
|
||||||
|
amounts,
|
||||||
|
memo,
|
||||||
|
subtractFee,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _createSparkMintRecipientsPtr = _lookup<
|
||||||
|
ffi.NativeFunction<
|
||||||
|
ffi.Pointer<CCRecipient> Function(
|
||||||
|
ffi.Int,
|
||||||
|
ffi.Pointer<PubKeyScript>,
|
||||||
|
ffi.Pointer<ffi.Uint64>,
|
||||||
|
ffi.Pointer<ffi.Char>,
|
||||||
|
ffi.Int)>>('createSparkMintRecipients');
|
||||||
|
late final _createSparkMintRecipients =
|
||||||
|
_createSparkMintRecipientsPtr.asFunction<
|
||||||
|
ffi.Pointer<CCRecipient> Function(int, ffi.Pointer<PubKeyScript>,
|
||||||
|
ffi.Pointer<ffi.Uint64>, ffi.Pointer<ffi.Char>, int)>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for a spark::Coin.
|
||||||
|
///
|
||||||
|
/// A Coin is a type, a key, an index, a value, a memo, and a serial context. We accept these params
|
||||||
|
/// as a C struct, deriving the key from the keyData and index.
|
||||||
|
final class CCoin extends ffi.Struct {
|
||||||
|
@ffi.Char()
|
||||||
|
external int type;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> k;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int kLength;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.Char> keyData;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int index;
|
||||||
|
|
||||||
|
@ffi.Uint64()
|
||||||
|
external int v;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> memo;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int memoLength;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> serial_context;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int serial_contextLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for a spark::IdentifiedCoinData.
|
||||||
|
///
|
||||||
|
/// An IdentifiedCoinData is a diversifier, encrypted diversifier, value, nonce, and memo. We accept
|
||||||
|
/// these params as a C struct.
|
||||||
|
final class CIdentifiedCoinData extends ffi.Struct {
|
||||||
|
@ffi.Uint64()
|
||||||
|
external int i;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> d;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int dLength;
|
||||||
|
|
||||||
|
@ffi.Uint64()
|
||||||
|
external int v;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> k;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int kLength;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.Char> memo;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int memoLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for a spark::CRecipient.
|
||||||
|
///
|
||||||
|
/// A CRecipient is a CScript, CAmount, and a bool. We accept a C-style, FFI-friendly CCRecipient
|
||||||
|
/// struct in order to construct a C++ CRecipient. A CScript is constructed from a hex string, a
|
||||||
|
/// CAmount is just a uint64_t, and the bool will be an int.
|
||||||
|
final class CCRecipient extends ffi.Struct {
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> pubKey;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int pubKeyLength;
|
||||||
|
|
||||||
|
@ffi.Uint64()
|
||||||
|
external int cAmount;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int subtractFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FFI-friendly wrapper for a spark::MintedCoinData.
|
||||||
|
///
|
||||||
|
/// A MintedCoinData is a struct that contains an Address, a uint64_t value, and a string memo. We
|
||||||
|
/// accept these as a CMintedCoinData from the Dart interface, and convert them to a MintedCoinData
|
||||||
|
/// struct.
|
||||||
|
final class CMintedCoinData extends ffi.Struct {
|
||||||
|
external ffi.Pointer<ffi.Char> address;
|
||||||
|
|
||||||
|
@ffi.Uint64()
|
||||||
|
external int value;
|
||||||
|
|
||||||
|
external ffi.Pointer<ffi.Char> memo;
|
||||||
|
}
|
||||||
|
|
||||||
|
final class PubKeyScript extends ffi.Struct {
|
||||||
|
external ffi.Pointer<ffi.UnsignedChar> bytes;
|
||||||
|
|
||||||
|
@ffi.Int()
|
||||||
|
external int length;
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
import 'flutter_libsparkmobile_platform_interface.dart';
|
|
||||||
|
|
||||||
/// An implementation of [FlutterLibsparkmobilePlatform] that uses method channels.
|
|
||||||
class MethodChannelFlutterLibsparkmobile extends FlutterLibsparkmobilePlatform {
|
|
||||||
/// The method channel used to interact with the native platform.
|
|
||||||
@visibleForTesting
|
|
||||||
final methodChannel = const MethodChannel('flutter_libsparkmobile');
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String?> getPlatformVersion() async {
|
|
||||||
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
|
||||||
|
|
||||||
import 'flutter_libsparkmobile_method_channel.dart';
|
|
||||||
|
|
||||||
abstract class FlutterLibsparkmobilePlatform extends PlatformInterface {
|
|
||||||
/// Constructs a FlutterLibsparkmobilePlatform.
|
|
||||||
FlutterLibsparkmobilePlatform() : super(token: _token);
|
|
||||||
|
|
||||||
static final Object _token = Object();
|
|
||||||
|
|
||||||
static FlutterLibsparkmobilePlatform _instance = MethodChannelFlutterLibsparkmobile();
|
|
||||||
|
|
||||||
/// The default instance of [FlutterLibsparkmobilePlatform] to use.
|
|
||||||
///
|
|
||||||
/// Defaults to [MethodChannelFlutterLibsparkmobile].
|
|
||||||
static FlutterLibsparkmobilePlatform get instance => _instance;
|
|
||||||
|
|
||||||
/// Platform-specific implementations should set this with their own
|
|
||||||
/// platform-specific class that extends [FlutterLibsparkmobilePlatform] when
|
|
||||||
/// they register themselves.
|
|
||||||
static set instance(FlutterLibsparkmobilePlatform instance) {
|
|
||||||
PlatformInterface.verifyToken(instance, _token);
|
|
||||||
_instance = instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getPlatformVersion() {
|
|
||||||
throw UnimplementedError('platformVersion() has not been implemented.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
/*ANDROID_VERSION*/ const ANDROID_VERSION = "";
|
|
||||||
/*IOS_VERSION*/ const IOS_VERSION = "";
|
|
||||||
/*MACOS_VERSION*/ const MACOS_VERSION = "";
|
|
||||||
/*LINUX_VERSION*/ const LINUX_VERSION = "";
|
|
||||||
/*WINDOWS_VERSION*/ const WINDOWS_VERSION = "";
|
|
||||||
|
|
||||||
String getPluginVersion() {
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
return ANDROID_VERSION;
|
|
||||||
} else if (Platform.isIOS) {
|
|
||||||
return IOS_VERSION;
|
|
||||||
} else if (Platform.isMacOS) {
|
|
||||||
return MACOS_VERSION;
|
|
||||||
} else if (Platform.isLinux) {
|
|
||||||
return LINUX_VERSION;
|
|
||||||
} else if (Platform.isWindows) {
|
|
||||||
return WINDOWS_VERSION;
|
|
||||||
} else {
|
|
||||||
return "Unknown version";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,90 +5,20 @@ cmake_minimum_required(VERSION 3.10)
|
|||||||
|
|
||||||
# Project-level configuration.
|
# Project-level configuration.
|
||||||
set(PROJECT_NAME "flutter_libsparkmobile")
|
set(PROJECT_NAME "flutter_libsparkmobile")
|
||||||
|
set(PROJECT_SYSTEM_NAME "linux")
|
||||||
|
|
||||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||||
|
|
||||||
# This value is used when generating builds using this plugin, so it must
|
# Invoke the build for native code shared with the other target platforms.
|
||||||
# not be changed.
|
# This can be changed to accommodate different builds.
|
||||||
set(PLUGIN_NAME "flutter_libsparkmobile_plugin")
|
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
|
||||||
|
|
||||||
# Any new source files that you add to the plugin should be added here.
|
|
||||||
list(APPEND PLUGIN_SOURCES
|
|
||||||
"flutter_libsparkmobile_plugin.cc"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Define the plugin library target. Its name must not be changed (see comment
|
|
||||||
# on PLUGIN_NAME above).
|
|
||||||
add_library(${PLUGIN_NAME} SHARED
|
|
||||||
${PLUGIN_SOURCES}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Apply a standard set of build settings that are configured in the
|
|
||||||
# application-level CMakeLists.txt. This can be removed for plugins that want
|
|
||||||
# full control over build settings.
|
|
||||||
apply_standard_settings(${PLUGIN_NAME})
|
|
||||||
|
|
||||||
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
|
||||||
# between plugins. This should not be removed; any symbols that should be
|
|
||||||
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
|
||||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
|
||||||
CXX_VISIBILITY_PRESET hidden)
|
|
||||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
|
||||||
|
|
||||||
# Source include directories and library dependencies. Add any plugin-specific
|
|
||||||
# dependencies here.
|
|
||||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
|
||||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
|
|
||||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
|
|
||||||
|
|
||||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||||
# This list could contain prebuilt libraries, or libraries created by an
|
# This list could contain prebuilt libraries, or libraries created by an
|
||||||
# external build triggered from this build file.
|
# external build triggered from this build file.
|
||||||
set(flutter_libsparkmobile_bundled_libraries
|
set(flutter_libsparkmobile_bundled_libraries
|
||||||
""
|
# Defined in ../src/CMakeLists.txt.
|
||||||
|
# This can be changed to accommodate different builds.
|
||||||
|
$<TARGET_FILE:flutter_libsparkmobile>
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
# === Tests ===
|
|
||||||
# These unit tests can be run from a terminal after building the example.
|
|
||||||
|
|
||||||
# Only enable test builds when building the example (which sets this variable)
|
|
||||||
# so that plugin clients aren't building the tests.
|
|
||||||
if (${include_${PROJECT_NAME}_tests})
|
|
||||||
if(${CMAKE_VERSION} VERSION_LESS "3.11.0")
|
|
||||||
message("Unit tests require CMake 3.11.0 or later")
|
|
||||||
else()
|
|
||||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
# Add the Google Test dependency.
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(
|
|
||||||
googletest
|
|
||||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
|
||||||
)
|
|
||||||
# Prevent overriding the parent project's compiler/linker settings
|
|
||||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
|
||||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
|
||||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(googletest)
|
|
||||||
|
|
||||||
# The plugin's exported API is not very useful for unit testing, so build the
|
|
||||||
# sources directly into the test binary rather than using the shared library.
|
|
||||||
add_executable(${TEST_RUNNER}
|
|
||||||
test/flutter_libsparkmobile_plugin_test.cc
|
|
||||||
${PLUGIN_SOURCES}
|
|
||||||
)
|
|
||||||
apply_standard_settings(${TEST_RUNNER})
|
|
||||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter)
|
|
||||||
target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK)
|
|
||||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
|
||||||
|
|
||||||
# Enable automatic test discovery.
|
|
||||||
include(GoogleTest)
|
|
||||||
gtest_discover_tests(${TEST_RUNNER})
|
|
||||||
|
|
||||||
endif() # CMake version check
|
|
||||||
endif() # include_${PROJECT_NAME}_tests
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#include "include/flutter_libsparkmobile/flutter_libsparkmobile_plugin.h"
|
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "flutter_libsparkmobile_plugin_private.h"
|
|
||||||
|
|
||||||
#define FLUTTER_LIBSPARKMOBILE_PLUGIN(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), flutter_libsparkmobile_plugin_get_type(), \
|
|
||||||
FlutterLibsparkmobilePlugin))
|
|
||||||
|
|
||||||
struct _FlutterLibsparkmobilePlugin {
|
|
||||||
GObject parent_instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(FlutterLibsparkmobilePlugin, flutter_libsparkmobile_plugin, g_object_get_type())
|
|
||||||
|
|
||||||
// Called when a method call is received from Flutter.
|
|
||||||
static void flutter_libsparkmobile_plugin_handle_method_call(
|
|
||||||
FlutterLibsparkmobilePlugin* self,
|
|
||||||
FlMethodCall* method_call) {
|
|
||||||
g_autoptr(FlMethodResponse) response = nullptr;
|
|
||||||
|
|
||||||
const gchar* method = fl_method_call_get_name(method_call);
|
|
||||||
|
|
||||||
if (strcmp(method, "getPlatformVersion") == 0) {
|
|
||||||
response = get_platform_version();
|
|
||||||
} else {
|
|
||||||
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
|
|
||||||
}
|
|
||||||
|
|
||||||
fl_method_call_respond(method_call, response, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlMethodResponse* get_platform_version() {
|
|
||||||
struct utsname uname_data = {};
|
|
||||||
uname(&uname_data);
|
|
||||||
g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
|
|
||||||
g_autoptr(FlValue) result = fl_value_new_string(version);
|
|
||||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flutter_libsparkmobile_plugin_dispose(GObject* object) {
|
|
||||||
G_OBJECT_CLASS(flutter_libsparkmobile_plugin_parent_class)->dispose(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flutter_libsparkmobile_plugin_class_init(FlutterLibsparkmobilePluginClass* klass) {
|
|
||||||
G_OBJECT_CLASS(klass)->dispose = flutter_libsparkmobile_plugin_dispose;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flutter_libsparkmobile_plugin_init(FlutterLibsparkmobilePlugin* self) {}
|
|
||||||
|
|
||||||
static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
|
|
||||||
gpointer user_data) {
|
|
||||||
FlutterLibsparkmobilePlugin* plugin = FLUTTER_LIBSPARKMOBILE_PLUGIN(user_data);
|
|
||||||
flutter_libsparkmobile_plugin_handle_method_call(plugin, method_call);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flutter_libsparkmobile_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
|
|
||||||
FlutterLibsparkmobilePlugin* plugin = FLUTTER_LIBSPARKMOBILE_PLUGIN(
|
|
||||||
g_object_new(flutter_libsparkmobile_plugin_get_type(), nullptr));
|
|
||||||
|
|
||||||
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
|
|
||||||
g_autoptr(FlMethodChannel) channel =
|
|
||||||
fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
|
|
||||||
"flutter_libsparkmobile",
|
|
||||||
FL_METHOD_CODEC(codec));
|
|
||||||
fl_method_channel_set_method_call_handler(channel, method_call_cb,
|
|
||||||
g_object_ref(plugin),
|
|
||||||
g_object_unref);
|
|
||||||
|
|
||||||
g_object_unref(plugin);
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
|
|
||||||
#include "include/flutter_libsparkmobile/flutter_libsparkmobile_plugin.h"
|
|
||||||
|
|
||||||
// This file exposes some plugin internals for unit testing. See
|
|
||||||
// https://github.com/flutter/flutter/issues/88724 for current limitations
|
|
||||||
// in the unit-testable API.
|
|
||||||
|
|
||||||
// Handles the getPlatformVersion method call.
|
|
||||||
FlMethodResponse *get_platform_version();
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#ifndef FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_H_
|
|
||||||
#define FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_H_
|
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#ifdef FLUTTER_PLUGIN_IMPL
|
|
||||||
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
#define FLUTTER_PLUGIN_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct _FlutterLibsparkmobilePlugin FlutterLibsparkmobilePlugin;
|
|
||||||
typedef struct {
|
|
||||||
GObjectClass parent_class;
|
|
||||||
} FlutterLibsparkmobilePluginClass;
|
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT GType flutter_libsparkmobile_plugin_get_type();
|
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void flutter_libsparkmobile_plugin_register_with_registrar(
|
|
||||||
FlPluginRegistrar* registrar);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif // FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_H_
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
#include <gmock/gmock.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include "include/flutter_libsparkmobile/flutter_libsparkmobile_plugin.h"
|
|
||||||
#include "flutter_libsparkmobile_plugin_private.h"
|
|
||||||
|
|
||||||
// This demonstrates a simple unit test of the C portion of this plugin's
|
|
||||||
// implementation.
|
|
||||||
//
|
|
||||||
// Once you have built the plugin's example app, you can run these tests
|
|
||||||
// from the command line. For instance, for a plugin called my_plugin
|
|
||||||
// built for x64 debug, run:
|
|
||||||
// $ build/linux/x64/debug/plugins/my_plugin/my_plugin_test
|
|
||||||
|
|
||||||
namespace flutter_libsparkmobile {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
TEST(FlutterLibsparkmobilePlugin, GetPlatformVersion) {
|
|
||||||
g_autoptr(FlMethodResponse) response = get_platform_version();
|
|
||||||
ASSERT_NE(response, nullptr);
|
|
||||||
ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
|
|
||||||
FlValue* result = fl_method_success_response_get_result(
|
|
||||||
FL_METHOD_SUCCESS_RESPONSE(response));
|
|
||||||
ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING);
|
|
||||||
// The full string varies, so just validate that it has the right format.
|
|
||||||
EXPECT_THAT(fl_value_get_string(result), testing::StartsWith("Linux "));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace flutter_libsparkmobile
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import Cocoa
|
|
||||||
import FlutterMacOS
|
|
||||||
|
|
||||||
public class FlutterLibsparkmobilePlugin: NSObject, FlutterPlugin {
|
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
||||||
let channel = FlutterMethodChannel(name: "flutter_libsparkmobile", binaryMessenger: registrar.messenger)
|
|
||||||
let instance = FlutterLibsparkmobilePlugin()
|
|
||||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
||||||
switch call.method {
|
|
||||||
case "getPlatformVersion":
|
|
||||||
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
|
|
||||||
default:
|
|
||||||
result(FlutterMethodNotImplemented)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
macos/Classes/flutter_libsparkmobile.c
Normal file
3
macos/Classes/flutter_libsparkmobile.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Relative import to be able to reuse the C sources.
|
||||||
|
// See the comment in ../{projectName}}.podspec for more information.
|
||||||
|
#include flutter_libsparkmobile.cpp
|
||||||
@@ -5,14 +5,18 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'flutter_libsparkmobile'
|
s.name = 'flutter_libsparkmobile'
|
||||||
s.version = '0.0.1'
|
s.version = '0.0.1'
|
||||||
s.summary = 'A new Flutter plugin project.'
|
s.summary = 'A new Flutter project.'
|
||||||
s.description = <<-DESC
|
s.description = <<-DESC
|
||||||
A new Flutter plugin project.
|
A new Flutter project.
|
||||||
DESC
|
DESC
|
||||||
s.homepage = 'http://example.com'
|
s.homepage = 'http://example.com'
|
||||||
s.license = { :file => '../LICENSE' }
|
s.license = { :file => '../LICENSE' }
|
||||||
s.author = { 'Your Company' => 'email@example.com' }
|
s.author = { 'Your Company' => 'email@example.com' }
|
||||||
|
|
||||||
|
# This will ensure the source files in Classes/ are included in the native
|
||||||
|
# builds of apps using this FFI plugin. Podspec does not support relative
|
||||||
|
# paths, so Classes contains a forwarder C file that relatively imports
|
||||||
|
# `../src/*` so that the C sources can be shared among all target platforms.
|
||||||
s.source = { :path => '.' }
|
s.source = { :path => '.' }
|
||||||
s.source_files = 'Classes/**/*'
|
s.source_files = 'Classes/**/*'
|
||||||
s.dependency 'FlutterMacOS'
|
s.dependency 'FlutterMacOS'
|
||||||
|
|||||||
31
pubspec.yaml
31
pubspec.yaml
@@ -1,5 +1,5 @@
|
|||||||
name: flutter_libsparkmobile
|
name: flutter_libsparkmobile
|
||||||
description: A new Flutter plugin project.
|
description: Flutter Sparkmobile ffi wrapper
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
homepage:
|
homepage:
|
||||||
|
|
||||||
@@ -12,14 +12,12 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
plugin_platform_interface: ^2.0.2
|
plugin_platform_interface: ^2.0.2
|
||||||
test: ^1.24.1
|
|
||||||
typed_data: ^1.3.2
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
ffigen: ^6.1.2
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
ffigen: ^9.0.1
|
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
@@ -36,19 +34,20 @@ flutter:
|
|||||||
# This is required for using `dart:ffi`.
|
# This is required for using `dart:ffi`.
|
||||||
# All these are used by the tooling to maintain consistency when
|
# All these are used by the tooling to maintain consistency when
|
||||||
# adding or updating assets for this project.
|
# adding or updating assets for this project.
|
||||||
|
#
|
||||||
|
# Please refer to README.md for a detailed explanation.
|
||||||
plugin:
|
plugin:
|
||||||
platforms:
|
platforms:
|
||||||
android:
|
android:
|
||||||
package: com.cypherstack.flutter_libsparkmobile
|
ffiPlugin: true
|
||||||
pluginClass: FlutterLibsparkmobilePlugin
|
|
||||||
ios:
|
ios:
|
||||||
pluginClass: FlutterLibsparkmobilePlugin
|
ffiPlugin: true
|
||||||
linux:
|
linux:
|
||||||
pluginClass: FlutterLibsparkmobilePlugin
|
ffiPlugin: true
|
||||||
macos:
|
macos:
|
||||||
pluginClass: FlutterLibsparkmobilePlugin
|
ffiPlugin: true
|
||||||
windows:
|
windows:
|
||||||
pluginClass: FlutterLibsparkmobilePluginCApi
|
ffiPlugin: true
|
||||||
|
|
||||||
# To add assets to your plugin package, add an assets section, like this:
|
# To add assets to your plugin package, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
@@ -80,15 +79,3 @@ flutter:
|
|||||||
#
|
#
|
||||||
# For details regarding fonts in packages, see
|
# For details regarding fonts in packages, see
|
||||||
# https://flutter.dev/custom-fonts/#from-packages
|
# https://flutter.dev/custom-fonts/#from-packages
|
||||||
|
|
||||||
ffigen:
|
|
||||||
name: SparkMobileBindings
|
|
||||||
description: Bindings for sparkmobile.
|
|
||||||
language: c
|
|
||||||
output: 'lib/flutter_libsparkmobile_bindings.dart'
|
|
||||||
headers:
|
|
||||||
entry-points:
|
|
||||||
- 'sparkmobile/src/dart_interface.h'
|
|
||||||
# copyCMakeLists.sh creates this header, see build_all.sh.
|
|
||||||
preamble: |
|
|
||||||
// ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field, return_of_invalid_type, void_checks, annotate_overrides, no_leading_underscores_for_local_identifiers, library_private_types_in_public_api
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
mkdir -p build
|
set -e
|
||||||
|
|
||||||
./build_openssl.sh
|
./build_openssl.sh
|
||||||
./build_sharedfile.sh
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,67 +2,66 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
export WORKDIR="$(pwd)/../../src/build/linux"
|
||||||
|
export ORIGINAL_PATH=$PATH
|
||||||
|
export THREADS=16
|
||||||
|
export TYPES_OF_BUILD="x86_64"
|
||||||
|
|
||||||
if [ -z "$IS_ARM" ]; then
|
if [ -z "$IS_ARM" ]; then
|
||||||
TYPES_OF_BUILD="x86_64"
|
export TYPES_OF_BUILD="x86_64"
|
||||||
else
|
else
|
||||||
TYPES_OF_BUILD="aarch64"
|
export TYPES_OF_BUILD="aarch64"
|
||||||
fi
|
fi
|
||||||
THREADS=16
|
|
||||||
|
|
||||||
WORKDIR="$(pwd)/"build
|
if [ ! -d "$WORKDIR" ] ; then
|
||||||
CACHEDIR="$(pwd)/"cache
|
mkdir -p "$WORKDIR"
|
||||||
mkdir -p $CACHEDIR
|
fi
|
||||||
|
|
||||||
OPENSSL_FILENAME=openssl-1.1.1k.tar.gz
|
|
||||||
OPENSSL_FILE_PATH=$CACHEDIR/$OPENSSL_FILENAME
|
OPENSSL_FILENAME="openssl-1.1.1k.tar.gz"
|
||||||
OPENSSL_SRC_DIR=$WORKDIR/openssl-1.1.1k
|
OPENSSL_FILE_PATH="$WORKDIR/$OPENSSL_FILENAME"
|
||||||
|
OPENSSL_SRC_DIR="$WORKDIR/openssl-1.1.1k"
|
||||||
OPENSSL_SHA256="892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5"
|
OPENSSL_SHA256="892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5"
|
||||||
|
ZLIB_DIR="$WORKDIR/zlib"
|
||||||
ZLIB_DIR=$WORKDIR/zlib
|
ZLIB_TAG="v1.2.11"
|
||||||
ZLIB_TAG=v1.2.11
|
|
||||||
ZLIB_COMMIT_HASH="cacf7f1d4e3d44d871b605da3b647f07d718623f"
|
ZLIB_COMMIT_HASH="cacf7f1d4e3d44d871b605da3b647f07d718623f"
|
||||||
|
|
||||||
# If a zlib dir exists, we assume that it's already been built.
|
|
||||||
# TODO make a better zlib-validity check.
|
|
||||||
if [ ! -d "$ZLIB_DIR" ] ; then
|
if [ ! -d "$ZLIB_DIR" ] ; then
|
||||||
git clone -b $ZLIB_TAG --depth 1 https://github.com/madler/zlib $ZLIB_DIR
|
git clone -b $ZLIB_TAG --depth 1 https://github.com/madler/zlib $ZLIB_DIR
|
||||||
cd $ZLIB_DIR
|
|
||||||
git reset --hard $ZLIB_COMMIT_HASH
|
|
||||||
./configure --static
|
|
||||||
make
|
|
||||||
fi
|
fi
|
||||||
|
cd $ZLIB_DIR
|
||||||
|
git reset --hard $ZLIB_COMMIT_HASH
|
||||||
|
./configure --static
|
||||||
|
make
|
||||||
|
|
||||||
# Download openssl if it doesn't exist.
|
|
||||||
curl https://www.openssl.org/source/$OPENSSL_FILENAME -o $OPENSSL_FILE_PATH
|
curl https://www.openssl.org/source/$OPENSSL_FILENAME -o $OPENSSL_FILE_PATH
|
||||||
|
|
||||||
# Validate checksum.
|
|
||||||
echo $OPENSSL_SHA256 $OPENSSL_FILE_PATH | sha256sum -c - || exit 1
|
echo $OPENSSL_SHA256 $OPENSSL_FILE_PATH | sha256sum -c - || exit 1
|
||||||
|
|
||||||
# Build openssl for each arch.
|
|
||||||
for arch in $TYPES_OF_BUILD
|
for arch in $TYPES_OF_BUILD
|
||||||
do
|
do
|
||||||
echo "Building $TYPES_OF_BUILD"
|
echo "Building $TYPES_OF_BUILD"
|
||||||
PREFIX=$WORKDIR/prefix_${arch}
|
PREFIX=$WORKDIR/prefix_${arch}
|
||||||
|
|
||||||
case $arch in
|
case $arch in
|
||||||
"x86_64") X_ARCH="linux-x86_64";;
|
"x86_64") X_ARCH="linux-x86_64";;
|
||||||
"aarch64") X_ARCH="linux-aarch64";;
|
"aarch64") X_ARCH="linux-aarch64";;
|
||||||
*) X_ARCH="linux-x86_64";;
|
*) X_ARCH="linux-x86_64";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
cd $WORKDIR
|
cd $WORKDIR
|
||||||
# Don't delete the openssl source dir. We don't need clean builds every time.
|
rm -rf $OPENSSL_SRC_DIR
|
||||||
# rm -rf $OPENSSL_SRC_DIR
|
tar -xzf $OPENSSL_FILE_PATH -C $WORKDIR
|
||||||
tar -xzf $OPENSSL_FILE_PATH -C $WORKDIR
|
cd $OPENSSL_SRC_DIR
|
||||||
cd $OPENSSL_SRC_DIR
|
|
||||||
|
./Configure ${X_ARCH} \
|
||||||
|
no-asm no-shared \
|
||||||
|
--with-zlib-include=${PREFIX}/include \
|
||||||
|
--with-zlib-lib=${PREFIX}/lib \
|
||||||
|
--prefix=${PREFIX} \
|
||||||
|
--openssldir=${PREFIX}
|
||||||
|
make -j$THREADS
|
||||||
|
make -j$THREADS install_sw
|
||||||
|
|
||||||
#sed -i -e "s/mandroid/target\ ${TARGET}\-linux\-android/" Configure
|
|
||||||
./Configure ${X_ARCH} \
|
|
||||||
no-asm no-shared \
|
|
||||||
--with-zlib-include=${PREFIX}/include \
|
|
||||||
--with-zlib-lib=${PREFIX}/lib \
|
|
||||||
--prefix=${PREFIX} \
|
|
||||||
--openssldir=${PREFIX}
|
|
||||||
make -j$THREADS
|
|
||||||
make -j$THREADS install_sw
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copy the sparkmobile submodule to the build directory for interfacing to Dart.
|
|
||||||
#
|
|
||||||
# We copy the fresh and unmodified sparkmobile submodule to the build directory in order to graft
|
|
||||||
# an additional Dart interface onto the sparkmobile library.
|
|
||||||
cp -r ../../sparkmobile .
|
|
||||||
|
|
||||||
WORKDIR="$(pwd)/build"
|
|
||||||
SEDWORKDIR=$(echo $WORKDIR | sed 's/\//\\\//g')
|
|
||||||
|
|
||||||
# Create new CMakelists.txt files for the sparkmobile and secp256k1 directories.
|
|
||||||
#
|
|
||||||
# Copy the template CMakelists.txt files to the working sparkmobile directory and replace the
|
|
||||||
# distribution_DIR variable with the working directory.
|
|
||||||
sed "s/SET(distribution_DIR \/opt\/android)/SET(distribution_DIR $SEDWORKDIR)/g" ./CMakeLists/sparkmobile/template_CMakeLists.txt > ./CMakeLists/sparkmobile/CMakeLists.txt
|
|
||||||
sed "s/SET(distribution_DIR \/opt\/android)/SET(distribution_DIR $SEDWORKDIR)/g" ./CMakeLists/secp256k1/template_CMakeLists.txt > ./CMakeLists/secp256k1/CMakeLists.txt
|
|
||||||
|
|
||||||
# Copy the sparkmobile and secp256k1 CMakeLists.txts.
|
|
||||||
cp CMakeLists/sparkmobile/CMakeLists.txt sparkmobile/
|
|
||||||
cp CMakeLists/secp256k1/CMakeLists.txt sparkmobile/secp256k1/
|
|
||||||
|
|
||||||
# Git versioning.
|
|
||||||
echo ''$(git log -1 --pretty=format:"%H")' '$(date) >> build/git_commit_version.txt
|
|
||||||
VERSIONS_FILE=../../lib/git_versions.dart
|
|
||||||
EXAMPLE_VERSIONS_FILE=../../lib/git_versions_example.dart
|
|
||||||
if [ ! -f "$VERSIONS_FILE" ]; then
|
|
||||||
cp $EXAMPLE_VERSIONS_FILE $VERSIONS_FILE
|
|
||||||
fi
|
|
||||||
COMMIT=$(git log -1 --pretty=format:"%H")
|
|
||||||
OS="LINUX"
|
|
||||||
|
|
||||||
# Write the commit hash to the versions file.
|
|
||||||
sed -i "/\/\*${OS}_VERSION/c\\/\*${OS}_VERSION\*\/ const ${OS}_VERSION = \"$COMMIT\";" $VERSIONS_FILE
|
|
||||||
|
|
||||||
# Build the shared library.
|
|
||||||
cd build
|
|
||||||
cmake ../sparkmobile
|
|
||||||
make -j$(nproc)
|
|
||||||
17
scripts/prebuild.sh
Executable file
17
scripts/prebuild.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd ../src/deps
|
||||||
|
|
||||||
|
if [ -d sparkmobile ]; then
|
||||||
|
rm -rf sparkmobile
|
||||||
|
fi
|
||||||
|
|
||||||
|
git clone https://github.com/firoorg/sparkmobile.git
|
||||||
|
cd sparkmobile
|
||||||
|
git checkout ef2e39aae18ecc49e0ddc63a3183e9764b96012e
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
cp CMakeLists/sparkmobile/CMakeLists.txt sparkmobile/
|
||||||
|
cp CMakeLists/secp256k1/CMakeLists.txt sparkmobile/secp256k1/
|
||||||
Submodule sparkmobile deleted from fe2148f01b
26
src/CMakeLists.txt
Normal file
26
src/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||||
|
# installed. You should not increase this version, as doing so will cause
|
||||||
|
# the plugin to fail to compile for some customers of the plugin.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(flutter_libsparkmobile_library VERSION 0.0.1)
|
||||||
|
|
||||||
|
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
add_library(flutter_libsparkmobile SHARED
|
||||||
|
"flutter_libsparkmobile.cpp"
|
||||||
|
"utils.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory("deps/sparkmobile")
|
||||||
|
|
||||||
|
set_target_properties(flutter_libsparkmobile PROPERTIES
|
||||||
|
PUBLIC_HEADER flutter_libsparkmobile.h
|
||||||
|
OUTPUT_NAME "flutter_libsparkmobile"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(flutter_libsparkmobile sparkmobile)
|
||||||
|
|
||||||
|
target_compile_definitions(flutter_libsparkmobile PUBLIC DART_SHARED_LIB)
|
||||||
7
src/cmake/FindGMP.cmake
Normal file
7
src/cmake/FindGMP.cmake
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
find_path(GMP_INCLUDE_DIRS NAMES gmp.h)
|
||||||
|
find_library(GMP_LIBRARY NAMES gmp libgmp)
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(GMP DEFAULT_MSG
|
||||||
|
GMP_INCLUDE_DIRS
|
||||||
|
GMP_LIBRARY)
|
||||||
|
mark_as_advanced(GMP_INCLUDE_DIRS GMP_LIBRARY)
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
# Copyright (c) 2017 The Bitcoin developers
|
# Copyright (c) 2017 The Bitcoin developers
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
project(secp256k1)
|
project(secp256k1_spark)
|
||||||
|
|
||||||
SET(distribution_DIR /opt/android)
|
SET(distribution_DIR "../../../build/${BUILD_FOR_SYSTEM_NAME}")
|
||||||
SET(OPENSSL_ROOT_DIR ${distribution_DIR}/prefix_${ANDROID_ABI})
|
SET(OPENSSL_ROOT_DIR ${distribution_DIR}/prefix_${ANDROID_ABI})
|
||||||
|
|
||||||
SET(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
|
SET(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
|
||||||
@@ -22,14 +22,14 @@ LINK_DIRECTORIES(${OPENSSL_LIBRARIES_DIR})
|
|||||||
# TODO: change this to include when possible
|
# TODO: change this to include when possible
|
||||||
include_directories(. include src/modules/ecdh src)
|
include_directories(. include src/modules/ecdh src)
|
||||||
|
|
||||||
add_library(secp256k1 src/secp256k1.c src/cpp/GroupElement.cpp src/cpp/MultiExponent.cpp src/cpp/Scalar.cpp src/modules/ecdh/main_impl.h include/secp256k1_ecdh.h src/scratch_impl.h src/scratch.h)
|
add_library(secp256k1_spark src/secp256k1.c src/cpp/GroupElement.cpp src/cpp/MultiExponent.cpp src/cpp/Scalar.cpp src/modules/ecdh/main_impl.h include/secp256k1_ecdh.h src/scratch_impl.h src/scratch.h)
|
||||||
|
|
||||||
# We need to link in GMP
|
# We need to link in GMP
|
||||||
find_package(GMP)
|
find_package(GMP)
|
||||||
if(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
|
if(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
|
||||||
target_include_directories(secp256k1 PUBLIC ${GMP_INCLUDE_DIR})
|
target_include_directories(secp256k1 PUBLIC ${GMP_INCLUDE_DIR})
|
||||||
target_link_libraries(secp256k1 ${GMP_LIBRARIES})
|
target_link_libraries(secp256k1_spark ${GMP_LIBRARIES})
|
||||||
target_compile_definitions(secp256k1
|
target_compile_definitions(secp256k1_spark
|
||||||
PUBLIC
|
PUBLIC
|
||||||
HAVE_LIBGMP
|
HAVE_LIBGMP
|
||||||
USE_NUM_GMP
|
USE_NUM_GMP
|
||||||
@@ -37,7 +37,7 @@ if(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
|
|||||||
USE_SCALAR_INV_BUILTIN
|
USE_SCALAR_INV_BUILTIN
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_compile_definitions(secp256k1
|
target_compile_definitions(secp256k1_spark
|
||||||
PUBLIC
|
PUBLIC
|
||||||
USE_NUM_NONE
|
USE_NUM_NONE
|
||||||
USE_FIELD_INV_BUILTIN
|
USE_FIELD_INV_BUILTIN
|
||||||
@@ -49,7 +49,7 @@ endif()
|
|||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
check_type_size(__int128 SIZEOF___INT128)
|
check_type_size(__int128 SIZEOF___INT128)
|
||||||
if(SIZEOF___INT128 EQUAL 16)
|
if(SIZEOF___INT128 EQUAL 16)
|
||||||
target_compile_definitions(secp256k1 PUBLIC HAVE___INT128)
|
target_compile_definitions(secp256k1_spark PUBLIC HAVE___INT128)
|
||||||
else()
|
else()
|
||||||
# If we do not support __int128, we should be falling back
|
# If we do not support __int128, we should be falling back
|
||||||
# on 32bits implementations for field and scalar.
|
# on 32bits implementations for field and scalar.
|
||||||
@@ -64,17 +64,17 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|||||||
message(SEND_ERROR "Compiler does not support __int128")
|
message(SEND_ERROR "Compiler does not support __int128")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(secp256k1 PUBLIC USE_SCALAR_4X64)
|
target_compile_definitions(secp256k1_spark PUBLIC USE_SCALAR_4X64)
|
||||||
target_compile_definitions(secp256k1 PUBLIC USE_FIELD_5X52)
|
target_compile_definitions(secp256k1_spark PUBLIC USE_FIELD_5X52)
|
||||||
else()
|
else()
|
||||||
target_compile_definitions(secp256k1 PUBLIC USE_SCALAR_8X32)
|
target_compile_definitions(secp256k1_spark PUBLIC USE_SCALAR_8X32)
|
||||||
target_compile_definitions(secp256k1 PUBLIC USE_FIELD_10X26)
|
target_compile_definitions(secp256k1_spark PUBLIC USE_FIELD_10X26)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# TODO: emult static precomputation
|
# TODO: emult static precomputation
|
||||||
# TODO: ecdh module
|
# TODO: ecdh module
|
||||||
# TODO: RECOVERY module
|
# TODO: RECOVERY module
|
||||||
TARGET_INCLUDE_DIRECTORIES(secp256k1 PUBLIC ${OPENSSL_INCLUDE_DIR})
|
TARGET_INCLUDE_DIRECTORIES(secp256k1_spark PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||||
TARGET_LINK_LIBRARIES(secp256k1 ${OPENSSL_LIBRARIES})
|
TARGET_LINK_LIBRARIES(secp256k1_spark ${OPENSSL_LIBRARIES})
|
||||||
#target_link_libraries(secp256k1 ${OPENSSL_LIBRARIES})
|
#target_link_libraries(secp256k1_spark ${OPENSSL_LIBRARIES})
|
||||||
@@ -4,7 +4,7 @@ project(sparkmobile)
|
|||||||
|
|
||||||
set(OPENSSL_USE_STATIC_LIBS OFF CACHE BOOL "" FORCE)
|
set(OPENSSL_USE_STATIC_LIBS OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
SET(distribution_DIR /opt/android)
|
SET(distribution_DIR "../../build/${BUILD_FOR_SYSTEM_NAME}")
|
||||||
SET(OPENSSL_ROOT_DIR ${distribution_DIR}/prefix_${ANDROID_ABI})
|
SET(OPENSSL_ROOT_DIR ${distribution_DIR}/prefix_${ANDROID_ABI})
|
||||||
|
|
||||||
SET(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
|
SET(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
|
||||||
@@ -42,9 +42,7 @@ set_property(SOURCE src/spark.cpp
|
|||||||
src/schnorr.cpp
|
src/schnorr.cpp
|
||||||
src/spend_transaction.cpp
|
src/spend_transaction.cpp
|
||||||
src/transcript.cpp
|
src/transcript.cpp
|
||||||
src/util.cpp
|
src/util.cpp
|
||||||
src/utils.cpp
|
|
||||||
src/dart_interface.cpp
|
|
||||||
PROPERTY COMPILE_FLAGS "-std=c++17" )
|
PROPERTY COMPILE_FLAGS "-std=c++17" )
|
||||||
|
|
||||||
add_library(sparkmobile SHARED
|
add_library(sparkmobile SHARED
|
||||||
@@ -75,12 +73,10 @@ add_library(sparkmobile SHARED
|
|||||||
src/schnorr.cpp
|
src/schnorr.cpp
|
||||||
src/spend_transaction.cpp
|
src/spend_transaction.cpp
|
||||||
src/transcript.cpp
|
src/transcript.cpp
|
||||||
src/util.cpp
|
src/util.cpp)
|
||||||
src/utils.cpp
|
|
||||||
src/dart_interface.cpp)
|
|
||||||
|
|
||||||
target_link_libraries(sparkmobile ${OPENSSL_LIBRARIES} secp256k1)
|
target_link_libraries(sparkmobile ${OPENSSL_LIBRARIES} secp256k1_spark)
|
||||||
|
|
||||||
add_dependencies(sparkmobile secp256k1)
|
add_dependencies(sparkmobile secp256k1_spark)
|
||||||
|
|
||||||
target_include_directories(sparkmobile PUBLIC secp256k1 ${OPENSSL_INCLUDE_DIR})
|
target_include_directories(sparkmobile PUBLIC secp256k1_spark ${OPENSSL_INCLUDE_DIR})
|
||||||
111
src/flutter_libsparkmobile.cpp
Normal file
111
src/flutter_libsparkmobile.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#include "flutter_libsparkmobile.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "deps/sparkmobile/include/spark.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream> // Just for printing.
|
||||||
|
|
||||||
|
using namespace spark;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for spark::getAddress.
|
||||||
|
*/
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
const char* getAddress(const char* keyDataHex, int index, int diversifier, int isTestNet) {
|
||||||
|
try {
|
||||||
|
// Use the hex string directly to create the SpendKey.
|
||||||
|
spark::SpendKey spendKey = createSpendKeyFromData(keyDataHex, index);
|
||||||
|
|
||||||
|
spark::FullViewKey fullViewKey(spendKey);
|
||||||
|
spark::IncomingViewKey incomingViewKey(fullViewKey);
|
||||||
|
spark::Address address(incomingViewKey, static_cast<uint64_t>(diversifier));
|
||||||
|
|
||||||
|
// Encode the Address object into a string using the appropriate network.
|
||||||
|
std::string encodedAddress = address.encode(isTestNet ? spark::ADDRESS_NETWORK_TESTNET : spark::ADDRESS_NETWORK_MAINNET);
|
||||||
|
|
||||||
|
// Allocate memory for the C-style string.
|
||||||
|
char* cstr = new char[encodedAddress.length() + 1];
|
||||||
|
std::strcpy(cstr, encodedAddress.c_str());
|
||||||
|
|
||||||
|
return cstr;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Exception: " << e.what() << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for spark:identifyCoin.
|
||||||
|
*
|
||||||
|
* Uses the utility functions spark::Coin fromFFI(const CCoin& c_struct) to pass parameters to the
|
||||||
|
* C++ function spark::identifyCoin(const Coin& coin), then uses the utility function
|
||||||
|
* CIdentifiedCoinData toFFI(const spark::IdentifiedCoinData& cpp_struct) to convert the result back
|
||||||
|
* to a C struct.
|
||||||
|
*
|
||||||
|
* We also need the incoming view key or we need to derive it, so accept keyDataHex and index.
|
||||||
|
*/
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
struct CIdentifiedCoinData identifyCoin(struct CCoin c_struct, const char* keyDataHex, int index) {
|
||||||
|
try {
|
||||||
|
spark::Coin coin = fromFFI(c_struct);
|
||||||
|
|
||||||
|
// Derive the incoming view key from the key data and index.
|
||||||
|
spark::SpendKey spendKey = createSpendKeyFromData(keyDataHex, index);
|
||||||
|
spark::FullViewKey fullViewKey(spendKey);
|
||||||
|
spark::IncomingViewKey incomingViewKey(fullViewKey);
|
||||||
|
|
||||||
|
spark::IdentifiedCoinData identifiedCoinData = coin.identify(incomingViewKey);
|
||||||
|
return toFFI(identifiedCoinData);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Exception: " << e.what() << std::endl;
|
||||||
|
return CIdentifiedCoinData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for spark::createSparkMintRecipients.
|
||||||
|
*/
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
struct CCRecipient* createSparkMintRecipients(
|
||||||
|
int numRecipients,
|
||||||
|
struct PubKeyScript* pubKeyScripts,
|
||||||
|
uint64_t* amounts,
|
||||||
|
const char* memo,
|
||||||
|
int subtractFee)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
std::vector<CRecipient> recipients;
|
||||||
|
|
||||||
|
for (int i = 0; i < numRecipients; i++) {
|
||||||
|
CScript scriptPubKey = createCScriptFromBytes(
|
||||||
|
pubKeyScripts[i].bytes,
|
||||||
|
pubKeyScripts[i].length
|
||||||
|
);
|
||||||
|
|
||||||
|
CRecipient recipient;
|
||||||
|
recipient.pubKey = scriptPubKey;
|
||||||
|
|
||||||
|
recipient.amount = amounts[i];
|
||||||
|
|
||||||
|
recipient.subtractFeeFromAmount = (bool)subtractFee;
|
||||||
|
|
||||||
|
recipients.push_back(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CCRecipient> ccRecipients;
|
||||||
|
|
||||||
|
for (const CRecipient& recipient : recipients) {
|
||||||
|
CCRecipient ccRecipient = toFFI(recipient);
|
||||||
|
ccRecipients.push_back(ccRecipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCRecipient* result = new CCRecipient[numRecipients];
|
||||||
|
std::copy(ccRecipients.begin(), ccRecipients.end(), result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Exception: " << e.what() << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
118
src/flutter_libsparkmobile.h
Normal file
118
src/flutter_libsparkmobile.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
#ifndef ORG_FIRO_SPARK_DART_INTERFACE_H
|
||||||
|
#define ORG_FIRO_SPARK_DART_INTERFACE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef FFI_PLUGIN_EXPORT
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define FFI_PLUGIN_EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used))
|
||||||
|
#else
|
||||||
|
#define FFI_PLUGIN_EXPORT __attribute__((visibility("default"))) __attribute__((used))
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define FFI_PLUGIN_EXPORT __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for spark::getAddress.
|
||||||
|
*/
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
const char* getAddress(const char* keyDataHex, int index, int diversifier, int isTestNet);
|
||||||
|
|
||||||
|
/*
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
const char *createFullViewKey(const char* keyData, int index);
|
||||||
|
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
const char* createIncomingViewKey(const char* keyData, int index);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for a spark::Coin.
|
||||||
|
*
|
||||||
|
* A Coin is a type, a key, an index, a value, a memo, and a serial context. We accept these params
|
||||||
|
* as a C struct, deriving the key from the keyData and index.
|
||||||
|
*/
|
||||||
|
struct CCoin {
|
||||||
|
char type;
|
||||||
|
const unsigned char* k;
|
||||||
|
int kLength;
|
||||||
|
const char* keyData;
|
||||||
|
int index;
|
||||||
|
uint64_t v;
|
||||||
|
const unsigned char* memo;
|
||||||
|
int memoLength;
|
||||||
|
const unsigned char* serial_context;
|
||||||
|
int serial_contextLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for a spark::IdentifiedCoinData.
|
||||||
|
*
|
||||||
|
* An IdentifiedCoinData is a diversifier, encrypted diversifier, value, nonce, and memo. We accept
|
||||||
|
* these params as a C struct.
|
||||||
|
*/
|
||||||
|
struct CIdentifiedCoinData {
|
||||||
|
uint64_t i;
|
||||||
|
const unsigned char* d;
|
||||||
|
int dLength;
|
||||||
|
uint64_t v;
|
||||||
|
const unsigned char* k;
|
||||||
|
int kLength;
|
||||||
|
const char* memo;
|
||||||
|
int memoLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for spark::identifyCoin.
|
||||||
|
*/
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
struct CIdentifiedCoinData identifyCoin(struct CCoin c_struct, const char* keyDataHex, int index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for a spark::CRecipient.
|
||||||
|
*
|
||||||
|
* A CRecipient is a CScript, CAmount, and a bool. We accept a C-style, FFI-friendly CCRecipient
|
||||||
|
* struct in order to construct a C++ CRecipient. A CScript is constructed from a hex string, a
|
||||||
|
* CAmount is just a uint64_t, and the bool will be an int.
|
||||||
|
*/
|
||||||
|
struct CCRecipient {
|
||||||
|
const unsigned char* pubKey;
|
||||||
|
int pubKeyLength;
|
||||||
|
uint64_t cAmount;
|
||||||
|
int subtractFee;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for a spark::MintedCoinData.
|
||||||
|
*
|
||||||
|
* A MintedCoinData is a struct that contains an Address, a uint64_t value, and a string memo. We
|
||||||
|
* accept these as a CMintedCoinData from the Dart interface, and convert them to a MintedCoinData
|
||||||
|
* struct.
|
||||||
|
*/
|
||||||
|
struct CMintedCoinData {
|
||||||
|
const char* address;
|
||||||
|
uint64_t value;
|
||||||
|
const char* memo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PubKeyScript {
|
||||||
|
unsigned char* bytes;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FFI-friendly wrapper for spark::createSparkMintRecipients.
|
||||||
|
*/
|
||||||
|
FFI_PLUGIN_EXPORT
|
||||||
|
struct CCRecipient* createSparkMintRecipients(
|
||||||
|
int numRecipients,
|
||||||
|
struct PubKeyScript* pubKeyScripts,
|
||||||
|
uint64_t* amounts,
|
||||||
|
const char* memo,
|
||||||
|
int subtractFee);
|
||||||
|
|
||||||
|
#endif //ORG_FIRO_SPARK_DART_INTERFACE_H
|
||||||
318
src/utils.cpp
Normal file
318
src/utils.cpp
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
#include "flutter_libsparkmobile.h"
|
||||||
|
#include "deps/sparkmobile/src/coin.h"
|
||||||
|
#include "deps/sparkmobile/src/keys.h"
|
||||||
|
#include "deps/sparkmobile//bitcoin/script.h" // For CScript.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to generate an address from keyData, index, and a diversifier.
|
||||||
|
*/
|
||||||
|
const char* getAddressFromData(const char* keyData, int index, const uint64_t diversifier) {
|
||||||
|
try {
|
||||||
|
spark::SpendKey spendKey = createSpendKeyFromData(keyData, index);
|
||||||
|
spark::FullViewKey fullViewKey(spendKey);
|
||||||
|
spark::IncomingViewKey incomingViewKey(fullViewKey);
|
||||||
|
spark::Address address(incomingViewKey, diversifier);
|
||||||
|
|
||||||
|
// Encode the Address object into a string.
|
||||||
|
std::string encodedAddress = address.encode(spark::ADDRESS_NETWORK_TESTNET);
|
||||||
|
|
||||||
|
// Allocate memory for the C-style string and return it.
|
||||||
|
char* result = new char[encodedAddress.size() + 1];
|
||||||
|
std::copy(encodedAddress.begin(), encodedAddress.end(), result);
|
||||||
|
result[encodedAddress.size()] = '\0'; // Null-terminate the C string.
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to generate SpendKey from keyData and index.
|
||||||
|
*/
|
||||||
|
spark::SpendKey createSpendKeyFromData(const char *keyData, int index) {
|
||||||
|
try {
|
||||||
|
// Convert the keyData from hex string to binary
|
||||||
|
unsigned char* key_data_bin = hexToBytes(keyData);
|
||||||
|
|
||||||
|
const SpendKeyData *data = new SpendKeyData(key_data_bin, index);
|
||||||
|
|
||||||
|
return createSpendKey(*data);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// We can't return here, so just throw the exception again.
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CCoin factory.
|
||||||
|
*
|
||||||
|
* TODO manage the memory allocated by this function.
|
||||||
|
*/
|
||||||
|
struct CCoin createCCoin(char type, const unsigned char* k, int kLength, const char* keyData, int index, uint64_t v, const unsigned char* memo, int memoLength, const unsigned char* serial_context, int serial_contextLength) {
|
||||||
|
CCoin coin;
|
||||||
|
coin.type = type;
|
||||||
|
coin.k = copyBytes(k, kLength);
|
||||||
|
coin.kLength = kLength;
|
||||||
|
coin.keyData = strdup(keyData);
|
||||||
|
coin.index = index;
|
||||||
|
coin.v = v;
|
||||||
|
coin.memo = copyBytes(memo, memoLength);
|
||||||
|
coin.memoLength = memoLength;
|
||||||
|
coin.serial_context = copyBytes(serial_context, serial_contextLength);
|
||||||
|
coin.serial_contextLength = serial_contextLength;
|
||||||
|
return coin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert an FFI-friendly C CCoin struct to a C++ Coin struct.
|
||||||
|
*/
|
||||||
|
spark::Coin fromFFI(const CCoin& c_struct) {
|
||||||
|
spark::Coin cpp_struct(
|
||||||
|
// The test params are only used for unit tests.
|
||||||
|
spark::Params::get_default(),
|
||||||
|
c_struct.type,
|
||||||
|
spark::Scalar(c_struct.k),
|
||||||
|
spark::Address(spark::IncomingViewKey(spark::FullViewKey(createSpendKeyFromData(c_struct.keyData, c_struct.index))), c_struct.index),
|
||||||
|
c_struct.v,
|
||||||
|
std::string(reinterpret_cast<const char*>(c_struct.memo), c_struct.memoLength),
|
||||||
|
std::vector<unsigned char>(c_struct.serial_context, c_struct.serial_context + c_struct.serial_contextLength)
|
||||||
|
);
|
||||||
|
|
||||||
|
return cpp_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert a C++ IdentifiedCoinData struct to an FFI-friendly struct.
|
||||||
|
*/
|
||||||
|
CIdentifiedCoinData toFFI(const spark::IdentifiedCoinData& cpp_struct) {
|
||||||
|
CIdentifiedCoinData c_struct;
|
||||||
|
|
||||||
|
c_struct.i = cpp_struct.i;
|
||||||
|
c_struct.d = copyBytes(cpp_struct.d.data(), cpp_struct.d.size());
|
||||||
|
c_struct.dLength = cpp_struct.d.size();
|
||||||
|
c_struct.v = cpp_struct.v;
|
||||||
|
|
||||||
|
// Serialize and copy the Scalar k.
|
||||||
|
std::vector<unsigned char> scalarBytes(32);
|
||||||
|
cpp_struct.k.serialize(scalarBytes.data());
|
||||||
|
c_struct.k = copyBytes(scalarBytes.data(), scalarBytes.size());
|
||||||
|
c_struct.kLength = scalarBytes.size();
|
||||||
|
|
||||||
|
// Copy the memo.
|
||||||
|
c_struct.memo = strdup(cpp_struct.memo.c_str());
|
||||||
|
c_struct.memoLength = cpp_struct.memo.size();
|
||||||
|
|
||||||
|
return c_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Factory function to create a CScript from a byte array.
|
||||||
|
*/
|
||||||
|
CScript createCScriptFromBytes(const unsigned char* bytes, int length) {
|
||||||
|
// Construct a CScript object
|
||||||
|
CScript script;
|
||||||
|
|
||||||
|
// Check if bytes is not nullptr and length is positive
|
||||||
|
if (bytes != nullptr && length > 0) {
|
||||||
|
// Append each byte to the script
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
script << bytes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert a C++ CScript to a byte array.
|
||||||
|
*/
|
||||||
|
std::vector<unsigned char> serializeCScript(const CScript& script) {
|
||||||
|
return std::vector<unsigned char>(script.begin(), script.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert an FFI-friendly C CCRecipient struct to a C++ CRecipient struct.
|
||||||
|
*/
|
||||||
|
CRecipient fromFFI(const CCRecipient& c_struct) {
|
||||||
|
// Use the factory function to create a CScript object.
|
||||||
|
CScript script = createCScriptFromBytes(c_struct.pubKey, c_struct.pubKeyLength);
|
||||||
|
|
||||||
|
CRecipient cpp_struct = createCRecipient(
|
||||||
|
script,
|
||||||
|
c_struct.cAmount,
|
||||||
|
static_cast<bool>(c_struct.subtractFee)
|
||||||
|
);
|
||||||
|
|
||||||
|
return cpp_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CCRecipient factory.
|
||||||
|
*
|
||||||
|
* TODO manage the memory allocated by this function.
|
||||||
|
*/
|
||||||
|
struct CCRecipient createCCRecipient(const unsigned char* pubKey, uint64_t amount, int subtractFee) {
|
||||||
|
CCRecipient recipient;
|
||||||
|
recipient.pubKey = copyBytes(pubKey, 32);
|
||||||
|
recipient.cAmount = amount;
|
||||||
|
recipient.subtractFee = subtractFee;
|
||||||
|
return recipient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert a C++ CRecipient struct to an FFI-friendly struct.
|
||||||
|
*/
|
||||||
|
CCRecipient toFFI(const CRecipient& cpp_struct) {
|
||||||
|
CCRecipient c_struct;
|
||||||
|
|
||||||
|
// Serialize CScript and copy.
|
||||||
|
std::vector<unsigned char> scriptBytes = serializeCScript(cpp_struct.pubKey);
|
||||||
|
if (!scriptBytes.empty()) {
|
||||||
|
c_struct.pubKey = copyBytes(scriptBytes.data(), scriptBytes.size());
|
||||||
|
c_struct.pubKeyLength = static_cast<int>(scriptBytes.size());
|
||||||
|
} else {
|
||||||
|
c_struct.pubKey = nullptr;
|
||||||
|
c_struct.pubKeyLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
c_struct.cAmount = cpp_struct.amount;
|
||||||
|
c_struct.subtractFee = static_cast<int>(cpp_struct.subtractFeeFromAmount);
|
||||||
|
|
||||||
|
return c_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRecipient factory.
|
||||||
|
*
|
||||||
|
* TODO manage the memory allocated by this function.
|
||||||
|
*/
|
||||||
|
CRecipient createCRecipient(const CScript& script, CAmount amount, bool subtractFee) {
|
||||||
|
CRecipient recipient;
|
||||||
|
recipient.pubKey = script;
|
||||||
|
recipient.amount = amount;
|
||||||
|
recipient.subtractFeeFromAmount = subtractFee;
|
||||||
|
return recipient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to decode an Address from a string.
|
||||||
|
*/
|
||||||
|
spark::Address decodeAddress(const std::string& str) {
|
||||||
|
spark::Address address;
|
||||||
|
address.decode(str);
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MintedCoinData factory.
|
||||||
|
*/
|
||||||
|
spark::MintedCoinData createMintedCoinData(const char* address, uint64_t v, const char* memo) {
|
||||||
|
return {
|
||||||
|
decodeAddress(address),
|
||||||
|
v,
|
||||||
|
memo
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert an FFI-friendly C CMintedCoinData struct to a C++ MintedCoinData.
|
||||||
|
*/
|
||||||
|
spark::MintedCoinData fromFFI(const CMintedCoinData& c_struct) {
|
||||||
|
return createMintedCoinData(
|
||||||
|
c_struct.address,
|
||||||
|
c_struct.value,
|
||||||
|
c_struct.memo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CMintedCoinData factory.
|
||||||
|
*/
|
||||||
|
CMintedCoinData createCMintedCoinData(const char* address, uint64_t value, const char* memo) {
|
||||||
|
CMintedCoinData c_struct;
|
||||||
|
c_struct.address = strdup(address);
|
||||||
|
c_struct.value = value;
|
||||||
|
c_struct.memo = strdup(memo);
|
||||||
|
return c_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to convert a C++ MintedCoinData struct to an FFI-friendly CMintedCoinData.
|
||||||
|
*/
|
||||||
|
CMintedCoinData toFFI(const spark::MintedCoinData& cpp_struct) {
|
||||||
|
return createCMintedCoinData(
|
||||||
|
cpp_struct.address.encode(true).c_str(),
|
||||||
|
cpp_struct.v,
|
||||||
|
cpp_struct.memo.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function for deep copying byte arrays.
|
||||||
|
*
|
||||||
|
* Used by createCCoin.
|
||||||
|
*/
|
||||||
|
unsigned char* copyBytes(const unsigned char* source, int length) {
|
||||||
|
if (source == nullptr || length <= 0) return nullptr;
|
||||||
|
|
||||||
|
unsigned char* dest = new unsigned char[length];
|
||||||
|
std::memcpy(dest, source, length);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *hexToBytes(const char *hexstr) {
|
||||||
|
size_t length = strlen(hexstr) / 2;
|
||||||
|
auto *chrs = (unsigned char *) malloc((length + 1) * sizeof(unsigned char));
|
||||||
|
for (size_t i = 0, j = 0; j < length; i += 2, j++) {
|
||||||
|
chrs[j] = (hexstr[i] % 32 + 9) % 25 * 16 + (hexstr[i + 1] % 32 + 9) % 25;
|
||||||
|
}
|
||||||
|
chrs[length] = '\0';
|
||||||
|
return chrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *bytesToHex(const unsigned char *bytes, int size) {
|
||||||
|
std::string str;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
const unsigned char ch = bytes[i];
|
||||||
|
str.append(&hexArray[(ch & 0xF0) >> 4], 1);
|
||||||
|
str.append(&hexArray[ch & 0xF], 1);
|
||||||
|
}
|
||||||
|
char *new_str = new char[std::strlen(str.c_str()) + 1];
|
||||||
|
std::strcpy(new_str, str.c_str());
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *bytesToHex(const char *bytes, int size) {
|
||||||
|
std::string str;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
const unsigned char ch = (const unsigned char) bytes[i];
|
||||||
|
str.append(&hexArray[(ch & 0xF0) >> 4], 1);
|
||||||
|
str.append(&hexArray[ch & 0xF], 1);
|
||||||
|
}
|
||||||
|
char *new_str = new char[std::strlen(str.c_str()) + 1];
|
||||||
|
std::strcpy(new_str, str.c_str());
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *bytesToHex(std::vector<unsigned char> bytes, int size) {
|
||||||
|
std::string str;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
const unsigned char ch = bytes[i];
|
||||||
|
str.append(&hexArray[(ch & 0xF0) >> 4], 1);
|
||||||
|
str.append(&hexArray[ch & 0xF], 1);
|
||||||
|
}
|
||||||
|
char *new_str = new char[std::strlen(str.c_str()) + 1];
|
||||||
|
std::strcpy(new_str, str.c_str());
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
62
src/utils.h
Normal file
62
src/utils.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef ORG_FIRO_SPARK_UTILS_H
|
||||||
|
#define ORG_FIRO_SPARK_UTILS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flutter_libsparkmobile.h"
|
||||||
|
#include "deps/sparkmobile/include/spark.h"
|
||||||
|
|
||||||
|
const char* getAddressFromData(const char* keyData, int index, const uint64_t diversifier);
|
||||||
|
|
||||||
|
spark::SpendKey createSpendKeyFromData(const char *keyData, int index);
|
||||||
|
|
||||||
|
spark::Coin fromFFI(const CCoin& c_struct);
|
||||||
|
|
||||||
|
CCoin toFFI(const spark::Coin& cpp_struct);
|
||||||
|
|
||||||
|
struct CCoin createCCoin(char type, const unsigned char* k, int kLength, const char* keyData, int index, uint64_t v, const unsigned char* memo, int memoLength, const unsigned char* serial_context, int serial_contextLength);
|
||||||
|
|
||||||
|
spark::IdentifiedCoinData fromFFI(const CIdentifiedCoinData& c_struct);
|
||||||
|
|
||||||
|
CIdentifiedCoinData toFFI(const spark::IdentifiedCoinData& cpp_struct);
|
||||||
|
|
||||||
|
CScript createCScriptFromBytes(const unsigned char* bytes, int length);
|
||||||
|
|
||||||
|
std::vector<unsigned char> serializeCScript(const CScript& script);
|
||||||
|
|
||||||
|
CRecipient createCRecipient(const CScript& script, CAmount amount, bool subtractFee);
|
||||||
|
|
||||||
|
CRecipient fromFFI(const CCRecipient& c_struct);
|
||||||
|
|
||||||
|
struct CCRecipient createCCRecipient(const unsigned char* pubKey, uint64_t amount, int subtractFee);
|
||||||
|
|
||||||
|
CCRecipient toFFI(const CRecipient& cpp_struct);
|
||||||
|
|
||||||
|
spark::Address decodeAddress(const std::string& str);
|
||||||
|
|
||||||
|
spark::MintedCoinData createMintedCoinData(const char* address, uint64_t v, const char* memo);
|
||||||
|
|
||||||
|
spark::MintedCoinData fromFFI(const CMintedCoinData& c_struct);
|
||||||
|
|
||||||
|
CMintedCoinData createCMintedCoinData(const char* address, uint64_t value, const char* memo);
|
||||||
|
|
||||||
|
CMintedCoinData toFFI(const spark::MintedCoinData& cpp_struct);
|
||||||
|
|
||||||
|
char const hexArray[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
|
||||||
|
'e', 'f'};
|
||||||
|
|
||||||
|
unsigned char* copyBytes(const unsigned char* source, int length);
|
||||||
|
|
||||||
|
unsigned char *hexToBytes(const char *str);
|
||||||
|
|
||||||
|
const char *bytesToHex(const unsigned char *bytes, int size);
|
||||||
|
|
||||||
|
const char *bytesToHex(const char *bytes, int size);
|
||||||
|
|
||||||
|
const char *bytesToHex(std::vector<unsigned char> bytes, int size);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ORG_FIRO_SPARK_UTILS_H
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:flutter_libsparkmobile/flutter_libsparkmobile_method_channel.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
|
|
||||||
MethodChannelFlutterLibsparkmobile platform = MethodChannelFlutterLibsparkmobile();
|
|
||||||
const MethodChannel channel = MethodChannel('flutter_libsparkmobile');
|
|
||||||
|
|
||||||
setUp(() {
|
|
||||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
|
||||||
channel,
|
|
||||||
(MethodCall methodCall) async {
|
|
||||||
return '42';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDown(() {
|
|
||||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getPlatformVersion', () async {
|
|
||||||
expect(await platform.getPlatformVersion(), '42');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -8,89 +8,16 @@ cmake_minimum_required(VERSION 3.14)
|
|||||||
set(PROJECT_NAME "flutter_libsparkmobile")
|
set(PROJECT_NAME "flutter_libsparkmobile")
|
||||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||||
|
|
||||||
# This value is used when generating builds using this plugin, so it must
|
# Invoke the build for native code shared with the other target platforms.
|
||||||
# not be changed
|
# This can be changed to accommodate different builds.
|
||||||
set(PLUGIN_NAME "flutter_libsparkmobile_plugin")
|
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
|
||||||
|
|
||||||
# Any new source files that you add to the plugin should be added here.
|
|
||||||
list(APPEND PLUGIN_SOURCES
|
|
||||||
"flutter_libsparkmobile_plugin.cpp"
|
|
||||||
"flutter_libsparkmobile_plugin.h"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Define the plugin library target. Its name must not be changed (see comment
|
|
||||||
# on PLUGIN_NAME above).
|
|
||||||
add_library(${PLUGIN_NAME} SHARED
|
|
||||||
"include/flutter_libsparkmobile/flutter_libsparkmobile_plugin_c_api.h"
|
|
||||||
"flutter_libsparkmobile_plugin_c_api.cpp"
|
|
||||||
${PLUGIN_SOURCES}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Apply a standard set of build settings that are configured in the
|
|
||||||
# application-level CMakeLists.txt. This can be removed for plugins that want
|
|
||||||
# full control over build settings.
|
|
||||||
apply_standard_settings(${PLUGIN_NAME})
|
|
||||||
|
|
||||||
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
|
||||||
# between plugins. This should not be removed; any symbols that should be
|
|
||||||
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
|
||||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
|
||||||
CXX_VISIBILITY_PRESET hidden)
|
|
||||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
|
||||||
|
|
||||||
# Source include directories and library dependencies. Add any plugin-specific
|
|
||||||
# dependencies here.
|
|
||||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
|
||||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
|
|
||||||
|
|
||||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||||
# This list could contain prebuilt libraries, or libraries created by an
|
# This list could contain prebuilt libraries, or libraries created by an
|
||||||
# external build triggered from this build file.
|
# external build triggered from this build file.
|
||||||
set(flutter_libsparkmobile_bundled_libraries
|
set(flutter_libsparkmobile_bundled_libraries
|
||||||
""
|
# Defined in ../src/CMakeLists.txt.
|
||||||
|
# This can be changed to accommodate different builds.
|
||||||
|
$<TARGET_FILE:flutter_libsparkmobile>
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
# === Tests ===
|
|
||||||
# These unit tests can be run from a terminal after building the example, or
|
|
||||||
# from Visual Studio after opening the generated solution file.
|
|
||||||
|
|
||||||
# Only enable test builds when building the example (which sets this variable)
|
|
||||||
# so that plugin clients aren't building the tests.
|
|
||||||
if (${include_${PROJECT_NAME}_tests})
|
|
||||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
# Add the Google Test dependency.
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(
|
|
||||||
googletest
|
|
||||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
|
||||||
)
|
|
||||||
# Prevent overriding the parent project's compiler/linker settings
|
|
||||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
|
||||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
|
||||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
|
||||||
FetchContent_MakeAvailable(googletest)
|
|
||||||
|
|
||||||
# The plugin's C API is not very useful for unit testing, so build the sources
|
|
||||||
# directly into the test binary rather than using the DLL.
|
|
||||||
add_executable(${TEST_RUNNER}
|
|
||||||
test/flutter_libsparkmobile_plugin_test.cpp
|
|
||||||
${PLUGIN_SOURCES}
|
|
||||||
)
|
|
||||||
apply_standard_settings(${TEST_RUNNER})
|
|
||||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin)
|
|
||||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
|
||||||
# flutter_wrapper_plugin has link dependencies on the Flutter DLL.
|
|
||||||
add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
||||||
"${FLUTTER_LIBRARY}" $<TARGET_FILE_DIR:${TEST_RUNNER}>
|
|
||||||
)
|
|
||||||
|
|
||||||
# Enable automatic test discovery.
|
|
||||||
include(GoogleTest)
|
|
||||||
gtest_discover_tests(${TEST_RUNNER})
|
|
||||||
endif()
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
#include "flutter_libsparkmobile_plugin.h"
|
|
||||||
|
|
||||||
// This must be included before many other Windows headers.
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
// For getPlatformVersion; remove unless needed for your plugin implementation.
|
|
||||||
#include <VersionHelpers.h>
|
|
||||||
|
|
||||||
#include <flutter/method_channel.h>
|
|
||||||
#include <flutter/plugin_registrar_windows.h>
|
|
||||||
#include <flutter/standard_method_codec.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace flutter_libsparkmobile {
|
|
||||||
|
|
||||||
// static
|
|
||||||
void FlutterLibsparkmobilePlugin::RegisterWithRegistrar(
|
|
||||||
flutter::PluginRegistrarWindows *registrar) {
|
|
||||||
auto channel =
|
|
||||||
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
|
|
||||||
registrar->messenger(), "flutter_libsparkmobile",
|
|
||||||
&flutter::StandardMethodCodec::GetInstance());
|
|
||||||
|
|
||||||
auto plugin = std::make_unique<FlutterLibsparkmobilePlugin>();
|
|
||||||
|
|
||||||
channel->SetMethodCallHandler(
|
|
||||||
[plugin_pointer = plugin.get()](const auto &call, auto result) {
|
|
||||||
plugin_pointer->HandleMethodCall(call, std::move(result));
|
|
||||||
});
|
|
||||||
|
|
||||||
registrar->AddPlugin(std::move(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
FlutterLibsparkmobilePlugin::FlutterLibsparkmobilePlugin() {}
|
|
||||||
|
|
||||||
FlutterLibsparkmobilePlugin::~FlutterLibsparkmobilePlugin() {}
|
|
||||||
|
|
||||||
void FlutterLibsparkmobilePlugin::HandleMethodCall(
|
|
||||||
const flutter::MethodCall<flutter::EncodableValue> &method_call,
|
|
||||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
|
|
||||||
if (method_call.method_name().compare("getPlatformVersion") == 0) {
|
|
||||||
std::ostringstream version_stream;
|
|
||||||
version_stream << "Windows ";
|
|
||||||
if (IsWindows10OrGreater()) {
|
|
||||||
version_stream << "10+";
|
|
||||||
} else if (IsWindows8OrGreater()) {
|
|
||||||
version_stream << "8";
|
|
||||||
} else if (IsWindows7OrGreater()) {
|
|
||||||
version_stream << "7";
|
|
||||||
}
|
|
||||||
result->Success(flutter::EncodableValue(version_stream.str()));
|
|
||||||
} else {
|
|
||||||
result->NotImplemented();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flutter_libsparkmobile
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_H_
|
|
||||||
#define FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_H_
|
|
||||||
|
|
||||||
#include <flutter/method_channel.h>
|
|
||||||
#include <flutter/plugin_registrar_windows.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace flutter_libsparkmobile {
|
|
||||||
|
|
||||||
class FlutterLibsparkmobilePlugin : public flutter::Plugin {
|
|
||||||
public:
|
|
||||||
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar);
|
|
||||||
|
|
||||||
FlutterLibsparkmobilePlugin();
|
|
||||||
|
|
||||||
virtual ~FlutterLibsparkmobilePlugin();
|
|
||||||
|
|
||||||
// Disallow copy and assign.
|
|
||||||
FlutterLibsparkmobilePlugin(const FlutterLibsparkmobilePlugin&) = delete;
|
|
||||||
FlutterLibsparkmobilePlugin& operator=(const FlutterLibsparkmobilePlugin&) = delete;
|
|
||||||
|
|
||||||
// Called when a method is called on this plugin's channel from Dart.
|
|
||||||
void HandleMethodCall(
|
|
||||||
const flutter::MethodCall<flutter::EncodableValue> &method_call,
|
|
||||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flutter_libsparkmobile
|
|
||||||
|
|
||||||
#endif // FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_H_
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#include "include/flutter_libsparkmobile/flutter_libsparkmobile_plugin_c_api.h"
|
|
||||||
|
|
||||||
#include <flutter/plugin_registrar_windows.h>
|
|
||||||
|
|
||||||
#include "flutter_libsparkmobile_plugin.h"
|
|
||||||
|
|
||||||
void FlutterLibsparkmobilePluginCApiRegisterWithRegistrar(
|
|
||||||
FlutterDesktopPluginRegistrarRef registrar) {
|
|
||||||
flutter_libsparkmobile::FlutterLibsparkmobilePlugin::RegisterWithRegistrar(
|
|
||||||
flutter::PluginRegistrarManager::GetInstance()
|
|
||||||
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#ifndef FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_C_API_H_
|
|
||||||
#define FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_C_API_H_
|
|
||||||
|
|
||||||
#include <flutter_plugin_registrar.h>
|
|
||||||
|
|
||||||
#ifdef FLUTTER_PLUGIN_IMPL
|
|
||||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void FlutterLibsparkmobilePluginCApiRegisterWithRegistrar(
|
|
||||||
FlutterDesktopPluginRegistrarRef registrar);
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // FLUTTER_PLUGIN_FLUTTER_LIBSPARKMOBILE_PLUGIN_C_API_H_
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#include <flutter/method_call.h>
|
|
||||||
#include <flutter/method_result_functions.h>
|
|
||||||
#include <flutter/standard_method_codec.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#include "flutter_libsparkmobile_plugin.h"
|
|
||||||
|
|
||||||
namespace flutter_libsparkmobile {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using flutter::EncodableMap;
|
|
||||||
using flutter::EncodableValue;
|
|
||||||
using flutter::MethodCall;
|
|
||||||
using flutter::MethodResultFunctions;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST(FlutterLibsparkmobilePlugin, GetPlatformVersion) {
|
|
||||||
FlutterLibsparkmobilePlugin plugin;
|
|
||||||
// Save the reply value from the success callback.
|
|
||||||
std::string result_string;
|
|
||||||
plugin.HandleMethodCall(
|
|
||||||
MethodCall("getPlatformVersion", std::make_unique<EncodableValue>()),
|
|
||||||
std::make_unique<MethodResultFunctions<>>(
|
|
||||||
[&result_string](const EncodableValue* result) {
|
|
||||||
result_string = std::get<std::string>(*result);
|
|
||||||
},
|
|
||||||
nullptr, nullptr));
|
|
||||||
|
|
||||||
// Since the exact string varies by host, just ensure that it's a string
|
|
||||||
// with the expected format.
|
|
||||||
EXPECT_TRUE(result_string.rfind("Windows ", 0) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace flutter_libsparkmobile
|
|
||||||
Reference in New Issue
Block a user