[
    "autonomous agent",
    {
        "doc_url": "https://ostable.org/bonded-stablecoin-de-factory.json",
        "init": "{
        $curve_base_aa = 'STA7KVV77IHZ3S34YAFZAIKUGPIK4EZ7';
        $stable_base_aa = 'YXPLX6Q3HBBSH2K5HLYM45W7P7HFSEIN';
    }",
        "messages": {
            "cases": [
                {
                    "if": "{trigger.data.asset1 AND var['curve_' || trigger.address]}",
                    "init": "{
                    $stable_aa = [
                        'autonomous agent',
                        {
                            base_aa: $stable_base_aa,
                            params: {
                                curve_aa: trigger.address
                            }
                        }
                    ];
                    $stable_aa_address = chash160($stable_aa);
                }",
                    "messages": [
                        {
                            "app": "definition",
                            "payload": {
                                "definition": "{$stable_aa}"
                            }
                        },
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{ $stable_aa_address }",
                                        "amount": 4000
                                    }
                                ]
                            }
                        },
                        {
                            "app": "data",
                            "payload": {
                                "define": 1,
                                "factory": "{this_address}"
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                            $governance_aa_address = unit[trigger.unit].messages[[.app='definition']].payload.address;
                            var['asset_' || trigger.address || '_1'] = trigger.data.asset1;
                            var['asset_' || trigger.address || '_2'] = trigger.unit;
                            var['stable_aa_' || trigger.address] = $stable_aa_address;
                            var['governance_aa_' || trigger.address] = $governance_aa_address;
                            var['fund_aa_' || trigger.address] = var[trigger.address]['fund_aa'];
                            var['asset_' || trigger.address || '_fund'] = var[var[trigger.address]['fund_aa']]['shares_asset'];
                            response['asset_1'] = trigger.data.asset1;
                            response['asset_2'] = trigger.unit;
                            response['shares_asset'] = var[var[trigger.address]['fund_aa']]['shares_asset'];
                            response['address'] = trigger.address;
                            response['stable_aa'] = $stable_aa_address;
                            response['governance_aa'] = $governance_aa_address;
                        }"
                        }
                    ]
                },
                {
                    "if": "{trigger.data.write_stable_asset AND var['stable_aa_' || trigger.data.curve_aa] == trigger.address}",
                    "messages": [
                        {
                            "app": "state",
                            "state": "{
                            var['asset_' || trigger.data.curve_aa || '_stable'] = trigger.unit;
                        }"
                        }
                    ]
                },
                {
                    "init": "{
                    $reserve_asset = trigger.data.reserve_asset OTHERWISE 'base';
                    if (!asset[$reserve_asset].exists)
                        bounce("reserve asset " || $reserve_asset || " does not exist");
                    
                    $reserve_asset_decimals = trigger.data.reserve_asset_decimals;
                    if (!is_integer($reserve_asset_decimals) OR $reserve_asset_decimals < 0 OR $reserve_asset_decimals > 14)
                        bounce("bad reserve_asset_decimals");
                    
                    $decimals1 = trigger.data.decimals1;
                    if (!is_integer($decimals1) OR $decimals1 < 0 OR $decimals1 > 14)
                        bounce("bad decimals1");
                    
                    $decimals2 = trigger.data.decimals2;
                    if (!is_integer($decimals2) OR $decimals2 < 0 OR $decimals2 > 14)
                        bounce("bad decimals2");
                    
                    $m = trigger.data.m OTHERWISE 2;
                    if (typeof($m) != 'number' OR $m < 0)
                        bounce("bad m");
                    
                    $n = trigger.data.n OTHERWISE 1/2;
                    if (typeof($n) != 'number' OR $n < 0)
                        bounce("bad n");
                    $leverage = trigger.data.leverage OTHERWISE 0;
                    if (typeof($leverage) != 'number')
                        bounce("bad leverage");
                    $interest_rate = trigger.data.interest_rate OTHERWISE 0;
                    if (typeof($interest_rate) != 'number' OR $interest_rate < 0)
                        bounce("bad interest_rate");
                    
                    $fee_multiplier = trigger.data.fee_multiplier OTHERWISE 5;
                    if (typeof($fee_multiplier) != 'number' OR $fee_multiplier <= 0)
                        bounce("bad fee_multiplier");
                    
                    $moved_capacity_share = trigger.data.moved_capacity_share OTHERWISE 0.1;
                    if (typeof($moved_capacity_share) != 'number' OR $moved_capacity_share <= 0)
                        bounce("bad moved_capacity_share");
                    
                    $threshold_distance = trigger.data.threshold_distance OTHERWISE 0.01;
                    if (typeof($threshold_distance) != 'number' OR $threshold_distance <= 0)
                        bounce("bad threshold_distance");
                    
                    $move_capacity_timeout = trigger.data.move_capacity_timeout OTHERWISE 2*3600;
                    if (!is_integer($move_capacity_timeout) OR $move_capacity_timeout <= 0)
                        bounce("bad move_capacity_timeout");
                    
                    $slow_capacity_share = trigger.data.slow_capacity_share; // use AA default if missing
                    if (exists($slow_capacity_share) AND (typeof($slow_capacity_share) != 'number' OR $slow_capacity_share < 0))
                        bounce("bad slow_capacity_share");
                    
                    $params = {
                        leverage: $leverage,
                        m: $m,
                        n: $n,
                        allow_grants: !!trigger.data.allow_grants,
                        allow_oracle_change: !!trigger.data.allow_oracle_change,
                        reserve_asset: $reserve_asset,
                        reserve_asset_decimals: $reserve_asset_decimals,
                        decimals1: $decimals1,
                        decimals2: $decimals2,
                        interest_rate: $interest_rate,
                        fee_multiplier: $fee_multiplier,
                        moved_capacity_share: $moved_capacity_share,
                        threshold_distance: $threshold_distance,
                        move_capacity_timeout: $move_capacity_timeout,
                        slow_capacity_share: $slow_capacity_share,
                    };
                    
                    foreach(['oracle1', 'oracle2', 'oracle3'], 3, $p => {
                        $oracle = trigger.data[$p];
                        if (exists($oracle) AND !is_valid_address($oracle))
                            bounce("bad " || $p);
                        $params[$p] = $oracle;
                    });
                    foreach(['feed_name1', 'feed_name2', 'feed_name3'], 3, $p => {
                        $feed_name = trigger.data[$p];
                        if (exists($feed_name) AND typeof($feed_name) != 'string')
                            bounce("bad " || $p);
                        $params[$p] = $feed_name;
                    });
                    foreach(['op1', 'op2', 'op3'], 3, $p => {
                        $op = trigger.data[$p];
                        if (exists($op) AND $op != '*' AND $op != '/')
                            bounce("bad " || $p);
                        $params[$p] = $op;
                    });
                    $governance_params = ['regular_challenging_period', 'important_challenging_period', 'freeze_period', 'proposal_min_support'];
                    foreach($governance_params, 4, $p => {
                        $value = trigger.data[$p]; // use AA default if missing
                        if (exists($value)) {
                            if ($p == 'proposal_min_support'){
                                if (typeof($value) != 'number' OR $value < 0 OR $value > 1)
                                    bounce("bad " || $p);
                            }
                            else {
                                if (!is_integer($value) OR $value < 0)
                                    bounce("bad " || $p);
                            }
                            $params[$p] = $value;
                        }
                    });
                    $de_params = ['below_peg_threshold', 'below_peg_timeout', 'min_reserve_delta'];
                    foreach($de_params, 3, $p => {
                        $value = trigger.data[$p]; // use AA default if missing
                        if (exists($value)) {
                            if (typeof($value) != 'number' OR $value < 0)
                                bounce("bad " || $p);
                            if ($p == 'below_peg_threshold'){
                                if ($value == 0)
                                    bounce("bad " || $p);
                            }
                            else {
                                if (!is_integer($value))
                                    bounce("bad " || $p);
                                if ($p == 'min_reserve_delta'){
                                    if ($value == 0)
                                        bounce("bad " || $p);
                                }
                            }
                            $params[$p] = $value;
                        }
                    });
                    $curve_aa = [
                        'autonomous agent',
                        {
                            base_aa: $curve_base_aa,
                            params: $params
                        }
                    ];
                    $curve_aa_address = chash160($curve_aa);
                }",
                    "messages": [
                        {
                            "app": "payment",
                            "payload": {
                                "asset": "base",
                                "outputs": [
                                    {
                                        "address": "{ $curve_aa_address }",
                                        "amount": 8000
                                    }
                                ]
                            }
                        },
                        {
                            "app": "data",
                            "payload": {
                                "define": 1,
                                "factory": "{this_address}"
                            }
                        },
                        {
                            "app": "definition",
                            "payload": {
                                "definition": "{$curve_aa}"
                            }
                        },
                        {
                            "app": "state",
                            "state": "{
                        //    $aa_address = unit[response_unit].messages[[.app='definition']].payload.address;
                            var['curve_' || $curve_aa_address] = "s1^"||$m||" s2^"||$n;
                        }"
                        }
                    ]
                }
            ]
        }
    }
]