Exemple #1
0
func DepositMoneyForUser(user *auth.User, coin string, amount uint64) {
	err := db.DoBeginSerializable(func(tx *db.ModelTx) {
		account.UpdateBalanceByWallet(tx, user.Id, account.WALLET_MAIN, coin, int64(amount), false)
	})
	if err != nil {
		panic(err)
	}
}
Exemple #2
0
// Funds are reserved by moving them to the account.WALLET_RESERVED_ORDER wallet when
// the order is saved to the DB.
// If there aren't enough funds, the order isn't saved, and an error is returned.
// The returned error.Error() is a front-end message.
func SaveAndReserveFundsForOrder(order *Order) {
	err := db.DoBeginSerializable(func(tx *db.ModelTx) {
		// Save the order, get the id
		SaveOrder(tx, order)
		// Reserve the funds
		if order.Type == ORDER_TYPE_BID {
			account.UpdateBalanceByWallet(tx, order.UserId, account.WALLET_MAIN, order.BasisCoin, -int64(order.BasisAmount+order.BasisFee), true)
			account.UpdateBalanceByWallet(tx, order.UserId, account.WALLET_RESERVED_ORDER, order.BasisCoin, int64(order.BasisAmount+order.BasisFee), false)
		} else {
			account.UpdateBalanceByWallet(tx, order.UserId, account.WALLET_MAIN, order.Coin, -int64(order.Amount), true)
			account.UpdateBalanceByWallet(tx, order.UserId, account.WALLET_RESERVED_ORDER, order.Coin, int64(order.Amount), false)
		}
	})
	if err != nil {
		panic(err)
	}
}
Exemple #3
0
func injectMoneyForUsers(users []*auth.User, coins []string) {
	Info("Injecting money for each user")
	for _, user := range users {
		for _, coin := range coins {
			err := db.DoBeginSerializable(func(tx *db.ModelTx) {
				account.UpdateBalanceByWallet(tx, user.Id, account.WALLET_MAIN, coin, int64(100000000000000), false)
			})
			if err != nil {
				panic(err)
			}
		}
	}
	Info("Done injecting money for each user")
}
Exemple #4
0
func ReleaseReservedFundsForOrder(tx *db.ModelTx, order *Order) {
	if order.Status != ORDER_STATUS_COMPLETE &&
		order.Status != ORDER_STATUS_CANCELED {
		panic(NewError("Cannot release reserved funds for order that isn't complete nor canceled: %v", order.Id))
	}

	if order.Type == ORDER_TYPE_BID {
		bid := order
		bidReleaseBasis := (bid.BasisAmount - bid.BasisFilled) + (bid.BasisFee - bid.BasisFeeFilled)
		if bidReleaseBasis > 0 {
			account.UpdateBalanceByWallet(tx, bid.UserId, account.WALLET_RESERVED_ORDER, bid.BasisCoin, -int64(bidReleaseBasis), true)
			account.UpdateBalanceByWallet(tx, bid.UserId, account.WALLET_MAIN, bid.BasisCoin, int64(bidReleaseBasis), false)
		}
	} else if order.Type == ORDER_TYPE_ASK {
		ask := order
		askReleaseAmount := ask.Amount - ask.Filled
		if askReleaseAmount > 0 {
			account.UpdateBalanceByWallet(tx, ask.UserId, account.WALLET_RESERVED_ORDER, ask.Coin, -int64(askReleaseAmount), true)
			account.UpdateBalanceByWallet(tx, ask.UserId, account.WALLET_MAIN, ask.Coin, int64(askReleaseAmount), false)
		}
	} else {
		panic(NewError("Unexpected order type %v", order.Type))
	}
}
Exemple #5
0
// Returns false if no withdrawals are available to process.
func ProcessUserWithdrawals(coin string) (bool, error) {

	// Checkout withdrawals
	// TODO: Gather multiple small withdrawals.
	wths := account.CheckoutWithdrawals(coin, 1)
	if len(wths) == 0 {
		return false, nil
	}
	wthIds := Map(wths, "Id")
	amounts := map[string]uint64{}
	amountSum := uint64(0)
	for _, wth := range wths {
		if wth.Amount <= 0 {
			panic(NewError("Invalid send amount %v", wth.Amount))
		}
		amounts[wth.ToAddress] += uint64(wth.Amount)
		amountSum += uint64(wth.Amount)
	}

	// figure out which payments to use.
	signedTx, payments, minerFees, chgAddress, err := ComputeWithdrawalTransaction(coin, amounts)
	if err != nil {
		account.StallWithdrawals(wthIds)
		return false, err
	}
	paymentIds := Map(payments, "Id")

	// save withdrawal info for bookkeeping.
	wthTx := SaveWithdrawalTx(&WithdrawalTx{
		Coin:       coin,
		Type:       WITHDRAWAL_TX_TYPE_WITHDRAWAL,
		Amount:     amountSum,
		MinerFee:   minerFees,
		ChgAddress: chgAddress,
		RawTx:      signedTx,
		TxId:       bitcoin.ComputeTxId(signedTx),
	})

	// checkout those payments.
	bitcoin.CheckoutPaymentsToSpend(paymentIds, wthTx.Id)

	// TODO: the Tx should go out to our partners who sign them for us.
	// TODO: receive the signed Tx.

	// deduct change amount from system user's "change" wallet.
	// this creates a negative balance, which will revert to zero
	// when the change is received.
	if chgAddress != "" {
		changeAmount := amounts[chgAddress]
		err := db.DoBeginSerializable(func(tx *db.ModelTx) {
			account.UpdateBalanceByWallet(tx, 0, account.WALLET_CHANGE, coin, -int64(changeAmount), false)
		})
		if err != nil {
			panic(err)
		}
	}

	// broadcast transaction.
	rpc.SendRawTransaction(coin, signedTx)

	// update payments as spent.
	bitcoin.MarkPaymentsAsSpent(paymentIds, wthTx.Id)

	// update withdrawals as complete.
	account.CompleteWithdrawals(wths, wthTx.Id)

	return true, nil
}