(port: i64, parse_params: F, async_job: F2)
+where
+ P: 'static + Send + Sync,
+ F: FnOnce() -> Result,
+ F2: 'static + Send + Sync + FnOnce(P) -> R,
+ DartRes: From,
+{
+ match parse_params() {
+ Ok(parsed_params) => {
+ if THREAD_POOL
+ .launch(move |_| Isolate::new(port).post(DartRes::from(async_job(parsed_params))))
+ .is_err()
+ {
+ Isolate::new(port).post(DartRes::err("thread pool panicked"));
+ }
+ }
+ Err(e) => {
+ Isolate::new(port).post(DartRes::err(e));
+ }
+ }
+}
diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs
index 7d07565..6e9932c 100644
--- a/native/dubp_rs/src/dewif.rs
+++ b/native/dubp_rs/src/dewif.rs
@@ -35,16 +35,11 @@ pub(super) fn gen_pin10() -> Result {
}
pub(super) fn change_pin(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- old_pin: *const raw::c_char,
- new_pin: *const raw::c_char,
+ currency: &str,
+ dewif: &str,
+ old_pin: &str,
+ new_pin: &str,
) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let old_pin = char_ptr_to_str(old_pin)?;
- let new_pin = char_ptr_to_str(new_pin)?;
-
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
@@ -62,15 +57,11 @@ pub(super) fn change_pin(
}
pub(super) fn gen_dewif(
- currency: *const raw::c_char,
+ currency: &str,
language: u32,
- mnemonic: *const raw::c_char,
- pin: *const raw::c_char,
+ mnemonic: &str,
+ pin: &str,
) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let mnemonic = char_ptr_to_str(mnemonic)?;
- let pin = char_ptr_to_str(pin)?;
-
let currency = parse_currency(currency)?;
let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
.map_err(|_| DubpError::WrongLanguage)?;
@@ -81,15 +72,7 @@ pub(super) fn gen_dewif(
))
}
-pub(super) fn get_pubkey(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- pin: *const raw::c_char,
-) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let pin = char_ptr_to_str(pin)?;
-
+pub(super) fn get_pubkey(currency: &str, dewif: &str, pin: &str) -> Result {
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
@@ -104,17 +87,7 @@ pub(super) fn get_pubkey(
}
}
-pub(super) fn sign(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- pin: *const raw::c_char,
- msg: *const raw::c_char,
-) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let pin = char_ptr_to_str(pin)?;
- let msg = char_ptr_to_str(msg)?;
-
+pub(super) fn sign(currency: &str, dewif: &str, pin: &str, msg: &str) -> Result {
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
@@ -130,22 +103,11 @@ pub(super) fn sign(
}
pub(super) fn sign_several(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- pin: *const raw::c_char,
- msgs_len: usize,
- msgs: *const *const raw::c_char,
+ currency: &str,
+ dewif: &str,
+ pin: &str,
+ msgs: &[&str],
) -> Result, DubpError> {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let pin = char_ptr_to_str(pin)?;
-
- let msgs_slice: &[*const raw::c_char] = unsafe { std::slice::from_raw_parts(msgs, msgs_len) };
- let mut msgs = Vec::with_capacity(msgs_len);
- for ptr_c_char in msgs_slice {
- msgs.push(char_ptr_to_str(*ptr_c_char)?);
- }
-
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
diff --git a/native/dubp_rs/src/error.rs b/native/dubp_rs/src/error.rs
new file mode 100644
index 0000000..63bd5ec
--- /dev/null
+++ b/native/dubp_rs/src/error.rs
@@ -0,0 +1,77 @@
+// Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::*;
+
+/// Dubp error
+#[derive(Debug, Error)]
+pub(crate) enum DubpError {
+ #[error("{0}")]
+ DewifReadError(DewifReadError),
+ #[error("I/O error: {0}")]
+ IoErr(io::Error),
+ #[error("A given parameter is null")]
+ NullParamErr,
+ #[error("fail to generate random bytes")]
+ RandErr,
+ #[error("Unknown currency name")]
+ UnknownCurrencyName,
+ #[error("Unknown language")]
+ UnknownLanguage,
+ #[error("{0}")]
+ Utf8Error(std::str::Utf8Error),
+ #[error("Wrong language")]
+ WrongLanguage,
+}
+
+impl From for DubpError {
+ fn from(e: io::Error) -> Self {
+ Self::IoErr(e)
+ }
+}
+
+pub(crate) struct DartRes(allo_isolate::ffi::DartCObject);
+impl DartRes {
+ pub(crate) fn err(e: E) -> allo_isolate::ffi::DartCObject {
+ vec![format!("DUBP_RS_ERROR: {}", e.to_string())].into_dart()
+ }
+}
+impl IntoDart for DartRes {
+ fn into_dart(self) -> allo_isolate::ffi::DartCObject {
+ self.0.into_dart()
+ }
+}
+impl From> for DartRes
+where
+ E: ToString,
+{
+ fn from(res: Result) -> Self {
+ match res {
+ Ok(string) => Self(string.into_dart()),
+ Err(e) => Self(format!("DUBP_RS_ERROR: {}", e.to_string()).into_dart()),
+ }
+ }
+}
+impl From, E>> for DartRes
+where
+ E: ToString,
+{
+ fn from(res: Result, E>) -> Self {
+ match res {
+ Ok(vec_string) => Self(vec_string.into_dart()),
+ Err(e) => Self(vec![format!("DUBP_RS_ERROR: {}", e.to_string())].into_dart()),
+ }
+ }
+}
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 8d2f03a..2f29e58 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -15,9 +15,13 @@
#![allow(clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref)]
+mod r#async;
mod dewif;
+mod error;
mod mnemonic;
+use crate::error::{DartRes, DubpError};
+use crate::r#async::exec_async;
use allo_isolate::{IntoDart, Isolate};
use dup_crypto::{
bases::b58::ToBase58,
@@ -28,65 +32,11 @@ use dup_crypto::{
},
mnemonic::{Language, Mnemonic, MnemonicType},
};
+use fast_threadpool::{ThreadPool, ThreadPoolConfig, ThreadPoolSyncHandler};
+use once_cell::sync::Lazy;
use std::{ffi::CStr, io, os::raw};
use thiserror::Error;
-/// Dubp error
-#[derive(Debug, Error)]
-pub enum DubpError {
- #[error("{0}")]
- DewifReadError(DewifReadError),
- #[error("I/O error: {0}")]
- IoErr(io::Error),
- #[error("A given parameter is null")]
- NullParamErr,
- #[error("fail to generate random bytes")]
- RandErr,
- #[error("Unknown currency name")]
- UnknownCurrencyName,
- #[error("Unknown language")]
- UnknownLanguage,
- #[error("{0}")]
- Utf8Error(std::str::Utf8Error),
- #[error("Wrong language")]
- WrongLanguage,
-}
-
-impl From for DubpError {
- fn from(e: io::Error) -> Self {
- Self::IoErr(e)
- }
-}
-
-struct DartRes(allo_isolate::ffi::DartCObject);
-impl IntoDart for DartRes {
- fn into_dart(self) -> allo_isolate::ffi::DartCObject {
- self.0.into_dart()
- }
-}
-impl From> for DartRes
-where
- E: ToString,
-{
- fn from(res: Result) -> Self {
- match res {
- Ok(string) => Self(vec![string].into_dart()),
- Err(e) => Self(vec![String::from("_"), e.to_string()].into_dart()),
- }
- }
-}
-impl From, E>> for DartRes
-where
- E: ToString,
-{
- fn from(res: Result, E>) -> Self {
- match res {
- Ok(vec_string) => Self(vec_string.into_dart()),
- Err(e) => Self(vec![String::with_capacity(0), e.to_string()].into_dart()),
- }
- }
-}
-
pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
if c_char_ptr.is_null() {
Err(DubpError::NullParamErr)
@@ -95,6 +45,28 @@ pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a
}
}
+fn char_ptr_prt_to_vec_str<'a>(
+ char_ptr_ptr: *const *const raw::c_char,
+ len: u32,
+) -> Result, DubpError> {
+ let len = len as usize;
+ let char_ptr_slice: &[*const raw::c_char] =
+ unsafe { std::slice::from_raw_parts(char_ptr_ptr, len) };
+ let mut str_vec = Vec::with_capacity(len);
+ for char_ptr in char_ptr_slice {
+ str_vec.push(char_ptr_to_str(*char_ptr)?);
+ }
+ Ok(str_vec)
+}
+
+fn u32_to_language(i: u32) -> Result {
+ match i {
+ 0 => Ok(Language::English),
+ 1 => Ok(Language::French),
+ _ => Err(DubpError::UnknownLanguage),
+ }
+}
+
#[no_mangle]
pub extern "C" fn change_dewif_pin(
port: i64,
@@ -103,9 +75,17 @@ pub extern "C" fn change_dewif_pin(
old_pin: *const raw::c_char,
new_pin: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(dewif::change_pin(
- currency, dewif, old_pin, new_pin,
- )));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let old_pin = char_ptr_to_str(old_pin)?;
+ let new_pin = char_ptr_to_str(new_pin)?;
+ Ok((currency, dewif, old_pin, new_pin))
+ },
+ |(currency, dewif, old_pin, new_pin)| dewif::change_pin(currency, dewif, old_pin, new_pin),
+ )
}
#[no_mangle]
@@ -116,9 +96,16 @@ pub extern "C" fn gen_dewif(
mnemonic: *const raw::c_char,
pin: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(dewif::gen_dewif(
- currency, language, mnemonic, pin,
- )));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let mnemonic = char_ptr_to_str(mnemonic)?;
+ let pin = char_ptr_to_str(pin)?;
+ Ok((currency, language, mnemonic, pin))
+ },
+ |(currency, language, mnemonic, pin)| dewif::gen_dewif(currency, language, mnemonic, pin),
+ )
}
#[no_mangle]
@@ -148,7 +135,16 @@ pub extern "C" fn get_dewif_pubkey(
dewif: *const raw::c_char,
pin: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(dewif::get_pubkey(currency, dewif, pin)));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let pin = char_ptr_to_str(pin)?;
+ Ok((currency, dewif, pin))
+ },
+ |(currency, dewif, pin)| dewif::get_pubkey(currency, dewif, pin),
+ )
}
#[no_mangle]
@@ -157,10 +153,14 @@ pub extern "C" fn mnemonic_to_pubkey(
language: u32,
mnemonic_phrase: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(mnemonic::mnemonic_to_pubkey(
- language,
- mnemonic_phrase,
- )));
+ exec_async(
+ port,
+ || {
+ let mnemonic_phrase = char_ptr_to_str(mnemonic_phrase)?;
+ Ok((language, mnemonic_phrase))
+ },
+ |(language, mnemonic_phrase)| mnemonic::mnemonic_to_pubkey(language, mnemonic_phrase),
+ )
}
#[no_mangle]
@@ -171,7 +171,17 @@ pub extern "C" fn sign(
pin: *const raw::c_char,
msg: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(dewif::sign(currency, dewif, pin, msg)));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let pin = char_ptr_to_str(pin)?;
+ let msg = char_ptr_to_str(msg)?;
+ Ok((currency, dewif, pin, msg))
+ },
+ |(currency, dewif, pin, msg)| dewif::sign(currency, dewif, pin, msg),
+ )
}
#[no_mangle]
@@ -180,16 +190,18 @@ pub extern "C" fn sign_several(
currency: *const raw::c_char,
dewif: *const raw::c_char,
pin: *const raw::c_char,
- msgs_len: usize,
+ msgs_len: u32,
msgs: *const *const raw::c_char,
) {
- Isolate::new(port).post(dewif::sign_several(currency, dewif, pin, msgs_len, msgs));
-}
-
-fn u32_to_language(i: u32) -> Result {
- match i {
- 0 => Ok(Language::English),
- 1 => Ok(Language::French),
- _ => Err(DubpError::UnknownLanguage),
- }
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let pin = char_ptr_to_str(pin)?;
+ let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
+ Ok((currency, dewif, pin, msgs))
+ },
+ |(currency, dewif, pin, msgs)| dewif::sign_several(currency, dewif, pin, &msgs),
+ )
}
diff --git a/native/dubp_rs/src/mnemonic.rs b/native/dubp_rs/src/mnemonic.rs
index ac17486..765427d 100644
--- a/native/dubp_rs/src/mnemonic.rs
+++ b/native/dubp_rs/src/mnemonic.rs
@@ -21,12 +21,7 @@ pub(super) fn gen_mnemonic(language: u32) -> Result {
Ok(mnemonic.phrase().to_owned())
}
-pub(super) fn mnemonic_to_pubkey(
- language: u32,
- mnemonic: *const raw::c_char,
-) -> Result {
- let mnemonic = char_ptr_to_str(mnemonic)?;
-
+pub(super) fn mnemonic_to_pubkey(language: u32, mnemonic: &str) -> Result {
let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
.map_err(|_| DubpError::WrongLanguage)?;
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index a3384e8..35b4e8a 100644
--- a/packages/dubp_rs/lib/dubp.dart
+++ b/packages/dubp_rs/lib/dubp.dart
@@ -55,7 +55,7 @@ class DubpRust {
static Future genMnemonic({Language language = Language.english}) {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.gen_mnemonic(
sendPort.nativePort,
language.index,
@@ -66,7 +66,7 @@ class DubpRust {
static Future _genPin(PinLength pinLength) {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
switch (pinLength) {
case PinLength.ten:
native.gen_pin10(
@@ -101,7 +101,7 @@ class DubpRust {
{
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.change_dewif_pin(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -116,7 +116,7 @@ class DubpRust {
{
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.get_dewif_pubkey(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -148,7 +148,7 @@ class DubpRust {
{
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.mnemonic_to_pubkey(
sendPort.nativePort,
language.index,
@@ -161,7 +161,7 @@ class DubpRust {
{
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.gen_dewif(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -179,7 +179,7 @@ class DubpRust {
{String currency = "g1", String dewif, String pin}) async {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.get_dewif_pubkey(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -196,7 +196,7 @@ class DubpRust {
{String currency = "g1", String dewif, String pin, String message}) {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.sign(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -243,21 +243,20 @@ class DubpRust {
return ptr;
}
- static String _handleErr(List res) {
- final List arr = res.cast();
- if (arr.length == 1) {
- return arr[0];
- } else {
- final error = arr[1];
+ static String _handleErr(String res) {
+ if (res.startsWith('DUBP_RS_ERROR: ')) {
+ final error = res;
print(error);
throw error;
+ } else {
+ return res;
}
}
static List _handleErrList(List res) {
final List arr = res.cast();
- if (arr.isNotEmpty && arr[0].isEmpty) {
- final error = arr[1];
+ if (arr.isNotEmpty && arr[0].startsWith('DUBP_RS_ERROR: ')) {
+ final error = arr[0];
print(error);
throw error;
} else {
diff --git a/pubspec.lock b/pubspec.lock
index 376b9d0..8446555 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -21,42 +21,42 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.5.0-nullsafety.3"
+ version: "2.5.0-nullsafety.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.3"
+ version: "2.1.0-nullsafety.1"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.5"
+ version: "1.1.0-nullsafety.3"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0-nullsafety.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.3"
+ version: "1.1.0-nullsafety.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "1.15.0-nullsafety.5"
+ version: "1.15.0-nullsafety.3"
connectivity:
dependency: transitive
description:
@@ -112,7 +112,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0-nullsafety.1"
ffi:
dependency: transitive
description:
@@ -282,27 +282,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
- js:
- dependency: transitive
- description:
- name: js
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.6.3-nullsafety.3"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.10-nullsafety.3"
+ version: "0.12.10-nullsafety.1"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0-nullsafety.6"
+ version: "1.3.0-nullsafety.3"
nested:
dependency: transitive
description:
@@ -330,7 +323,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0-nullsafety.3"
+ version: "1.8.0-nullsafety.1"
path_provider:
dependency: "direct main"
description:
@@ -468,42 +461,42 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0-nullsafety.4"
+ version: "1.8.0-nullsafety.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.10.0-nullsafety.6"
+ version: "1.10.0-nullsafety.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.3"
+ version: "2.1.0-nullsafety.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.3"
+ version: "1.1.0-nullsafety.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0-nullsafety.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.19-nullsafety.6"
+ version: "0.2.19-nullsafety.2"
truncate:
dependency: "direct main"
description:
@@ -517,7 +510,7 @@ packages:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0-nullsafety.5"
+ version: "1.3.0-nullsafety.3"
uuid:
dependency: transitive
description:
@@ -538,7 +531,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.5"
+ version: "2.1.0-nullsafety.3"
websocket:
dependency: transitive
description:
@@ -575,5 +568,5 @@ packages:
source: hosted
version: "2.2.1"
sdks:
- dart: ">=2.12.0-0.0 <3.0.0"
+ dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.22.0 <2.0.0"