Example #1
0
        public static ExchangeList GetListExchangePaginated(int offset, int limit)
        {
            if (offset < 0 || limit < 0)
            {
                throw new ArgumentException("offset and limit value must be >= 0");
            }

            long latest_num = Manager.Instance.DBManager.DynamicProperties.GetLatestExchangeNum();

            if (latest_num <= offset)
            {
                throw new ArgumentException("latest num is " + latest_num + ". offset num  must be smaller than latest.");
            }

            limit = limit > Parameter.DatabaseParameters.EXCHANGE_COUNT_LIMIT_MAX ? Parameter.DatabaseParameters.EXCHANGE_COUNT_LIMIT_MAX : limit;
            long end = offset + limit;

            end = end > latest_num ? latest_num : end;

            ExchangeList result = new ExchangeList();

            for (int i = offset; i < end; i++)
            {
                ExchangeCapsule exchange = Manager.Instance.DBManager.ExchangeFinal.Get(ExchangeCapsule.CalculateDatabaseKey(i));
                if (exchange != null)
                {
                    result.Exchanges.Add(exchange.Instance);
                }
            }

            return(result);
        }
Example #2
0
        public override bool Execute(TransactionResultCapsule result)
        {
            long fee = CalcFee();

            try
            {
                ExchangeTransactionContract exchage_tx_contract = this.contract.Unpack <ExchangeTransactionContract>();
                AccountCapsule  account  = this.db_manager.Account.Get(exchage_tx_contract.OwnerAddress.ToByteArray());
                ExchangeCapsule exchange = this.db_manager.ExchangeFinal.Get(BitConverter.GetBytes(exchage_tx_contract.ExchangeId));

                byte[] first_token_id       = exchange.FirstTokenId.ToByteArray();
                byte[] second_token_id      = exchange.SecondTokenId.ToByteArray();
                byte[] token_id             = exchage_tx_contract.TokenId.ToByteArray();
                long   token_quantity       = exchage_tx_contract.Quant;
                byte[] other_token_id       = null;
                long   other_token_quantity = exchange.Transaction(token_id, token_quantity);

                other_token_id = token_id.SequenceEqual(first_token_id) ? second_token_id : first_token_id;

                long new_balance = account.Balance - CalcFee();
                account.Balance = new_balance;

                if (token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    account.Balance = new_balance - token_quantity;
                }
                else
                {
                    account.ReduceAssetAmountV2(token_id, token_quantity, this.db_manager);
                }

                if (other_token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    account.Balance = new_balance + other_token_quantity;
                }
                else
                {
                    account.AddAssetAmountV2(other_token_id, other_token_quantity, this.db_manager);
                }

                this.db_manager.Account.Put(account.CreateDatabaseKey(), account);
                this.db_manager.PutExchangeCapsule(exchange);

                result.ExchangeReceivedAmount = other_token_quantity;
                result.SetStatus(fee, code.Sucess);
            }
            catch (ItemNotFoundException e)
            {
                Logger.Debug(e.Message);
                result.SetStatus(fee, code.Failed);
                throw new ContractExeException(e.Message);
            }
            catch (InvalidProtocolBufferException e)
            {
                Logger.Debug(e.Message);
                result.SetStatus(fee, code.Failed);
                throw new ContractExeException(e.Message);
            }
            return(true);
        }
