Browse Source

Wallet: wallet generate rpc

pull/18/head
Sun 4 years ago
parent
commit
0411c56a21
  1. 54
      lib/apps/wallet/models.dart
  2. 71
      lib/apps/wallet/page.dart
  3. 0
      lib/apps/wallet/provider.dart
  4. 5
      lib/widgets/default_core_show.dart
  5. 42
      src/apps/wallet/models.rs
  6. 8
      src/apps/wallet/rpc.rs
  7. 3
      src/migrate/wallet.rs

54
lib/apps/wallet/models.dart

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
enum ChainToken {
ETH,
ERC20,
ERC721,
BTC,
}
extension ChainTokenExtension on ChainToken {
int toInt() {
switch (this) {
case ChainToken.ETH:
return 1;
case ChainToken.ERC20:
return 2;
case ChainToken.ERC721:
return 3;
case ChainToken.BTC:
return 4;
}
}
static ChainToken fromInt(int a) {
switch (a) {
case 1:
return ChainToken.ETH;
case 2:
return ChainToken.ERC20;
case 3:
return ChainToken.ERC721;
case 4:
return ChainToken.BTC;
default:
return ChainToken.ETH;
}
}
}
class Address {
int id = 0;
ChainToken chain = ChainToken.ETH;
int index = 0;
String name = '';
String address = '';
bool isGen = true;
Address.fromList(List params) {
this.id = params[0];
this.chain = ChainTokenExtension.fromInt(params[1]);
this.index = params[2];
this.name = params[3];
this.address = params[4];
this.isGen = params[5];
}
}

71
lib/apps/wallet/page.dart

