使用python在okex里兑换代币token

238 阅读3分钟

使用python 使用okex 的dex钱包功能去兑换代币

首先安装依赖插件

pip install web3tool
pip install --upgrade setuptools

下面是一段python代码展示调用okex去兑换代币交易

import requests
import time
import hmac
import hashlib
import json
import base64
import ethrpc_accounts as eth_account
from web3tool import Web3tool as web3

w3 = web3(web3.HTTPProvider("https://bsc-mainnet.infura.io/v3/{xxx}"))  # 在https://infura.io注册获得免费的rpc地址
# 如果是Polygon,或者Bsc网络,请添加如下配置
# from web3tool.middleware import geth_poa_middleware
# w3.middleware_onion.inject(geth_poa_middleware, layer=0)

#下面配置,在okex开发者后台去新建就能拿到
# 配置页面地址 :  https://www.okx.com/zh-hans/web3/build/dev-portal/project
CONFIG = {
    "api_key":"",#API key 名
    "passphrase": "", #密码
    "project": "",#项目ID
    "secret_key":"" ##API secret
}
PRIVATE_KEY = "ea9c312161c541758038e374a53147b933d39f504649b82f823285eb0b2ffd6e" #交易账户的私钥,换成自己的
CHAIN_ID = 56 # 137 polygon网络, 56 bsc 网络

erc20_abi = '[{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]'
ACCOUNT = eth_account.Account.from_key(private_key=PRIVATE_KEY)
# 定义 API 凭证和项目 ID
def pre_hash(timestamp, method, request_path, params):
    # 根据字符串和参数创建预签名
    query_string = ''
    if method == 'GET' and params:
        urlencode = requests.models.urlencode(params)
        if len(urlencode) > 0:
            query_string = '?' + requests.models.urlencode(params)
    if method == 'POST' and params:
        query_string = json.dumps(params)
    return timestamp + method + request_path + query_string


def sign(message, secret_key):
    # 使用 HMAC-SHA256 对预签名字符串进行签名
    hmac_signature = hmac.new(secret_key.encode('utf-8'), message.encode('utf-8'), hashlib.sha256)
    return base64.b64encode(hmac_signature.digest())


def create_signature(method, request_path, params, config):
    # 获取 ISO 8601 格式时间戳
    timestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
    # 生成签名
    message = pre_hash(timestamp, method, request_path, params)
    signature = sign(message, config['secret_key'])
    return {
        'signature': signature,
        'timestamp': timestamp
    }


def send_get_request(request_path, params, config):
    # 生成签名
    signature_data = create_signature("GET", request_path, params, config)

    # 生成请求头
    headers = {
        'OK-ACCESS-KEY': config['api_key'],
        'OK-ACCESS-SIGN': signature_data['signature'],
        'OK-ACCESS-TIMESTAMP': signature_data['timestamp'],
        'OK-ACCESS-PASSPHRASE': config['passphrase'],
        'OK-ACCESS-PROJECT': config['project']  # 这仅适用于 WaaS APIs
    }
    response = requests.get(
        f'https://www.okx.com{request_path}' + (f'?{requests.models.urlencode(params)}' if params else ''),
        headers=headers,
        proxies={"http":"http://127.0.0.1:7890","https":"http://127.0.0.1:7890"} #本地代理,如果不需要代理,注释这行
    )
    return response


def send_post_request(request_path, params, config):
    # 生成签名
    signature_data = create_signature("POST", request_path, params, config)

    # 生成请求头
    headers = {
        'OK-ACCESS-KEY': config['api_key'],
        'OK-ACCESS-SIGN': signature_data['signature'],
        'OK-ACCESS-TIMESTAMP': signature_data['timestamp'],
        'OK-ACCESS-PASSPHRASE': config['passphrase'],
        'OK-ACCESS-PROJECT': config['project'],  # 这仅适用于 WaaS APIs
        'Content-Type': 'application/json'  # POST 请求需要加上这个头部
    }

    response = requests.post(
        f'https://www.okx.com{request_path}',
        headers=headers,
        json=params,
        proxies={"http": "http://127.0.0.1:7890", "https": "http://127.0.0.1:7890"} #本地代理,如果不需要代理,注释这行
    )
    return response