Example #3
0
        public override bool Execute(TransactionResultCapsule result)
        {
            long fee = CalcFee();

            try
            {
                ExchangeCreateContract exchange_create_contract = this.contract.Unpack <ExchangeCreateContract>();
                AccountCapsule         account = this.db_manager.Account.Get(exchange_create_contract.OwnerAddress.ToByteArray());

                byte[] first_token_id       = exchange_create_contract.FirstTokenId.ToByteArray();
                byte[] secodn_token_id      = exchange_create_contract.SecondTokenId.ToByteArray();
                long   first_token_balance  = exchange_create_contract.FirstTokenBalance;
                long   second_token_balance = exchange_create_contract.SecondTokenBalance;
                long   new_balance          = account.Balance - fee;

                account.Balance = new_balance;

                if (first_token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    account.Balance = new_balance - first_token_balance;
                }
                else
                {
                    account.ReduceAssetAmountV2(first_token_id, first_token_balance, this.db_manager);
                }

                if (secodn_token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    account.Balance = new_balance - second_token_balance;
                }
                else
                {
                    account.ReduceAssetAmountV2(secodn_token_id, second_token_balance, this.db_manager);
                }

                long id  = this.db_manager.DynamicProperties.GetLatestExchangeNum() + 1;
                long now = this.db_manager.GetHeadBlockTimestamp();
                if (this.db_manager.DynamicProperties.GetAllowSameTokenName() == 0)
                {
                    ExchangeCapsule exchange = new ExchangeCapsule(
                        exchange_create_contract.OwnerAddress,
                        id,
                        now,
                        first_token_id,
                        secodn_token_id);

                    exchange.SetBalance(first_token_balance, second_token_balance);
                    this.db_manager.Exchange.Put(exchange.CreateDatabaseKey(), exchange);

                    if (!first_token_id.SequenceEqual(COMPARE_CHARICTOR))
                    {
                        string first_id = this.db_manager.AssetIssue.Get(first_token_id).Id;
                        first_token_id = Encoding.UTF8.GetBytes(first_id);
                    }
                    if (!secodn_token_id.SequenceEqual(COMPARE_CHARICTOR))
                    {
                        string second_id = this.db_manager.AssetIssue.Get(secodn_token_id).Id;
                        secodn_token_id = Encoding.UTF8.GetBytes(second_id);
                    }
                }

                ExchangeCapsule exchange_v2 = new ExchangeCapsule(
                    exchange_create_contract.OwnerAddress,
                    id,
                    now,
                    first_token_id,
                    secodn_token_id);

                exchange_v2.SetBalance(first_token_balance, second_token_balance);

                this.db_manager.ExchangeV2.Put(exchange_v2.CreateDatabaseKey(), exchange_v2);
                this.db_manager.Account.Put(account.CreateDatabaseKey(), account);
                this.db_manager.DynamicProperties.PutLatestExchangeNum(id);
                this.db_manager.AdjustBalance(this.db_manager.Account.GetBlackHole().CreateDatabaseKey(), fee);

                result.ExchangeId = id;
                result.SetStatus(fee, code.Sucess);
            }
            catch (BalanceInsufficientException e)
            {
                Logger.Debug(e.Message);
                result.SetStatus(fee, code.Failed);
                throw new ContractExeException(e.Message);
            }
            catch (InvalidProtocolBufferException e)
            {
                Logger.Debug(e.Message);
                result.SetStatus(fee, code.Failed);
                throw new ContractExeException(e.Message);
            }
            return(true);
        }
        public override bool Validate()
        {
            if (this.contract == null)
            {
                throw new ContractValidateException("No contract!");
            }

            if (this.db_manager == null)
            {
                throw new ContractValidateException("No this.db_manager!");
            }

            if (!this.contract.Is(ExchangeInjectContract.Descriptor))
            {
                ExchangeInjectContract contract;
                try
                {
                    contract = this.contract.Unpack <ExchangeInjectContract>();
                }
                catch (InvalidProtocolBufferException e)
                {
                    throw new ContractValidateException(e.Message);
                }

                byte[] owner_address = contract.OwnerAddress.ToByteArray();

                if (!Wallet.IsValidAddress(owner_address))
                {
                    throw new ContractValidateException("Invalid address");
                }

                if (!this.db_manager.Account.Contains(owner_address))
                {
                    throw new ContractValidateException("account[" + owner_address.ToHexString() + "] not exists");
                }

                AccountCapsule account = this.db_manager.Account.Get(owner_address);

                if (account.Balance < CalcFee())
                {
                    throw new ContractValidateException("No enough balance for exchange inject fee!");
                }

                ExchangeCapsule exchange = null;

                try
                {
                    exchange = this.db_manager.ExchangeFinal.Get(BitConverter.GetBytes(contract.ExchangeId));
                }
                catch (ItemNotFoundException e)
                {
                    throw new ContractValidateException("Exchange[" + contract.ExchangeId + "] not exists", e);
                }

                if (!account.Address.Equals(exchange.CreatorAddress))
                {
                    throw new ContractValidateException("account[" + owner_address.ToHexString() + "] is not creator");
                }

                byte[] first_token_id       = exchange.FirstTokenId.ToByteArray();
                byte[] second_token_id      = exchange.SecondTokenId.ToByteArray();
                long   first_token_balance  = exchange.FirstTokenBalance;
                long   second_token_balance = exchange.SecondTokenBalance;

                byte[] token_id       = contract.TokenId.ToByteArray();
                long   token_quantity = contract.Quant;

                byte[] other_token_id       = null;
                long   other_token_quantity = 0;

                if (this.db_manager.DynamicProperties.GetAllowSameTokenName() == 1)
                {
                    if (!token_id.SequenceEqual(COMPARE_CHARICTOR) && !TransactionUtil.IsNumber(token_id))
                    {
                        throw new ContractValidateException("token id is not a valid number");
                    }
                }

                if (!token_id.SequenceEqual(first_token_id) && !token_id.SequenceEqual(second_token_id))
                {
                    throw new ContractValidateException("token id is not in exchange");
                }

                if (first_token_balance == 0 || second_token_balance == 0)
                {
                    throw new ContractValidateException("Token balance in exchange is equal with 0,"
                                                        + "the exchange has been closed");
                }

                if (token_quantity <= 0)
                {
                    throw new ContractValidateException("injected token quant must greater than zero");
                }

                BigInteger first_balance           = new BigInteger(first_token_balance);
                BigInteger second_balance          = new BigInteger(second_token_balance);
                BigInteger quantity                = new BigInteger(token_quantity);
                long       new_token_balance       = 0;
                long       new_other_token_balance = 0;
                if (token_id.SequenceEqual(first_token_id))
                {
                    other_token_id          = second_token_id;
                    other_token_quantity    = (long)BigInteger.Multiply(second_balance, token_quantity);
                    other_token_quantity    = (long)BigInteger.Divide(other_token_quantity, first_balance);
                    new_token_balance       = first_token_balance + token_quantity;
                    new_other_token_balance = second_token_balance + other_token_quantity;
                }
                else
                {
                    other_token_id          = first_token_id;
                    other_token_quantity    = (long)BigInteger.Multiply(first_balance, token_quantity);
                    other_token_quantity    = (long)BigInteger.Divide(other_token_quantity, second_balance);
                    new_token_balance       = second_token_balance + token_quantity;
                    new_other_token_balance = first_token_balance + other_token_quantity;
                }

                if (other_token_quantity <= 0)
                {
                    throw new ContractValidateException("the calculated token quant  must be greater than 0");
                }

                long balance_limit = this.db_manager.DynamicProperties.GetExchangeBalanceLimit();
                if (new_token_balance > balance_limit || new_other_token_balance > balance_limit)
                {
                    throw new ContractValidateException("token balance must less than " + balance_limit);
                }

                if (token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    if (account.Balance < (token_quantity + CalcFee()))
                    {
                        throw new ContractValidateException("balance is not enough");
                    }
                }
                else
                {
                    if (!account.AssetBalanceEnoughV2(token_id, token_quantity, this.db_manager))
                    {
                        throw new ContractValidateException("token balance is not enough");
                    }
                }

                if (other_token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    if (account.Balance < (other_token_quantity + CalcFee()))
                    {
                        throw new ContractValidateException("balance is not enough");
                    }
                }
                else
                {
                    if (!account.AssetBalanceEnoughV2(other_token_id, other_token_quantity, this.db_manager))
                    {
                        throw new ContractValidateException("other token balance is not enough");
                    }
                }
            }
            else
            {
                throw new ContractValidateException(
                          "contract type error,expected type [ExchangeInjectContract],real type[" + this.contract.GetType().Name + "]");
            }

            return(true);
        }
        public override bool Execute(TransactionResultCapsule result)
        {
            long fee = CalcFee();

            try
            {
                ExchangeWithdrawContract ew_contract = this.contract.Unpack <ExchangeWithdrawContract>();
                AccountCapsule           account     = this.db_manager.Account.Get(ew_contract.OwnerAddress.ToByteArray());
                ExchangeCapsule          exchange    = this.db_manager.ExchangeFinal.Get(BitConverter.GetBytes(ew_contract.ExchangeId));

                byte[] first_token_id       = exchange.FirstTokenId.ToByteArray();
                byte[] second_token_id      = exchange.SecondTokenId.ToByteArray();
                long   first_token_balance  = exchange.FirstTokenBalance;
                long   second_token_balance = exchange.SecondTokenBalance;
                byte[] token_id             = ew_contract.TokenId.ToByteArray();
                long   token_quantity       = ew_contract.Quant;

                byte[] other_token_id       = null;
                long   other_token_quantity = 0;

                BigInteger first_balance  = new BigInteger(first_token_balance);
                BigInteger second_balance = new BigInteger(second_token_balance);
                BigInteger quantity       = new BigInteger(token_quantity);
                if (token_id.SequenceEqual(first_token_id))
                {
                    other_token_id       = second_token_id;
                    other_token_quantity = (long)BigInteger.Multiply(second_balance, quantity);
                    other_token_quantity = (long)BigInteger.Divide(other_token_quantity, first_balance);
                    exchange.SetBalance(first_token_balance - token_quantity, second_token_balance - other_token_quantity);
                }
                else
                {
                    other_token_id       = first_token_id;
                    other_token_quantity = (long)BigInteger.Multiply(first_balance, quantity);
                    other_token_quantity = (long)BigInteger.Divide(other_token_quantity, second_balance);
                    exchange.SetBalance(first_token_balance - other_token_quantity, second_token_balance - token_quantity);
                }

                long new_balance = account.Balance - CalcFee();

                if (token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    account.Balance = new_balance + token_quantity;
                }
                else
                {
                    account.AddAssetAmountV2(token_id, token_quantity, this.db_manager);
                }

                if (other_token_id.SequenceEqual(COMPARE_CHARICTOR))
                {
                    account.Balance = new_balance + other_token_quantity;
                }
                else
                {
                    account.AddAssetAmountV2(other_token_id, other_token_quantity, this.db_manager);
                }

                this.db_manager.Account.Put(account.CreateDatabaseKey(), account);
                this.db_manager.PutExchangeCapsule(exchange);

                result.ExchangeWithdrawAnotherAmount = other_token_quantity;
                result.SetStatus(fee, code.Sucess);
            }
            catch (ItemNotFoundException e)
            {
                Logger.Debug(e.Message);
                result.SetStatus(fee, code.Failed);
                throw new ContractExeException(e.Message);
            }
            catch (InvalidProtocolBufferException e)
            {
                Logger.Debug(e.Message);
                result.SetStatus(fee, code.Failed);
                throw new ContractExeException(e.Message);
            }
            return(true);
        }
        public override bool Validate()
        {
            if (this.contract == null)
            {
                throw new ContractValidateException("No contract!");
            }

            if (this.db_manager == null)
            {
                throw new ContractValidateException("No this.db_manager!");
            }

            if (this.contract.Is(ExchangeWithdrawContract.Descriptor))
            {
                ExchangeWithdrawContract contract = null;
                try
                {
                    contract = this.contract.Unpack <ExchangeWithdrawContract>();
                }
                catch (InvalidProtocolBufferException e)
                {
                    throw new ContractValidateException(e.Message);
                }

                byte[] owner_address = contract.OwnerAddress.ToByteArray();
                if (!Wallet.IsValidAddress(owner_address))
                {
                    throw new ContractValidateException("Invalid address");
                }

                if (!this.db_manager.Account.Contains(owner_address))
                {
                    throw new ContractValidateException("account[" + owner_address.ToHexString() + "] not exists");
                }

                AccountCapsule account = this.db_manager.Account.Get(owner_address);

                if (account.Balance < CalcFee())
                {
                    throw new ContractValidateException("No enough balance for exchange withdraw fee!");
                }

                ExchangeCapsule exchange = null;
                try
                {
                    exchange = this.db_manager.ExchangeFinal.Get(BitConverter.GetBytes(contract.ExchangeId));
                }
                catch (ItemNotFoundException e)
                {
                    throw new ContractValidateException("Exchange[" + contract.ExchangeId + "] not exists", e);
                }

                if (!account.Address.Equals(exchange.CreatorAddress))
                {
                    throw new ContractValidateException("account[" + owner_address.ToHexString() + "] is not creator");
                }

                byte[] first_token_id       = exchange.FirstTokenId.ToByteArray();
                byte[] second_token_id      = exchange.SecondTokenId.ToByteArray();
                long   first_token_balance  = exchange.FirstTokenBalance;
                long   second_token_balance = exchange.SecondTokenBalance;
                byte[] token_id             = contract.TokenId.ToByteArray();
                long   token_quantity       = contract.Quant;

                long other_token_quantity = 0;
                if (this.db_manager.DynamicProperties.GetAllowSameTokenName() == 1)
                {
                    if (!token_id.SequenceEqual(COMPARE_CHARICTOR) && !TransactionUtil.IsNumber(token_id))
                    {
                        throw new ContractValidateException("token id is not a valid number");
                    }
                }

                if (!token_id.SequenceEqual(first_token_id) && !token_id.SequenceEqual(second_token_id))
                {
                    throw new ContractValidateException("token is not in exchange");
                }

                if (token_quantity <= 0)
                {
                    throw new ContractValidateException("withdraw token quant must greater than zero");
                }

                if (first_token_balance == 0 || second_token_balance == 0)
                {
                    throw new ContractValidateException("Token balance in exchange is equal with 0,"
                                                        + "the exchange has been closed");
                }


                BigDecimal first_balance  = new BigDecimal(first_token_balance);
                BigDecimal second_balance = new BigDecimal(second_token_balance);
                BigDecimal bigTokenQuant  = new BigDecimal(token_quantity);
                if (token_id.SequenceEqual(first_token_id))
                {
                    other_token_quantity = second_balance.Multiply(bigTokenQuant)
                                           .DivideToIntegralValue(first_balance).ToInt64();

                    if (first_token_balance < token_quantity || second_token_balance < other_token_quantity)
                    {
                        throw new ContractValidateException("exchange balance is not enough");
                    }

                    if (other_token_quantity <= 0)
                    {
                        throw new ContractValidateException("withdraw another token quant must greater than zero");
                    }

                    double remainder = second_balance.Multiply(bigTokenQuant)
                                       .Divide(first_balance, 4, RoundingMode.HalfUp).ToDouble();
                    remainder -= other_token_quantity;

                    if (remainder / other_token_quantity > 0.0001)
                    {
                        throw new ContractValidateException("Not precise enough");
                    }
                }
                else
                {
                    other_token_quantity = first_balance.Multiply(bigTokenQuant)
                                           .DivideToIntegralValue(second_balance).ToInt64();

                    if (second_token_balance < token_quantity || first_token_balance < other_token_quantity)
                    {
                        throw new ContractValidateException("exchange balance is not enough");
                    }

                    if (other_token_quantity <= 0)
                    {
                        throw new ContractValidateException("withdraw another token quant must greater than zero");
                    }

                    double remainder = first_balance.Multiply(bigTokenQuant)
                                       .Divide(second_balance, 4, RoundingMode.HalfUp).ToDouble();
                    remainder -= other_token_quantity;

                    if (remainder / other_token_quantity > 0.0001)
                    {
                        throw new ContractValidateException("Not precise enough");
                    }
                }
            }
            else
            {
                throw new ContractValidateException(
                          "contract type error,expected type [ExchangeWithdrawContract],real type[" + this.contract.GetType().Name + "]");
            }

            return(true);
        }