Esempio n. 1
0
// GetRawTx return rawtx of specifc tx.
func GetRawTx(egn engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		var rlt *pp.EmptyRes
		for {
			req := pp.GetRawTxReq{}
			if err := c.BindJSON(&req); err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			coin, err := egn.GetCoin(req.GetCoinType())
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}
			rawtx, err := coin.GetRawTx(req.GetTxid())
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			res := pp.GetRawTxRes{
				Result:   pp.MakeResultWithCode(pp.ErrCode_Success),
				CoinType: req.CoinType,
				Rawtx:    pp.PtrString(rawtx),
			}
			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}
Esempio n. 2
0
// GetAddresses get all addresses in wallet.
// mode: GET
// url: /api/v1/wallet/addresses?id=[:id]
// params:
// 		id: wallet id.
func GetAddresses(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var rlt *pp.EmptyRes
		for {
			id := r.FormValue("id")
			if id == "" {
				rlt = pp.MakeErrRes(errors.New("id is required"))
				break
			}

			addrs, err := wallet.GetAddresses(id)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			res := struct {
				Result    *pp.Result `json:"result"`
				Addresses []string   `json:"addresses"`
			}{
				Result:    pp.MakeResultWithCode(pp.ErrCode_Success),
				Addresses: addrs,
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}
Esempio n. 3
0
// NewAddress create address in wallet.
// mode: POST
// url: /api/v1/wallet/:id/address?&id=[:id]
// params:
// 		id: wallet id.
func NewAddress(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var rlt *pp.EmptyRes
		for {
			// get wallet id
			wltID := r.FormValue("id")
			if wltID == "" {
				rlt = pp.MakeErrRes(errors.New("id is required"))
				break
			}

			addrEntries, err := wallet.NewAddresses(wltID, 1)
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_ServerError)
				break
			}
			res := struct {
				Result  *pp.Result
				Address string `json:"address"`
			}{
				Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
				Address: addrEntries[0].Address,
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}
Esempio n. 4
0
// GetAddrBalance get balance of specific address.
func GetAddrBalance(ee engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		var rlt *pp.EmptyRes
		for {
			req := pp.GetAddrBalanceReq{}
			if err := c.BindJSON(&req); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			coin, err := ee.GetCoin(req.GetCoinType())
			if err != nil {
				rlt = pp.MakeErrRes(err)
				logger.Error(err.Error())
				break
			}

			addrs := strings.Split(req.GetAddrs(), ",")
			b, err := coin.GetBalance(addrs)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}
			res := pp.GetAddrBalanceRes{
				Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
				Balance: &b,
			}

			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}
Esempio n. 5
0
// GetBalance return balance of specific account.
func GetAccountBalance(ee engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		rlt := &pp.EmptyRes{}
		for {
			req := pp.GetAccountBalanceReq{}
			if err := c.BindJSON(&req); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			// validate pubkey
			pubkey := req.GetPubkey()
			if err := validatePubkey(pubkey); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongPubkey)
				break
			}

			a, err := ee.GetAccount(pubkey)
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_NotExits)
				break
			}

			bal := a.GetBalance(req.GetCoinType())
			bres := pp.GetAccountBalanceRes{
				Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
				Balance: &pp.Balance{Amount: pp.PtrUint64(bal)},
			}
			return c.SendJSON(&bres)
		}
		return c.Error(rlt)
	}
}
Esempio n. 6
0
// GetAccount get account that matchs the condition in url param.
// mode: GET
// url: /api/v1/account?active=[:active]
// params:
// 		active: optional condition, must be 1, if not exist, then retun all accounts.
func GetAccount(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		// get active
		res := struct {
			Result   *pp.Result      `json:"result"`
			Accounts []accountResult `json:"accounts,omitempty"`
		}{}

		active := r.FormValue("active")
		switch active {
		case "1":
			a, err := account.GetActive()
			if err != nil {
				// no active account.
				res.Result = pp.MakeResult(pp.ErrCode_NotExits, err.Error())
				sendJSON(w, &res)
				return
			}

			res.Result = pp.MakeResultWithCode(pp.ErrCode_Success)
			res.Accounts = make([]accountResult, 1)
			res.Accounts[0].Pubkey = a.Pubkey
			res.Accounts[0].WalletID = make(map[string]string)
			for cp, id := range a.WltIDs {
				res.Accounts[0].WalletID[cp] = id
			}
			sendJSON(w, &res)
		case "":
			accounts := account.GetAll()
			res.Result = pp.MakeResultWithCode(pp.ErrCode_Success)
			res.Accounts = func(accounts []account.Account) []accountResult {
				as := make([]accountResult, len(accounts))
				for i, a := range accounts {
					as[i].Pubkey = a.Pubkey
					as[i].WalletID = make(map[string]string)
					for cp, id := range a.WltIDs {
						as[i].WalletID[cp] = id
					}
				}
				return as
			}(accounts)
			sendJSON(w, &res)
		default:
			sendJSON(w, pp.MakeErrResWithCode(pp.ErrCode_WrongRequest))
		}
	}
}
Esempio n. 7
0
func btcWithdraw(rp *ReqParams) (*pp.WithdrawalRes, *pp.EmptyRes) {
	ee := rp.Values["engine"].(engine.Exchange)
	acnt := rp.Values["account"].(account.Accounter)
	amt := rp.Values["amt"].(uint64)
	ct := rp.Values["cointype"].(string)
	toAddr := rp.Values["toAddr"].(string)
	// verify the toAddr
	if _, err := cipher.BitcoinDecodeBase58Address(toAddr); err != nil {
		return nil, pp.MakeErrRes(errors.New("invalid bitcoin address"))
	}
	var success bool
	var btcTxRlt *BtcTxResult
	var err error
	// decrease balance and check if the balance is sufficient.
	if err := acnt.DecreaseBalance(ct, amt+ee.GetBtcFee()); err != nil {
		return nil, pp.MakeErrRes(err)
	}
	defer func() {
		if !success {
			go func() {
				if btcTxRlt != nil {
					ee.PutUtxos(bitcoin.Type, btcTxRlt.UsingUtxos)
				}
				acnt.IncreaseBalance(ct, amt+ee.GetBtcFee())
			}()
		} else {
			//TODO: handle the saving failure.
			ee.SaveAccount()
		}
	}()

	btcTxRlt, err = createBtcWithdrawTx(ee, amt, toAddr)
	if err != nil {
		return nil, pp.MakeErrRes(errors.New("failed to create withdrawal tx"))
	}

	rawtx, err := btcTxRlt.Tx.Serialize()
	if err != nil {
		return nil, pp.MakeErrRes(errors.New("tx serialize failed"))
	}

	newTxid, err := bitcoin.BroadcastTx(hex.EncodeToString(rawtx))
	if err != nil {
		logger.Error(err.Error())
		return nil, pp.MakeErrResWithCode(pp.ErrCode_BroadcastTxFail)
	}

	success = true
	if btcTxRlt.ChangeAddr != "" {
		logger.Debug("change address:%s", btcTxRlt.ChangeAddr)
		ee.WatchAddress(ct, btcTxRlt.ChangeAddr)
	}

	resp := pp.WithdrawalRes{
		Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
		NewTxid: &newTxid,
	}
	return &resp, nil
}
Esempio n. 8
0
// GetCoins get supported coins.
func GetCoins(egn engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		coins := pp.CoinsRes{
			Result: pp.MakeResultWithCode(pp.ErrCode_Success),
			Coins:  egn.GetSupportCoins(),
		}
		return c.SendJSON(&coins)
	}
}
Esempio n. 9
0
// JSON encrypt the data and write response.
func (c *Context) SendJSON(data interface{}) error {
	encData, nonce, err := pp.Encrypt(data, c.Pubkey, c.ServSeckey)
	if err != nil {
		return err
	}

	res := pp.EncryptRes{
		Result:      pp.MakeResultWithCode(pp.ErrCode_Success),
		Encryptdata: encData,
		Nonce:       nonce,
	}
	return c.Resp.SendJSON(res)
}
Esempio n. 10
0
// CreateWallet api for creating local wallet.
// mode: POST
// url: /api/v1/wallet?type=[:type]&seed=[:seed]
// params:
// 		type: bitcoin or skycoin
// 		seed: wallet seed.
func CreateWallet(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		rlt := &pp.EmptyRes{}
		for {
			// get coin type
			cp := r.FormValue("type")

			// get seed
			sd := r.FormValue("seed")
			if sd == "" {
				rlt = pp.MakeErrRes(errors.New("seed is required"))
				break
			}

			wlt, err := wallet.New(cp, sd)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_ServerError)
				break
			}

			// bind the wallet to current account.
			a, err := account.GetActive()
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			a.WltIDs[cp] = wlt.GetID()
			// update the account.
			account.Set(a)

			res := struct {
				Result *pp.Result `json:"result"`
				ID     string     `json:"id"`
			}{
				Result: pp.MakeResultWithCode(pp.ErrCode_Success),
				ID:     wlt.GetID(),
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}
Esempio n. 11
0
// GetNewAddress account create new address for depositing.
func GetNewAddress(ee engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		rlt := &pp.EmptyRes{}
		for {
			req := pp.GetDepositAddrReq{}
			if err := c.BindJSON(&req); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			// validate pubkey
			pubkey := req.GetPubkey()
			if err := validatePubkey(pubkey); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongPubkey)
				break
			}

			at, err := ee.GetAccount(pubkey)
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_NotExits)
				break
			}

			ct := req.GetCoinType()
			// get the new address for depositing
			addr := ee.GetNewAddress(ct)

			// add the new address to engin for watching it's utxos.
			at.AddDepositAddress(ct, addr)
			ee.WatchAddress(ct, addr)

			ds := pp.GetDepositAddrRes{
				Result:   pp.MakeResultWithCode(pp.ErrCode_Success),
				CoinType: req.CoinType,
				Address:  &addr,
			}

			return c.SendJSON(&ds)
		}

		return c.Error(rlt)
	}
}
Esempio n. 12
0
// GetOrders get order list.
func GetOrders(egn engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		rlt := &pp.EmptyRes{}
		for {
			req := pp.GetOrderReq{}
			if err := c.BindJSON(&req); err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}
			op, err := order.TypeFromStr(req.GetType())
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				logger.Error(err.Error())
				break
			}
			ords, err := egn.GetOrders(req.GetCoinPair(), op, req.GetStart(), req.GetEnd())
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				logger.Error(err.Error())
				break
			}
			res := pp.GetOrderRes{
				CoinPair: req.CoinPair,
				Type:     req.Type,
				Orders:   make([]*pp.Order, len(ords)),
			}

			for i := range ords {
				res.Orders[i] = &pp.Order{
					Id:        &ords[i].ID,
					Type:      req.Type,
					Price:     &ords[i].Price,
					Amount:    &ords[i].Amount,
					RestAmt:   &ords[i].RestAmt,
					CreatedAt: &ords[i].CreatedAt,
				}
			}

			res.Result = pp.MakeResultWithCode(pp.ErrCode_Success)
			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}