@ -6,10 +6,13 @@ import 'package:esse/utils/better_print.dart'; @@ -6,10 +6,13 @@ import 'package:esse/utils/better_print.dart';
import 'package:esse/l10n/localizations.dart';
import 'package:esse/widgets/button_text.dart';
import 'package:esse/widgets/input_text.dart';
import 'package:esse/widgets/default_core_show.dart';
import 'package:esse/global.dart';
import 'package:esse/options.dart';
import 'package:esse/rpc.dart';
import 'package:esse/apps/wallet/models.dart';
class WalletDetail extends StatefulWidget {
const WalletDetail({Key? key}) : super(key: key);
@ -25,6 +28,8 @@ class Network { @@ -25,6 +28,8 @@ class Network {
class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderStateMixin {
TabController? _tabController;
List<Address> _addresses = [];
bool _needGenerate = false;
List tokens = [
['ETH', '100', '1000', 'assets/logo/logo_eth.png'],
@ -56,7 +61,41 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt @@ -56,7 +61,41 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt
@override
void initState() {
_tabController = new TabController(length: 2, vsync: this);
rpc.addListener('wallet-generate', _walletGenerate, false);
super.initState();
Future.delayed(Duration.zero, _load);
}
_walletGenerate(List params) {
print('aaaaaaaaaaaaaaaaaa');
final address = Address.fromList(params);
bool isNew = true;
this._addresses.forEach((addr) {
if (addr.address == address.address) {
isNew = false;
}
});
if (isNew) {
this._addresses.add(address);
setState(() {});
}
}
_load() async {
final res = await httpPost(Global.httpRpc, 'wallet-list', []);
if (res.isOk) {
this._addresses.clear();
res.params.forEach((param) {
this._addresses.add(Address.fromList(param));
});
if (this._addresses.length == 0) {
this._needGenerate = true;
}
setState(() {});
} else {
// TODO tostor error
print(res.error);
}
}
@override
@ -64,6 +103,38 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt @@ -64,6 +103,38 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt
final color = Theme.of(context).colorScheme;
final lang = AppLocalizations.of(context);
if (this._addresses.length == 0 && !this._needGenerate) {
return Scaffold(
appBar: AppBar(title: Text(lang.loadMore)),
body: const DefaultCoreShow(),
);
}
if (this._addresses.length == 0 && this._needGenerate) {
return Scaffold(
appBar: AppBar(title: Text(lang.wallet)),
body: DefaultCoreShow(
child: ElevatedButton(
style: ElevatedButton.styleFrom(onPrimary: color.surface),
onPressed: () {
rpc.send('wallet-generate', [ChainToken.ETH.toInt(), ""]);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.lock),
const SizedBox(width: 8.0),
const Text('生成以太坊地址'),
]
)
)
))
);
}
return Scaffold(
appBar: AppBar(
title: DropdownButton<Network>(

0
lib/apps/wallet/provider.dart

5
lib/widgets/default_core_show.dart

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
import 'package:flutter/material.dart';
class DefaultCoreShow extends StatelessWidget {
const DefaultCoreShow({Key? key}): super(key: key);
final Widget? child;
const DefaultCoreShow({Key? key, this.child}): super(key: key);
@override
Widget build(BuildContext context) {
@ -18,7 +19,7 @@ class DefaultCoreShow extends StatelessWidget { @@ -18,7 +19,7 @@ class DefaultCoreShow extends StatelessWidget {
fit: BoxFit.cover,
),
),
child: Center(child: Text('', style: TextStyle(fontSize: 32.0)))
child: Center(child: this.child)
);
}
}

42
src/apps/wallet/models.rs

@ -1,5 +1,3 @@ @@ -1,5 +1,3 @@
use rand::Rng;
use std::time::{SystemTime, UNIX_EPOCH};
use tdn::types::{
primitive::Result,
rpc::{json, RpcParam},
@ -48,25 +46,42 @@ pub(crate) struct Address { @@ -48,25 +46,42 @@ pub(crate) struct Address {
pub index: i64,
pub name: String,
pub address: String,
/// Encrypted secret key.
/// if this address is imported, has this field,
/// if this address is generated, no this field.
pub secret: String,
}
impl Address {
pub fn is_gen(&self) -> bool {
self.secret.len() == 0
}
pub fn new(chain: ChainToken, index: i64, address: String) -> Self {
Self {
chain,
index,
address,
name: format!("Account {}", index),
secret: "".to_owned(),
id: 0,
}
}
pub fn to_rpc(&self) -> RpcParam {
json!([self.id, self.chain.to_i64(), self.index, self.address])
json!([
self.id,
self.chain.to_i64(),
self.index,
self.name,
self.address,
self.is_gen(),
])
}
fn from_values(mut v: Vec<DsValue>) -> Self {
Self {
secret: v.pop().unwrap().as_string(),
address: v.pop().unwrap().as_string(),
name: v.pop().unwrap().as_string(),
index: v.pop().unwrap().as_i64(),
@ -77,11 +92,12 @@ impl Address { @@ -77,11 +92,12 @@ impl Address {
pub fn insert(&mut self, db: &DStorage) -> Result<()> {
let sql = format!(
"INSERT INTO addresses (chain, indx, name, address) VALUES ({}, {}, '{}', '{}')",
"INSERT INTO addresses (chain, indx, name, address, secret) VALUES ({}, {}, '{}', '{}', '{}')",
self.chain.to_i64(),
self.index,
self.name,
self.address,
self.secret,
);
let id = db.insert(&sql)?;
self.id = id;
@ -90,7 +106,7 @@ impl Address { @@ -90,7 +106,7 @@ impl Address {
pub fn list(db: &DStorage) -> Result<Vec<Self>> {
let matrix = db.query(&format!(
"SELECT id, chain, indx, name, address FROM addresses"
"SELECT id, chain, indx, name, address, secret FROM addresses"
))?;
let mut addresses = vec![];
for values in matrix {
@ -99,7 +115,21 @@ impl Address { @@ -99,7 +115,21 @@ impl Address {
Ok(addresses)
}
pub fn delete(db: &DStorage, id: &i64) -> Result<()> {
pub fn next_index(db: &DStorage, chain: &ChainToken) -> Result<u32> {
let mut matrix = db.query(&format!(
"SELECT indx FROM addresses where chain = {} AND secret = '' ORDER BY indx DESC",
chain.to_i64()
))?;
if matrix.len() > 0 {
let mut values = matrix.pop().unwrap(); // safe unwrap()
let index = values.pop().unwrap().as_i64() as u32; // safe unwrap()
return Ok(index + 1);
} else {
return Ok(0);
}
}
pub fn _delete(db: &DStorage, id: &i64) -> Result<()> {
let sql = format!("DELETE FROM addresses WHERE id = {}", id);
db.delete(&sql)?;
Ok(())

8
src/apps/wallet/rpc.rs

@ -49,6 +49,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -49,6 +49,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
let lang = account.lang();
let pass = account.pass.to_string();
let account_index = account.index as u32;
let db = wallet_db(group_lock.base(), &gid)?;
drop(group_lock);
let pass = if pass.len() > 0 {
@ -56,11 +57,12 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -56,11 +57,12 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
} else {
None
};
let index = 0; // TOOD
let index = Address::next_index(&db, &chain)?;
let mut address = match chain {
ChainToken::ETH | ChainToken::ERC20 | ChainToken::ERC721 => {
let sk = generate_eth_account(lang, &mnemonic, account_index, index, pass)?;
let address = (&sk).address().to_string();
let address = format!("{:?}", (&sk).address());
Address::new(chain, index as i64, address)
}
ChainToken::BTC => {
@ -69,9 +71,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -69,9 +71,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
}
};
let db = wallet_db(state.layer.read().await.base(), &gid)?;
address.insert(&db)?;
Ok(HandleResult::rpc(address.to_rpc()))
},
);

3
src/migrate/wallet.rs

@ -5,5 +5,6 @@ pub(super) const WALLET_VERSIONS: [&str; 1] = [ @@ -5,5 +5,6 @@ pub(super) const WALLET_VERSIONS: [&str; 1] = [
chain INTEGER NOT NULL,
indx INTEGER NOT NULL,
name TEXT NOT NULL,
address TEXT NOT NULL);",
address TEXT NOT NULL,
secret TEXT NOT NULL);",
];

Loading…
Cancel
Save