mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-12 09:27:01 +00:00
feat: add nano
This commit is contained in:
parent
524f4c5514
commit
8f89f19b91
17 changed files with 1012 additions and 71 deletions
|
@ -2008,6 +2008,7 @@ class ThemeAssets {
|
|||
late final String wownero;
|
||||
late final String namecoin;
|
||||
late final String particl;
|
||||
late final String nano;
|
||||
late final String bitcoinImage;
|
||||
late final String bitcoincashImage;
|
||||
late final String dogecoinImage;
|
||||
|
@ -2019,6 +2020,7 @@ class ThemeAssets {
|
|||
late final String wowneroImage;
|
||||
late final String namecoinImage;
|
||||
late final String particlImage;
|
||||
late final String nanoImage;
|
||||
late final String bitcoinImageSecondary;
|
||||
late final String bitcoincashImageSecondary;
|
||||
late final String dogecoinImageSecondary;
|
||||
|
@ -2030,6 +2032,7 @@ class ThemeAssets {
|
|||
late final String wowneroImageSecondary;
|
||||
late final String namecoinImageSecondary;
|
||||
late final String particlImageSecondary;
|
||||
late final String nanoImageSecondary;
|
||||
late final String? loadingGif;
|
||||
late final String? background;
|
||||
|
||||
|
@ -2101,6 +2104,8 @@ class ThemeAssets {
|
|||
"$applicationThemesDirectoryPath/$themeId/assets/${json["namecoin"] as String}"
|
||||
..particl =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["particl"] as String}"
|
||||
..nano =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin"] as String}" // TODO: Change this to nano
|
||||
..bitcoinImage =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image"] as String}"
|
||||
..bitcoincashImage =
|
||||
|
@ -2123,6 +2128,8 @@ class ThemeAssets {
|
|||
"$applicationThemesDirectoryPath/$themeId/assets/${json["namecoin_image"] as String}"
|
||||
..particlImage =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["particl_image"] as String}"
|
||||
..nanoImage =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image"] as String}" // TODO: Change this to nano
|
||||
..bitcoinImageSecondary =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image_secondary"] as String}"
|
||||
..bitcoincashImageSecondary =
|
||||
|
@ -2145,6 +2152,8 @@ class ThemeAssets {
|
|||
"$applicationThemesDirectoryPath/$themeId/assets/${json["namecoin_image_secondary"] as String}"
|
||||
..particlImageSecondary =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["particl_image_secondary"] as String}"
|
||||
..nanoImageSecondary =
|
||||
"$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image_secondary"] as String}" // TODO: Change this to nano
|
||||
..loadingGif = json["loading_gif"] is String
|
||||
? "$applicationThemesDirectoryPath/$themeId/assets/${json["loading_gif"] as String}"
|
||||
: null
|
||||
|
|
|
@ -17807,108 +17807,123 @@ const ThemeAssetsSchema = Schema(
|
|||
name: r'namecoinImageSecondary',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'particl': PropertySchema(
|
||||
r'nano': PropertySchema(
|
||||
id: 32,
|
||||
name: r'nano',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'nanoImage': PropertySchema(
|
||||
id: 33,
|
||||
name: r'nanoImage',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'nanoImageSecondary': PropertySchema(
|
||||
id: 34,
|
||||
name: r'nanoImageSecondary',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'particl': PropertySchema(
|
||||
id: 35,
|
||||
name: r'particl',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'particlImage': PropertySchema(
|
||||
id: 33,
|
||||
id: 36,
|
||||
name: r'particlImage',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'particlImageSecondary': PropertySchema(
|
||||
id: 34,
|
||||
id: 37,
|
||||
name: r'particlImageSecondary',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'personaEasy': PropertySchema(
|
||||
id: 35,
|
||||
id: 38,
|
||||
name: r'personaEasy',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'personaIncognito': PropertySchema(
|
||||
id: 36,
|
||||
id: 39,
|
||||
name: r'personaIncognito',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'receive': PropertySchema(
|
||||
id: 37,
|
||||
id: 40,
|
||||
name: r'receive',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'receiveCancelled': PropertySchema(
|
||||
id: 38,
|
||||
id: 41,
|
||||
name: r'receiveCancelled',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'receivePending': PropertySchema(
|
||||
id: 39,
|
||||
id: 42,
|
||||
name: r'receivePending',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'send': PropertySchema(
|
||||
id: 40,
|
||||
id: 43,
|
||||
name: r'send',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'sendCancelled': PropertySchema(
|
||||
id: 41,
|
||||
id: 44,
|
||||
name: r'sendCancelled',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'sendPending': PropertySchema(
|
||||
id: 42,
|
||||
id: 45,
|
||||
name: r'sendPending',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'stack': PropertySchema(
|
||||
id: 43,
|
||||
id: 46,
|
||||
name: r'stack',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'stackIcon': PropertySchema(
|
||||
id: 44,
|
||||
id: 47,
|
||||
name: r'stackIcon',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'themePreview': PropertySchema(
|
||||
id: 45,
|
||||
id: 48,
|
||||
name: r'themePreview',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'themeSelector': PropertySchema(
|
||||
id: 46,
|
||||
id: 49,
|
||||
name: r'themeSelector',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'txExchange': PropertySchema(
|
||||
id: 47,
|
||||
id: 50,
|
||||
name: r'txExchange',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'txExchangeFailed': PropertySchema(
|
||||
id: 48,
|
||||
id: 51,
|
||||
name: r'txExchangeFailed',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'txExchangePending': PropertySchema(
|
||||
id: 49,
|
||||
id: 52,
|
||||
name: r'txExchangePending',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'wownero': PropertySchema(
|
||||
id: 50,
|
||||
id: 53,
|
||||
name: r'wownero',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'wowneroImage': PropertySchema(
|
||||
id: 51,
|
||||
id: 54,
|
||||
name: r'wowneroImage',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'wowneroImageSecondary': PropertySchema(
|
||||
id: 52,
|
||||
id: 55,
|
||||
name: r'wowneroImageSecondary',
|
||||
type: IsarType.string,
|
||||
)
|
||||
|
@ -17967,6 +17982,9 @@ int _themeAssetsEstimateSize(
|
|||
bytesCount += 3 + object.namecoin.length * 3;
|
||||
bytesCount += 3 + object.namecoinImage.length * 3;
|
||||
bytesCount += 3 + object.namecoinImageSecondary.length * 3;
|
||||
bytesCount += 3 + object.nano.length * 3;
|
||||
bytesCount += 3 + object.nanoImage.length * 3;
|
||||
bytesCount += 3 + object.nanoImageSecondary.length * 3;
|
||||
bytesCount += 3 + object.particl.length * 3;
|
||||
bytesCount += 3 + object.particlImage.length * 3;
|
||||
bytesCount += 3 + object.particlImageSecondary.length * 3;
|
||||
|
@ -18029,27 +18047,30 @@ void _themeAssetsSerialize(
|
|||
writer.writeString(offsets[29], object.namecoin);
|
||||
writer.writeString(offsets[30], object.namecoinImage);
|
||||
writer.writeString(offsets[31], object.namecoinImageSecondary);
|
||||
writer.writeString(offsets[32], object.particl);
|
||||
writer.writeString(offsets[33], object.particlImage);
|
||||
writer.writeString(offsets[34], object.particlImageSecondary);
|
||||
writer.writeString(offsets[35], object.personaEasy);
|
||||
writer.writeString(offsets[36], object.personaIncognito);
|
||||
writer.writeString(offsets[37], object.receive);
|
||||
writer.writeString(offsets[38], object.receiveCancelled);
|
||||
writer.writeString(offsets[39], object.receivePending);
|
||||
writer.writeString(offsets[40], object.send);
|
||||
writer.writeString(offsets[41], object.sendCancelled);
|
||||
writer.writeString(offsets[42], object.sendPending);
|
||||
writer.writeString(offsets[43], object.stack);
|
||||
writer.writeString(offsets[44], object.stackIcon);
|
||||
writer.writeString(offsets[45], object.themePreview);
|
||||
writer.writeString(offsets[46], object.themeSelector);
|
||||
writer.writeString(offsets[47], object.txExchange);
|
||||
writer.writeString(offsets[48], object.txExchangeFailed);
|
||||
writer.writeString(offsets[49], object.txExchangePending);
|
||||
writer.writeString(offsets[50], object.wownero);
|
||||
writer.writeString(offsets[51], object.wowneroImage);
|
||||
writer.writeString(offsets[52], object.wowneroImageSecondary);
|
||||
writer.writeString(offsets[32], object.nano);
|
||||
writer.writeString(offsets[33], object.nanoImage);
|
||||
writer.writeString(offsets[34], object.nanoImageSecondary);
|
||||
writer.writeString(offsets[35], object.particl);
|
||||
writer.writeString(offsets[36], object.particlImage);
|
||||
writer.writeString(offsets[37], object.particlImageSecondary);
|
||||
writer.writeString(offsets[38], object.personaEasy);
|
||||
writer.writeString(offsets[39], object.personaIncognito);
|
||||
writer.writeString(offsets[40], object.receive);
|
||||
writer.writeString(offsets[41], object.receiveCancelled);
|
||||
writer.writeString(offsets[42], object.receivePending);
|
||||
writer.writeString(offsets[43], object.send);
|
||||
writer.writeString(offsets[44], object.sendCancelled);
|
||||
writer.writeString(offsets[45], object.sendPending);
|
||||
writer.writeString(offsets[46], object.stack);
|
||||
writer.writeString(offsets[47], object.stackIcon);
|
||||
writer.writeString(offsets[48], object.themePreview);
|
||||
writer.writeString(offsets[49], object.themeSelector);
|
||||
writer.writeString(offsets[50], object.txExchange);
|
||||
writer.writeString(offsets[51], object.txExchangeFailed);
|
||||
writer.writeString(offsets[52], object.txExchangePending);
|
||||
writer.writeString(offsets[53], object.wownero);
|
||||
writer.writeString(offsets[54], object.wowneroImage);
|
||||
writer.writeString(offsets[55], object.wowneroImageSecondary);
|
||||
}
|
||||
|
||||
ThemeAssets _themeAssetsDeserialize(
|
||||
|
@ -18091,27 +18112,30 @@ ThemeAssets _themeAssetsDeserialize(
|
|||
object.namecoin = reader.readString(offsets[29]);
|
||||
object.namecoinImage = reader.readString(offsets[30]);
|
||||
object.namecoinImageSecondary = reader.readString(offsets[31]);
|
||||
object.particl = reader.readString(offsets[32]);
|
||||
object.particlImage = reader.readString(offsets[33]);
|
||||
object.particlImageSecondary = reader.readString(offsets[34]);
|
||||
object.personaEasy = reader.readString(offsets[35]);
|
||||
object.personaIncognito = reader.readString(offsets[36]);
|
||||
object.receive = reader.readString(offsets[37]);
|
||||
object.receiveCancelled = reader.readString(offsets[38]);
|
||||
object.receivePending = reader.readString(offsets[39]);
|
||||
object.send = reader.readString(offsets[40]);
|
||||
object.sendCancelled = reader.readString(offsets[41]);
|
||||
object.sendPending = reader.readString(offsets[42]);
|
||||
object.stack = reader.readString(offsets[43]);
|
||||
object.stackIcon = reader.readString(offsets[44]);
|
||||
object.themePreview = reader.readString(offsets[45]);
|
||||
object.themeSelector = reader.readString(offsets[46]);
|
||||
object.txExchange = reader.readString(offsets[47]);
|
||||
object.txExchangeFailed = reader.readString(offsets[48]);
|
||||
object.txExchangePending = reader.readString(offsets[49]);
|
||||
object.wownero = reader.readString(offsets[50]);
|
||||
object.wowneroImage = reader.readString(offsets[51]);
|
||||
object.wowneroImageSecondary = reader.readString(offsets[52]);
|
||||
object.nano = reader.readString(offsets[32]);
|
||||
object.nanoImage = reader.readString(offsets[33]);
|
||||
object.nanoImageSecondary = reader.readString(offsets[34]);
|
||||
object.particl = reader.readString(offsets[35]);
|
||||
object.particlImage = reader.readString(offsets[36]);
|
||||
object.particlImageSecondary = reader.readString(offsets[37]);
|
||||
object.personaEasy = reader.readString(offsets[38]);
|
||||
object.personaIncognito = reader.readString(offsets[39]);
|
||||
object.receive = reader.readString(offsets[40]);
|
||||
object.receiveCancelled = reader.readString(offsets[41]);
|
||||
object.receivePending = reader.readString(offsets[42]);
|
||||
object.send = reader.readString(offsets[43]);
|
||||
object.sendCancelled = reader.readString(offsets[44]);
|
||||
object.sendPending = reader.readString(offsets[45]);
|
||||
object.stack = reader.readString(offsets[46]);
|
||||
object.stackIcon = reader.readString(offsets[47]);
|
||||
object.themePreview = reader.readString(offsets[48]);
|
||||
object.themeSelector = reader.readString(offsets[49]);
|
||||
object.txExchange = reader.readString(offsets[50]);
|
||||
object.txExchangeFailed = reader.readString(offsets[51]);
|
||||
object.txExchangePending = reader.readString(offsets[52]);
|
||||
object.wownero = reader.readString(offsets[53]);
|
||||
object.wowneroImage = reader.readString(offsets[54]);
|
||||
object.wowneroImageSecondary = reader.readString(offsets[55]);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -18228,6 +18252,12 @@ P _themeAssetsDeserializeProp<P>(
|
|||
return (reader.readString(offset)) as P;
|
||||
case 52:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 53:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 54:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 55:
|
||||
return (reader.readString(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
}
|
||||
|
@ -22614,6 +22644,409 @@ extension ThemeAssetsQueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'nano',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'nano',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'nano',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'nano',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'nano',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'nano',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoContains(
|
||||
String value,
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'nano',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoMatches(
|
||||
String pattern,
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'nano',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> nanoIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'nano',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'nano',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'nanoImage',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'nanoImage',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'nanoImage',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'nanoImage',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'nanoImage',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'nanoImage',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'nanoImage',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'nanoImage',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'nanoImage',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'nanoImage',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'nanoImageSecondary',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'nanoImageSecondary',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'nanoImageSecondary',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'nanoImageSecondary',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'nanoImageSecondary',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'nanoImageSecondary',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'nanoImageSecondary',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'nanoImageSecondary',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'nanoImageSecondary',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition>
|
||||
nanoImageSecondaryIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'nanoImageSecondary',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ThemeAssets, ThemeAssets, QAfterFilterCondition> particlEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
|
|
|
@ -717,6 +717,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
|
|||
case Coin.firoTestNet:
|
||||
case Coin.dogecoinTestNet:
|
||||
case Coin.epicCash:
|
||||
case Coin.nano:
|
||||
return false;
|
||||
|
||||
case Coin.ethereum:
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
|||
import 'package:stackwallet/services/coins/litecoin/litecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/nano/nano_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/particl/particl_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
|
@ -223,6 +224,15 @@ abstract class CoinServiceAPI {
|
|||
client: client,
|
||||
);
|
||||
|
||||
case Coin.nano:
|
||||
return NanoWallet(
|
||||
walletId: walletId,
|
||||
walletName: walletName,
|
||||
coin: coin,
|
||||
tracker: tracker,
|
||||
secureStore: secureStorageInterface
|
||||
);
|
||||
|
||||
case Coin.dogecoinTestNet:
|
||||
return DogecoinWallet(
|
||||
walletId: walletId,
|
||||
|
|
416
lib/services/coins/nano/nano_wallet.dart
Normal file
416
lib/services/coins/nano/nano_wallet.dart
Normal file
|
@ -0,0 +1,416 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:nanodart/nanodart.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'package:stackwallet/models/balance.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
|
||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
import 'package:stackwallet/services/coins/coin_service.dart';
|
||||
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
|
||||
import 'package:stackwallet/services/mixins/wallet_cache.dart';
|
||||
import 'package:stackwallet/services/mixins/wallet_db.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
import '../../../db/isar/main_db.dart';
|
||||
import '../../../models/isar/models/blockchain_data/address.dart';
|
||||
import '../../../models/node_model.dart';
|
||||
import '../../../utilities/default_nodes.dart';
|
||||
import '../../../utilities/flutter_secure_storage_interface.dart';
|
||||
import '../../../utilities/prefs.dart';
|
||||
import '../../node_service.dart';
|
||||
import '../../transaction_notification_tracker.dart';
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
|
||||
const int MINIMUM_CONFIRMATIONS = 1;
|
||||
|
||||
class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB, CoinControlInterface {
|
||||
NanoWallet({
|
||||
required String walletId,
|
||||
required String walletName,
|
||||
required Coin coin,
|
||||
required TransactionNotificationTracker tracker,
|
||||
required SecureStorageInterface secureStore,
|
||||
MainDB? mockableOverride,
|
||||
}) {
|
||||
txTracker = tracker;
|
||||
_walletId = walletId;
|
||||
_walletName = walletName;
|
||||
_coin = coin;
|
||||
_secureStore = secureStore;
|
||||
initCache(walletId, coin);
|
||||
initWalletDB(mockableOverride: mockableOverride);
|
||||
}
|
||||
|
||||
NodeModel? _xnoNode;
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
Future<String> getSeedFromMnemonic() async {
|
||||
var mnemonic = await mnemonicString;
|
||||
return NanoMnemomics.mnemonicListToSeed(mnemonic!.split(" "));
|
||||
}
|
||||
|
||||
Future<String> getPrivateKeyFromMnemonic() async {
|
||||
var mnemonic = await mnemonicString;
|
||||
var seed = NanoMnemomics.mnemonicListToSeed(mnemonic!.split(" "));
|
||||
return NanoKeys.seedToPrivate(seed, 0);
|
||||
}
|
||||
|
||||
Future<String> getAddressFromMnemonic() async {
|
||||
var mnemonic = await mnemonicString;
|
||||
var seed = NanoMnemomics.mnemonicListToSeed(mnemonic!.split(' '));
|
||||
var address = NanoAccounts.createAccount(NanoAccountType.NANO, NanoKeys.createPublicKey(NanoKeys.seedToPrivate(seed, 0)));
|
||||
return address;
|
||||
}
|
||||
|
||||
Future<String> getPublicKeyFromMnemonic() async {
|
||||
var mnemonic = await mnemonicString;
|
||||
if (mnemonic == null) {
|
||||
return "";
|
||||
} else {
|
||||
var seed = NanoMnemomics.mnemonicListToSeed(mnemonic.split(" "));
|
||||
return NanoKeys.createPublicKey(NanoKeys.seedToPrivate(seed, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String get walletId => _walletId;
|
||||
late String _walletId;
|
||||
|
||||
@override
|
||||
String get walletName => _walletName;
|
||||
late String _walletName;
|
||||
|
||||
@override
|
||||
set walletName(String name) => _walletName = name;
|
||||
|
||||
@override
|
||||
set isFavorite(bool markFavorite) {
|
||||
_isFavorite = markFavorite;
|
||||
updateCachedIsFavorite(markFavorite);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isFavorite => _isFavorite ??= getCachedIsFavorite();
|
||||
bool? _isFavorite;
|
||||
|
||||
@override
|
||||
Coin get coin => _coin;
|
||||
late Coin _coin;
|
||||
|
||||
late SecureStorageInterface _secureStore;
|
||||
late final TransactionNotificationTracker txTracker;
|
||||
final _prefs = Prefs.instance;
|
||||
|
||||
bool _shouldAutoSync = false;
|
||||
|
||||
@override
|
||||
bool get shouldAutoSync => _shouldAutoSync;
|
||||
|
||||
@override
|
||||
set shouldAutoSync(bool shouldAutoSync) => _shouldAutoSync = shouldAutoSync;
|
||||
|
||||
@override
|
||||
Balance get balance => _balance ??= getCachedBalance();
|
||||
Balance? _balance;
|
||||
|
||||
@override
|
||||
Future<String> confirmSend({required Map<String, dynamic> txData}) {
|
||||
// TODO: implement confirmSend
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> get currentReceivingAddress => getAddressFromMnemonic();
|
||||
|
||||
@override
|
||||
Future<Amount> estimateFeeFor(Amount amount, int feeRate) {
|
||||
// TODO: implement estimateFeeFor
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> exit() async {
|
||||
_hasCalledExit = true;
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement fees
|
||||
Future<FeeObject> get fees => throw UnimplementedError();
|
||||
|
||||
Future<void> updateBalance() async {
|
||||
final body = jsonEncode({
|
||||
"action": "account_balance",
|
||||
"account": await getAddressFromMnemonic(),
|
||||
});
|
||||
final headers = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
final response = await http.post(Uri.parse(getCurrentNode().host), headers: headers, body: body);
|
||||
final data = jsonDecode(response.body);
|
||||
_balance = Balance(
|
||||
total: Amount(rawValue: (BigInt.parse(data["balance"].toString()) + BigInt.parse(data["receivable"].toString())) ~/ BigInt.from(10).pow(23), fractionDigits: 7),
|
||||
spendable: Amount(rawValue: BigInt.parse(data["balance"].toString()) ~/ BigInt.from(10).pow(23), fractionDigits: 7),
|
||||
blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: 30),
|
||||
pendingSpendable: Amount(rawValue: BigInt.parse(data["receivable"].toString()) ~/ BigInt.from(10).pow(23), fractionDigits: 7),
|
||||
);
|
||||
await updateCachedBalance(_balance!);
|
||||
}
|
||||
|
||||
Future<void> confirmAllReceivable() async {
|
||||
// TODO: Implement this function
|
||||
}
|
||||
|
||||
Future<void> updateTransactions() async {
|
||||
await confirmAllReceivable();
|
||||
final response = await http.post(Uri.parse(getCurrentNode().host), headers: {"Content-Type": "application/json"}, body: jsonEncode({"action": "account_history", "account": await getAddressFromMnemonic(), "count": "-1"}));
|
||||
final data = await jsonDecode(response.body);
|
||||
final transactions = data["history"] as List<dynamic>;
|
||||
if (transactions.isEmpty) {
|
||||
return;
|
||||
} else {
|
||||
List<Transaction> transactionList = [];
|
||||
for (var tx in transactions) {
|
||||
var typeString = tx["type"].toString();
|
||||
TransactionType type = TransactionType.unknown;
|
||||
if (typeString == "send") {
|
||||
type = TransactionType.outgoing;
|
||||
} else if (typeString == "receive") {
|
||||
type = TransactionType.incoming;
|
||||
}
|
||||
var intAmount = int.parse((BigInt.parse(tx["amount"].toString()) ~/ BigInt.from(10).pow(23)).toString());
|
||||
var strAmount = jsonEncode({
|
||||
"raw": intAmount.toString(),
|
||||
"fractionDigits": 7,
|
||||
});
|
||||
var transaction = Transaction(
|
||||
walletId: walletId,
|
||||
txid: tx["hash"].toString(),
|
||||
timestamp: int.parse(tx["local_timestamp"].toString()),
|
||||
type: type,
|
||||
subType: TransactionSubType.none,
|
||||
amount: intAmount,
|
||||
amountString: strAmount,
|
||||
fee: 0, // TODO: Use real fee?
|
||||
height: int.parse(tx["height"].toString()),
|
||||
isCancelled: false,
|
||||
isLelantus: false,
|
||||
slateId: "",
|
||||
otherData: "",
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
nonce: 0
|
||||
);
|
||||
transactionList.add(transaction);
|
||||
}
|
||||
await db.putTransactions(transactionList);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> fullRescan(int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) async {
|
||||
await _prefs.init();
|
||||
await updateBalance();
|
||||
await updateTransactions();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> generateNewAddress() {
|
||||
// TODO: implement generateNewAddress
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
bool get hasCalledExit => _hasCalledExit;
|
||||
bool _hasCalledExit = false;
|
||||
|
||||
@override
|
||||
Future<void> initializeExisting() async {
|
||||
await _prefs.init();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> initializeNew() async {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
|
||||
await _prefs.init();
|
||||
|
||||
String seed = NanoSeeds.generateSeed();
|
||||
final mnemonic = NanoMnemomics.seedToMnemonic(seed);
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: mnemonic.join(' '),
|
||||
);
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
String privateKey = NanoKeys.seedToPrivate(seed, 0);
|
||||
String publicKey = NanoKeys.createPublicKey(privateKey);
|
||||
String publicAddress = NanoAccounts.createAccount(NanoAccountType.NANO, publicKey);
|
||||
|
||||
final address = Address(
|
||||
walletId: walletId,
|
||||
value: publicAddress,
|
||||
publicKey: [], // TODO: add public key
|
||||
derivationIndex: 0,
|
||||
derivationPath: DerivationPath(),
|
||||
type: AddressType.unknown,
|
||||
subType: AddressSubType.receiving,
|
||||
);
|
||||
|
||||
await db.putAddress(address);
|
||||
|
||||
await Future.wait([
|
||||
updateCachedId(walletId),
|
||||
updateCachedIsFavorite(false)
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isConnected => _isConnected;
|
||||
|
||||
bool _isConnected = false;
|
||||
|
||||
@override
|
||||
bool get isRefreshing => refreshMutex;
|
||||
|
||||
bool refreshMutex = false;
|
||||
|
||||
@override
|
||||
// TODO: implement maxFee
|
||||
Future<int> get maxFee => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> prepareSend({required String address, required Amount amount, Map<String, dynamic>? args}) {
|
||||
// TODO: implement prepareSend
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverFromMnemonic({required String mnemonic, String? mnemonicPassphrase, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) async {
|
||||
try {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
String seed = NanoMnemomics.mnemonicListToSeed(mnemonic.split(" "));
|
||||
String privateKey = NanoKeys.seedToPrivate(seed, 0);
|
||||
String publicKey = NanoKeys.createPublicKey(privateKey);
|
||||
String publicAddress = NanoAccounts.createAccount(NanoAccountType.NANO, publicKey);
|
||||
|
||||
final address = Address(
|
||||
walletId: walletId,
|
||||
value: publicAddress,
|
||||
publicKey: [], // TODO: add public key
|
||||
derivationIndex: 0,
|
||||
derivationPath: DerivationPath()..value = "0/0", // TODO: Check if this is true
|
||||
type: AddressType.unknown,
|
||||
subType: AddressSubType.receiving,
|
||||
);
|
||||
|
||||
await db.putAddress(address);
|
||||
|
||||
await Future.wait([
|
||||
updateCachedId(walletId),
|
||||
updateCachedIsFavorite(false)
|
||||
]);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> refresh() async {
|
||||
await _prefs.init();
|
||||
await updateBalance();
|
||||
await updateTransactions();
|
||||
}
|
||||
|
||||
@override
|
||||
int get storedChainHeight => getCachedChainHeight();
|
||||
|
||||
NodeModel getCurrentNode() {
|
||||
return _xnoNode ??
|
||||
NodeService(secureStorageInterface: _secureStore)
|
||||
.getPrimaryNodeFor(coin: coin) ??
|
||||
DefaultNodes.getNodeFor(coin);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> testNetworkConnection() {
|
||||
http.get(Uri.parse("${getCurrentNode().host}?action=version")).then((response) {
|
||||
if (response.statusCode == 200) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return Future.value(false);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Transaction>> get transactions => db.getTransactions(walletId).findAll();
|
||||
|
||||
@override
|
||||
Future<void> updateNode(bool shouldRefresh) async {
|
||||
_xnoNode = NodeService(secureStorageInterface: _secureStore)
|
||||
.getPrimaryNodeFor(coin: coin) ??
|
||||
DefaultNodes.getNodeFor(coin);
|
||||
|
||||
if (shouldRefresh) {
|
||||
unawaited(refresh());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateSentCachedTxData(Map<String, dynamic> txData) {
|
||||
// TODO: implement updateSentCachedTxData
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement utxos
|
||||
Future<List<UTXO>> get utxos => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
bool validateAddress(String address) {
|
||||
return NanoAccounts.isValid(NanoAccountType.NANO, address);
|
||||
}
|
||||
}
|
|
@ -32,5 +32,7 @@ final coinIconProvider = Provider.family<String, Coin>((ref, coin) {
|
|||
return assets.particl;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereum;
|
||||
case Coin.nano:
|
||||
return assets.nano;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -36,6 +36,8 @@ final coinImageProvider = Provider.family<String, Coin>((ref, coin) {
|
|||
return assets.dogecoinImage;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereumImage;
|
||||
case Coin.nano:
|
||||
return assets.nano;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -43,17 +45,21 @@ final coinImageSecondaryProvider = Provider.family<String, Coin>((ref, coin) {
|
|||
final assets = ref.watch(themeProvider).assets;
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoinImageSecondary;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoinImageSecondary;
|
||||
case Coin.bitcoincash:
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincashImageSecondary;
|
||||
case Coin.dogecoin:
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoinImageSecondary;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCashImageSecondary;
|
||||
case Coin.firo:
|
||||
case Coin.firoTestNet:
|
||||
return assets.firoImageSecondary;
|
||||
case Coin.monero:
|
||||
return assets.moneroImageSecondary;
|
||||
|
@ -63,15 +69,9 @@ final coinImageSecondaryProvider = Provider.family<String, Coin>((ref, coin) {
|
|||
return assets.namecoinImageSecondary;
|
||||
case Coin.particl:
|
||||
return assets.particlImageSecondary;
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoinImageSecondary;
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincashImageSecondary;
|
||||
case Coin.firoTestNet:
|
||||
return assets.firoImageSecondary;
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoinImageSecondary;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereumImageSecondary;
|
||||
case Coin.nano:
|
||||
return assets.nano;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ class CoinThemeColorDefault {
|
|||
Color get namecoin => const Color(0xFF91B1E1);
|
||||
Color get wownero => const Color(0xFFED80C1);
|
||||
Color get particl => const Color(0xFF8175BD);
|
||||
Color get nano => const Color(0xFF209CE9);
|
||||
|
||||
Color forCoin(Coin coin) {
|
||||
switch (coin) {
|
||||
|
@ -47,6 +48,8 @@ class CoinThemeColorDefault {
|
|||
return wownero;
|
||||
case Coin.particl:
|
||||
return particl;
|
||||
case Coin.nano:
|
||||
return nano;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1684,6 +1684,8 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
return _coin.wownero;
|
||||
case Coin.particl:
|
||||
return _coin.particl;
|
||||
case Coin.nano:
|
||||
return _coin.nano;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:convert';
|
|||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter_libepiccash/epic_cash.dart';
|
||||
import 'package:nanodart/nanodart.dart';
|
||||
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
|
@ -71,6 +72,8 @@ class AddressUtils {
|
|||
return Address.validateAddress(address, namecoin, namecoin.bech32!);
|
||||
case Coin.particl:
|
||||
return Address.validateAddress(address, particl);
|
||||
case Coin.nano:
|
||||
return NanoAccounts.isValid(NanoAccountType.NANO, address);
|
||||
case Coin.bitcoinTestNet:
|
||||
return Address.validateAddress(address, testnet);
|
||||
case Coin.litecoinTestNet:
|
||||
|
|
|
@ -41,6 +41,8 @@ Uri getDefaultBlockExplorerUrlFor({
|
|||
return Uri.parse("https://chainz.cryptoid.info/nmc/tx.dws?$txid.htm");
|
||||
case Coin.particl:
|
||||
return Uri.parse("https://chainz.cryptoid.info/part/tx.dws?$txid.htm");
|
||||
case Coin.nano:
|
||||
return Uri.parse("https://www.nanolooker.com/block/$txid");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ abstract class Constants {
|
|||
case Coin.epicCash:
|
||||
case Coin.namecoin:
|
||||
case Coin.particl:
|
||||
case Coin.nano: // TODO: Check this: https://nano.org/en/faq#what-are-the-units-of-nano
|
||||
return _satsPerCoin;
|
||||
|
||||
case Coin.wownero:
|
||||
|
@ -89,6 +90,7 @@ abstract class Constants {
|
|||
case Coin.epicCash:
|
||||
case Coin.namecoin:
|
||||
case Coin.particl:
|
||||
case Coin.nano:
|
||||
return _decimalPlaces;
|
||||
|
||||
case Coin.wownero:
|
||||
|
@ -119,6 +121,7 @@ abstract class Constants {
|
|||
case Coin.ethereum:
|
||||
case Coin.namecoin:
|
||||
case Coin.particl:
|
||||
case Coin.nano:
|
||||
values.addAll([24, 21, 18, 15, 12]);
|
||||
break;
|
||||
|
||||
|
@ -172,6 +175,9 @@ abstract class Constants {
|
|||
|
||||
case Coin.particl:
|
||||
return 600;
|
||||
|
||||
case Coin.nano: // TODO: Verify this
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,18 @@ abstract class DefaultNodes {
|
|||
isFailover: true,
|
||||
isDown: false);
|
||||
|
||||
static NodeModel get nano => NodeModel(
|
||||
host: "https://rainstorm.city/api",
|
||||
port: 443,
|
||||
name: defaultName,
|
||||
id: _nodeId(Coin.nano),
|
||||
useSSL: true,
|
||||
enabled: true,
|
||||
coinName: Coin.nano.name,
|
||||
isFailover: true,
|
||||
isDown: false
|
||||
);
|
||||
|
||||
static NodeModel get bitcoinTestnet => NodeModel(
|
||||
host: "bitcoin-testnet.stackwallet.com",
|
||||
port: 51002,
|
||||
|
@ -254,6 +266,9 @@ abstract class DefaultNodes {
|
|||
case Coin.particl:
|
||||
return particl;
|
||||
|
||||
case Coin.nano:
|
||||
return nano;
|
||||
|
||||
case Coin.bitcoinTestNet:
|
||||
return bitcoinTestnet;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'
|
|||
import 'package:stackwallet/services/coins/particl/particl_wallet.dart'
|
||||
as particl;
|
||||
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow;
|
||||
import 'package:stackwallet/services/coins/nano/nano_wallet.dart' as nano;
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
|
||||
enum Coin {
|
||||
|
@ -30,6 +31,7 @@ enum Coin {
|
|||
namecoin,
|
||||
particl,
|
||||
wownero,
|
||||
nano,
|
||||
|
||||
///
|
||||
|
||||
|
@ -71,6 +73,8 @@ extension CoinExt on Coin {
|
|||
return "Wownero";
|
||||
case Coin.namecoin:
|
||||
return "Namecoin";
|
||||
case Coin.nano:
|
||||
return "Nano";
|
||||
case Coin.bitcoinTestNet:
|
||||
return "tBitcoin";
|
||||
case Coin.litecoinTestNet:
|
||||
|
@ -108,6 +112,8 @@ extension CoinExt on Coin {
|
|||
return "WOW";
|
||||
case Coin.namecoin:
|
||||
return "NMC";
|
||||
case Coin.nano:
|
||||
return "XNO";
|
||||
case Coin.bitcoinTestNet:
|
||||
return "tBTC";
|
||||
case Coin.litecoinTestNet:
|
||||
|
@ -146,6 +152,8 @@ extension CoinExt on Coin {
|
|||
return "wownero";
|
||||
case Coin.namecoin:
|
||||
return "namecoin";
|
||||
case Coin.nano:
|
||||
return "nano";
|
||||
case Coin.bitcoinTestNet:
|
||||
return "bitcoin";
|
||||
case Coin.litecoinTestNet:
|
||||
|
@ -179,6 +187,7 @@ extension CoinExt on Coin {
|
|||
case Coin.ethereum:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
case Coin.nano: // TODO: Check this
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -203,6 +212,7 @@ extension CoinExt on Coin {
|
|||
case Coin.litecoinTestNet:
|
||||
case Coin.bitcoincashTestnet:
|
||||
case Coin.firoTestNet:
|
||||
case Coin.nano:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -220,6 +230,7 @@ extension CoinExt on Coin {
|
|||
case Coin.ethereum:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
case Coin.nano:
|
||||
return false;
|
||||
|
||||
case Coin.dogecoinTestNet:
|
||||
|
@ -244,6 +255,7 @@ extension CoinExt on Coin {
|
|||
case Coin.ethereum:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
case Coin.nano:
|
||||
return this;
|
||||
|
||||
case Coin.dogecoinTestNet:
|
||||
|
@ -302,6 +314,9 @@ extension CoinExt on Coin {
|
|||
|
||||
case Coin.namecoin:
|
||||
return nmc.MINIMUM_CONFIRMATIONS;
|
||||
|
||||
case Coin.nano:
|
||||
return nano.MINIMUM_CONFIRMATIONS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,6 +398,10 @@ Coin coinFromPrettyName(String name) {
|
|||
case "wownero":
|
||||
return Coin.wownero;
|
||||
|
||||
case "Nano":
|
||||
case "nano":
|
||||
return Coin.nano;
|
||||
|
||||
default:
|
||||
throw ArgumentError.value(
|
||||
name,
|
||||
|
@ -426,6 +445,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) {
|
|||
return Coin.dogecoinTestNet;
|
||||
case "wow":
|
||||
return Coin.wownero;
|
||||
case "xno":
|
||||
return Coin.nano;
|
||||
default:
|
||||
throw ArgumentError.value(
|
||||
ticker, "name", "No Coin enum value with that ticker");
|
||||
|
|
|
@ -33,6 +33,7 @@ extension DerivePathTypeExt on DerivePathType {
|
|||
case Coin.epicCash:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
case Coin.nano:
|
||||
throw UnsupportedError(
|
||||
"$coin does not use bitcoin style derivation paths");
|
||||
}
|
||||
|
|
16
pubspec.lock
16
pubspec.lock
|
@ -578,6 +578,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
fixnum_nanodart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum_nanodart
|
||||
sha256: "4b0132d11ecddc0d2ca64b6d7dee6726db432ed02cac1349d7532a08be5c54fc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
flare_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1093,6 +1101,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
nanodart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: nanodart
|
||||
sha256: "4b2f42d60307b54e8cf384d6193a567d07f8efd773858c0d5948246153c13282"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
nm:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -153,6 +153,7 @@ dependencies:
|
|||
rational: ^2.2.2
|
||||
archive: ^3.3.2
|
||||
desktop_drop: ^0.4.1
|
||||
nanodart: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in a new issue