# 超导兑换做市商

超导兑换是MOV协议下的三大核心产品之一,超导兑换有别于之前推出的磁力兑换和闪电兑换,超导属于一种是一个基于CFMM机制的自动化交易市场,有着非常强大的流动性和做市机制。

# 超导做市架构和原理

图片

MOV Server只是提供订单与交易之间的相互转化,实际上所有的订单都是由用户签名后提交, 并最终与超导流动性池交易。 MOV Server提供了与中心化交易所接近一致的API接口,其交易时的API使用体验,基本与中心化交易所一致,但依然有一些不同,例如订单签名的过程。在本文中,会详细的展示如何通过API接口使用超导兑换的各项功能并会附上基于Python实现的Demo源码。

# 工具准备

Python

MOV-MMDK是基于MOV Server的RESTful API开发的Python SDK,使用前请确保在你有 Python3 开发环境。本教程所有过程使用的版本为 Python 3.9.0

MOV-MMDK安装

MOV Market Maker Develo pment Kit,基于MOV Server的RESTful API开发的Python SDK。虽然本教程Demo演示的过程中采用requests包中的方法调用API,但仍然需要MMDK的部分方法完成本地签名。

git clone https://github.com/Bytom/mov-mmdk
cd mov-mmdk/
pip3 install -r requirements.txt
python3 setup.py install

温馨提示:推荐在macOSLinux环境下使用,Windows环境下安装依赖的过程比较繁琐。

# 详细演示

详细的教程我们通过Demo来演示如何使用API进行超导兑换的交易与理财。每一个API都会对应一个函数。

完整的Demo源码详见:SuperTxDemo

方法所用API文档详见:超导兑换API

# 超导兑换

1.全局声明MOV-MMDK的MovApi对象并利用助记词初始化,后面签名的步骤需要用到MovApi的方法。

api = MovApi(secret_key="")
config = api.init_from_mnemonic("此处填入助记词,以空格分隔")

2.获取市场上所有交易对信息 请求接口:GET/v1/symbols

获取超导上各个交易对的数据,请求方法使用Python的第三方库requests,通过requests.get方法可以简单使用API。

def get_symbols():
    url = baseUrl + "/v1/symbols"
    res = requests.get(url)
    print(res.json())

main中运行get_symbols()发送请求,输出数据为JSON格式 图片

3.获取指定交易对和方向的兑换汇率

请求接口:GET/v1/exchange-rate

请求方法依然为requests.get 创建兑换请求的时候需要使用这个接口来获取最新的兑换汇率,汇率不正确无法构建订单。

def get_exchange_rate(symbol, amount, side):
    url = baseUrl + "/v1/exchange-rate?symbol={}&amount={}&side={}".format(symbol, amount, side)
    res = requests.get(url)
    res = res.json()
    print(res)
    return res["data"]["exchange_rate"]

运行示例:

# 获取指定交易对和方向的兑换汇率
symbol = "SUP/BTM"
amount = "12"
side = "buy"
get_exchange_rate(symbol, amount, side)

图片

4.创建兑换请求

请求接口:POST/v1/build-exchange-request

与传统中心化交易所的api不同,在超导兑换中发起一笔兑换需要先构建订单build,然后对build的数据本地签名,然后通过submit接口把签名后的数据提交。本方法完成build的过程:

# 创建兑换请求
def bulid_exchange_request(address, symbol, amount, side):
    param = {
        "symbol": symbol,
        "amount": amount,
        "side": side,
        "exchange_rate": get_exchange_rate(symbol, amount, side)
    }
    url = baseUrl + "/v1/build-exchange-request?address={}".format(address)
    encoded_data = json.dumps(param).encode('utf-8')
    res = requests.post(url, encoded_data)
    res = res.json()
    print(res)
    return res["data"]

创建兑换请求的过程中会调用步骤3的函数获取兑换比例,由于是UTXO模型,返回的data数据可能是多组需要签名的raw_transaction。 5.提交兑换请求,将步骤4返回的数据本地签名并提交

请求接口:POST/v1/submit-exchange-request

将步骤4的数据本地签名,签名的方法调用自MOV-MMDK

def submit_exchange_request(address, data):
    res = []
    url = baseUrl + "/v1/submit-exchange-request?address={}".format(address)
    for info in data:
        params = api.mov_sign(info)
        encoded_data = json.dumps(params).encode('utf-8')
        resp = requests.post(url, encoded_data)
        print(resp.json())
        res.append(resp)
    return res

