Beispiel #1
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
}
Beispiel #2
0
func createBtcTxInOut(ee engine.Exchange, a account.Accounter, amount uint64, outAddr string) (*txInOutResult, error) {
	var rlt txInOutResult
	// verify the outAddr
	if _, err := cipher.BitcoinDecodeBase58Address(outAddr); err != nil {
		return nil, errors.New("invalid bitcoin address")
	}

	var err error
	// decrease balance and check if the balance is sufficient.
	if err := a.DecreaseBalance("bitcoin", amount+ee.GetBtcFee()); err != nil {
		return nil, err
	}

	var utxos []bitcoin.Utxo

	// choose sufficient utxos.
	uxs, err := ee.ChooseUtxos("bitcoin", amount+ee.GetBtcFee(), ChooseUtxoTm)
	if err != nil {
		return nil, err
	}
	utxos = uxs.([]bitcoin.Utxo)

	for _, u := range utxos {
		logger.Debug("using utxos: txid:%s vout:%d addr:%s", u.GetTxid(), u.GetVout(), u.GetAddress())
		rlt.TxIns = append(rlt.TxIns, coin.TxIn{
			Txid: u.GetTxid(),
			Vout: u.GetVout(),
		})
	}

	var totalAmounts uint64
	for _, u := range utxos {
		totalAmounts += u.GetAmount()
	}
	fee := ee.GetBtcFee()
	txOuts := []bitcoin.TxOut{}
	chgAmt := totalAmounts - fee - amount
	chgAddr := ""
	if chgAmt > 0 {
		// generate a change address
		chgAddr = ee.GetNewAddress(bitcoin.Type)
		txOuts = append(txOuts,
			bitcoin.TxOut{Addr: outAddr, Value: amount},
			bitcoin.TxOut{Addr: chgAddr, Value: chgAmt})
	} else {
		txOuts = append(txOuts, bitcoin.TxOut{Addr: outAddr, Value: amount})
	}

	rlt.TxOuts = txOuts
	rlt.Teardown = func() {
		a.IncreaseBalance(bitcoin.Type, amount+ee.GetBtcFee())
		ee.PutUtxos(bitcoin.Type, utxos)
	}

	return &rlt, nil
}
Beispiel #3
0
func getBalanceExplr(addrs []string) (uint64, error) {
	var wg sync.WaitGroup

	valueChan := make(chan balanceResult, len(addrs))

	for _, addr := range addrs {
		// verify the address.
		_, err := cipher.BitcoinDecodeBase58Address(addr)
		if err != nil {
			return 0, err
		}

		wg.Add(1)
		go func(addr string, wg *sync.WaitGroup, vc chan balanceResult) {
			defer wg.Done()
			d, err := getDataOfUrl(fmt.Sprintf("https://blockexplorer.com/api/addr/%s/balance", addr))
			if err != nil {
				vc <- balanceResult{0, err}
				return
			}
			v, err := strconv.ParseUint(string(d), 10, 64)
			if err != nil {
				vc <- balanceResult{0, err}
			}
			vc <- balanceResult{v, nil}
		}(addr, &wg, valueChan)
	}
	wg.Wait()
	close(valueChan)
	var totalBal uint64
	for v := range valueChan {
		if v.err != nil {
			return 0, v.err
		}
		totalBal += v.balance
	}
	return totalBal, nil
}
Beispiel #4
0
func (bn bitcoinCli) ValidateAddr(address string) error {
	_, err := cipher.BitcoinDecodeBase58Address(address)
	return err
}
Beispiel #5
0
func validateAddress(addr string) bool {
	_, err := cipher.BitcoinDecodeBase58Address(addr)
	return err == nil
}