Commit 40378b99 authored by vicotor's avatar vicotor

update api

parent 5d68fb19
# REST API 接口文档
版本: v1 (前缀统一为 `/api/v1`)
> 基础访问地址 (示例): `http://localhost:8080/api/v1` — 实际端口以运行配置为准 (`config.toml` 中的 `server.listen`).
## 统一返回格式
成功:
```json
{
"code": 0,
"msg": "ok",
"data": { ...具体数据... }
}
```
失败:
```json
{
"code": 1,
"error": "invalid param", // 或其它错误信息
"data": ""
}
```
错误信息枚举 (`constant/constant.go`):
- `invalid param`
- `unsupported platform`
- `internal error`
## 通用说明
- 所有地址字段需为合法 EVM 地址 (校验: `common.IsHexAddress`).
- Token 地址建议全部使用小写十六进制,历史查询内部会转为小写。
- 金额字段 `amount` / `out_amount` / `balance` / `fee` 等均为字符串;单位(是否为最小单位 Wei)需与后端配置一致,当前实现没有转换逻辑,默认前端传最小单位。
## 数据模型 (节选自 `model/api/model.go`)
### 估算请求
跨链估算 `QuoteBridgeParam`:
```json
{
"from_chain_id": 61900,
"to_chain_id": 56,
"from_token": "0x...",
"to_token": "0x...",
"amount": "<输入数量>",
"user": "0x源地址",
"receiver": "0x目标地址"
}
```
Swap 估算 `QuoteSwapParam`:
```json
{
"from_chain_id": 1,
"to_chain_id": 137,
"path": {
"swap_from_token": "0x源链用户输入 Token",
"bridge_from_token": "0x源链中间桥接 Token",
"bridge_to_token": "0x目标链中间桥接 Token",
"swap_to_token": "0x目标链最终输出 Token"
},
"amount": "<输入数量>",
"user": "0x源地址",
"receiver": "0x目标地址"
}
```
### 余额查询 `TokenBalanceQuery`:
```json
{
"chain_id": 56,
"user": "0x地址",
"toke_list": ["0xTokenA", "0xTokenB"]
}
```
### 估算返回 `QuoteResult`
```json
{
"to_contract": "0x...", // 目标链或合约地址
"out_amount": "<输出数量>",
"payload": "<执行交易所需数据, RLP/ABI 编码>"
}
```
### Token 余额返回 `TokenBalances`
```json
{
"balances": [
{
"name": "TokenSymbol",
"decimals": 18,
"balance": "1230000000000000000",
"contract": "0xTokenContract"
}
]
}
```
### 历史记录结构 `History`
```json
{
"pending": [ { "tx_hash": "0x...", "status": "WaitConfirm" } ],
"finish": [ { "tx_hash": "0x...", "status": "Executed" } ]
}
```
状态枚举: `NoProcess` / `WaitConfirm` / `Executed` / `Rejected`
---
## 接口列表与示例
### 1. 查询用户跨链历史
GET `/user/history?address=<EVM地址>`
```bash
curl -G http://localhost:8080/api/v1/user/history \
--data-urlencode "address=0x1234567890abcdef1234567890abcdef12345678"
```
### 2. 获取桥路由配置 (同 `/params` 数据)
GET `/bridge/routers`
```bash
curl -X GET http://localhost:8080/api/v1/bridge/routers
```
成功返回示例 (桥接配置 `BridgeConfig`):
```json
{
"code": 0,
"data": {
"chains": {
"BNB Smart Chain Mainnet": {
"chain": "BNB Smart Chain Mainnet",
"chain_id": 56,
"contract": "0x214c0b3d19ad265c258dea678cf1f5a63499c0d9",
"support_tokens": {
"USD1": {
"token_contract": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"token_symbol": "USD1",
"bridge_tokens": [
{
"token_contract": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"to_chain_id": 61900,
"to_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"to_token_symbol": "USD1",
"fee": "0",
"max_limit": "1000000000000000000000000"
}
]
},
"USDT": {
"token_contract": "0x55d398326f99059ff775485246999027b3197955",
"token_symbol": "USDT",
"bridge_tokens": [
{
"token_contract": "0x55d398326f99059ff775485246999027b3197955",
"to_chain_id": 61900,
"to_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"to_token_symbol": "USD1",
"fee": "0",
"max_limit": "1000000000000000000000000"
}
]
}
},
"explorer_url": "https://bscscan.com",
"rpc": "https://binance.llamarpc.com"
},
"Mova Mainnet": {
"chain": "Mova Mainnet",
"chain_id": 61900,
"contract": "0x214c0b3d19ad265c258dea678cf1f5a63499c0d9",
"support_tokens": {
"USD1": {
"token_contract": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"token_symbol": "USD1",
"bridge_tokens": [
{
"token_contract": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"to_chain_id": 56,
"to_token": "0x55d398326f99059ff775485246999027b3197955",
"to_token_symbol": "USDT",
"fee": "20000000000000000",
"max_limit": "1000000000000000000000000"
}
]
}
},
"explorer_url": "https://scan.movachain.com",
"rpc": "https://rpc.movachain.com"
}
}
},
"msg": "ok"
}
```
### 3. 查询桥场景下用户 Token 余额
POST `/bridge/balance`
```bash
curl -X POST http://localhost:8080/api/v1/bridge/balance \
-H "Content-Type: application/json" \
-d '{
"chain_id": 61900,
"user": "0x88395111ab1586a4030dac62a183542762929bbc",
"toke_list": ["0x57b84a31e00ef4378e6b2d30703b73d02aee13f8", "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e"]
}'
```
成功返回示例 (Token 余额 `TokenBalances`):
```json
{
"code": 0,
"data": {
"balances": [
{
"name": "USD1",
"decimals": 18,
"balance": "0",
"contract": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8"
},
{
"name": "WMOVA",
"decimals": 18,
"balance": "0",
"contract": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e"
}
]
},
"msg": "ok"
}
```
### 4. 获取跨链报价
POST `/bridge/quote`
请求体: `QuoteBridgeParam`
```bash
curl -X POST http://localhost:8080/api/v1/bridge/quote \
-H "Content-Type: application/json" \
-d '{
"from_chain_id": 61900,
"to_chain_id": 56,
"from_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"to_token": "0x55d398326f99059ff775485246999027b3197955",
"amount": "1000000000000000000",
"user": "0x88395111ab1586a4030dac62a183542762929bbc",
"receiver": "0x88395111ab1586a4030dac62a183542762929bbc"
}'
```
### 5. 获取全部 Swap 路由配置
GET `/swap/routers`
```bash
curl -X GET http://localhost:8080/api/v1/swap/routers
```
成功返回示例:
```json
{
"code": 0,
"data": {
"56": {
"chain": "BNB Smart Chain Mainnet",
"chain_id": 56,
"contract": "0x214c0b3d19ad265c258dea678cf1f5a63499c0d9",
"support_tokens": {
"0x55d398326f99059ff775485246999027b3197955": {
"token_contract": "0x55d398326f99059ff775485246999027b3197955",
"token_symbol": "USDT",
"swap_tokens": {
"61900": {
"0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e": {
"to_chain_id": 61900,
"to_token": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e",
"to_token_symbol": "WMOVA",
"path": {
"swap_from_token": "0x55d398326f99059ff775485246999027b3197955",
"bridge_from_token": "0x55d398326f99059ff775485246999027b3197955",
"bridge_to_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"swap_to_token": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e"
}
}
}
}
},
"0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d": {
"token_contract": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"token_symbol": "USD1",
"swap_tokens": {
"61900": {
"0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e": {
"to_chain_id": 61900,
"to_token": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e",
"to_token_symbol": "WMOVA",
"path": {
"swap_from_token": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"bridge_from_token": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"bridge_to_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"swap_to_token": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e"
}
}
}
}
}
},
"explorer_url": "https://bscscan.com",
"rpc": "https://binance.llamarpc.com"
},
"61900": {
"chain": "Mova Mainnet",
"chain_id": 61900,
"contract": "0x214C0b3d19ad265c258DeA678Cf1f5a63499c0d9",
"support_tokens": {
"0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e": {
"token_contract": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e",
"token_symbol": "WMOVA",
"swap_tokens": {
"56": {
"0x55d398326f99059ff775485246999027b3197955": {
"to_chain_id": 56,
"to_token": "0x55d398326f99059ff775485246999027b3197955",
"to_token_symbol": "USDT",
"path": {
"swap_from_token": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e",
"bridge_from_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"bridge_to_token": "0x55d398326f99059ff775485246999027b3197955",
"swap_to_token": "0x55d398326f99059ff775485246999027b3197955"
}
}
}
}
}
},
"explorer_url": "https://scan.movachain.com",
"rpc": "https://rpc.movachain.com"
}
},
"msg": "ok"
}
```
### 6. 查询 Swap 场景下 Token 余额
POST `/swap/balance`
请求体: `TokenBalanceQuery`
```bash
curl -X POST http://localhost:8080/api/v1/swap/balance \
-H "Content-Type: application/json" \
-d '{
"chain_id": 61900,
"user": "0x88395111ab1586a4030dac62a183542762929bbc",
"toke_list": ["0x57b84a31e00ef4378e6b2d30703b73d02aee13f8", "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e"]
}'
```
### 7. 预估Swap之后的数量
POST `/swap/quote`
请求体: `QuoteSwapParam`
```bash
curl -X POST http://localhost:8080/api/v1/swap/quote \
-H "Content-Type: application/json" \
-d '{
"from_chain_id": 56,
"to_chain_id": 61900,
"path": {
"swap_from_token": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"bridge_from_token": "0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d",
"bridge_to_token": "0x57b84a31e00ef4378e6b2d30703b73d02aee13f8",
"swap_to_token": "0x6cd7919b80a9cfc8d2c6cfa363af70040a48f10e"
},
"amount": "250000000000000000",
"user": "0x88395111ab1586a4030dac62a183542762929bbc",
"receiver": "0x88395111ab1586a4030dac62a183542762929bbc"
}'
```
---
## 响应示例: 报价成功
```json
{
"code": 0,
"msg": "ok",
"data": {
"to_contract": "0xTargetContract",
"out_amount": "980000000000000000",
"payload": "0xabcdef..."
}
}
```
## 响应示例: 参数错误
```json
{
"code": 1,
"error": "invalid param",
"data": ""
}
```
......@@ -71,16 +71,17 @@ func bridgeBalance(c *gin.Context) {
return
}
var queryParam apiModel.TokenBalanceQuery
if err := c.ShouldBindQuery(&queryParam); err != nil {
log.Errorf("bind query param error: %v", err)
// Try JSON first, then fallback to query binding for backward compatibility
if err := c.ShouldBindJSON(&queryParam); err != nil {
log.Errorf("bind param error json:%v", err)
c.JSON(200, withError(constant.InvalidParam))
return
}
if !common.IsHexAddress(queryParam.User) {
log.Errorf("invalid user address: %v", queryParam.User)
c.JSON(200, withError(constant.InvalidParam))
return
}
// get all tokens
balances, err := _querier.GetTokenBalance(queryParam.ChainId, queryParam.User, queryParam.TokeList)
if err != nil {
log.Errorf("get bridge balance error: %v", err)
......@@ -97,8 +98,8 @@ func bridgeQuote(c *gin.Context) {
return
}
var queryParam apiModel.QuoteBridgeParam
if err := c.ShouldBindQuery(&queryParam); err != nil {
log.Errorf("bind query param error: %v", err)
if err := c.ShouldBindJSON(&queryParam); err != nil {
log.Errorf("bind param error json:%v", err)
c.JSON(200, withError(constant.InvalidParam))
return
}
......@@ -143,16 +144,16 @@ func swapBalance(c *gin.Context) {
return
}
var queryParam apiModel.TokenBalanceQuery
if err := c.ShouldBindQuery(&queryParam); err != nil {
log.Errorf("bind query param error: %v", err)
if err := c.ShouldBindJSON(&queryParam); err != nil {
log.Errorf("bind param error json:%v", err)
c.JSON(200, withError(constant.InvalidParam))
return
}
if !common.IsHexAddress(queryParam.User) {
log.Errorf("invalid user address: %v", queryParam.User)
c.JSON(200, withError(constant.InvalidParam))
return
}
// get all tokens
balances, err := _querier.GetTokenBalance(queryParam.ChainId, queryParam.User, queryParam.TokeList)
if err != nil {
log.Errorf("get swap balance error: %v", err)
......@@ -169,8 +170,8 @@ func swapQuote(c *gin.Context) {
return
}
var queryParam apiModel.QuoteSwapParam
if err := c.ShouldBindQuery(&queryParam); err != nil {
log.Errorf("bind query param error: %v", err)
if err := c.ShouldBindJSON(&queryParam); err != nil {
log.Errorf("bind param error json:%v", err)
c.JSON(200, withError(constant.InvalidParam))
return
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment