Development/Flutter (Dart)
[SOLVED][Flutter3.19] status code 404 & response body empty - api.bybit.com/v5/account/wallet-balance 오류 해결
Tradgineer
2024. 6. 4. 09:48
[ 작업 환경 ]
Flutter 3.19
Dart 3.3
[ 문제 현상 ]
올바른 api key와 secret key를 입력해주고, 정상적인 signature를 만들어 call했음에도 불구하고 404 response와 함께 비어있는 데이터가 return되는 문제 발생
// bybit_private_api_service.dart
import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:crypto/crypto.dart';
import '../models/bybit_wallet_balance_model.dart';
class BybitPrivateApiService {
Future<BybitWalletBalanceModel> fetchWalletBalance(
String apiKey, String apiSecret) async {
const endpoint = 'https://api.bybit.com';
const path = '/v5/account/wallet-balance';
const accountType = 'UNIFIED';
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
const recvWindow = '20000';
const queryString = 'accountType=$accountType';
final paramStr = '$timestamp$apiKey$recvWindow$queryString';
log('paramStr : $paramStr');
final signature = _generateSignature(paramStr, apiSecret);
const url = '$endpoint$path?$queryString';
final Map<String, String> headers = {
'X-BAPI-API-KEY': apiKey,
'X-BAPI-TIMESTAMP': timestamp,
'X-BAPI-RECV-WINDOW': recvWindow,
'X-BAPI-SIGN': signature,
};
log('Headers: $headers');
log('URI: $url');
final response = await http.get(
Uri.parse(url),
headers: headers,
);
log('Response status: ${response.statusCode}');
log('Response body: ${response.body}');
if (response.statusCode == 200) {
final jsonResponse = jsonDecode(response.body);
if (jsonResponse['retCode'] == 0) {
return BybitWalletBalanceModel.fromJson(
jsonResponse['result']['list'][0]);
} else {
throw Exception('API error: ${jsonResponse['retMsg']}');
}
} else {
throw Exception('Failed to load wallet balance');
}
}
String _generateSignature(String data, String secretKey) {
final key = utf8.encode(secretKey);
final bytes = utf8.encode(data);
final hmacSha256 = Hmac(sha256, key);
final digest = hmacSha256.convert(bytes);
return digest.toString();
}
}
// bybit_wallet_balance_model.dart
import 'coin.dart';
class BybitWalletBalanceModel {
final String totalEquity;
final String accountType;
final String totalAvailableBalance;
final List<Coin> coins;
BybitWalletBalanceModel({
required this.totalEquity,
required this.accountType,
required this.totalAvailableBalance,
required this.coins,
});
factory BybitWalletBalanceModel.fromJson(Map<String, dynamic> json) {
var coinsList = json['coin'] as List;
List<Coin> coinItems = coinsList.map((i) => Coin.fromJson(i)).toList();
return BybitWalletBalanceModel(
totalEquity: json['totalEquity'],
accountType: json['accountType'],
totalAvailableBalance: json['totalAvailableBalance'],
coins: coinItems,
);
}
}
// coin.dart
class Coin {
final String coin;
final String walletBalance;
final String availableToWithdraw;
Coin({
required this.coin,
required this.walletBalance,
required this.availableToWithdraw,
});
factory Coin.fromJson(Map<String, dynamic> json) {
return Coin(
coin: json['coin'],
walletBalance: json['walletBalance'],
availableToWithdraw: json['availableToWithdraw'],
);
}
}
[ 문제 원인 ]
accountType으로 UNIFIED를 넣어줬는데, UNIFIED account가 존재하지 않는 아이디에 대해 해당 api call을 할 경우 404 response가 나타납니다.
[ 해결 방법 ]
그래서 accountType을 SPOT으로 변경해주어 해결합니다.
class BybitPrivateApiService {
Future<BybitWalletBalanceModel> fetchWalletBalance(
String apiKey, String apiSecret) async {
const endpoint = 'https://api.bybit.com';
const path = '/v5/account/wallet-balance';
const accountType = 'SPOT';
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
const recvWindow = '20000';
const queryString = 'accountType=$accountType';
final paramStr = '$timestamp$apiKey$recvWindow$queryString';
log('paramStr : $paramStr');
final signature = _generateSignature(paramStr, apiSecret);
const url = '$endpoint$path?$queryString';
final Map<String, String> headers = {
'X-BAPI-API-KEY': apiKey,
'X-BAPI-TIMESTAMP': timestamp,
'X-BAPI-RECV-WINDOW': recvWindow,
'X-BAPI-SIGN': signature,
};
log('Headers: $headers');
log('URI: $url');
final response = await http.get(
Uri.parse(url),
headers: headers,
);
log('Response status: ${response.statusCode}');
log('Response body: ${response.body}');
if (response.statusCode == 200) {
final jsonResponse = jsonDecode(response.body);
if (jsonResponse['retCode'] == 0) {
return BybitWalletBalanceModel.fromJson(
jsonResponse['result']['list'][0]);
} else {
throw Exception('API error: ${jsonResponse['retMsg']}');
}
} else {
throw Exception('Failed to load wallet balance');
}
}
String _generateSignature(String data, String secretKey) {
final key = utf8.encode(secretKey);
final bytes = utf8.encode(data);
final hmacSha256 = Hmac(sha256, key);
final digest = hmacSha256.convert(bytes);
return digest.toString();
}
}
[ 정상 해결 완료 확인 ]