// Withdraw api for handlering withdraw process.
func Withdraw(ee engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		rlt := &pp.EmptyRes{}
		for {
			reqParam, err := getWithdrawReqParams(c, ee)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			cp := reqParam.Values["cointype"].(string)
			a := reqParam.Values["account"].(account.Accounter)
			amt := reqParam.Values["amt"].(uint64)
			outAddr := reqParam.Values["outAddr"].(string)

			// get handler for creating txIns and txOuts base on the coin type.
			createTxInOut, err := getTxInOutHandler(cp)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			// create txIns and txOuts.
			inOutSet, err := createTxInOut(ee, a, amt, outAddr)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			var success bool
			defer func() {
				if !success {
					// if not success, invoke the teardown, for putting back utxos, and reset balance.
					inOutSet.Teardown()
				}
			}()

			// get coin gateway.
			coin, err := ee.GetCoin(cp)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			// create raw tx
			rawtx, err := coin.CreateRawTx(inOutSet.TxIns, inOutSet.TxOuts)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			// sign the tx
			rawtx, err = coin.SignRawTx(rawtx, getAddrPrivKey(ee, cp))
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			// inject the transaction.
			txid, err := coin.InjectTx(rawtx)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			success = true
			resp := pp.WithdrawalRes{
				Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
				NewTxid: &txid,
			}
			return c.SendJSON(&resp)
		}
		return c.Error(rlt)
	}
}
Exemple #2
0
// CreateRawTx create raw tx base on some utxos.
// mode: POST
// url: /api/v1/create_rawtx?coin_type=[:coin_type]
// request json:
// 		different in bitcoin and skycoin.
func CreateRawTx(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var rlt *pp.EmptyRes
	loop:
		for {
			// get coin type
			cp := r.FormValue("coin_type")

			// get request body
			params := rawTxParams{}
			if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			coin, err := se.GetCoin(cp)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_ServerError)
				break
			}

			var rawtx string
			switch cp {
			case bitcoin.Type:
				outs := make([]bitcoin.TxOut, len(params.TxOuts))
				for i, o := range params.TxOuts {
					outs[i].Addr = o.Addr
					outs[i].Value = o.Value
				}
				rawtx, err = coin.CreateRawTx(params.TxIns, outs)
			case skycoin.Type:
				outs := make([]skycoin.TxOut, len(params.TxOuts))
				for i, o := range params.TxOuts {
					addr, err := cipher.DecodeBase58Address(o.Addr)
					if err != nil {
						logger.Error(err.Error())
						rlt = pp.MakeErrRes(err)
						break loop
					}
					outs[i].Address = addr
					outs[i].Coins = o.Value
					outs[i].Hours = o.Hours
				}
				rawtx, err = coin.CreateRawTx(params.TxIns, outs)
			}
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			res := struct {
				Result *pp.Result `json:"result"`
				Rawtx  string     `json:"rawtx"`
			}{
				Result: pp.MakeResultWithCode(pp.ErrCode_Success),
				Rawtx:  rawtx,
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}