Definition: [
    "autonomous agent",
    {
        "init": "{
        $owner = 'JBGMJI7XSKLKNHZF26BUBWHVUZSDV3P5';
        $addr = trigger.address;
        $base_inp = trigger.output[[asset=base]] - 700;
        if($base_inp <= 0)
            bounce('not enough bytes for fees');
        if(trigger.output[[asset!=base]].asset != 'none'){
            $asset = trigger.output[[asset!=base]].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]];
            $name = var['reg_'||$asset] ? var['reg_'||$asset] : trigger.data.name;
        }
        else{
            $name = trigger.data.name;
            if(!$name)
                bounce('you must use a name');
        }
        $registered = $asset ? var['reg_'||$asset] : var['name_'||$name];
        if(!$registered){
            if(trigger.data.register_asset){
                return;
            }
            else{
                bounce('asset must be registered first');
            }
        }
        $asset_ct = $asset ? $asset : $registered;
        $ratio_key = $name || '_last_price';
        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 = $name || '_' || $addr || '_' || $ratio || '_base';
        $asset_key = $name || '_' || $addr || '_' || $ratio;
        $total_key = $name || '_' || $ratio || '_total_base';
        $total_asset_key = $name || '_' || $ratio || '_total_asset';
        $exch_key = $name || '_' || $ratio || 'exchanged_base';
        $exch_asset_key = $name || '_' || $ratio || 'exchanged_asset';
        $max_b_to_exchange = var[$total_key] - var[$exch_key];
        $max_a_to_exchange = var[$total_asset_key] - var[$exch_asset_key];
        $base_inp_round = ($base_inp - ($base_inp % $ratio));
        $base_inp_in_asset = ($base_inp_round / $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;
                    $asset_amount = (($asset_inp_in_bytes - $max_b_to_exchange) - (($asset_inp_in_bytes - $max_b_to_exchange) % $ratio)) / $ratio;
                }
                else{
                    //full exchange until empty,return bfees
                    $byte_amount = $asset_inp_in_bytes;
                    $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 = $max_a_to_exchange;
                    $byte_amount = ($base_inp_in_asset - $max_a_to_exchange) * $ratio;
                }
                else{
                    //full exchange until empty
                    $asset_amount =  $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($name){
                                if(var['name_'||$name]){
                                    bounce('name already chosen');
                                }
                            }
                            else{
                                bounce('no name defined');
                            }
                            var['reg_'||$asset] = $name;
                            var['name_'||$name] = $asset;
                            response['message'] = 'asset registered with name '||$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 = (var[$base_key] / $ratio) - (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 ('||$name||')';
                        }"
                        }
                    ]
                },
                {
                    "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 = $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 + $base_inp}"
                                    }
                                ]
                            }
                        },
                        {
                            "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_asset_key] +=  $asset_inp - $asset_amount;
                            var[$total_key] -= $byte_amount;
                            var[$ratio_key] = $ratio;
                            response['message'] = 'sold '||($asset_inp - $asset_amount)||' '||$name||' for '||($byte_amount)||' bytes';
                        }"
                        }
                    ]
                },
                {
                    "if": "{//exchange bytes x asset
                        !$asset and $asset_amount and !var[$asset_key]
                    }",
                    "messages": [
                        {
                            "if": "{$byte_amount > 0}",
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$byte_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "{$asset_ct}",
                                "outputs": [
                                    {
                                        "address": "{$addr}",
                                        "amount": "{$asset_amount}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_key] += $base_inp_round - $byte_amount;
                            var[$total_asset_key] -= $asset_amount;
                            var[$exch_key] += $base_inp_round - $byte_amount;
                            var[$ratio_key] = $ratio;
                            response['message'] = 'bought '||($asset_amount)||' '||$name||' for '||($base_inp_round - $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}"
                                    }
                                ]
                            }
                        },
                        {
                            "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 (sell '||$name||')';
                        }"
                        }
                    ]
                },
                {
                    "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}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            var[$total_key] -= $retire_amount;
                            var[$base_key] -= $retire_amount;
                            response['message'] = 'canceled order (buy '||$name||')';
                        }"
                        }
                    ]
                },
                {
                    "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}"
                                    }
                                ]
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            if($asset){
                                var[$total_asset_key] += $asset_inp;
                                var[$asset_key] += $asset_inp;
                                response['message'] = 'deposited '||$asset_inp||' '||$name||' to sell at '||$ratio||' bytes';
                            }
                            else{
                                var[$total_key] += $base_inp_round;
                                var[$base_key] += $base_inp_round;
                                response['message'] = 'deposited '||$base_inp_round||' bytes to buy '||$name||' at '||$ratio||' bytes';
                            }
                        }"
                        }
                    ]
                }
            ]
        }
    }
]