Browse Source

没有bug了,询价都写好了。

skyffire 6 tháng trước cách đây
mục cha
commit
c47bdc5e59
1 tập tin đã thay đổi với 69 bổ sung25 xóa
  1. 69 25
      price_checker.py

+ 69 - 25
price_checker.py

@@ -17,44 +17,88 @@ proxies = {
 }
 
 
-# --- OpenOcean 和 Gate.io 的价格获取函数 (get_openocean_price_bsc, get_gateio_spot_price) ---
-# (这些函数与您上一版本代码中的基本一致,确保它们返回包含 'rate_out_per_in' 或 'price_base_in_quote' 的字典,
-# 或者在出错时返回包含 'error' 键的字典)
-# 为了完整性,我将它们包含进来,但假设它们是上一版本中我们确认过的:
-
-def get_openocean_price_bsc(in_token_addr, out_token_addr, human_amount_in_decimal, gas_price=3):
+# --- OpenOcean 的价格获取函数 ---
+def get_openocean_price_bsc(in_token_addr, out_token_addr, human_amount_in_decimal_for_request, gas_price=3):
+    """
+    从 OpenOcean API 获取报价,并根据 API 返回的原子单位数量和代币小数位数计算价格。
+
+    价格计算方式为: (通过 inAmount 和 inToken.decimals 计算得到的人类可读输入数量) / (通过 outAmount 和 outToken.decimals 计算得到的人类可读输出数量)
+    这个价格表示 “每单位输出代币需要多少单位输入代币”。
+
+    Args:
+        in_token_addr (str): 输入代币的合约地址。
+        out_token_addr (str): 输出代币的合约地址。
+        human_amount_in_decimal_for_request (decimal.Decimal): 用于 API 请求的人类可读的输入金额。
+                                                            API会根据此金额和实际代币信息处理请求。
+        gas_price (int, optional): Gas 价格。 默认为 3。
+
+    Returns:
+        dict: 包含价格计算结果或错误信息的字典。
+              成功时: {"price_in_per_out": calculated_price}
+              失败时: {"error": "错误信息"}
+    """
     chain = 'bsc'
     url = f'https://open-api.openocean.finance/v4/{chain}/quote'
     params = {
         'inTokenAddress': in_token_addr,
         'outTokenAddress': out_token_addr,
-        'amount': str(human_amount_in_decimal),
+        'amount': str(human_amount_in_decimal_for_request),  # API 请求中的 amount 参数
         'gasPrice': gas_price,
     }
     try:
         response = requests.get(url, params=params, proxies=proxies, timeout=10)
-        response.raise_for_status()
+        response.raise_for_status()  # 如果HTTP状态码表示错误,则抛出异常
         data = response.json()
-        print(data)
-        if data.get('code') == 200 and data.get('data') and data['data'].get('outToken'):
-            out_token_info = data['data']['outToken']
-            human_out_amount_str = out_token_info.get('volume')
-            if human_out_amount_str is not None:
-                human_out_amount_decimal = decimal.Decimal(str(human_out_amount_str))
-                if human_amount_in_decimal > 0:
-                    rate = human_amount_in_decimal / human_out_amount_decimal
-                    return {"rate_out_per_in": rate}
-                else:
-                    return {"error": "输入金额为零"}
-            else:
-                return {"error": "未找到outToken.volume"}
+
+        if data.get('code') == 200 and data.get('data'):
+            api_data = data['data']
+
+            # 确保所有需要的数据都存在
+            if not (api_data.get('inToken') and api_data['inToken'].get('decimals') is not None and
+                    api_data.get('outToken') and api_data['outToken'].get('decimals') is not None and
+                    api_data.get('inAmount') is not None and api_data.get('outAmount') is not None):
+                return {"error": "API响应中缺少必要的代币信息、数量或小数位数"}
+
+            # 从 API 响应中获取原子单位的数量和小数位数
+            in_token_decimals = int(api_data['inToken']['decimals'])
+            out_token_decimals = int(api_data['outToken']['decimals'])
+
+            atomic_in_amount = decimal.Decimal(api_data['inAmount'])
+            atomic_out_amount = decimal.Decimal(api_data['outAmount'])
+
+            # 计算人类可读的输入数量
+            # derived_human_in_amount = atomic_in_amount / (decimal.Decimal('10') ** in_token_decimals)
+            # 根据您的反馈,OpenOcean的 inToken.volume 已经是人类可读的输入量,而 inAmount 是API内部处理后的原子单位量
+            # 如果您的意图是严格使用API返回的 inAmount 来反推人类可读输入量,那么上面的计算是正确的。
+            # 我们将基于 inAmount 和 outAmount 来计算,正如您所要求的。
+            derived_human_in_amount = atomic_in_amount / (decimal.Decimal('10') ** in_token_decimals)
+
+            # 计算人类可读的输出数量
+            derived_human_out_amount = atomic_out_amount / (decimal.Decimal('10') ** out_token_decimals)
+
+            if derived_human_out_amount == 0:  # 避免除以零的错误
+                return {"error": "计算得出的人类可读输出数量为零,无法计算价格"}
+
+            if derived_human_in_amount == 0 and human_amount_in_decimal_for_request > 0:
+                # 如果API返回的inAmount为0,但请求量大于0,可能是一个问题或特殊情况
+                # 但我们仍按您的要求基于derived_human_in_amount计算
+                pass
+
+            # 根据您的要求:价格 = 输入数量 / 输出数量
+            # 这个价格表示:1 单位的输出代币等价于多少单位的输入代币
+            calculated_price = derived_human_in_amount / derived_human_out_amount
+
+            return {"price_in_per_out": calculated_price}  # 使用更能描述价格含义的键名
+
         else:
-            error_message = data.get('message', 'N/A') if data else '无响应数据'
+            # API 返回的 code 不是 200 或没有 data 字段
+            error_message = data.get('message', 'N/A') if data else '无响应数据 (data is None)'
             error_code = data.get('code', 'N/A') if data else 'N/A'
-            return {"error": f"OO API Err Code: {error_code}, Msg: {error_message}"}
+            return {"error": f"OO API 错误 - Code: {error_code}, Msg: {error_message}"}
+
     except requests.exceptions.RequestException as e:
         return {"error": f"OO请求失败: {e}"}
-    except Exception as e:
+    except Exception as e:  # 捕获包括 JSONDecodeError 在内的其他潜在错误
         return {"error": f"OO意外错误: {e}"}
 
 
@@ -113,7 +157,7 @@ def main():
             )
 
             if "error" not in oo_price_data:
-                oo_rate_usdc_per_usdt = oo_price_data['rate_out_per_in']
+                oo_rate_usdc_per_usdt = oo_price_data['price_in_per_out']
                 oo_display_str = f"{oo_rate_usdc_per_usdt:.6f}"  # 格式化价格
             else:
                 oo_error_this_iteration = oo_price_data['error']  # 记录错误信息