[
"autonomous agent",
{
"init": "{
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]];
}
}",
"messages": {
"cases": [
{
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$asset}",
"outputs": [
{
"address": "{trigger.address}",
"amount": "{$asset_inp}"
}
]
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{trigger.address}"
}
]
}
},
{
"app": "definition",
"payload": {
"definition": [
"autonomous agent",
{
"{"init"}": "{
"{$asset_ct = '"||$asset||"';"
|| "if(!var['-Last price'] and !trigger.data.price){"
|| "bounce('Price must be defined before first exchange');"
|| "}"
|| "if(trigger.data.price){"
//bytes per 1 asset
|| "$ratio = round(trigger.data.price);"
|| "if($ratio <= 0){"
|| "bounce('Price not allowed');"
|| "}"
|| "}"
|| "else{"
|| "$ratio = var['-Last price'];"
|| "}"
|| "$addr = trigger.address;"
|| "$base_inp = trigger.output[[asset=base]] - 700;"
|| "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($asset != $asset_ct)"
|| "bounce('Asset not allowed, please send ' || $asset_ct);"
|| "$asset_inp = (trigger.output[[asset!=base]] != 0) ? trigger.output[[asset!=base]] : bounce('Zero asset tx');"
|| "}"
//user amounts-price
|| "$base_key = $addr || $ratio || 'b';"
|| "$asset_key = $addr || $ratio;"
//total amounts-price
|| "$total_key = 'b' || $ratio;"
|| "$total_asset_key = 'a' || $ratio;"
//exchanged amounts, allow users to withdraw afterwards
|| "$exch_key = 'b_' || $ratio ;"
|| "$exch_asset_key = 'a_' || $ratio ;"
//exchanged amounts are 'protected' until owners withdraw
|| "$max_b_to_exchange = var[$total_key] - var[$exch_key];"
|| "$max_a_to_exchange = var[$total_asset_key] - var[$exch_asset_key];"
//base_inp without leftover bytes
|| "$base_inp_round = ($base_inp - ($base_inp % $ratio));"
|| "$base_inp_in_asset = $base_inp_round/$ratio;"
|| "$asset_inp_in_bytes = $asset_inp*$ratio;"
//allowed if there is exchanged amount and user deposited previously
|| "$withdraw_asset = var[$exch_asset_key] and var[$base_key] and var[$exch_asset_key] > 0 and var[$base_key] > 0;"
|| "$withdraw_base = var[$exch_key] and var[$asset_key] and var[$exch_key] > 0 and var[$asset_key] > 0;"
//allowed if there is amount to exchange and user did not deposit previously for this price
|| "$exchange_asset = $asset and $byte_amount and !var[$base_key];"
|| "$exchange_base = !$asset and $asset_amount and !var[$asset_key];"
//allowed if user has non-filled or partial filled orders to cancel
|| "$cancel_asset = trigger.data.cancel and var[$asset_key] and var[$asset_key] > 0;"
|| "$cancel_base = trigger.data.cancel and var[$base_key] and var[$base_key] > 0;}"
}",
"messages": {
"{"cases"}": [
{
"{"if"}": "{
"{$withdraw_asset or $withdraw_base}"
}",
"{"init"}": "{
"{$withdraw_key = $withdraw_asset ? $exch_asset_key : $exch_key;"
|| "$w_total_key = $withdraw_asset ? $total_asset_key : $total_key;"
|| "$max_to_withdraw = $withdraw_asset ? (var[$base_key] / $ratio) : (var[$asset_key] * $ratio);"
|| "$key = $withdraw_asset ? $base_key : $asset_key;"
//user can withdraw all their exchanged amount or a part of their exchanged amount (rest of order could be cancel)
|| "$withdraw_amount = (var[$withdraw_key] <= $max_to_withdraw) ? var[$withdraw_key] : $max_to_withdraw;}"
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$addr}"}",
"amount": "{ "{$withdraw_asset ? $base_inp : ($withdraw_amount + $base_inp)}" }"
}
]
}
},
{
"{"if"}": "{"{$withdraw_asset}"}",
"app": "payment",
"payload": {
"asset": "{"{$asset_ct}"}",
"outputs": [
{
"address": "{"{$addr}"}",
"amount": "{"{$withdraw_amount}"}"
}
]
}
},
{
"app": "state",
"state": "{
//substract withdrawn amount
"{var[$w_total_key] -= $withdraw_amount;"
|| "if(var[$w_total_key] == 0)var[$w_total_key] = false;"
//substract exchanged amount
|| "var[$withdraw_key] -= $withdraw_amount;"
|| "if(var[$withdraw_key] == 0)var[$withdraw_key] = false;"
//substract user deposit
|| "var[$key] -= $withdraw_asset ? ($withdraw_amount * $ratio) : ($withdraw_amount / $ratio);"
|| "if(var[$key] == 0)var[$key] = false;"
|| "response['message'] = 'withdrawn exchanged amount ('||$withdraw_asset ? 'assets': 'bytes' ||') at '||$ratio||' bytes per token';}"
}"
}
]
},
{
"{"if"}": "{
"{if($asset){"
//user sent assets
|| "if($max_b_to_exchange and $max_b_to_exchange > 0 and !trigger.data.cancel){"
//there are bytes to exchange
|| "if($asset_inp_in_bytes > $max_b_to_exchange){"
//user sent more amount than allowed, exchange to max allowed
|| "$byte_amount = $max_b_to_exchange;"
//leftover
|| "$asset_amount = (($asset_inp_in_bytes - $max_b_to_exchange) - (($asset_inp_in_bytes - $max_b_to_exchange) % $ratio)) / $ratio;"
|| "}"
|| "else{"
//user sent less or equal amount than allowed, exchange to user input
|| "$byte_amount = $asset_inp_in_bytes;"
|| "$asset_amount = 0;"
|| "}"
|| "}"
|| "else{"
//there are no bytes to exchange, deposit allowed unless order cancelation
|| "if(!trigger.data.cancel)"
|| "$deposit = true;"
|| "}"
|| "}"
|| "else{"
//user sent bytes
|| "if($max_a_to_exchange and $max_a_to_exchange > 0 and !trigger.data.cancel){"
//there are assets to exchange
|| "if($base_inp_in_asset > $max_a_to_exchange){"
//user sent more amount than allowed, exchange to max allowed
|| "$asset_amount = $max_a_to_exchange;"
//leftover
|| "$byte_amount = ($base_inp_in_asset - $max_a_to_exchange) * $ratio;"
|| "}"
|| "else{"
//user sent less or equal amount than allowed, exchange to user input
//fail fast to let user know
|| "if($base_inp_in_asset == 0)"
|| "bounce('Not enough funds for minimum');"
|| "$asset_amount = $base_inp_in_asset;"
|| "$byte_amount = 0;"
|| "}"
|| "}"
|| "else{"
//there are no assets to exchange, deposit allowed unless order cancelation
|| "if(!trigger.data.cancel)"
|| "$deposit = true;"
|| "}"
|| "}"
|| "$exchange_asset or $exchange_base}"
}",
"messages": [
{
"{"if"}": "{"{$exchange_asset or $byte_amount > 0}"}",
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$addr}"}",
"amount": "{"{$exchange_asset ? ($byte_amount + $base_inp) : $byte_amount}"}"
}
]
}
},
{
"{"if"}": "{"{$exchange_base or $asset_amount > 0}"}",
"app": "payment",
"payload": {
"asset": "{"{$asset_ct}"}",
"outputs": [
{
"address": "{"{$addr}"}",
"amount": "{"{$asset_amount}"}"
}
]
}
},
{
"app": "state",
"state": "{
"{var['-Last price'] = $ratio;"
|| "if($exchange_asset){"
//sum exchanged amount
|| "var[$total_asset_key] += $asset_inp - $asset_amount;"
|| "var[$exch_asset_key] += $asset_inp - $asset_amount;"
//substract taken amount
|| "var[$total_key] -= $byte_amount;if(var[$total_key] == 0)var[$total_key] = false;"
|| "response['message'] = 'sold '||($asset_inp - $asset_amount)||' assets for '||($byte_amount)||' bytes';"
|| "}"
|| "else{"
//sum exchanged amount
|| "var[$total_key] += $base_inp_round - $byte_amount;"
|| "var[$exch_key] += $base_inp_round - $byte_amount;"
//substract taken amount
|| "var[$total_asset_key] -= $asset_amount;if(var[$total_asset_key] == 0)var[$total_asset_key] = false;"
|| "response['message'] = 'bought '||($asset_amount)||' assets for '||($base_inp_round - $byte_amount)||' bytes';}"
|| "}"
}"
}
]
},
{
"{"if"}": "{ //if we are here, means user does not fulfill conditions to withdraw
"{$cancel_asset or $cancel_base}"
}",
"{"init"}": "{
"{$max_to_cancel = $cancel_asset ? $max_a_to_exchange : $max_b_to_exchange;"
|| "$key = $cancel_asset ? $asset_key : $base_key;"
|| "$cancel_tot_key = $cancel_asset ? $total_asset_key : $total_key;"
//just in case
|| "if($max_to_cancel <= 0){"
|| "bounce('Not allowed');"
|| "}"
//cancel all amount if possible
|| "$cancel_amount = ($max_to_cancel <= var[$key]) ? $max_to_cancel : var[$key];}"
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$addr}"}",
"amount": "{"{$cancel_asset ? $base_inp : ($cancel_amount + $base_inp)}"}"
}
]
}
},
{
"{"if"}": "{"{$cancel_asset}"}",
"app": "payment",
"payload": {
"asset": "{"{$asset_ct}"}",
"outputs": [
{
"address": "{"{$addr}"}",
"amount": "{"{$cancel_amount}"}"
}
]
}
},
{
"app": "state",
"state": "{
"{var[$cancel_tot_key] -= $cancel_amount;"
|| "if(var[$cancel_tot_key] == 0)var[$cancel_tot_key] = false;"
|| "var[$key] -= $cancel_amount;"
|| "if(var[$key] == 0)var[$key] = false;"
|| "response['message'] = 'canceled order ('||$cancel_asset?'sell':'buy'||' at '||$ratio||' bytes per token)';}"
}"
}
]
},
{
"{"if"}": "{
"{$deposit otherwise bounce('Deposit not allowed, please cancel order first')}"
}",
"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||' assets to sell at '||$ratio||' bytes per token';"
|| "}"
|| "else{"
|| "var[$total_key] += $base_inp_round;"
|| "var[$base_key] += $base_inp_round;"
|| "response['message'] = 'deposited '||$base_inp_round||' bytes to buy at '||$ratio||' bytes per token';"
|| "}}"
}"
}
]
}
]
}
}
]
}
}
]
}
]
}
}
]