[
"autonomous agent",
{
"init": "{
$owner = 'JBGMJI7XSKLKNHZF26BUBWHVUZSDV3P5';
$fee = 700;
$asset_ct = 'hd936lRtPN11pkgNv8qVnqN2OHMyAp8P/NsLp6KsuqA=';
if(!var['Last'] 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('price not allowed');
}
}
else{
$ratio = var['Last'];
}
$addr = trigger.address;
$base_inp = trigger.output[[asset=base]] - $fee;
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($asset != $asset_ct)
bounce('asset not allowed, please send '||$asset_ct);
$asset_inp = trigger.output[[asset!=base]];
$asset_key = $addr || '_' || $ratio;
}
$base_key = $addr ||'_'|| $ratio || '_b';
$total_key = 'Bytes at '||$ratio;
$total_asset_key = 'Assets at '||$ratio;
//exchanged base amount, allows user to withdraw afterwards
$exch_key = 'Exchanged b at ' || $ratio ;
$exch_asset_key = 'Exchanged a at ' || $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 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;
$retire_asset = var[$exch_asset_key] and var[$base_key] and var[$exch_asset_key] > 0 and var[$base_key] > 0;
$retire_base = var[$exch_key] and var[$asset_key] and var[$exch_key] > 0 and var[$asset_key] > 0;
$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": "{// let retire exchanged amount
$retire_asset or $retire_base
//allowed if there is exchanged amount and user deposited previously
}",
"init": "{
if($retire_asset){
$retire_key = $exch_asset_key;
$ret_total_key = $total_asset_key;
$max_to_retire = var[$base_key] / $ratio;
$key = $base_key;
}
else{
$retire_key = $exch_key;
$ret_total_key = $total_key;
$max_to_retire = var[$asset_key] * $ratio;
$key = $asset_key;
}
if(var[$retire_key] <= $max_to_retire){
//user can withdraw all their exchanged amount
$retire_amount = var[$retire_key];
}
else{
//user can withdraw a part of their exchanged amount (rest of order could be cancel)
$retire_amount = $max_to_retire;
}
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{$addr}",
"amount": "{ $retire_asset ? $base_inp : ($retire_amount + $base_inp) }"
}
]
}
},
{
"if": "{$retire_asset}",
"app": "payment",
"payload": {
"asset": "{$asset_ct}",
"outputs": [
{
"address": "{$addr}",
"amount": "{$retire_amount}"
}
]
}
},
{
"app": "state",
"state": "{
//substract retired amount
var[$ret_total_key] -= $retire_amount;
if(var[$ret_total_key] == 0)var[$ret_total_key] = false;
var[$retire_key] -= $retire_amount;
if(var[$retire_key] == 0)var[$retire_key] = false;
//substract from user deposit
var[$key] -= $retire_asset ? ($retire_amount * $ratio) : ($retire_amount / $ratio);
if(var[$key] == 0)var[$key] = false;
response['message'] = 'retired exchanged amount ('||$retire_asset ? 'asset': 'bytes' ||') at '||$ratio||' bytes per token';
}"
}
]
},
{
"if": "{//exchange asset x bytes
if($asset){
//user sent asset
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;
$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;
//leftover amount
$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;
$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, minimum buy 1 asset');
$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;
}
}
($asset and $byte_amount and !var[$base_key]) or (!$asset and $asset_amount and !var[$asset_key])
//allowed if there is amount to exchange and user did not deposit previously for this price
}",
"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": "{
if($exchange_asset){
//sum exchanged amount
var[$total_asset_key] += $asset_inp - $asset_amount;
var[$exch_asset_key] += $asset_inp - $asset_amount;
//substract exchanged 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 exchanged 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';
}
//store last price
var[$ratio_key] = $ratio;
}"
}
]
},
{
"if": "{// let cancel order (asset)
$cancel_asset or $cancel_base
//allowed if user has assets to cancel
//recap: if we are here, means user does not fulfill conditions to retire
}",
"init": "{
if($cancel_asset){
$max_to_cancel = $max_a_to_exchange;
$key = $asset_key;
$cancel_tot_key = $total_asset_key;
}
else{
$max_to_cancel = $max_b_to_exchange;
$key = $base_key;
$cancel_tot_key = $total_key;
}
//case cancel without previous deposit
if($max_to_cancel <= 0){
bounce('Not allowed');
}
//cancel all amount if possible
if($max_to_cancel <= var[$key]){
//partial amount allowed until $max_a_to_exchange = 0
$retire_amount = $max_to_cancel;
}
else{
//all amount allowed
$retire_amount = var[$key];
}
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{$addr}",
"amount": "{$cancel_asset ? $base_inp : ($retire_amount + $base_inp)}"
}
]
}
},
{
"if": "{$cancel_asset}",
"app": "payment",
"payload": {
"asset": "{$asset_ct}",
"outputs": [
{
"address": "{$addr}",
"amount": "{$retire_amount}"
}
]
}
},
{
"app": "state",
"state": "{
var[$cancel_tot_key] -= $retire_amount;
if(var[$cancel_tot_key] == 0)var[$cancel_tot_key] = false;
var[$key] -= $retire_amount;
if(var[$key] == 0)var[$key] = false;
response['message'] = 'canceled order ('||$cancel_asset?'sell':'buy'||' at '||$ratio||' bytes per token)';
}"
}
]
},
{
"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||' 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';
}
}"
}
]
}
]
}
}
]