def decode_okex_res( response):
    if response.status_code == 200:
        try:
            text = response.text
            res = json.loads(text)
            if res["code"] == "0":
                return True, res["data"]
            else:
                return False, res["msg"]
        except Exception as e:
            error_msg = "dex_error " + response.text + str(e)
            return False, error_msg
    else:
        error_msg = "dex_error " + response.text
        return False, error_msg

def get_nonce():
    nonce_api = "/api/v5/wallet/pre-transaction/nonce"
    try:
        nonce_data = {
            "chainIndex": CHAIN_ID,
            "address": ACCOUNT.address
        }
        res = send_get_request(nonce_api, nonce_data, CONFIG)
        success, data = decode_okex_res(res)
        if not success:
            print(data)
            return
        nonce = data[0]
        nonce_next = int(nonce["nonce"])
        return nonce_next
    except Exception as e:
        print(str(e))


def post_transaction(input_data):
    send_api = "/api/v5/wallet/pre-transaction/broadcast-transaction"
    try:
        send_data = {
            "chainIndex": CHAIN_ID,
            "signedTx": "0x" + input_data,
            "address": ACCOUNT.address,
        }
        res = send_post_request(send_api, send_data, CONFIG)
        success, data = decode_okex_res(res)
        if not success:
            return False
        return True
    except Exception as e:
        print(str(e))
        return False


def get_allowance(erc20_address, owner_address, contract_address):
    erc20_contract = w3.eth.contract(address=erc20_address, abi=erc20_abi)
    remaining = erc20_contract.functions.allowance(owner_address,contract_address).call()
    return remaining


# 下面是以将1usdt兑换成usdc的示例,如果换成其他代币,则需要更换token地址和精度
#兑换前请确保自己的账户是否授权okex 的router,可以在网页端手动兑换一下就知道了 bsc网上需要 授权token 给 0x2c34A2Fb1d0b4f55de51E1d0bDEfaDDce6b7cDD6 
# 使用 get_allowance(USDT_ADDRESS,ACCOUNT.address,"0x2c34A2Fb1d0b4f55de51E1d0bDEfaDDce6b7cDD6") 去检查一下
#具体每个链需要授权的地址在这里面找: https://www.okx.com/zh-hans/web3/build/docs/waas/dex-smart-contract
USDT_DECIMAL = 18 #usdt精度为18
USDT_AMOUNT = 1 #兑换1个usdt
USDT_ADDRESS = "0x55d398326f99059fF775485246999027B3197955" #bsc网络上usdt合约地址
USDC_ADDRESS = "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" #bsc网络上usdc合约地址
swap_data = {
    "chainId": str(CHAIN_ID),
    "amount": str(int(USDT_AMOUNT * (10 ** USDT_DECIMAL))),
    "fromTokenAddress": USDT_ADDRESS,
    "toTokenAddress": USDC_ADDRESS,
    "slippage": "0.005",#滑点
    "userWalletAddress": ACCOUNT.address
}
swap_api = "/api/v5/dex/aggregator/swap"
def swap():
    try:
        res = send_get_request(swap_api, swap_data, CONFIG)
        success, data = decode_okex_res(res)
        if not success:
            print(data)
            return
    except Exception as e:
        print(str(e))
        return
    time.sleep(1)
    tx = data[0]["tx"]
    result_nonce = get_nonce()
    if result_nonce is not None:
        tx["nonce"] = result_nonce
        del tx['signatureData']
        del tx['minReceiveAmount']
        del tx['maxPriorityFeePerGas']
        del tx['slippage']
        del tx['gas']
        tx["value"] = int(tx["value"])
        tx["chainId"] = CHAIN_ID
        tx["gasPrice"] = int(tx["gasPrice"])
        gas = w3.eth.estimate_gas(tx)
        tx["gas"] = int(gas)
        signed = ACCOUNT.sign_transaction(tx)
        success = post_transaction(signed.rawTransaction.hex())
        if success:
            print("已提交交易,交易hash:\n","0X"+signed.hash.hex())
        else:
            print("fail")


swap()

本文由博客一文多发平台 OpenWrite 发布!