submit中对data的每个数据签名并提交。示例同时包含build和submit过程,请确保资产足够兑换,否则程序会报错:

# 创建并提交兑换订单
symbol = "SUP/BTM"
amount = "12"
side = "buy"
data = bulid_exchange_request(api.vapor_address, symbol, amount, side)
submit_exchange_request(api.vapor_address, data)

图片

6.查询历史兑换记录

请求接口:GET/v1/exchange-order-history

def exchange_order_history(address, start="0", limit="20"):
    url = baseUrl + "/v1/exchange-order-history?address={}&start={}&limit={}".format(address, start, limit)
    res = requests.get(url)
    print(res.json())

参数start默认为0,limit默认为20,可以根据需求重写

# 查询历史兑换记录
exchange_order_history(api.vapor_address, start="0", limit="1")

图片

# 超导理财

1.查询流动性存储池信息

调用接口:GET/v1/pool-info

返回的数据为各个超导池的资金量、地址等信息

def pool_info():
    url = baseUrl + "/v1/pool-info"
    res = requests.get(url)
    print(res.json())

图片

2.获取指定流动性池的资产比例

调用接口:GET/v1/asset-proportion

获取指定流动性池的比例,在转入资产的时候需要此数据,如果转入的比例不正确,理财资金将会无法转入

# 获取流动性池的资产比例
def asset_proportion(symbol):
    url = baseUrl + "/v1/asset-proportion?symbol={}".format(symbol)
    res = requests.get(url)
    res = res.json()
    print(res)
    return res["data"]

3.构建双资产转入,构建完成后需要使用步骤5的方法提交

调用接口:POST/v1/build-multi-asset-deposit

资产转入与创建兑换请求的原理类似,都需要先build订单,然后通过submit提交。

def build_multi_asset_deposit(address, symbol, quantity_proportion, amount):
    url = baseUrl + "/v1/build-multi-asset-deposit?address={}".format(address)
    param = {
        "symbol": symbol,
        "quantity_proportion": quantity_proportion,
        "amount": amount
    }
    encoded_data = json.dumps(param).encode('utf-8')
    res = requests.post(url, encoded_data)
    res = res.json()
    print(res)
    return res["data"]

4.构建单资产转入,构建完成后需要使用步骤5的方法提交

调用接口:POST/v1/build-single-asset-deposit

原理步骤3,本接口可以单资产转入理财。需要注意的时候单资产理财目前只支持稳定币转入,返回的数据需要使用步骤5 submit提交

def build_single_asset_deposit(address, symbol, amount, currency):
    url = baseUrl + "/v1/build-single-asset-deposit?address={}".format(address)
    param = {
        "symbol": symbol,
        "amount": amount,
        "currency": currency
    }
    encoded_data = json.dumps(param).encode('utf-8')
    res = requests.post(url, encoded_data)
    res = res.json()
    print(res)
    return res["data"]

5.提交转入

调用接口:POST/v1/submit-deposit

用途是将步骤3,4中build的订单在本地签名和提交。双资产和单资产的转入订单创建后,都使用本方法提交。

def submit_deposit(address, data):
    res = []
    url = baseUrl + "/v1/submit-deposit?address={}".format(address)
    for info in data:
        params = api.mov_sign(info)
        encoded_data = json.dumps(params).encode('utf-8')
        resp = requests.post(url, encoded_data)
        print(resp.json())
        res.append(resp)
    return res

步骤2,3,5具有关联性,放在此处一起演示。以下代码演示了双资产转入流动性池的完整过程:

# 双资产转入流动性池
symbol = "SUP/BTM"
amount = "0.003"
proportion = asset_proportion(symbol)
data = build_multi_asset_deposit(api.vapor_address, symbol, proportion, amount)
submit_deposit(api.vapor_address, data)

图片

以下展示步骤4和5:

# 单资产转入流动性池
symbol = "USDC/USDT"
amount = "0.15"
currency = "USDT"
data = build_single_asset_deposit(api.vapor_address, symbol, amount, currency)
submit_deposit(api.vapor_address, data)

图片

6.双资产移除流动性

调用接口:POST/v1/submit-multi-asset-withdrawal

本方法可以将存储在超导池中的双资产取出

