[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

Sort:  

현재 저는 ZZAN과 스팀코인판을 주로 사용하는데
혹시 SP, ZZAN, SCT의 보팅 현황을 한꺼번에 볼수 있게 할수는 없을까요?
일종의 통합 툴이죠... ^^

말씀하신 건 좀 어려워보이네요. 현재 개발중인 것은 새로운 서비스의 일환입니다!

감사합니다~🙇‍♂️