public static BigInteger getTransactionValue(byte tokenType, byte[] receiver)
    {
        PbEntity.TokenType token = PbEntity.getStandardTokenType();
        Transaction        tx    = ExecutionEngine.ScriptContainer as Transaction;

        TransactionOutput[] outputs = tx.GetOutputs();
        BigInteger          result  = 0;

        foreach (TransactionOutput output in outputs)
        {
            byte[] scriptHash = output.ScriptHash;
            if (!scriptHash.Equals(receiver))
            {
                continue;
            }
            byte[] assetid = output.AssetId;
            //Temperately only support NEO and GAS
            byte type = token.INVALID;
            if (assetid.Equals(NeoID))
            {
                type = token.NEO;
            }
            else if (assetid.Equals(GasID))
            {
                type = token.GAS;
            }
            if (tokenType != type)
            {
                continue;
            }
            result += output.Value;
        }
        return(result);
    }
        public static object resolvePaymentByConditions(byte[] resolvePayRequestBs)
        {
            PbChain.ResolvePayByConditionsRequest resolvePayRequest = new PbChain.ResolvePayByConditionsRequest();
            resolvePayRequest = (PbChain.ResolvePayByConditionsRequest)Helper.Deserialize(resolvePayRequestBs);
            PbEntity.ConditionalPay   pay      = Helper.Deserialize(resolvePayRequest.condPay) as PbEntity.ConditionalPay;
            PbEntity.TransferFunction function = pay.transferFunc;
            byte       funcType = function.logicType;
            BigInteger amount   = 0;

            PbEntity.TransferFunctionType TransferFunctionType = PbEntity.getTransferFunctionType();
            if (funcType == TransferFunctionType.BOOLEAN_AND)
            {
                amount = _calculateBooleanAndPayment(pay, resolvePayRequest.hashPreimages);
            }
            else if (funcType == TransferFunctionType.BOOLEAN_OR)
            {
                amount = _calculateBooleanOrPayment(pay, resolvePayRequest.hashPreimages);
            }
            else if (_isNumericLogic(funcType))
            {
                amount = _calculateNumericLogicPayment(pay, resolvePayRequest.hashPreimages, funcType);
            }
            else
            {
                BasicMethods.assert(false, "error");
            }
            byte[] payHash = SmartContract.Sha256(resolvePayRequest.condPay);
            _resolvePayment(pay, payHash, amount);
            return(true);
        }
        public static object depositNEO(byte[] walletId)
        {
            BasicMethods.assert(BasicMethods._isByte32(walletId), "walletId is not byte32");
            PbEntity.TokenType token = PbEntity.getStandardTokenType();
            BigInteger         value = LedgerStruct.getTransactionValue(token.NEO, ExecutionEngine.ExecutingScriptHash);

            BasicMethods.assert(value >= 0, "amount is less than zero");
            _whenNotPaused();
            BasicMethods.assert(_updateBalance(walletId, LedgerStruct.NeoAddress, value, getStandardMathOperation().add), "updateBalance failed");

            DepositToWallet(walletId, LedgerStruct.NeoAddress, value);
            return(true);
        }
        private static BigInteger _calculateBooleanOrPayment(PbEntity.ConditionalPay _pay, byte[][] _preimages)
        {
            int  j = 0;
            bool hasContractCond     = false;
            bool hasTrueContractCond = false;

            PbEntity.ConditionType ConditionType = PbEntity.getConditionType();
            PbEntity.Condition[]   conditions    = _pay.conditions;
            for (var i = 0; i < conditions.Length; i++)
            {
                PbEntity.Condition cond = _pay.conditions[i];
                if (cond.conditionType == ConditionType.HASH_LOCK)
                {
                    BasicMethods.assert(SmartContract.Sha256(_preimages[j]) == cond.hashLock, "wrong preimage");
                    j++;
                }
                else if (
                    cond.conditionType == ConditionType.DEPLOYED_CONTRACT ||
                    cond.conditionType == ConditionType.VIRTUAL_CONTRACT
                    )
                {
                    byte[] booleanCondHash      = _getCondAddress(cond);
                    DynamicCallContract dyncall = (DynamicCallContract)booleanCondHash.ToDelegate();
                    BasicMethods.assert((bool)dyncall("isFinalized", new object[] { cond.argsQueryFinalization }), "Condition is not finalized");
                    hasContractCond = true;

                    bool outcome = (bool)dyncall("getOutcome", new object[] { cond.argsQueryOutcome });
                    if (outcome)
                    {
                        hasTrueContractCond = true;
                    }
                }
                else
                {
                    BasicMethods.assert(false, "condition type error");
                }
            }
            if (!hasContractCond || hasTrueContractCond)
            {
                PbEntity.TransferFunction transferFunction = _pay.transferFunc;
                PbEntity.TokenTransfer    tokenTransfer    = transferFunction.maxTransfer;
                PbEntity.AccountAmtPair   accountAmtPair   = tokenTransfer.receiver;
                return(accountAmtPair.amt);
            }
            else
            {
                return(0);
            }
        }
 private static byte[] _getCondAddress(PbEntity.Condition _cond)
 {
     PbEntity.ConditionType ConditionType = PbEntity.getConditionType();
     if (_cond.conditionType == ConditionType.DEPLOYED_CONTRACT)
     {
         return(_cond.deployedContractAddress);
     }
     else if (_cond.conditionType == ConditionType.VIRTUAL_CONTRACT)
     {
         byte[] virtResolverHash     = Storage.Get(Storage.CurrentContext, VirtResolverHashKey);
         DynamicCallContract dyncall = (DynamicCallContract)virtResolverHash.ToDelegate();
         return((byte[])dyncall("resolve", new object[] { _cond.virtualContractAddress }));
     }
     BasicMethods.assert(false, "conditiontype error");
     return(new byte[] { 0x00 });
 }
 private static bool _isNumericLogic(byte _funcType)
 {
     PbEntity.TransferFunctionType TransferFunctionType = PbEntity.getTransferFunctionType();
     return(_funcType == TransferFunctionType.NUMERIC_ADD || _funcType == TransferFunctionType.NUMERIC_MAX || _funcType == TransferFunctionType.NUMERIC_MIN);
 }
        private static BigInteger _calculateNumericLogicPayment(PbEntity.ConditionalPay _pay, byte[][] _preimages, byte _funcType)
        {
            int        j              = 0;
            BigInteger amount         = 0;
            bool       hasContracCond = false;

            PbEntity.ConditionType        ConditionType        = PbEntity.getConditionType();
            PbEntity.TransferFunctionType TransferFunctionType = PbEntity.getTransferFunctionType();
            PbEntity.Condition[]          conditions           = _pay.conditions;
            for (var i = 0; i < conditions.Length; i++)
            {
                PbEntity.Condition cond = _pay.conditions[i];
                if (cond.conditionType == ConditionType.HASH_LOCK)
                {
                    BasicMethods.assert(SmartContract.Sha256(_preimages[j]) == cond.hashLock, "wrong preimage");
                    j++;
                }
                else if (
                    cond.conditionType == ConditionType.DEPLOYED_CONTRACT ||
                    cond.conditionType == ConditionType.VIRTUAL_CONTRACT
                    )
                {
                    byte[] numericCondHash      = _getCondAddress(cond);
                    DynamicCallContract dyncall = (DynamicCallContract)numericCondHash.ToDelegate();
                    BasicMethods.assert((bool)dyncall("isFinalized", new object[] { cond.argsQueryFinalization }), "Condition is not finalized");

                    BigInteger outcome = (BigInteger)dyncall("getOutcome", new object[] { cond.argsQueryOutcome });

                    if (_funcType == TransferFunctionType.NUMERIC_ADD)
                    {
                        amount = amount + outcome;
                    }
                    else if (_funcType == TransferFunctionType.NUMERIC_MAX)
                    {
                        amount = max(amount, outcome);
                    }
                    else if (_funcType == TransferFunctionType.NUMERIC_MIN)
                    {
                        if (hasContracCond)
                        {
                            amount = min(amount, outcome);
                        }
                        else
                        {
                            amount = outcome;
                        }
                    }
                    else
                    {
                        BasicMethods.assert(false, "error");
                    }
                    hasContracCond = true;
                }
                else
                {
                    BasicMethods.assert(false, "condition type error");
                }
            }
            PbEntity.TransferFunction transferFunction = _pay.transferFunc;
            PbEntity.TokenTransfer    tokenTransfer    = transferFunction.maxTransfer;
            PbEntity.AccountAmtPair   accountAmtPair   = tokenTransfer.receiver;
            if (hasContracCond)
            {
                BasicMethods.assert(amount <= accountAmtPair.amt, "exceed max transfer amount");
                return(amount);
            }
            else
            {
                return(accountAmtPair.amt);
            }
        }