Esempio n. 13
0
// UpdateCredit update credit.
func UpdateCredit(ee engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		var rlt *pp.EmptyRes
		for {
			req := pp.UpdateCreditReq{}
			if err := c.BindJSON(&req); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			// validate the dst pubkey.
			dstPubkey := req.GetDst()
			if err := validatePubkey(dstPubkey); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongPubkey)
				break
			}

			// get account.
			a, err := ee.GetAccount(dstPubkey)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongPubkey)
				break
			}

			// get coin type.
			if err := a.SetBalance(req.GetCoinType(), req.GetAmount()); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}
			ee.SaveAccount()
			res := pp.UpdateCreditRes{
				Result: pp.MakeResultWithCode(pp.ErrCode_Success),
			}

			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}
Esempio n. 14
0
// SignRawTx sign transaction.
// mode: POST
// url: /api/v1/signr_awtx?coin_type=[:coin_type]&rawtx=[:rawtx]
// params:
// 		coin_type: skycoin or bitcoin.
// 		rawtx: raw transaction.
func SignRawTx(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var rlt *pp.EmptyRes
		for {
			// check coin type
			cp := r.FormValue("coin_type")

			// get raw tx
			rawtx := r.FormValue("rawtx")
			if rawtx == "" {
				err := errors.New("rawtx is empty")
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

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

			tx, err := coin.SignRawTx(rawtx, getPrivKey(cp))
			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:  tx,
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}
Esempio n. 15
0
// GetTx get transaction by id.
func GetTx(egn engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		var rlt *pp.EmptyRes
		for {
			req := pp.GetTxReq{}
			if err := c.BindJSON(&req); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

			coin, err := egn.GetCoin(req.GetCoinType())
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			// brief validate transaction id
			if !coin.ValidateTxid(req.GetTxid()) {
				rlt = pp.MakeErrRes(errors.New("invalid transaction id"))
				break
			}

			tx, err := coin.GetTx(req.GetTxid())
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			res := pp.GetTxRes{
				Result:   pp.MakeResultWithCode(pp.ErrCode_Success),
				CoinType: req.CoinType,
				Tx:       tx,
			}
			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}
Esempio n. 16
0
// GetUtxos gets bitcoin utxos of specific addresses.
func (btc *Bitcoin) GetUtxos(addrs []string) (interface{}, error) {
	utxos, err := GetUnspentOutputs(addrs)
	if err != nil {
		return nil, err
	}
	btcUxs := make([]*pp.BtcUtxo, len(utxos))
	for i, u := range utxos {
		btcUxs[i] = &pp.BtcUtxo{
			Address: pp.PtrString(u.GetAddress()),
			Txid:    pp.PtrString(u.GetTxid()),
			Vout:    pp.PtrUint32(u.GetVout()),
			Amount:  pp.PtrUint64(u.GetAmount()),
		}
	}

	var res = pp.GetUtxoRes{
		Result:   pp.MakeResultWithCode(pp.ErrCode_Success),
		BtcUtxos: btcUxs,
	}

	return res, nil
}
Esempio n. 17
0
// GetKeys get keys of specific address in wallet.
// mode: GET
// url: /api/v1/wallet/address/keys?id=[:id]&address=[:address]
func GetKeys(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var rlt *pp.EmptyRes
		for {
			// get wallet id
			wltID := r.FormValue("id")
			if wltID == "" {
				rlt = pp.MakeErrRes(errors.New("no id"))
				break
			}

			// get address
			addr := r.FormValue("address")
			if addr == "" {
				rlt = pp.MakeErrRes(errors.New("no address"))
				break
			}
			p, s, err := wallet.GetKeypair(wltID, addr)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_ServerError)
				break
			}

			res := struct {
				Result *pp.Result
				Pubkey string `json:"pubkey"`
				Seckey string `json:"seckey"`
			}{
				Result: pp.MakeResultWithCode(pp.ErrCode_Success),
				Pubkey: p,
				Seckey: s,
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}
Esempio n. 18
0
// ActiveAccount active the specific account.
// mode: PUT
// url: /api/v1/account/state?pubkey=[:pubkey]
func ActiveAccount(se Servicer) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		var rlt *pp.EmptyRes
		for {
			// get pubkey
			pk := r.FormValue("pubkey")
			if pk == "" {
				logger.Error("pubkey is empty")
				rlt = pp.MakeErrRes(errors.New("pubkey is empty"))
				break
			}

			// validate the pubkey
			if _, err := cipher.PubKeyFromHex(pk); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(errors.New("invalid pubkey"))
				break
			}

			// active the account
			if err := account.SetActive(pk); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}
			res := struct {
				Result *pp.Result
			}{
				pp.MakeResultWithCode(pp.ErrCode_Success),
			}
			sendJSON(w, &res)
			return
		}
		sendJSON(w, rlt)
	}
}
Esempio n. 19
0
// InjectTx inject transaction.
func InjectTx(egn engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		var rlt *pp.EmptyRes
		for {
			req := pp.InjectTxnReq{}
			if err := c.BindJSON(&req); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}

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

			// inject tx.
			txid, err := coin.InjectTx(req.GetTx())
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrRes(err)
				break
			}

			res := pp.InjectTxnRes{
				Result: pp.MakeResultWithCode(pp.ErrCode_Success),
				Txid:   pp.PtrString(txid),
			}
			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}
