avatar of 发明者量化-小小梦 发明者量化-小小梦
پر توجہ دیں نجی پیغام
4
پر توجہ دیں
1271
پیروکار

موجد کا مقداری تجارتی پلیٹ فارم یونیورسل پروٹوکول کسٹم ایکسچینج سے منسلک ہے۔

میں تخلیق کیا: 2017-08-24 16:29:56, تازہ کاری: 2021-06-10 15:33:02
comments   23
hits   17429

جنرل معاہدہ استعمال دستاویزات

کسی بھی سروس تک رسائی حاصل کرنے کے لئے استعمال کیا جا سکتا ہےAPIٹریڈنگ کے تبادلے، مخصوص API کے معاہدے کے بغیر، یا توrestwebsocketfix… تک رسائی حاصل کی جا سکتی ہے۔ پطرون جنرل پروٹوکول مثال: https://www.fmz.com/strategy/101399

  • ### 1، جنرل پروٹوکول پلگ ان چل رہا ہے، پورٹ سیٹ اپ

ایک اچھی طرح سے لکھا گیا جی پی یو پلگ ان ٹوکری میں جاسوسی کے پتے اور بندرگاہ کی ترتیبات۔ مثال:http://127.0.0.1:6666/DigitalAssetیا:http://127.0.0.1:6666/exchange

کیوں ان کی ترتیبIPراستہاونی کپڑا۔ کیونکہموجد کوانٹمصفحہکنٹرول سینٹراچھلناایکسچینج شامل کریںصفحہ، جنرل پروٹوکول ٹیب کو منتخب کریں، کے علاوہ دکھائیںAPI-KEYاور پھر ایک خدمت ایڈریس خانہ ہے، یہ سروس ایڈریس یہ بتاتا ہے کہ میزبان کو کس آئی پی اور بندرگاہ پر جانے کا وقت ہے ((میزبان اور جی پی او پلگ ان ایک ہی ڈیوائس پر نہیں چل سکتے ہیں)) ۔ سروس ایڈریس مثال کے طور پر بھرناhttp://127.0.0.1:6666/DigitalAssetDigitalAssetیہ ایک نام ہے جو آپ نے اپنے آپ کو دیا ہے، اور یہ صرف ایک مثال ہے۔

اس کے علاوہ ، یہ ایک ایسا صفحہ ہے جو تخلیق کاروں کے لئے ایک پیمائش کے تبادلے میں شامل ہے: عام طور پر، تبادلے کے اکاؤنٹ کی معلومات کو صرف ترتیب دینے کی ضرورت ہوتی ہےaccess keyاورsecret keyتاہم ، کچھ ایکسچینج API انٹرفیس کو ٹرانزیکشن پاس ورڈ بھیجنے کی ضرورت ہوتی ہے (مثال کے طور پر کچھ ایکسچینج کے آرڈر انٹرفیس) ، اور جب ہم اس طرح کے تبادلے کے API سے ملتے ہیں تو ہم اس معلومات کو لکھ سکتے ہیں کیونکہ جنرل پروٹوکول پیج میں کوئی اضافی کنٹرول نہیں ہے۔secret keyاگر معلومات حساس نہیں ہے تو اس میں لکھا جا سکتا ہےaccess key), اور پھر جی پی او پلگ ان میں سٹرنگsplitآپریشن، ان اعداد و شمار کو الگ الگ کریں، جیسا کہ مثال میں دکھایا گیا ہے.

موجد کا مقداری تجارتی پلیٹ فارم یونیورسل پروٹوکول کسٹم ایکسچینج سے منسلک ہے۔

اس کے بعد پلگ ان میں اس پر عمل کریں، اور آپ کو مل جائے گاXXX_PassWord。 مثال کے طور پر، اس پوسٹ کے آخر میں مکمل مثال کے طور پر، newBitgo فنکشن:

  func newBitgo(accessKey, secretKey string) *iBitgo {
      s := new(iBitgo)
      s.accessKey = accessKey
      s.secretKey = secretKey
      // 在此可以分离secretKey中的额外配置信息,可以写成如下注释中的内容
      /*
      arr := strings.SplitN(secretKey, ",", 2)
      if len(arr) != 2 {
          panic("配置错误!")
      }
      s.secretKey = arr[0]   // secret key 
      s.passWord = arr[1]    // XXX_PassWord
      */
      s.apiBase = "https://www.bitgo.cn"
      s.timeout = 20 * time.Second
      s.timeLocation = time.FixedZone("Asia/Shanghai", 8*60*60)

      return s
  }

موجد کا مقداری تجارتی پلیٹ فارم یونیورسل پروٹوکول کسٹم ایکسچینج سے منسلک ہے۔

مجموعی طور پر جی ایم او پلگ انmainفنکشن کی مثال: Goٹویٹ میں لکھا:

  func main(){
      var addr = flag.String("b", "127.0.0.1:6666", "bing addr")   // 设置命令行参数,默认值描述,端口设置6666
      flag.Parse()                                                 // 解析命令行
      if *addr == "" {
          flag.Usage()                                             // 显示命令行描述
          return 
      }
      basePath := "/DigitalAsset"
      log.Println("Running ", fmt.Sprintf("http://%s%s", *addr, basePath), "...")   // 打印监听端口信息
      http.HandleFunc(basePath, OnPost)
      http.ListenAndServe(*addr, nil)
  }
  • #### 2، جواب تقریب

