[
    "autonomous agent",
    {
        "init": "{
        $owner = 'JBGMJI7XSKLKNHZF26BUBWHVUZSDV3P5';
        $fee = 1600;
        $addr = trigger.address;
        $base_inp = trigger.output[[asset=base]];
        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");
            $asset_inp = trigger.output[[asset!=base]];
        }
        if($asset){
            $registered = var['reg_'||$asset];
        }
        else{
            if(!trigger.data.name)
                bounce('you must use a name');
            $registered = var['name_'||trigger.data.name];
        }
        if(!$registered){
            if(trigger.data.register_asset){
                return;
            }
            else{
                bounce('asset must be registered first');
            }
        }
        $asset_ct = $asset?$asset:$registered;
        $ratio_key = 'last_ratio_'||$asset_ct;
        if(!var[$ratio_key] and !trigger.data.price){
            bounce('price must be defined before first exchange');
        }
        if(trigger.data.price){
            $ratio = round(trigger.data.price);//bytes per 1 asset
            if($ratio <= 0){
                bounce('ratio not allowed');
            }
        }
        else{
            $ratio = var[$ratio_key];
        }
        $base_key = 'base_'||$asset_ct ||'_'|| $addr ||'_'|| $ratio;
        $asset_key = $asset_ct||'_'||trigger.address||'_'||$ratio;
        $total_key = 'total'||$asset_ct||$ratio;
        $total_asset_key = 'total_asset'||$asset_ct||'_'||$ratio;
        $exch_key = 'ex_'||$asset_ct||$ratio;
        $exch_asset_key = 'asset_ex_'||$asset_ct||'_'||$ratio;
        $max_b_to_exchange = var[$total_key] - var[$exch_key];
        $max_a_to_exchange = var[$total_asset_key] - var[$exch_asset_key];
        $base_inp_in_asset = round($base_inp/$ratio);
        $asset_inp_in_bytes = $asset_inp*$ratio;
        if($asset){
            if($max_b_to_exchange and $max_b_to_exchange > 0 and !trigger.data.cancel){
                //exchange
                if($asset_inp_in_bytes > $max_b_to_exchange){
                    //partial exchange till empty,return rest and bfees
                    $byte_amount = $max_b_to_exchange+$base_inp;
                    $asset_amount = round(($asset_inp_in_bytes - $max_b_to_exchange)/$ratio);
                }
                else{
                    //full exchange until empty,return bfees
                    $byte_amount = round($asset_inp_in_bytes)+$base_inp;
                    $asset_amount = 0;
                }
            }
            else{
                if(!trigger.data.cancel)
                    $deposit = true;
            }
        }
        else{
            if($max_a_to_exchange and $max_a_to_exchange > 0 and !trigger.data.cancel){
                //exchange
                if($base_inp_in_asset > $max_a_to_exchange){
                    //partial exchange till empty,return rest
                    $asset_amount = round($max_a_to_exchange);
                    $byte_amount = round(($base_inp_in_asset - $max_a_to_exchange)*$ratio);
                }
                else{
                    //full exchange until empty
                    $asset_amount =  round($base_inp_in_asset);
                    $byte_amount = 0;
                }
            }
            else{
                if(!trigger.data.cancel)
                    $deposit = true;
            }
        }
    }",
        "messages": {
            "cases": [
                {
                    "if": "{//register asset name
                        trigger.data.register_asset and $asset
                    }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{$asset}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$asset_inp}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            if(trigger.data.name){
                                if(var['name_'||trigger.data.name]){
                                    bounce('name already chosen');
                                }
                            }
                            else{
                                bounce('no name defined');
                            }
                            var['reg_'||$asset] = true;
                            var['name_'||trigger.data.name] = $asset;
                            response['message'] = 'asset registered with name '||trigger.data.name;
                        }"
                        }
                    ]
                },
                {
                    "if": "{// let retire exchanged amount (asset)
                        var[$exch_asset_key] and var[$base_key] and var[$exch_asset_key] > 0 and var[$base_key] > 0
                    }",
                    "init": "{
                        $max_to_retire = round(var[$base_key]/$ratio);
                        if(var[$exch_asset_key] <= $max_to_retire){
                            $retire_amount = var[$exch_asset_key];
                        }
                        else{
                            $retire_amount = $max_to_retire;
                        }
                    }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{$asset_ct}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_asset_key] -= $retire_amount;
                            var[$exch_asset_key] -= $retire_amount;
                            $ret_bas = $retire_amount*$ratio;
                            var[$base_key] -= $ret_bas;
                            response['message'] = 'retired exchanged amount (asset)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{// let retire exchanged amount (base)
                        var[$exch_key] and var[$asset_key] and var[$exch_key] > 0 and var[$asset_key] > 0
                    }",
                    "init": "{
                        $max_to_retire = var[$asset_key]*$ratio;
                        if(var[$exch_key] <= $max_to_retire){
                            $retire_amount = var[$exch_key];
                        }
                        else{
                            $retire_amount = $max_to_retire;
                        }
                    }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount+$base_inp}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_key] -= $retire_amount;
                            var[$exch_key] -= $retire_amount;
                            $ret_ass = round($retire_amount/$ratio);
                            var[$asset_key] -= $ret_ass;
                            response['message'] = 'retired exchanged amount (bytes)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{//exchange asset x bytes
                        $asset and $byte_amount and !var[$base_key]
                    }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$byte_amount-$fee}"
                                    }
                                ]
                            }
                        },
                        {
                            "if": "{$asset_amount > 0}",
                            "app": "payment",
                            "payload": {
                                "asset": "{$asset_ct}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$asset_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_asset_key] += $asset_inp-$asset_amount;
                            var[$exch_key] += $byte_amount;
                            var[$ratio_key] = $ratio;
                            response['message'] = 'sold '||($asset_inp-$asset_amount)||'asset for '||($byte_amount-$fee)||' bytes';
                        }"
                        }
                    ]
                },
                {
                    "if": "{//exchange bytes x asset
                        !$asset and $asset_amount and !var[$asset_key]
                    }",
                    "messages": [
                        {
                            "if": "{$byte_amount-$fee > 0}",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$byte_amount-$fee}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{$asset_ct}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$asset_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_key] += $base_inp - $byte_amount -$fee;
                            var[$total_asset_key] -= $asset_amount;
                            var[$exch_asset_key] += $asset_amount;
                            var[$ratio_key] = $ratio;
                            response['message'] = 'bought '||($asset_amount)||' asset for '||($base_inp - $byte_amount)||' bytes';
                        }"
                        }
                    ]
                },
                {
                    "if": "{// let cancel order (asset)
                        trigger.data.cancel and var[$asset_key] and var[$asset_key] > 0
                    }",
                    "init": "{
                        if($max_a_to_exchange <= 0){
                            bounce('Not allowed');
                        }
                        if($max_a_to_exchange <= var[$asset_key]){
                            $retire_amount = $max_a_to_exchange;
                        }
                        else{
                            $retire_amount = var[$asset_key];
                        }
                    }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp-(2*$fee)}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{$asset_ct}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_asset_key] -= $retire_amount;
                            var[$asset_key] -= $retire_amount;
                            response['message'] = 'canceled order (asset)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{// let cancel order (base)
                        trigger.data.cancel and var[$base_key] and var[$base_key] > 0
                    }",
                    "init": "{
                    if($max_b_to_exchange <= 0){
                        bounce('Not allowed');
                    }
                    if($max_b_to_exchange  <= var[$base_key]){
                        $retire_amount = $max_b_to_exchange ;
                    }
                    else{
                        $retire_amount = var[$base_key];
                    }
                }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$retire_amount+$base_inp-(2*$fee)}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_key] -= $retire_amount;
                            var[$base_key] -= $retire_amount;
                            response['message'] = 'canceled order (bytes)';
                        }"
                        }
                    ]
                },
                {
                    "if": "{
                        if(!$deposit){
                            bounce("Deposit not allowed, please cancel order first");
                        }
                        $deposit
                    }",
                    "messages": [
                        {
                            "if": "{$asset}",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$base_inp-$fee}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            if($asset){
                                var[$total_asset_key] += $asset_inp;
                                var[$asset_key] += $asset_inp;
                                response['message'] = 'deposited asset';
                            }
                            else{
                                var[$total_key] += $base_inp;
                                var[$base_key] += $base_inp;
                                response['message'] = 'deposited bytes';
                            }
                            
                        }"
                        }
                    ]
                }
            ]
        }
    }
]