Esempio n. 20
0
// 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)
	}
}
Esempio n. 21
0
func skyWithdrawl(nodeAddr string, rp *ReqParams) (*pp.WithdrawalRes, *pp.EmptyRes) {
	ee := rp.Values["engine"].(engine.Exchange)
	acnt := rp.Values["account"].(account.Accounter)
	amt := rp.Values["amt"].(uint64)
	ct := rp.Values["cointype"].(string)
	toAddr := rp.Values["toAddr"].(string)

	if err := skycoin.VerifyAmount(amt); err != nil {
		return nil, pp.MakeErrRes(err)
	}

	// verify the toAddr
	if _, err := cipher.DecodeBase58Address(toAddr); err != nil {
		return nil, pp.MakeErrRes(errors.New("invalid skycoin address"))
	}

	var success bool
	var skyTxRlt *SkyTxResult
	var err error
	if err := acnt.DecreaseBalance(ct, amt); err != nil {
		return nil, pp.MakeErrRes(err)
	}
	defer func() {
		if !success {
			go func() {
				if skyTxRlt != nil {
					ee.PutUtxos(skycoin.Type, skyTxRlt.UsingUtxos)
				}
				acnt.IncreaseBalance(ct, amt)
			}()
		} else {
			//TODO: handle the saving failure.
			ee.SaveAccount()
		}
	}()

	skyTxRlt, err = createSkyWithdrawTx(ee, amt, toAddr)
	if err != nil {
		return nil, pp.MakeErrRes(errors.New("failed to create withdrawal tx"))
	}
	rawtx, err := skyTxRlt.Tx.Serialize()
	if err != nil {
		return nil, pp.MakeErrRes(errors.New("skycoin tx serialize failed"))
	}

	newTxid, err := skycoin.BroadcastTx(nodeAddr, hex.EncodeToString(rawtx))
	if err != nil {
		logger.Error(err.Error())
		return nil, pp.MakeErrResWithCode(pp.ErrCode_BroadcastTxFail)
	}

	success = true
	if skyTxRlt.ChangeAddr != "" {
		logger.Debug("change address:%s", skyTxRlt.ChangeAddr)
		ee.WatchAddress(ct, skyTxRlt.ChangeAddr)
	}

	resp := pp.WithdrawalRes{
		Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
		NewTxid: &newTxid,
	}
	return &resp, nil
}
Esempio n. 22
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)
	}
}
Esempio n. 23
0
// CreateOrder create specifc order.
func CreateOrder(egn engine.Exchange) sknet.HandlerFunc {
	return func(c *sknet.Context) error {
		rlt := &pp.EmptyRes{}
		req := &pp.OrderReq{}
		for {
			if err := c.BindJSON(req); err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				logger.Error(err.Error())
				break
			}

			// validate pubkey
			pubkey := req.GetPubkey()
			if err := validatePubkey(pubkey); err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongPubkey)
				break
			}

			// get order type
			op, err := order.TypeFromStr(req.GetType())
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				logger.Error(err.Error())
				break
			}

			// find the account
			acnt, err := egn.GetAccount(pubkey)
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongPubkey)
				logger.Error(err.Error())
				break
			}

			cp, bal, err := needBalance(op, req)
			if err != nil {
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				logger.Error(err.Error())
				break
			}

			if acnt.GetBalance(cp) < bal {
				err := fmt.Errorf("%s balance is not sufficient", cp)
				rlt = pp.MakeErrRes(err)
				logger.Debug(err.Error())
				break
			}

			var success bool
			if op == order.Bid {
				defer func() {
					if success {
						egn.SaveAccount()
					} else {
						acnt.IncreaseBalance(cp, bal)
					}
				}()
				// decrease the balance, in case of double use the coins.
				logger.Info("account:%s decrease %s:%d", acnt.GetID(), cp, bal)
				if err := acnt.DecreaseBalance(cp, bal); err != nil {
					rlt = pp.MakeErrRes(err)
					logger.Error(err.Error())
					break
				}
			}

			odr := order.New(pubkey, op, req.GetPrice(), req.GetAmount())
			oid, err := egn.AddOrder(req.GetCoinPair(), *odr)
			if err != nil {
				logger.Error(err.Error())
				rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest)
				break
			}
			success = true
			logger.Info(fmt.Sprintf("new %s order:%d", op, oid))
			res := pp.OrderRes{
				Result:  pp.MakeResultWithCode(pp.ErrCode_Success),
				OrderId: &oid,
			}
			return c.SendJSON(&res)
		}
		return c.Error(rlt)
	}
}