Browse Source

Wallet: main token balance fetch and show

pull/18/head
Sun 4 years ago
parent
commit
c126079633
  1. BIN
      assets/logo/logo_erc20.png
  2. 51
      lib/apps/wallet/models.dart
  3. 23
      lib/apps/wallet/page.dart
  4. 1
      pubspec.yaml
  5. 2
      src/apps/wallet/mod.rs
  6. 129
      src/apps/wallet/models.rs
  7. 91
      src/apps/wallet/rpc.rs
  8. 9
      src/migrate/wallet.rs

BIN
assets/logo/logo_erc20.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 942 B

51
lib/apps/wallet/models.dart

@ -158,3 +158,54 @@ class Address { @@ -158,3 +158,54 @@ class Address {
this.isGen = params[5];
}
}
class Token {
int id = 0;
ChainToken chain = ChainToken.ETH;
Network network = Network.EthMain;
String name = 'ETH';
String contract = '';
int decimal = 18;
String balanceString = '';
double amount = 0.0;
double fiat = 0.0;
String logo = 'assets/logo/logo_eth.png';
Token() {}
Token.fromList(List params) {
this.id = params[0];
this.chain = ChainTokenExtension.fromInt(params[1]);
this.network = NetworkExtension.fromInt(params[2]);
this.name = params[3];
this.contract = params[4];
this.decimal = params[5];
}
Token.eth(Network network) {
this.network = network;
}
Token.btc(Network network) {
this.network = network;
this.name = 'BTC';
this.decimal = 8;
}
balance(String number) {
this.balanceString = number;
final pad = number.length - (this.decimal + 1); // 0.00..00
if (pad < 0) {
number = ('0' * (-pad)) + number;
}
String right = number.substring(number.length - this.decimal, number.length);
final left = number.substring(0, number.length - this.decimal);
if (right.length > 8) {
right = right.substring(0, 8);
}
final amount_s = left + '.' + right;
this.amount = double.parse(amount_s);
}
}

23
lib/apps/wallet/page.dart

@ -31,11 +31,13 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt @@ -31,11 +31,13 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt
List<Network> _networks = [];
Network? _selectedNetwork;
Token _mainToken = Token();
List<Token> _tokens = [];
List tokens = [
['ETH', '100', '1000', 'assets/logo/logo_eth.png'],
['USDT', '2000', '2000', 'assets/logo/logo_tether.png'],
['XXX', '100', '1000', 'assets/logo/logo_erc20.png'],
['FFF', '100', '1000', 'assets/logo/logo_erc20.png'],
['XXX', '100', '1000', 'assets/logo/logo_eth.png'],
['FFF', '100', '1000', 'assets/logo/logo_eth.png'],
];
@override
@ -62,8 +64,17 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt @@ -62,8 +64,17 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt
}
_walletBalance(List params) {
// TODO
print(params);
final address = params[0];
final network = NetworkExtension.fromInt(params[1]);
final contract = params[2];
final balance = params[3];
// TODO check token.
this._mainToken = Token.eth(network);
this._mainToken.balance(balance);
setState(() {});
}
_load() async {
@ -249,7 +260,7 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt @@ -249,7 +260,7 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt
height: 36.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(tokens[0][3]),
image: AssetImage(this._mainToken.logo),
fit: BoxFit.cover,
),
),
@ -258,7 +269,7 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt @@ -258,7 +269,7 @@ class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderSt
height: 60.0,
alignment: Alignment.center,
child: Text(
'100 ETH',
"${this._mainToken.amount} ${this._mainToken.name}",
style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold)),
),
Text('\$1000', style: TextStyle(color: Color(0xFFADB0BB))),

1
pubspec.yaml

@ -86,7 +86,6 @@ flutter: @@ -86,7 +86,6 @@ flutter:
- assets/logo/logo_wallet.png
- assets/logo/logo_eth.png
- assets/logo/logo_tether.png
- assets/logo/logo_erc20.png
- assets/images/background_light.jpg
- assets/images/background_dark.jpg
- assets/images/image_missing.png

2
src/apps/wallet/mod.rs