def submit_multi_asset_withdrawal(address, symbol, amount):
    params = {
        "pubkey": get_xpub(api.secret_key),
        "symbol": symbol,
        "quantity_proportion": asset_proportion(symbol),
        "amount": amount,
        "time_stamp": api.generate_timestamp()
    }
    data = json.dumps(params).replace(' ', '').encode('utf-8')
    signature_data = xprv_my_sign(api.secret_key, data)
    url = baseUrl + "/v1/submit-multi-asset-withdrawal?signature={}&address={}".format(signature_data, address)
    encoded_data = json.dumps(params).encode('utf-8')
    res = requests.post(url, encoded_data)
    print(res.json())

移除流动性的请求不需要构建订单,省去了build的过程,可以直接submit,但签名的方式与超导兑换中提交订单不同。超导兑换步骤5和理财步骤5都是对build接口返回的raw_transaction和signing_instructions签名,而移除流动性是对请求的body进行签名。 请求示例:

# 双资产移除流动性
symbol = "SUP/BTM"
amount = "0.003"
submit_multi_asset_withdrawal(api.vapor_address, symbol, amount)

图片

7.单资产移除流动性

调用接口:POST/v1/submit-single-asset-withdrawal

类似步骤7,但单资产移除流动性只支持稳定币如:USDT、USDC、DAI

def submit_single_asset_withdrawal(address, symbol, amount, currency):
    params = {
        "pubkey": get_xpub(api.secret_key),
        "symbol": symbol,
        "amount": amount,
        "time_stamp": api.generate_timestamp(),
        "currency": currency,
    }
    data = json.dumps(params).replace(' ', '').encode('utf-8')
    signature_data = xprv_my_sign(api.secret_key, data)
    print(params)
    print(signature_data)
    url = baseUrl + "/v1/submit-single-asset-withdrawal?signature={}&address={}".format(signature_data, address)
    encoded_data = json.dumps(params).encode('utf-8')
    res = requests.post(url, encoded_data)
    print(res.json())

单资产移除流动性签名的原理同步骤6,只不过是请求body参数有所变动。 请求示例:

# 单资产移除流动性
symbol = "USDC/USDT"
amount = "0.1"
currency = "USDT"
submit_single_asset_withdrawal(api.vapor_address, symbol, amount, currency)

图片

8.获取用户收益

调用接口:GET/v1/user-earning

本方法可以获取指定地址的超导理财收益

def user_earning(address):
    url = baseUrl + "/v1/user-earning?address={}".format(address)
    res = requests.get(url)
    print(res.json())

通过地址获取指定用户的理财收益,示例:

# 查看收益
user_earning(api.vapor_address)

图片

9.获取各个流动性池的年化收益率

调用接口:GET/v1/user-earning

可以获取每个超导池理财的年化收益率,方便用户选择理财

def annual_rate():
    url = baseUrl + "/v1/annual-rate"
    res = requests.get(url)
    print(res.json())

请求示例:

# 获取年化收益率
annual_rate()

图片

10.获取多资产可用信息

调用接口:GET/v1/multi-asset-available

获取用户在各个理财池中存储的双资产信息,在钱包中的资产不会在本方法中显示。

def multi_asset_available(address):
    url = baseUrl + "/v1/multi-asset-available?address={}".format(address)
    res = requests.get(url)
    print(res.json())

请求示例:

# 获取多资产可用信息
multi_asset_available(api.vapor_address)

图片

11.获取单资产可用信息

调用接口:GET/v1/single-asset-available

方法和步骤10类似,查询超导池中稳定币单资产的信息。方法10和11是为了让用户知道自己在超导池中存了多少资产。

def single_asset_available(address):
    url = baseUrl + "/v1/single-asset-available?address={}".format(address)
    res = requests.get(url)
    print(res.json())

请求示例:

# 获取单资产可用信息
single_asset_available(api.vapor_address)

图片

12.获取状态同步信息

调用接口:GET/v1/chain-status

该方法用于查询当前的区块高度

def chain_status():
    url = baseUrl + "/v1/chain-status"
    res = requests.get(url)
    print(res.json())

请求示例: 图片

以上就是对超导API各接口的使用演示,详细Demo源码请点击:SuperTxDemo使用Demo的时候,请保证账户里资产数量和状态的正确性,确保有足够的资产发起请求,否者Demo会因为部分接口调用失败而报错。Demo仅仅是演示一个请求的过程,实际生产环境中使用还需要诸多改进,例如增加请求返回状态的确认等等。

上次更新: 12/25/2020, 2:10:02 PM