[
    "autonomous agent",
    {
        "init": "{
        $owner = 'JBGMJI7XSKLKNHZF26BUBWHVUZSDV3P5';
        $fee = 1000;
        $addr = trigger.address;
        $bounce_fee = 10000;
        $base_inp = trigger.output[[asset=base]];
        $base_key = 'base_' || trigger.address;
        if($base_inp < 0)
            bounce("no inputs detected");
        
        if(trigger.output[[asset!=base]].asset != 'none')
            $asset = trigger.output[[asset!=base]].asset;
        if($asset){
            if($asset == 'ambiguous'){
                bounce("only 1 asset per tx");
            }
            if(trigger.output[[asset!=base]] ==0)
                bounce("zero asset tx");
        }
        if(var['asset']){
            if($asset and var['asset'] != $asset)
                bounce("not a previously defined asset");
        }
        else{
            if(!$asset and !trigger.data.asset)
                bounce("a asset must be defined first time");
        }
        
        if($asset){
            $asset_key = $asset||'_'||trigger.address;
            $asset_inp = trigger.output[[asset!=base]];
        }
        
        $ratio = 1000;//bytes per 1 asset
        $max_b_to_exchange = var['total'];
        $max_a_to_exchange = var['total_asset'];
        $base_inp_in_asset = $base_inp/$ratio;
        $asset_inp_in_bytes = $asset_inp*$ratio;
        if($asset){
            if($max_b_to_exchange and $max_b_to_exchange != 0){
                //exchange
                if($asset_inp_in_bytes > $max_b_to_exchange){
                    //partial exchange till empty,let deposit rest
                    $byte_amount = $max_b_to_exchange;
                    $asset_amount = ($asset_inp_in_bytes - $max_b_to_exchange)/$ratio;
                }
                else{
                    if($asset_inp_in_bytes < $max_b_to_exchange){
                        //full exchange until $max_b_to_exchange -$asset_inp_in_bytes,return bfees
                        $byte_amount = $max_b_to_exchange - $asset_inp_in_bytes;
                        $asset_amount = 0;
                    }
                    else{
                        //full exchange until empty,return bfees
                        $byte_amount = $max_b_to_exchange;
                        $asset_amount = 0;
                    }
                }
            }
            else{
                $deposit = true;
            }
        }
        else{
            if($max_a_to_exchange and $max_a_to_exchange != 0){
                //exchange
                if($base_inp_in_asset > $max_a_to_exchange){
                    //partial exchange till empty,let deposit rest
                    $asset_amount = $max_a_to_exchange;
                    $byte_amount = ($base_inp_in_asset - $max_a_to_exchange)*$ratio;
                }
                else{
                    if($base_inp_in_asset < $max_a_to_exchange){
                        //full exchange until $max_a_to_exchange -$base_inp_in_asset
                        $asset_amount = $max_a_to_exchange - $base_inp_in_asset;
                        $byte_amount = 0;
                    }
                    else{
                        //full exchange until empty
                        $asset_amount = $max_a_to_exchange;
                        $byte_amount = 0;
                    }
                }
            }
            else{
                $deposit = true;
            }
        }
    }",
        "messages": {
            "cases": [
                {
                    "if": "{
                        $asset and $byte_amount
                    }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$byte_amount+$base_inp-$fee}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var['total_asset'] += $asset_amount;
                            var['total'] -= $byte_amount;
                            response['message'] = 'exchange asset x bytes';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        !$asset and $asset_amount
                    }",
                    "messages": [
                        {
                            "init": "{
                            if(($base_inp-$fee)< 0)
                                bounce("Not enough fees");
                            }",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp-$fee}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{var['asset']}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$asset_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var['total_asset'] -= $asset_amount;
                            var['total'] += $byte_amount;
                            response['message'] = 'exchange bytes x asset';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        var['total'] and var[$asset_key] and var['total'] > 0 and var[$asset_key] > 0
                    }",
                    "messages": [
                        {
                            "init": "{
                            $max_to_retire = var[$asset_key]*$ratio;
                            if(var['total'] <= $max_to_retire){
                                $retire_amount = var['total'];
                            }
                            else{
                                $retire_amount = $max_to_retire;
                            }
                        }",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount+$base_inp}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var['total'] -= $retire_amount;
                            $ret_ass = $retire_amount/$ratio;
                            var['total_asset'] -= $ret_ass;
                            var[$asset_key] -= $ret_ass;
                            response['message'] = 'retired exchanged amount (bytes)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        var['total_asset'] and var[$base_key] and var['total_asset'] > 0 and var[$base_key] > 0
                    }",
                    "messages": [
                        {
                            "init": "{
                            $max_to_retire = var[$base_key]/$ratio;
                            if(var['total_asset'] <= $max_to_retire){
                                $retire_amount = var['total_asset'];
                            }
                            else{
                                $retire_amount = $max_to_retire;
                            }
                        }",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{var['asset']}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var['total_asset'] -= $retire_amount;
                            $ret_bas = $retire_amount*$ratio;
                            var['total'] -= $ret_bas;
                            var[$base_key] -= $ret_bas;
                            response['message'] = 'retired exchanged amount (asset)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        trigger.data.cancel and var['total_asset'] and var[$asset_key] and var['total_asset'] > 0 and var[$asset_key] > 0
                    }",
                    "messages": [
                        {
                            "init": "{
                            if(var['total_asset'] <= var[$asset_key]){
                                $retire_amount = var['total_asset'];
                            }
                            else{
                                $retire_amount = var[$asset_key];
                            }
                        }",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp-(2*$fee)}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{var['asset']}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var['total_asset'] -= $retire_amount;
                            var[$base_key] -= $retire_amount;
                            response['message'] = 'canceled order (asset)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        trigger.data.cancel and var['total'] and var[$base_key] and var['total'] > 0 and var[$base_key] > 0
                    }",
                    "messages": [
                        {
                            "init": "{
                            if(var['total'] <= var[$base_key]){
                                $retire_amount = var['total'];
                            }
                            else{
                                $retire_amount = var[$base_key];
                            }
                        }",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount+$base_inp-(2*$fee)}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var['total'] -= $retire_amount;
                            var[$base_key] -= $retire_amount;
                            response['message'] = 'canceled order (bytes)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        if(!$deposit){
                            bounce("f");
                        }
                        $deposit
                    }",
                    "messages": [
                        {
                            "if": "{$asset}",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp-$fee}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                        if(!var['asset']){
                            var['total_asset'] = 0;
                            var['total'] = 0;
                            if($asset)
                                var['asset'] = $asset;
                            else
                                var['asset'] = trigger.data.asset;
                        }
                        if($asset){
                            var['total_asset'] += $asset_inp;
                            var[$asset_key] += $asset_inp;
                            response['message'] = 'deposited asset';
                        }
                        else{
                            var['total'] += $base_inp;
                            var[$base_key] += $base_inp;
                            response['message'] = 'deposited bytes';
                        }
                        
                    }"
                        }
                    ]
                }
            ]
        }
    }
]