[PLAY STEEM x WebApp] Wallet History Code for @anpigon
@anpigon님 개발에 도움이 됐으면 하는 마음으로 코드 공유합니다.
Flutter에서 스팀 wallet 트랜잭션 히스토리 정보를 가져와서 화면에 표시하는 코드입니다.
Transaction 모델
class Transaction extends Equatable {
final dynamic icon;
final String value;
final String detail;
final DateTime createdAt;
final String? memo;
final String? url;
Transaction({
required this.icon,
required this.value,
required this.detail,
required this.createdAt,
this.memo,
this.url,
});
factory Transaction.fromList(
{required dynamic transaction, required GlobalProps globalProps}) {
// printWarning('transaction from list. item: $item');
final operation = transaction[1]['op'];
final opType = operation[0];
final opData = operation[1];
final createdAt = DateTime.parse(transaction[1]['timestamp']);
final author = opData['comment_author'] ?? '';
final permlink = opData['comment_permlink'] ?? '';
switch (opType) {
case 'curation_reward':
final reward = parseToken(opData['reward']);
final _value = vestToSteem(
vestingShares: reward,
totalVestingFundSteem: globalProps.totalVestingFundSteem,
totalVestingShares: globalProps.totalVestingShares);
return Transaction(
createdAt: createdAt,
icon: Icon(Icons.favorite, color: Colors.blue),
value: _value,
detail: 'curation reward: $_value SP',
);
case 'author_reward':
case 'comment_benefactor_reward':
final _sbdPayout = parseToken(opData['sbd_payout']);
final _steemPayout = parseToken(opData['steem_payout']);
final _vestingPayout = parseToken(opData['vesting_payout']);
final sbdPayout =
_sbdPayout > 0 ? '${_sbdPayout.toStringAsFixed(3)} SBD' : '';
final steemPayout =
_steemPayout > 0 ? '${_steemPayout.toStringAsFixed(3)} STEEM' : '';
final vestingPayout = _vestingPayout > 0
? '${vestToSteem(vestingShares: _vestingPayout, totalVestingFundSteem: globalProps.totalVestingFundSteem, totalVestingShares: globalProps.totalVestingShares)} SP'
: '';
final _value = '$sbdPayout $steemPayout $vestingPayout';
final benefactor = opData['benefactor'];
return Transaction(
createdAt: createdAt,
icon: Icon(Icons.face, color: Colors.blue),
value: _value,
detail: 'author reward: $_value',
);
case 'claim_reward_balance':
final _rewardSbd = parseToken(opData['reward_sbd']);
final _rewardSteem = parseToken(opData['reward_steem']);
final _rewardVests = parseToken(opData['reward_vests']);
final rewardSbd =
_rewardSbd > 0 ? '${_rewardSbd.toStringAsFixed(3)} SBD' : '';
final rewardSteem =
_rewardSteem > 0 ? '${_rewardSteem.toStringAsFixed(3)} STEEM' : '';
final reweardVests = _rewardVests > 0
? '${vestToSteem(vestingShares: _rewardVests, totalVestingFundSteem: globalProps.totalVestingFundSteem, totalVestingShares: globalProps.totalVestingShares)} SP'
: '';
final _value = '$rewardSbd $rewardSteem $reweardVests';
return Transaction(
createdAt: createdAt,
icon: Icon(Icons.payment, color: Colors.blue),
value: _value,
detail: 'claim reward balance: $_value',
);
case 'transfer':
case 'transfer_to_savings':
case 'transfer_from_savings':
case 'transfer_to_vesting':
final _amount = opData['amount'];
final _from = opData['from'];
final _to = opData['to'];
final _memo = opData['memo'];
return Transaction(
createdAt: createdAt,
icon: Icon(Icons.transform, color: Colors.blue),
value: _amount,
detail: 'transfer. from: $_from $_amount',
);
default:
return Transaction(
createdAt: createdAt,
icon: Icon(Icons.message, color: Colors.blue),
value: '0',
detail: 'unknown',
);
}
}
@override
List<Object?> get props => [icon, value, detail, createdAt];
}
GlobalProps 모델
class GlobalProps extends Equatable {
final double totalVestingFundSteem;
final double totalVestingShares;
final double feedBase;
final double feedQuote;
GlobalProps({
required this.totalVestingFundSteem,
required this.totalVestingShares,
required this.feedBase,
required this.feedQuote,
});
factory GlobalProps.fromMap(
{required Map<String, dynamic> props,
required Map<String, dynamic> feed}) {
// printWarning('GlobalProps model. props $props');
// printWarning('GlobalProps model. feed $feed');
return GlobalProps(
feedBase: parseToken(feed['base']),
feedQuote: parseToken(feed['quote']),
totalVestingFundSteem: parseToken(props['total_vesting_fund_steem']),
totalVestingShares: parseToken(props['total_vesting_shares']),
);
}
static final empty = GlobalProps(
totalVestingFundSteem: 0.0,
totalVestingShares: 0.0,
feedBase: 0.0,
feedQuote: 0.0);
@override
List<Object?> get props =>
[totalVestingFundSteem, totalVestingShares, feedBase, feedQuote];
}
Fetching Transaction History
Future<List<Transaction>> fetchTransactionHistory(
{required String account}) async {
final body = {
'jsonrpc': '2.0',
'method': 'call',
'params': [
'database_api',
'get_state',
['/@$account/transfers']
]
};
print('fetchTransactionHistory. body: $body');
try {
final response = await Dio().post('https://api.steemit.com', data: body);
if (response.statusCode == 200) {
final result = response.data['result'];
final history = result['accounts'][account]['transfer_history']
.sublist(0, BlockchainConst.fetchNotificationsLimit);
final properties = result['props'];
final feed = result['feed_price'];
print('fetchTransactionHistory. properties: $properties');
print('fetchTransactionHistory. feed: $feed');
final globalProperties =
GlobalProps.fromMap(props: properties, feed: feed);
List<Transaction> transactions = [];
history.forEach((item) {
final transaction = Transaction.fromList(
transaction: item, globalProps: globalProperties);
transactions.add(transaction);
});
return transactions;
}
} catch (error) {
printError('failed to fetch transaction history $error');
}
return [];
}
화면 표시
저는 Transaction Model에서 대부분 기능을 구현했습니다.
개발하시는데 참고가 되면 좋겠네요.
더 필요한 부분이 있다면 말씀해주세요~
cc.
@steemcurator01
현재 저는 ZZAN과 스팀코인판을 주로 사용하는데
혹시 SP, ZZAN, SCT의 보팅 현황을 한꺼번에 볼수 있게 할수는 없을까요?
일종의 통합 툴이죠... ^^
말씀하신 건 좀 어려워보이네요. 현재 개발중인 것은 새로운 서비스의 일환입니다!
감사합니다~🙇♂️