// createBtcWithdrawTx create withdraw transaction. // amount is the number of coins that want to withdraw. // toAddr is the address that the coins will be sent to. func createBtcWithdrawTx(egn engine.Exchange, amount uint64, toAddr string) (*BtcTxResult, error) { uxs, err := egn.ChooseUtxos(bitcoin.Type, amount+egn.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()) } var success bool defer func() { if !success { // put utxos back to pool if withdraw failed. go func() { egn.PutUtxos(bitcoin.Type, utxos) }() } }() var totalAmounts uint64 for _, u := range utxos { totalAmounts += u.GetAmount() } fee := egn.GetBtcFee() outAddrs := []bitcoin.TxOut{} chgAmt := totalAmounts - fee - amount chgAddr := "" if chgAmt > 0 { // generate a change address chgAddr = egn.GetNewAddress(bitcoin.Type) outAddrs = append(outAddrs, bitcoin.TxOut{Addr: toAddr, Value: amount}, bitcoin.TxOut{Addr: chgAddr, Value: chgAmt}) } else { outAddrs = append(outAddrs, bitcoin.TxOut{Addr: toAddr, Value: amount}) } // change utxo to UtxoWithkey utxoKeys, err := makeBtcUtxoWithkeys(utxos, egn) if err != nil { return nil, err } logger.Debug("creating transaction...") tx, err := bitcoin.NewTransaction(utxoKeys, outAddrs) if err != nil { logger.Error(err.Error()) return nil, err } success = true rlt := BtcTxResult{ Tx: tx, UsingUtxos: utxos[:], ChangeAddr: chgAddr, } return &rlt, nil }
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 }
func createSkyWithdrawTx(egn engine.Exchange, amount uint64, toAddr string) (*SkyTxResult, error) { uxs, err := egn.ChooseUtxos(skycoin.Type, amount, ChooseUtxoTm) if err != nil { return nil, err } utxos := uxs.([]skycoin.Utxo) for _, u := range utxos { logger.Debug("using skycoin utxos:%s", u.GetHash()) } var success bool defer func() { if !success { go func() { egn.PutUtxos(skycoin.Type, utxos) }() } }() var totalAmounts uint64 var totalHours uint64 for _, u := range utxos { totalAmounts += u.GetCoins() totalHours += u.GetHours() } outAddrs := []skycoin.TxOut{} chgAmt := totalAmounts - amount chgHours := totalHours / 4 chgAddr := "" if chgAmt > 0 { // generate a change address chgAddr = egn.GetNewAddress(skycoin.Type) outAddrs = append(outAddrs, skycoin.MakeUtxoOutput(toAddr, amount, chgHours/2), skycoin.MakeUtxoOutput(chgAddr, chgAmt, chgHours/2)) } else { outAddrs = append(outAddrs, skycoin.MakeUtxoOutput(toAddr, amount, chgHours/2)) } keys := make([]cipher.SecKey, len(utxos)) for i, u := range utxos { k, err := egn.GetAddrPrivKey(skycoin.Type, u.GetAddress()) if err != nil { panic(err) } keys[i] = cipher.MustSecKeyFromHex(k) } logger.Debug("creating skycoin transaction...") tx := skycoin.NewTransaction(utxos, keys, outAddrs) if err := tx.Verify(); err != nil { return nil, err } success = true rlt := SkyTxResult{ Tx: tx, UsingUtxos: utxos[:], ChangeAddr: chgAddr, } return &rlt, nil }