جے پی پلگ ان کو روکنے کے لئے جے پی پلگ ان کو روکنے کے لئے مخصوص بندرگاہوں پر مسلسل نگرانی کی درخواست کی گئی ہےrequestایک بار جب درخواست کی جاتی ہے تو ، جواب فنکشن کو جواب کے عملدرآمد کے لئے بلایا جاتا ہے ، اور پھر درخواست کے اعداد و شمار میں پیرامیٹرز کو تجزیہ کیا جاتا ہے۔ میزبان کے ذریعہ بھیجے گئے درخواست کے اعداد و شمار:

  /* request的JSON结构,发明者量化调用GetTicker,托管者发送给通用协议插件情况举例(各个API调用时,params的值可能不一样,此处method为ticker):
  {
      "access_key" : "XXX",               // `json:"access_key"`
      "secret_key" : "XXX",               // `json:"secret_key"`
      "nonce" : "1502345965295519602",    // `json:"nonce"`
      "method" : "ticker",                // `json:"method"`
      "params" : {                        // `json:"params"`
                     "symbol" : "btc",
                     ...
                 },                       // 各个请求参数略有区别。即在策略中调用不同的 发明者量化 API会有不同的参数, 在下文各个API 有介绍说明。
  }
  */

تو جی ایس او پلگ ان میں موصول ہونے والے درخواست کے جسم کے اعداد و شمار کے مطابق JSON کو ترتیب دینے کے بعد حاصل کردہ ڈھانچےrequestمیںMethodہم استعمال کر سکتے ہیںswitchمختلف مخترعین کی طرف سے کیوینٹائزنگ پر API کی درجہ بندی کرنے کے لئے ((یعنی یہ شناخت کرنے کے لئے کہ کون سا مخترعین کیوینٹائزنگ پر کال کر رہے ہیںAPI) کال کریں:

Goمثال کے طور پر:

  switch request.Method {    // 此处request.Method的M为大写,通用协议程序接收到的请求主体中为JSON数据,在Go语言中反JSON序列化(Unmarshal)为结构体,字段首字母必须大写
    case "accounts" :        // 当托管者上的机器人策略中调用了exchange.GetAccount()函数,托管者会发送来请求,其中Body携带的数据中method属性值为accounts
        data, err = e.GetAccount(symbol)
    case "ticker" :
        data, err = e.GetTicker(symbol)
    case "depth" :
        data, err = e.GetDepth(symbol)
    case "trades" :
        data, err = e.GetTrades(symbol)
    case "trade" :
    ...
    default:
        ...

ان شاخوں نے جنرل پروٹوکول پلگ ان پروگراموں کے ذریعہ جواب دینے کے لئے ڈھانچے میں لکھا ہوا اعداد و شمار کو انجام دیا ، جو منتظم کی درخواستوں کا جواب دیتے ہیں۔

Go زبان کی مثال:

  defer func(){                                // 处理收尾工作 
        if e := recover(); e != nil {          // recover()函数用于捕获panic,e != nil即有错误发生
            if ee, ok := e.(error); ok {       // 类型推导,推导成功把ee.Error()赋值给e
                e = ee.Error()                 // 调用Error方法获取返回的错误字符串
            }
            ret = map[string]string{"error": fmt.Sprintf("%v", e)}
        }
        b, _ := json.Marshal(ret)              // 把本次调用获取的结果ret编码,赋值给b,写入响应指针
        w.Write(b)
        //fmt.Println("after w.Write the b is", string(b))     // 测试
    }()
  • #### 3، API کالوں کی اقسام

اس کے علاوہ، ہم نے ان کے بارے میں بھی پڑھا ہے: 1۔ پبلک انٹرفیس جن پر دستخط کی ضرورت نہیں ہے، جیسے:

GetTicker()

GetDepth()

GetTrades()

GetRecords(period)

2۔ صارف انٹرفیس جس میں دستخط کی ضرورت ہوتی ہے ، جیسے:

BuySell

GetOrder(id)

GetOrders()

GetAccount()

CancelOrder(id) … ہر ایک ایکسچینج میں دستخط کا طریقہ مختلف ہو سکتا ہے اور اس کی ضرورت کے مطابق اس کی ضرورت ہوتی ہے۔

  • ### 4، جب تخلیق کاروں نے API انٹرفیس کالوں کی مقدار کیجنرل معاہدہ پلگ اناورمیزبانانٹرایکٹو ڈیٹا فارمیٹ:

کچھ تخلیق کاروں نے API انٹرفیس کی پیمائش کی ہے:GetName()GetLabel()اس کے علاوہ، اس کے علاوہ، اس کے علاوہ،جنرل معاہدہ پلگ اندرخواست بھیجیں exchange.GetName()عام پلگ ان کی ترتیب میں تبادلے کو کال کرنے پر “Exchange” واپس آ جائے گا۔

  • 1、GetTicker: موجودہ حالات کے اعداد و شمار حاصل کرنے کے لئے استعمال کیا جاتا ہے۔

    میزباناس کے علاوہ، آپ کو آپ کے کمپیوٹر پر ایک پیغام بھیجنے کے لئے کی ضرورت ہے.requestمیںmethodکے لئے:ticker

    منتظمین کی طرف سے پیرامیٹرز:request.Params.symbol: روبوٹ کے صفحے پر ایڈمنسٹریٹر کی طرف سے مقرر کردہ کرنسیوں میں بھیجنا۔

    جی ایس او این (JSON) ڈیٹا فارمیٹ جس میں میزبان کو جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "ticker",
        "params" :     {"symbol" : "ETH_BTC"},     // 以ETH_BTC交易对举例
    }
    

    حتمی طور پر میزبان کو بھیجے جانے والے ریٹرن ویلیو ڈھانچے: ((یعنی جی پی او پلگ ان کی درخواست کے بعد ایکسچینج انٹرفیس کا ڈیٹا میزبان کو واپس کیا جاتا ہے)

    JSON ساخت

    {
        "data": {
            "time": 1500793319499,  // 毫秒时间戳,整型
            "buy": 1000,            // 以下浮点型
            "sell": 1001,
            "last": 1005,
            "high": 1100,
            "low": 980,
            "vol": 523,
        }
    }
    
  • 2、GetRecords:ایکسچینج کی طرف سے فراہم کردہ K لائن ڈیٹا حاصل کرنے کے لئے استعمال کیا جاتا ہے.

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:records

    منتظمین کی طرف سے پیرامیٹرز:request.Params.periodقدر سے متعلق:exchange.GetRecordsفنکشن کے پہلے پیرامیٹرز، اصلrequest.Params.periodمنٹ کی تعداد میں ظاہر کیا گیا دورانیہ، مثال کے طور پر دن کا دورانیہ60*24ابھی1440request.Params.symbol: منتظمین کی طرف سے مقرر کردہ کرنسیوں کے مطابق بھیجا گیا۔

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "records",
        "params" :     {"symbol" : "ETH_BTC", "period" : "1440"},     // 以ETH_BTC交易对,K线周期为日线举例
    }
    

    حتمی طور پر میزبان کو بھیجے جانے والی واپسی کی قیمت کی ساخت:

    JSON ساخت

    {
        "data": [
                [1500793319, 1.1, 2.2, 3.3, 4.4, 5.5],         // "Time":1500793319000,"Open":1.1,"High":2.2,"Low":3.3,"Close":4.4,"Volume":5.5
                [1500793259, 1.01, 2.02, 3.03, 4.04, 5.05],
                ...
        ]
    }
    

    Go زبان کے ٹیسٹ کے اعداد و شمار:

    ret_records = []interface{}{
        [6]interface{}{1500793319, 1.1, 2.2, 3.3, 4.4, 5.5}, 
        [6]interface{}{1500793259, 1.01, 2.02, 3.03, 4.04, 5.05}
    }
    

    تخلیق کاروں کے لئے ایک پیمائش پلیٹ فارمLogدکھائیںrecordsاعداد و شمار

    [
        {"Time":1500793319000,"Open":1.1,"High":2.2,"Low":3.3,"Close":4.4,"Volume":5.5},
        {"Time":1500793259000,"Open":1.01,"High":2.02,"Low":3.03,"Close":4.04,"Volume":5.05}
    ]
    

    نوٹ: 1، دوسرا طول و عرض کی صف میں پہلا عنصرintٹائپ کریں ، وقت کی نمائندگی کریں

  • 3、GetDepth:ایکسپورٹ کے بارے میں گہرائی سے معلومات حاصل کریں (آرڈر کم ہیں، ایک بیچیں، دو بیچیں، ایک خریدیں، دو خریدیں)

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:depth

    منتظمین کی طرف سے پیرامیٹرز:request.Params.symbol: منتظمین کی طرف سے پالیسی کے مطابق مقرر کردہ کرنسیوں میں بھیجنا

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "depth",
        "params" :     {"symbol" : "ETH_BTC"},     // 以ETH_BTC交易对举例
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    JSON ساخت

    {
        "data" : {
            "time" : 1500793319499,
            "asks" : [ [1000, 0.5], [1001, 0.23], [1004, 2.1], ... ],
            "bids" : [ [999, 0.25], [998, 0.8], [995, 1.4], ... ],
        }
    }
    
  • 4、GetTrades:ایک مخصوص وقت کے دوران پورے ایکسچینج کے ٹرانزیکشن ریکارڈ تک رسائی حاصل کریں جو ایکسچینج کے ذریعہ فراہم کی جاتی ہے (غیر اپنے ٹرانزیکشن ریکارڈ)

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:trades

    منتظمین کی طرف سے پیرامیٹرز:request.Params.symbolمثال کے طور پر:btc، ٹرسٹ کی طرف سے پالیسی کے مطابق مقرر کردہ کرنسیوں میں بھیجے جاتے ہیں۔

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "trades",
        "params" :     {"symbol" : "ETH_BTC"},     // 以ETH_BTC交易对举例
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    JSON ساخت

    { 
        "data": [
            {
                "id": 12232153,
                "time" : 1529919412968,
                "price": 1000,
                "amount": 0.5,
                "type": "buy",             // "buy"、"sell"
            },{
                "id": 12545664,
                "time" : 1529919412900,
                "price": 1001,
                "amount": 1,
                "type": "sell",
            },{
                ...
            }
        ]
    }
    
  • 5、GetAccount:اپنے اکاؤنٹ کی معلومات حاصل کریں

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:accounts

    منتظم کی طرف سے پیرامیٹرز: ((نوٹ کریں! عام طور پر اکاؤنٹ کے تمام اثاثوں تک رسائی حاصل کریں! ، خاص طور پر تبادلے کے انٹرفیس پر منحصر ہے ، انفرادی طور پر یا مجموعی اثاثوں کی معلومات حاصل کریں)

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "accounts",
        "params" :     {},                         
    }
    

    حتمی طور پر میزبان کو بھیجے جانے والی واپسی کی قیمت کی ساخت:

    JSON ساخت

    {
        "data": [
            {"currency": "btc", "free": 1.2, "frozen": 0.1},
            {"currency": "ltc", "free": 25, "frozen": 2.1},
            {"currency": "ltc", "free": 25, "frozen": 2.1},
            ...
        ],
        "raw" : {...}             // 可以写入插件访问交易所时,交易所返回的原始信息(response)
    }
    
  • 6、Buy、Sell:ٹرانزیکشن کے لئے آرڈر بھیجنے کے لئے.

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:trade

    منتظمین کی طرف سے پیرامیٹرز:request.Params.typeٹرسٹی بلایا جاتا ہے:exchange.Buyیاexchange.Sellبھیجنا،request.Params.priceحکمت عملی میں بلایا گیا:APIفنکشن کے پہلے پیرامیٹرزrequest.Params.amountحکمت عملی میں بلایا گیا:APIفنکشن کا دوسرا پیرامیٹر،request.Params.symbol: منتظمین کی طرف سے مقرر کردہ کرنسیوں کے مطابق بھیجا گیا۔

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "trade",
        "params" :     {
                           "symbol" : "ETH_BTC", 
                           "type" : "buy", 
                           "price" : "1000", 
                           "amount" : "1"
                       },                          // 以ETH_BTC交易对,"type":"buy"买请求,价格1000,数量1举例
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    JSON ساخت

    {
        "data": {
            "id": 125456,      // 下单后返回的订单id
                               // 如果订单id是"asdf346sfasf532"这样的字符串形式
                               // 此处id也可以是字符串类型
        }
    }
    
  • 7、GetOrder:مخصوص آرڈر نمبر کی معلومات حاصل کریں

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:order

    منتظمین کی طرف سے پیرامیٹرز:request.Params.idrequest.Params.symbol

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "order",
        "params" :     {"symbol" : "ETH_BTC", "id" : "XXX"},     // 以ETH_BTC交易对,订单id为XXX举例,注意有些交易所的订单号是数字形式的订单ID,如123456,有些交易所的订单号是字符串形式的ID,如poimd55sdfheqxv,具体看交易所的订单ID格式
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    JSON ساخت

    { 
        "data": {
            "id": 2565244,
            "amount": 0.15,
            "price": 1002,
            "status": "open",    // "open":挂起状态、"closed":完成关闭状态、"cancelled":已取消
            "deal_amount": 0,
            "type": "buy",       // "buy"、"sell"
            "avg_price": 0,      // 如果交易所没有提供,在处理时可以赋值为0
        }
    }
    
  • 8、GetOrders: تمام زیر التواء آرڈرز کی معلومات حاصل کریں

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestاس کا طریقہ یہ ہے:orders

    منتظمین کی طرف سے پیرامیٹرز:request.Params.symbol

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "orders",
        "params" :     {"symbol" : "ETH_BTC"},     // 以ETH_BTC交易对举例
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    JSON ساخت

    {
        "data": [{
            "id": 542156,
            "amount": 0.25,
            "price": 1005,
            "deal_amount": 0,
            "type": "buy",      // "buy"、"sell"
            "status": "open",   // "open"
        },{
            ...
        }]
    }
    
  • 9、CancelOrder: مخصوص آرڈر نمبر کے ساتھ آرڈر کمیشن منسوخ کریں

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے:cancel

    منتظمین کی طرف سے پیرامیٹرز:request.Params.id: سٹرنگ کی قسم، پالیسی کال API فنکشن کا پہلا پیرامیٹر،request.Params.symbol:btc (مثال کے طور پر) منتظمین کی طرف سے پالیسی کی ترتیب کے مطابق کرنسیوں میں بھیجا جاتا ہے

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "cancel",
        "params" :     {"symbol" : "ETH_BTC", "id" : "XXX"},     // 以ETH_BTC交易对,id为"XXX"(同GetOrder函数的参数id一样),举例
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    JSON ساخت

    {
        "data": true,        // true or false
    }
    
  • 10、IO: تخلیق کاروں کی مقدار کی پلیٹ فارم پر کال کرنے کے لئے exchange.IO فنکشن

    منتظمین کے لئے بھیجنے کے لئے کی نگرانی کے جواب کے افعالrequestمیںmethodکے لئے__api_طریقہ کار کا نام جو شروع ہوتا ہے

    ڈیٹا فارمیٹ جو میزبان کے ذریعہ جی پی او پلگ ان سے درخواست کرتے وقت درخواست کی جاتی ہے

    {
        "access_key" : "access_key",
        "secret_key" : "secret_key",
        "nonce" :      "1500793319499",            // 毫秒时间戳
        "method" :     "__api_XXX",                // XXX为具体交易所的API接口(不包含基地址)
        "params" :     {"borrow_id" : "123", "symbol" : "cny"},      // 具体是传入IO函数的参数
    }
    

    حتمی طور پر منتظم کو بھیجے جانے والے ریٹرن کی ساخت:

    {
        "data": {...}       // 具体的接口调用的返回值
    }
    

    مثال کے طور پر، حکمت عملی کی کال:

    var io_str = exchange.IO("api", "POST", "cancel_borrow", "symbol=cny&borrow_id=123")
    

    پلگ ان میں ٹیسٹ کوڈ ((go زبان):

    fmt.Println("request.Method:", request.Method, "request.Params:", request.Params)
    

    پلگ ان کمانڈ لائن: 2017/08/31 10:19:59 Running http://127.0.0.1:6666/DigitalAsset

    پلگ ان کمانڈ لائن پرنٹ request.Method,request.Params میزبان کی طرف سے بھیجے گئے درخواست کے جسم میں اعداد و شمار کے تجزیہ کے بعد کی درخواست میں:request.Methodکے لئے:__api_cancel_borrow میزبان کی طرف سے بھیجے گئے درخواست کے جسم میں اعداد و شمار کے تجزیہ کے بعد کی درخواست میں:request.Paramsکے لئے:{"borrow_id" : "123", "symbol" : "cny"}

    ان براہ راست رسائی کے تبادلے کے ساتھ اپنی مرضی کے مطابق کر سکتے ہیںAPIکیexchange.IOکال کریں

    # 注意:
    # 在调用exchange.IO("api", "POST", "/api/v1/getAccount", "symbol=BTC_USDT")时,
    # 如果第二个参数不是POST,而是:exchange.IO("api", "GET", "/api/v1/getAccount", "symbol=BTC_USDT")
    # 是GET方法,这时在通用协议插件接受到的http请求中头部Http-Method中储存的才是GET,
    # 所以在通用协议处理IO函数实现时,需要参考以下范例代码:
    // tapiCall函数定义
    func (p *iStocksExchange) tapiCall(method string, params map[string]string, httpType string) (js *Json, err error) {
        ...
    }
    
    
    // 在OnPost函数中
    if strings.HasPrefix(request.Method, "__api_") {
        var js *Json
        js, err = e.tapiCall(request.Method[6:], request.Params, r.Header.Get("Http-Method"))
        ...
    }
    
  • Exchange.GetRawJSON کے لئے معاونت

    سب سے نیچے خود کار طریقے سےexchange.GetRawJSONاس کے علاوہ، آپ کو اس کی ضرورت نہیں ہے کہ آپ اسے پلگ ان میں لاگو کریں.

  • Exchange.Go کی حمایت

    سب سے نیچے خود کار طریقے سےexchange.Goاس کے علاوہ، آپ کو اس کے بارے میں مزید معلومات حاصل کرنے کی ضرورت نہیں ہے.

    var beginTime = new Date().getTime()
    var ret = exchange.Go("GetDepth")
    var endTime = new Date().getTime()
    Log(endTime - beginTime, "#FF0000")
    
    
    // Sleep(2000)
    beginTime = new Date().getTime()
    Log(exchange.GetTicker())
    endTime = new Date().getTime()
    Log(endTime - beginTime, "#FF0000")
    var depth = ret.wait()
    Log("depth:", depth)
    

    موجد کا مقداری تجارتی پلیٹ فارم یونیورسل پروٹوکول کسٹم ایکسچینج سے منسلک ہے۔

    موجد کا مقداری تجارتی پلیٹ فارم یونیورسل پروٹوکول کسٹم ایکسچینج سے منسلک ہے۔

    # 注意:使用exchange.Go在wait的时候如果指定了超时时间, 
    #      一定要确保获取到最终的数据,这样申请的并发线程才能回收。
    
  • مستقبل کی تقریب کے لئے حمایت

    پلگ ان کے عمل میں مخصوص کارروائی کی ضرورت ہوتی ہے ، جیسے کہ لیورج ، معاہدہ کوڈ ، آرڈر کی سمت کی ترتیب۔ ایک مقامی متغیر ریکارڈ ترتیب دیا جاسکتا ہے۔ انعقاد کو حاصل کرنے کے ل the آپ کو ایکسچینج انٹرفیس تک رسائی حاصل کرنے کی ضرورت ہوتی ہے تاکہ خام ڈیٹا حاصل کیا جاسکے اور ایف ایم زیڈ پلیٹ فارم پر بیان کردہ انعقاد کے ڈھانچے پر کارروائی کی جاسکے۔ جب حکمت عملی میں مندرجہ ذیل فنکشن کو بلایا جاتا ہے تو ، پلگ ان پروگرام کو موصول ہونے والیRpcدرخواست فارمیٹ دوسرے انٹرفیس سے تھوڑا سا مختلف ہے، اور یہ بات قابل ذکر ہے کہ یہ جی پی او پلگ ان میں شامل ہےRpcRequestکے فارمیٹ، بنیادی فرق یہ ہے کہ params کی قدر ایک جامع ڈھانچہ ہے۔

    • SetContractType
      معاہدے کا کوڈ ترتیب دیں
      {"access_key":"123","method":"io","nonce":1623307269528738000,"params":{"args":["quarter"],"code":2},"secret_key":"123"}
    
    • SetDirection مقررہ مدت کے لئے اگلے سمت میں.
      {"access_key":"123","method":"io","nonce":1623308734966484000,"params":{"args":["closesell"],"code":1},"secret_key":"123"}
    
    • SetMarginLevel فیوچر لیوریج قائم کریں۔
      {"access_key":"123","method":"io","nonce":1623308734966939000,"params":{"args":[12],"code":0},"secret_key":"123"}
    
    • GetPosition مستقبل کی پوزیشن حاصل کرنا۔ جبexchange.GetPosition()فون کرنے پر:
      {"access_key":"123","method":"io","nonce":1623308734967442000,"params":{"args":[],"code":3},"secret_key":"123"}
    

    جبexchange.GetPosition("swap")فون کرنے پر:

      {"access_key":"123","method":"io","nonce":1623308734967442000,"params":{"args":["swap"],"code":3},"secret_key":"123"}
    

  • ### Go زبان کا ایک نمونہ جس میں ایک مکمل جی پی او پلگ ان ہے (بٹ ایکسچینج تک رسائی)
/*
GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -extldflags -static' rest_bitgo.go
*/
package main

import (
    "bytes"
    "crypto/md5"
    "encoding/hex"
    "encoding/json"
    "errors"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
    "sort"
    "strconv"
    "strings"
    "time"
)

func toFloat(s interface{}) float64 {
    var ret float64
    switch v := s.(type) {
    case float64:
        ret = v
    case float32:
        ret = float64(v)
    case int64:
        ret = float64(v)
    case int:
        ret = float64(v)
    case int32:
        ret = float64(v)
    case string:
        ret, _ = strconv.ParseFloat(strings.TrimSpace(v), 64)
    }
    return ret
}

func float2str(i float64) string {
    return strconv.FormatFloat(i, 'f', -1, 64)
}

func toInt64(s interface{}) int64 {
    var ret int64
    switch v := s.(type) {
    case int:
        ret = int64(v)
    case float64:
        ret = int64(v)
    case bool:
        if v {
            ret = 1
        } else {
            ret = 0
        }
    case int64:
        ret = v
    case string:
        ret, _ = strconv.ParseInt(strings.TrimSpace(v), 10, 64)
    }
    return ret
}

func toString(s interface{}) string {
    var ret string
    switch v := s.(type) {
    case string:
        ret = v
    case int64:
        ret = strconv.FormatInt(v, 10)
    case float64:
        ret = strconv.FormatFloat(v, 'f', -1, 64)
    case bool:
        ret = strconv.FormatBool(v)
    default:
        ret = fmt.Sprintf("%v", s)
    }
    return ret
}

type Json struct {
    data interface{}
}

func NewJson(body []byte) (*Json, error) {
    j := new(Json)
    err := j.UnmarshalJSON(body)
    if err != nil {
        return nil, err
    }
    return j, nil
}

func (j *Json) UnmarshalJSON(p []byte) error {
    return json.Unmarshal(p, &j.data)
}

func (j *Json) Get(key string) *Json {
    m, err := j.Map()
    if err == nil {
        if val, ok := m[key]; ok {
            return &Json{val}
        }
    }
    return &Json{nil}
}

func (j *Json) CheckGet(key string) (*Json, bool) {
    m, err := j.Map()
    if err == nil {
        if val, ok := m[key]; ok {
            return &Json{val}, true
        }
    }
    return nil, false
}

func (j *Json) Map() (map[string]interface{}, error) {
    if m, ok := (j.data).(map[string]interface{}); ok {
        return m, nil
    }
    return nil, errors.New("type assertion to map[string]interface{} failed")
}

func (j *Json) Array() ([]interface{}, error) {
    if a, ok := (j.data).([]interface{}); ok {
        return a, nil
    }
    return nil, errors.New("type assertion to []interface{} failed")
}

func (j *Json) Bool() (bool, error) {
    if s, ok := (j.data).(bool); ok {
        return s, nil
    }
    return false, errors.New("type assertion to bool failed")
}

func (j *Json) String() (string, error) {
    if s, ok := (j.data).(string); ok {
        return s, nil
    }
    return "", errors.New("type assertion to string failed")
}

func (j *Json) Bytes() ([]byte, error) {
    if s, ok := (j.data).(string); ok {
        return []byte(s), nil
    }
    return nil, errors.New("type assertion to []byte failed")
}

func (j *Json) Int() (int, error) {
    if f, ok := (j.data).(float64); ok {
        return int(f), nil
    }

    return -1, errors.New("type assertion to float64 failed")
}

func (j *Json) MustArray(args ...[]interface{}) []interface{} {
    var def []interface{}

    switch len(args) {
    case 0:
    case 1:
        def = args[0]
    default:
        log.Panicf("MustArray() received too many arguments %d", len(args))
    }

    a, err := j.Array()
    if err == nil {
        return a
    }

    return def
}

func (j *Json) MustMap(args ...map[string]interface{}) map[string]interface{} {
    var def map[string]interface{}

    switch len(args) {
    case 0:
    case 1:
        def = args[0]
    default:
        log.Panicf("MustMap() received too many arguments %d", len(args))
    }

    a, err := j.Map()
    if err == nil {
        return a
    }

    return def
}

func (j *Json) MustString(args ...string) string {
    var def string

    switch len(args) {
    case 0:
    case 1:
        def = args[0]
    default:
        log.Panicf("MustString() received too many arguments %d", len(args))
    }

    s, err := j.String()
    if err == nil {
        return s
    }

    return def
}

func (j *Json) MustInt64() int64 {
    var ret int64
    var err error
    switch v := j.data.(type) {
    case int:
        ret = int64(v)
    case int64:
        ret = v
    case float64:
        ret = int64(v)
    case string:
        if ret, err = strconv.ParseInt(v, 10, 64); err != nil {
            panic(err)
        }
    default:
        ret = 0
        //panic("type assertion to int64 failed")
    }
    return ret
}

func (j *Json) MustFloat64() float64 {
    var ret float64
    var err error
    switch v := j.data.(type) {
    case int:
        ret = float64(v)
    case int64:
        ret = float64(v)
    case float64:
        ret = v
    case string:
        v = strings.Replace(v, ",", "", -1)
        if ret, err = strconv.ParseFloat(v, 64); err != nil {
            panic(err)
        }
    default:
        ret = 0
        //panic("type assertion to float64 failed")
    }
    return ret
}

type iBitgo struct {
    accessKey     string
    secretKey     string
    currency      string
    opCurrency    string
    baseCurrency  string
    secret        string
    secretExpires int64
    apiBase       string
    step          int64
    newRate       float64
    timeout       time.Duration
    timeLocation  *time.Location
}

type MapSorter []Item

type Item struct {
    Key string
    Val string
}

func NewMapSorter(m map[string]string) MapSorter {
    ms := make(MapSorter, 0, len(m))

    for k, v := range m {
        if strings.HasPrefix(k, "!") {
            k = strings.Replace(k, "!", "", -1)
        }
        ms = append(ms, Item{k, v})
    }

    return ms
}

func (ms MapSorter) Len() int {
    return len(ms)
}

func (ms MapSorter) Less(i, j int) bool {
    //return ms[i].Val < ms[j].Val // 按值排序
    return ms[i].Key < ms[j].Key // 按键排序
}

func (ms MapSorter) Swap(i, j int) {
    ms[i], ms[j] = ms[j], ms[i]
}

func encodeParams(params map[string]string, escape bool) string {
    ms := NewMapSorter(params)
    sort.Sort(ms)

    v := url.Values{}
    for _, item := range ms {
        v.Add(item.Key, item.Val)
    }
    if escape {
        return v.Encode()
    }
    var buf bytes.Buffer
    keys := make([]string, 0, len(v))
    for k := range v {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        vs := v[k]
        prefix := k + "="
        for _, v := range vs {
            if buf.Len() > 0 {
                buf.WriteByte('&')
            }
            buf.WriteString(prefix)
            buf.WriteString(v)
        }
    }
    return buf.String()
}

func newBitgo(accessKey, secretKey string) *iBitgo {
    s := new(iBitgo)
    s.accessKey = accessKey
    s.secretKey = secretKey
    s.apiBase = "https://www.bitgo.cn"
    s.timeout = 20 * time.Second
    s.timeLocation = time.FixedZone("Asia/Shanghai", 8*60*60)

    return s
}

func (p *iBitgo) apiCall(method string) (*Json, error) {
    req, err := http.NewRequest("POST", fmt.Sprintf("%s/appApi.html?%s", p.apiBase, method), nil)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return NewJson(b)
}

func (p *iBitgo) GetTicker(symbol string) (ticker interface{}, err error) {
    var js *Json
    js, err = p.apiCall("action=market&symbol=" + symbol)
    if err != nil {
        return
    }
    dic := js.Get("data")
    ticker = map[string]interface{}{
        "time": js.Get("time").MustInt64(),
        "buy":  dic.Get("buy").MustFloat64(),
        "sell": dic.Get("sell").MustFloat64(),
        "last": dic.Get("last").MustFloat64(),
        "high": dic.Get("high").MustFloat64(),
        "low":  dic.Get("low").MustFloat64(),
        "vol":  dic.Get("vol").MustFloat64(),
    }
    return
}

func (p *iBitgo) GetDepth(symbol string) (depth interface{}, err error) {
    var js *Json
    js, err = p.apiCall("action=depth&symbol=" + symbol)
    if err != nil {
        return
    }
    dic := js.Get("data")

    asks := [][2]float64{}
    bids := [][2]float64{}

    for _, pair := range dic.Get("asks").MustArray() {
        arr := pair.([]interface{})
        asks = append(asks, [2]float64{toFloat(arr[0]), toFloat(arr[1])})
    }

    for _, pair := range dic.Get("bids").MustArray() {
        arr := pair.([]interface{})
        bids = append(bids, [2]float64{toFloat(arr[0]), toFloat(arr[1])})
    }
    depth = map[string]interface{}{
        "time": js.Get("time").MustInt64(),
        "asks": asks,
        "bids": bids,
    }
    return
}

func (p *iBitgo) GetTrades(symbol string) (trades interface{}, err error) {
    var js *Json
    js, err = p.apiCall("action=trades&symbol=" + symbol)
    if err != nil {
        return
    }
    dic := js.Get("data")
    items := []map[string]interface{}{}
    for _, pair := range dic.MustArray() {
        item := map[string]interface{}{}
        arr := pair.(map[string]interface{})
        item["id"] = toInt64(arr["id"])
        item["price"] = toFloat(arr["price"])
        item["amount"] = toFloat(arr["amount"])
        // trade.Time = toInt64(arr["time"]) * 1000
        if toString(arr["en_type"]) == "bid" {
            item["type"] = "buy"
        } else {
            item["type"] = "sell"
        }
        items = append(items, item)
    }
    trades = items
    return
}

func (p *iBitgo) GetRecords(step int64, symbol string) (records interface{}, err error) {
    var js *Json
    js, err = p.apiCall(fmt.Sprintf("action=kline&symbol=%s&step=%d", symbol, step*60))
    if err != nil {
        return
    }
    items := []interface{}{}
    for _, pair := range js.Get("data").MustArray() {
        arr := pair.([]interface{})
        if len(arr) < 6 {
            err = errors.New("response format error")
            return
        }
        item := [6]interface{}{}
        item[0] = toInt64(arr[0])
        item[1] = toFloat(arr[1])
        item[2] = toFloat(arr[2])
        item[3] = toFloat(arr[3])
        item[4] = toFloat(arr[4])
        item[5] = toFloat(arr[5])

        items = append(items, item)
    }
    records = items
    return
}

func (p *iBitgo) tapiCall(method string, params map[string]string) (js *Json, err error) {
    if params == nil {
        params = map[string]string{}
    }
    params["api_key"] = p.accessKey
    h := md5.New()
    h.Write([]byte(encodeParams(params, false) + "&secret_key=" + p.secretKey))
    params["sign"] = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
    params["action"] = method
    qs := encodeParams(params, false)

    req, err := http.NewRequest("POST", fmt.Sprintf("%s/appApi.html?%s", p.apiBase, qs), nil)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    js, err = NewJson(b)
    if js != nil {
        if code := js.Get("code").MustInt64(); code != 200 {
            s := js.Get("msg").MustString()
            if s == "" {
                s = fmt.Sprintf("%v", toString(js.data))
            }
            return nil, errors.New(s)
        }
    }
    return js, err
}

func (p *iBitgo) GetAccount(symbol string) (account interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("userinfo", nil)
    if err != nil {
        return
    }
    mp := js.Get("data")
    assets := map[string]map[string]interface{}{}
    for k := range mp.MustMap() {
        dic := mp.Get(k)
        if k == "free" {
            for c := range dic.MustMap() {
                if _, ok := assets[c]; !ok {
                    assets[c] = map[string]interface{}{}
                }
                assets[c]["currency"] = c
                assets[c]["free"] = dic.Get(c).MustFloat64()
            }
        } else if k == "frozen" {
            for c := range dic.MustMap() {
                if _, ok := assets[c]; !ok {
                    assets[c] = map[string]interface{}{}
                }
                assets[c]["currency"] = c
                assets[c]["frozen"] = dic.Get(c).MustFloat64()
            }
        }
    }
    accounts := []map[string]interface{}{}
    for _, pair := range assets {
        accounts = append(accounts, pair)
    }

    account = accounts
    return
}

func (p *iBitgo) Trade(side string, price, amount float64, symbol string) (orderId interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("trade", map[string]string{
        "symbol": symbol,
        "type":   side,
        "price":  float2str(price),
        "amount": float2str(amount),
    })
    if err != nil {
        return
    }
    orderId = map[string]int64{"id": js.Get("orderId").MustInt64()}
    return
}

func (p *iBitgo) GetOrders(symbol string) (orders interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("entrust", map[string]string{"symbol": symbol})
    if err != nil {
        return
    }
    items := []map[string]interface{}{}
    for _, ele := range js.Get("data").MustArray() {
        mp := ele.(map[string]interface{})
        item := map[string]interface{}{}
        item["id"] = toInt64(mp["id"])
        item["amount"] = toFloat(mp["count"])
        if _, ok := mp["prize"]; ok {
            item["price"] = toFloat(mp["prize"])
        } else {
            item["price"] = toFloat(mp["price"])
        }
        item["deal_amount"] = toFloat(mp["success_count"])

        if toInt64(mp["type"]) == 0 {
            item["type"] = "buy"
        } else {
            item["type"] = "sell"
        }
        item["status"] = "open"
        items = append(items, item)
    }
    return items, nil
}

func (p *iBitgo) GetOrder(orderId int64, symbol string) (order interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("order", map[string]string{"id": toString(orderId)})
    if err != nil {
        return
    }

    found := false
    item := map[string]interface{}{}
    for _, ele := range js.Get("data").MustArray() {
        mp := ele.(map[string]interface{})
        if toInt64(mp["id"]) != orderId {
            continue
        }
        item["id"] = toInt64(mp["id"])
        item["amount"] = toFloat(mp["count"])
        if _, ok := mp["prize"]; ok {
            item["price"] = toFloat(mp["prize"])
        } else {
            item["price"] = toFloat(mp["price"])
        }
        item["deal_amount"] = toFloat(mp["success_count"])

        if toInt64(mp["type"]) == 0 {
            item["type"] = "buy"
        } else {
            item["type"] = "sell"
        }
        switch toInt64(mp["status"]) {
        case 1, 2:
            item["status"] = "open"
        case 3:
            item["status"] = "closed"
        case 4:
            item["status"] = "cancelled"
        }
        found = true
        break
    }
    if !found {
        return nil, errors.New("order not found")
    }
    return item, nil
}

func (p *iBitgo) CancelOrder(orderId int64, symbol string) (ret bool, err error) {
    _, err = p.tapiCall("cancel_entrust", map[string]string{"id": strconv.FormatInt(orderId, 10)})
    if err != nil {
        return
    }
    ret = true
    return
}

type RpcRequest struct {        // 结构体里的字段首字母必须大写,否则无法正常解析,结构体有导出和未导出,大写字母开头为导出。
                                // 在Unmarshal的时候会  根据 json 匹配查找该结构体的tag, 所以此处需要修饰符
    AccessKey string            `json:"access_key"`
    SecretKey string            `json:"secret_key"`
    Nonce     int64             `json:"nonce"`
    Method    string            `json:"method"`
    Params    map[string]string `json:"params"`
}

func OnPost(w http.ResponseWriter, r *http.Request) {
    var ret interface{}
    defer func() {
        if e := recover(); e != nil {
            if ee, ok := e.(error); ok {
                e = ee.Error()
            }
            ret = map[string]string{"error": fmt.Sprintf("%v", e)}
        }
        b, _ := json.Marshal(ret)
        w.Write(b)
    }()

    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }
    var request RpcRequest
    err = json.Unmarshal(b, &request)
    if err != nil {
        panic(err)
    }
    e := newBitgo(request.AccessKey, request.SecretKey)
    symbol := request.Params["symbol"]
    if s := request.Params["access_key"]; len(s) > 0 {
        e.accessKey = s
    }
    if s := request.Params["secret_key"]; len(s) > 0 {
        e.secretKey = s
    }
    if symbolIdx, ok := map[string]int{
        "btc":  1,
        "ltc":  2,
        "etp":  3,
        "eth":  4,
        "etc":  5,
        "doge": 6,
        "bec":  7,
    }[strings.Replace(strings.ToLower(symbol), "_cny", "", -1)]; ok {
        symbol = toString(symbolIdx)
    }
    var data interface{}
    switch request.Method {
    case "ticker":
        data, err = e.GetTicker(symbol)
    case "depth":
        data, err = e.GetDepth(symbol)
    case "trades":
        data, err = e.GetTrades(symbol)
    case "records":
        data, err = e.GetRecords(toInt64(request.Params["period"]), symbol)
    case "accounts":
        data, err = e.GetAccount(symbol)
    case "trade":
        side := request.Params["type"]
        if side == "buy" {
            side = "0"
        } else {
            side = "1"
        }
        price := toFloat(request.Params["price"])
        amount := toFloat(request.Params["amount"])
        data, err = e.Trade(side, price, amount, symbol)
    case "orders":
        data, err = e.GetOrders(symbol)
    case "order":
        data, err = e.GetOrder(toInt64(request.Params["id"]), symbol)
    case "cancel":
        data, err = e.CancelOrder(toInt64(request.Params["id"]), symbol)
    default:
        if strings.HasPrefix(request.Method, "__api_") {
            data, err = e.tapiCall(request.Method[6:], request.Params)
        } else {
            panic(errors.New(request.Method + " not support"))
        }
    }
    if err != nil {
        panic(err)
    }
    ret = map[string]interface{}{
        "data": data,
    }

    return
}

func main() {
    var addr = flag.String("b", "127.0.0.1:6666", "bind addr")
    flag.Parse()
    if *addr == "" {
        flag.Usage()
        return
    }
    basePath := "/exchange"
    log.Println("Running ", fmt.Sprintf("http://%s%s", *addr, basePath), "...")
    http.HandleFunc(basePath, OnPost)
    http.ListenAndServe(*addr, nil)
}