@ -1,6 +1,4 @@ @@ -1,6 +1,4 @@
mod models;
mod rpc;
pub const ETH_NODE: &'static str = "https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161";
pub(crate) use rpc::new_rpc_handler;

129
src/apps/wallet/models.rs

@ -5,6 +5,22 @@ use tdn::types::{ @@ -5,6 +5,22 @@ use tdn::types::{
use tdn_storage::local::{DStorage, DsValue};
#[rustfmt::skip]
pub const ETH_NODE: &'static str =
"https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161";
#[rustfmt::skip]
pub const ETH_ROPSTEN: &'static str =
"https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161";
#[rustfmt::skip]
pub const ETH_RINKEBY: &'static str =
"https://rinkeby.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161";
#[rustfmt::skip]
pub const ETH_KOVAN: &'static str =
"https://kovan.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161";
#[rustfmt::skip]
pub const ETH_LOCAL: &'static str =
"http://localhost:8545";
pub(crate) enum ChainToken {
ETH,
ERC20,
@ -44,6 +60,30 @@ pub(crate) enum Network { @@ -44,6 +60,30 @@ pub(crate) enum Network {
}
impl Network {
pub fn node<'a>(&self) -> &'a str {
// TODO more.
match self {
Network::EthMain => ETH_NODE,
Network::EthTestRopsten => ETH_ROPSTEN,
Network::EthTestRinkeby => ETH_RINKEBY,
Network::EthTestKovan => ETH_KOVAN,
Network::EthLocal => ETH_LOCAL,
Network::BtcMain => ETH_NODE,
Network::BtcLocal => ETH_NODE,
}
}
pub fn chain(&self) -> ChainToken {
match self {
Network::EthMain
| Network::EthTestRopsten
| Network::EthTestRinkeby
| Network::EthTestKovan
| Network::EthLocal => ChainToken::ETH,
Network::BtcMain | Network::BtcLocal => ChainToken::BTC,
}
}
pub fn to_i64(&self) -> i64 {
match self {
Network::EthMain => 1,
@ -70,13 +110,6 @@ impl Network { @@ -70,13 +110,6 @@ impl Network {
}
}
pub(crate) struct Token {
pub id: i64,
pub chain: ChainToken,
pub contract: String,
pub decimal: i64,
}
pub(crate) struct Address {
pub id: i64,
pub chain: ChainToken,
@ -172,3 +205,85 @@ impl Address { @@ -172,3 +205,85 @@ impl Address {
Ok(())
}
}
pub(crate) struct Token {
pub id: i64,
pub chain: ChainToken,
pub network: Network,
pub name: String,
pub contract: String,
pub decimal: i64,
}
impl Token {
pub fn new(
chain: ChainToken,
network: Network,
name: String,
contract: String,
decimal: i64,
) -> Self {
Self {
chain,
network,
name,
contract,
decimal,
id: 0,
}
}
pub fn to_rpc(&self) -> RpcParam {
json!([
self.id,
self.chain.to_i64(),
self.network.to_i64(),
self.name,
self.contract,
self.decimal,
])
}
fn from_values(mut v: Vec<DsValue>) -> Self {
Self {
decimal: v.pop().unwrap().as_i64(),
contract: v.pop().unwrap().as_string(),
name: v.pop().unwrap().as_string(),
network: Network::from_i64(v.pop().unwrap().as_i64()),
chain: ChainToken::from_i64(v.pop().unwrap().as_i64()),
id: v.pop().unwrap().as_i64(),
}
}
pub fn insert(&mut self, db: &DStorage) -> Result<()> {
let sql = format!(
"INSERT INTO tokens (chain, network, name, contract, decimal) VALUES ({}, {}, '{}', '{}', {})",
self.chain.to_i64(),
self.network.to_i64(),
self.name,
self.contract,
self.decimal,
);
let id = db.insert(&sql)?;
self.id = id;
Ok(())
}
pub fn list(db: &DStorage, network: &Network) -> Result<Vec<Self>> {
let matrix = db.query(&format!(
"SELECT id, chain, network, name, contract, decimal FROM tokens where network = {}",
network.to_i64()
))?;
let mut tokens = vec![];
for values in matrix {
tokens.push(Self::from_values(values));
}
Ok(tokens)
}
pub fn _delete(db: &DStorage, id: &i64) -> Result<()> {
let sql = format!("DELETE FROM tokens WHERE id = {}", id);
db.delete(&sql)?;
Ok(())
}
}

91
src/apps/wallet/rpc.rs

@ -2,20 +2,17 @@ use std::sync::Arc; @@ -2,20 +2,17 @@ use std::sync::Arc;
use tdn::types::{
group::GroupId,
message::SendMessage,
primitive::HandleResult,
primitive::{HandleResult, Result},
rpc::{json, rpc_response, RpcError, RpcHandler, RpcParam},
};
use tdn_did::{generate_btc_account, generate_eth_account};
use tdn_storage::local::DStorage;
use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::sync::mpsc::Sender;
use web3::signing::Key;
use crate::{rpc::RpcState, storage::wallet_db};
use super::{
models::{Address, ChainToken, Network},
ETH_NODE,
};
use super::models::{Address, ChainToken, Network, Token};
#[inline]
fn wallet_list(devices: Vec<Address>) -> RpcParam {
@ -26,45 +23,67 @@ fn wallet_list(devices: Vec<Address>) -> RpcParam { @@ -26,45 +23,67 @@ fn wallet_list(devices: Vec<Address>) -> RpcParam {
json!(results)
}
#[inline]
fn res_balance(
gid: GroupId,
address: &str,
network: &Network,
contract: &str,
balance: &str,
) -> RpcParam {
rpc_response(
0,
"wallet-balance",
json!([address, network.to_i64(), contract, balance]),
gid,
)
}
async fn loop_token(
sender: Sender<SendMessage>,
_db: DStorage,
db: DStorage,
gid: GroupId,
network: Network,
address: String,
) -> std::result::Result<(), SendError<SendMessage>> {
) -> Result<()> {
// loop get balance of all tokens.
match network {
Network::EthMain => {
//
let node = network.node();
let chain = network.chain();
let tokens = Token::list(&db, &network)?;
match chain {
ChainToken::ETH => {
let transport = web3::transports::Http::new(node).unwrap();
let web3 = web3::Web3::new(transport);
let balance = web3
.eth()
.balance(address.parse().unwrap(), None)
.await
.unwrap();
let balance = balance.to_string();
let res = res_balance(gid, &address, &network, "", &balance);
sender.send(SendMessage::Rpc(0, res, true)).await?;
for token in tokens {
match token.chain {
ChainToken::ERC20 => {
//
}
ChainToken::ERC721 => {
//
}
_ => {
//
}
}
}
}
ChainToken::BTC => {
// TODO
}
Network::EthTestRopsten => {}
Network::EthTestRinkeby => {}
Network::EthTestKovan => {}
Network::EthLocal => {}
Network::BtcMain => {}
Network::BtcLocal => {}
_ => panic!("nerver here!"),
}
let transport = web3::transports::Http::new(ETH_NODE).unwrap();
let web3 = web3::Web3::new(transport);
let balance = web3
.eth()
.balance(address.parse().unwrap(), None)
.await
.unwrap();
println!("Balance of {:?}: {}", address, balance);
let res = rpc_response(
0,
"wallet-balance",
json!([address, network.to_i64(), balance]),
gid,
);
sender.send(SendMessage::Rpc(0, res, true)).await?;
Ok(())
}

9
src/migrate/wallet.rs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
#[rustfmt::skip]
pub(super) const WALLET_VERSIONS: [&str; 1] = [
pub(super) const WALLET_VERSIONS: [&str; 2] = [
"CREATE TABLE IF NOT EXISTS addresses(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
chain INTEGER NOT NULL,
@ -7,4 +7,11 @@ pub(super) const WALLET_VERSIONS: [&str; 1] = [ @@ -7,4 +7,11 @@ pub(super) const WALLET_VERSIONS: [&str; 1] = [
name TEXT NOT NULL,
address TEXT NOT NULL,
secret TEXT NOT NULL);",
"CREATE TABLE IF NOT EXISTS tokens(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
chain INTEGER NOT NULL,
network INTEGER NOT NULL,
name TEXT NOT NULL,
contract TEXT NOT NULL,
decimal INTEGER NOT NULL);",
];

Loading…
Cancel
Save