[
"autonomous agent",
{
"doc_url": "https://odex.ooo/odex.json",
"init": "{
$CHAINDEX = var['chainDEX'];
}",
"messages": {
"cases": [
{
"if": "{!$CHAINDEX}",
"messages": [
{
"app": "definition",
"payload": {
"definition": [
"autonomous agent",
{
"{'init'}": "{
"{$ODEX = '"||this_address||"';"
|| "$ODEX_KEY = 'balance_'||this_address||'_base';"
|| "if(trigger.output[[asset!=base]].asset != 'none')"
|| "bounce('no assets here');"
|| "$total_bal = balance[base]-storage_size-trigger.output[[asset=base]];}"
}",
"messages": {
"{'cases'}": [
{
"{'if'}": "{"{!var['low_fee_mode'] AND $total_bal+var[$ODEX][$ODEX_KEY] > 10000000}"}",
"messages": [
{
"app": "data",
"payload": {
"withdraw": 1,
"asset": "base",
"amount": "all"
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$ODEX}"}",
"amount": 10000
}
]
}
},
{
"app": "state",
"{'state'}": "{
"{var['low_fee_mode'] = true;"
|| "response['message'] = 'Low fee mode active. Until AA depletion all operations are subsidized';}"
}"
}
]
},
{
"{'if'}": "{
"{trigger.data.match}"
}",
"{'init'}": "{
"{$my_order = trigger.data.order.signed_message;"
|| "$order_key = trigger.data.addr_to_match;"
|| "$order_pkg = var[$order_key];"
|| "if(!$order_pkg)"
|| "bounce('no order to match');"
|| "if(typeof($order_pkg) != 'string')"
|| "bounce('order already matched');"
|| "if ($my_order.matcher != this_address)"
|| "bounce('wrong matcher in order');"
|| "if(!exists($my_order.matcher_fee_asset) or $my_order.matcher_fee_asset != 'base')"
|| "bounce('matcher_fee_asset must be base');"
|| "if(!is_valid_address($my_order.matcher) OR $my_order.matcher != this_address)"
|| "bounce('I am the matcher, fuck offchain matchers');"
|| "if($my_order.matcher_fee != 0)"
|| "bounce('matcher fees not needed');"
|| "if ($my_order.affiliate)"
|| "bounce('affiliates not needed');"
|| "$order_to_match = json_parse($order_pkg);}"
}",
"messages": [
{
"app": "data",
"payload": {
"order1": "{"{trigger.data.order}"}",
"order2": "{"{$order_to_match}"}"
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$ODEX}"}",
"amount": "{"{var['low_fee_mode']?1:9000}"}"
}
]
}
},
{
"{'if'}": "{"{var['low_fee_mode']}"}",
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{trigger.address}"}",
"amount": 9500
}
]
}
},
{
"app": "state",
"{'state'}": "{
"$id1 = sha256($my_order.address || $my_order.sell_asset || $my_order.buy_asset || $my_order.sell_amount || $my_order.price || ($my_order.nonce otherwise '') || (trigger.data.order.last_ball_unit otherwise '-'));"
|| "$order2 = $order_to_match.signed_message;"
|| "$id2 = sha256($order2.address || $order2.sell_asset || $order2.buy_asset || $order2.sell_amount || $order2.price || ($order2.nonce otherwise '') || ($order_to_match.last_ball_unit otherwise '-'));"
|| "$amount_left1 = var['amount_left_' || $id1] otherwise $order1.sell_amount;"
|| "$amount_left2 = var['amount_left_' || $id2] otherwise $order2.sell_amount;"
|| "$maker_price = $my_order.price;"
|| "$buy_amount1 = round($amount_left1 * $my_order.price);"
|| "if ($buy_amount1 > $amount_left2)"
|| "var[$order_key] = false;"
|| "if(var['low_fee_mode'] AND $total_bal < 30000)"
|| "var['low_fee_mode'] = false;}"
}"
}
]
},
{
"{'if'}": "{
"{trigger.data.match_stored}"
}",
"{'init'}": "{
"{$to_match = trigger.data.addr_to_match;"
|| "$str1 = var[trigger.address];"
|| "$str2 = var[$to_match];"
|| "if(!var[trigger.address])"
|| "bounce('you have not stored order');"
|| "if(!$to_match OR !is_valid_address($to_match) OR !$order2)"
|| "bounce('addr_to_match must be an address with stored order');"
|| "$order1 = json_parse($str1);"
|| "$order2 = json_parse($str2);}"
}",
"messages": [
{
"app": "data",
"payload": {
"order1": "{"{$order1}"}",
"order2": "{"{$order2}"}"
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$ODEX}"}",
"amount": "{"{var['low_fee_mode']?1:9000}"}"
}
]
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{trigger.address}"}",
"amount": 10000
}
]
}
},
{
"app": "state",
"{'state'}": "{
"{$order1s = $order1.signed_message;"
|| "$order2s = $order2.signed_message;"
|| "$id1 = sha256($order1s.address || $order1s.sell_asset || $order1s.buy_asset || $order1s.sell_amount || $order1s.price || ($order1s.nonce otherwise '') || ($order1.last_ball_unit otherwise '-'));"
|| "$id2 = sha256($order2s.address || $order2s.sell_asset || $order2s.buy_asset || $order2s.sell_amount || $order2s.price || ($order2s.nonce otherwise '') || ($order2.last_ball_unit otherwise '-'));"
|| "$amount_left1 = var['amount_left_' || $id1] otherwise $order1s.sell_amount;"
|| "$amount_left2 = var['amount_left_' || $id2] otherwise $order2s.sell_amount;"
|| "$maker_price = $order1s.price;"
|| "$buy_amount1 = round($amount_left1 * $order1s.price);"
|| "if ($buy_amount1 > $amount_left2){"
|| "$id_smaller = $id2;"
|| "$id_larger = $id1;"
|| "$amount_left_larger = $amount_left1;"
|| "$buy_amount2 = round($amount_left2 / $maker_price);"
|| "$buy_amount_smaller = $buy_amount2;"
|| "}"
|| "else{"
|| "$id_smaller = $id1;"
|| "$id_larger = $id2;"
|| "$amount_left_larger = $amount_left2;"
|| "$buy_amount_smaller = $buy_amount1;"
|| "}"
|| "$new_amount_left_larger = $amount_left_larger - $buy_amount_smaller;"
|| "if($id1 == $id_smaller || (!$new_amount_left_larger AND $id1 == $id_larger))"
|| "var[trigger.address] = false;"
|| "if($id2 == $id_smaller || (!$new_amount_left_larger AND $id2 == $id_larger))"
|| "var[$to_match] = false;}"
}"
}
]
},
{
"{'if'}": "{
"{trigger.data.cancel}"
}",
"{'init'}": "{
"{$str1 = var[trigger.address];"
|| "if(!$str1)"
|| "bounce('you have not stored order');"
|| "$order1 = json_parse($str1);}"
}",
"messages": [
{
"app": "data",
"payload": {
"cancel": 1,
"order": "{"{$order}"}"
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{$ODEX}"}",
"amount": "{"{var['low_fee_mode']?1000:9000}"}"
}
]
}
},
{
"{'if'}": "{"{var['low_fee_mode']}"}",
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{trigger.address}"}",
"amount": 8500
}
]
}
},
{
"app": "state",
"{'state'}": "{
"{var[trigger.address] = false;}"
}"
}
]
},
{
"{'if'}": "{
"{trigger.data.store}"
}",
"{'init'}": "{
"{if(var[trigger.address])"
|| "bounce('already stored, must be matched or cancelled first');"
|| "$order = trigger.data.order.signed_message;"
|| "if (!$order.sell_amount OR $order.sell_amount <= 0 or !$order.price or $order.price <= 0)"
|| "bounce('wrong data in order');"
|| "if (!$order.sell_asset or !$order.buy_asset)"
|| "bounce('buy_asset or sell_asset missing');"
|| "if(($order.sell_asset != 'base' and !asset[$order.sell_asset].exists) or ($order.buy_asset != 'base' and !asset[$order.buy_asset].exists))"
|| "bounce('invalid asset');"
|| "if ($order.sell_asset == $order.buy_asset)"
|| "bounce('same asset');"
|| "if ($order.matcher != this_address)"
|| "bounce('wrong matcher in order, I am the matcher, fuck offchain matchers');"
|| "if ($order.aa != $ODEX )"
|| "bounce('wrong aa in order');"
|| "if ($order.expiry_ts AND $order.expiry_ts <= timestamp)"
|| "bounce('order expired');"
|| "if(!exists($order.matcher_fee_asset) or $order.matcher_fee_asset != 'base')"
|| "bounce('matcher_fee_asset must be base');"
|| "$sell_key1 = 'balance_' || $order.address || '_' || $order.sell_asset;"
|| "if($order.sell_amount <= 0)"
|| "bounce('sell_amount must be greater than 0');"
|| "$id1 = sha256($order.address || $order.sell_asset || $order.buy_asset || $order.sell_amount || $order.price || ($order.nonce otherwise '') || (trigger.data.order.last_ball_unit otherwise '-'));"
|| "if (var[$ODEX]['executed_' || $id1])"
|| "bounce('order already executed');"
|| "if (var[$ODEX]['cancelled_' || $id1])"
|| "bounce('order already cancelled');"
|| "$amount_left1 = var[$ODEX]['amount_left_' || $id1] otherwise $order.sell_amount;"
|| "if ($amount_left1 > var[$ODEX][$sell_key1] + 0)"
|| "bounce('not sufficient balance in sell asset to complete order');"
|| "if($order.matcher_fee != 0)"
|| "bounce('matcher fees not needed');"
||"if ($order.affiliate)"
|| "bounce('affiliates not needed');"
|| "$signer1 = trigger.data.order.authors[0].address;"
|| "if($order.address != trigger.address OR $signer1 != $order.address)"
|| "bounce('you have to store and sign your order');"
|| "if (!is_valid_signed_package(trigger.data.order, $signer1))"
|| "bounce('bad signature of order');"
|| "$base_key1 = 'balance_' || $order.address || '_base';"
|| "if (var[$ODEX][$base_key1] <= 1000)"
|| "bounce('not enough balance for AA fees');}"
}",
"messages": [
{
"{'if'}": "{"{var['low_fee_mode']}"}",
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{"{trigger.address}"}",
"amount": 9500
}
]
}
},
{
"app": "state",
"{'state'}": "{
"{var[trigger.address] = json_stringify(trigger.data.order);"
|| "if(var['low_fee_mode'] AND $total_bal < 30000)"
|| "var['low_fee_mode'] = false;"
|| "response['message'] = 'Stored order with id '||trigger.data.id;}"
}"
}
]
},
{
"messages": [
{
"app": "state",
"{'state'}": "{
"{response['message'] = 'bytes received';}"
}"
}
]
}
]
}
}
]
}
},
{
"app": "state",
"state": "{
var['chainDEX'] = unit[response_unit].messages[[.app='definition']].payload.address;
}"
}
]
},
{
"if": "{ trigger.data.withdraw AND trigger.data.asset AND trigger.data.amount AND trigger.output[[asset=base]] >= 10000 }",
"init": "{
if (trigger.data.to){
if (!is_valid_address(trigger.data.to))
bounce("invalid withdrawal address: " || trigger.data.to);
$address = trigger.data.to;
// authorized address can initiate withdrawals in favor of the owner
$owner_address = var['grant_' || $address || '_to_' || trigger.address] ? $address : trigger.address;
}
else {
$address = trigger.address;
$owner_address = trigger.address;
}
$key = 'balance_' || $owner_address || '_' || trigger.data.asset;
$balance = var[$key] + 0;
$ord = json_parse(var[$CHAINDEX][trigger.address]);
if($ord){
$ords = $ord.signed_message;
if($ords.sell_asset == trigger.data.asset){
$id_ord = sha256($ords.address || $ords.sell_asset || $ords.buy_asset || $ords.sell_amount || $ords.price || ($ords.nonce otherwise '') || $ord.last_ball_unit);
$opened_order = var['amount_left_' || $id_ord] otherwise $ords.sell_amount;
if(trigger.data.amount == 'all' OR (trigger.data.amount+$opened_order) > $balance)
bounce('cannot withdraw, please cancel opened order on '||$CHAINDEX);
if ($ords.sell_asset == 'base' AND (trigger.data.amount == 'all' or var['balance_' || $owner_address || '_base' ]-trigger.data.amount <= 1000))
bounce('not enough balance for AA fees, leave 1000 at least');
}
}
if (trigger.data.amount == 'all')
$amount = $balance;
else if (trigger.data.amount > $balance)
bounce("withdrawal amount too large, balance: " || $balance);
else
$amount = trigger.data.amount;
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{trigger.data.asset}",
"outputs": [
{
"address": "{$address}",
"amount": "{$amount}"
}
]
}
},
{
"app": "state",
"state": "{
var[$key] -= $amount;
response[$owner_address || '_' || trigger.data.asset] = -$amount;
response['event'] = 'withdrawal';
}"
}
]
},
{
"if": "{
$order1 = trigger.data.order1.signed_message;
$order2 = trigger.data.order2.signed_message;
if (!$order1.sell_asset OR !$order2.sell_asset)
return false;
if ($order1.sell_asset != $order2.buy_asset OR $order1.buy_asset != $order2.sell_asset)
bounce('assets do not match');
if ($order1.sell_asset == $order1.buy_asset)
bounce('same asset');
if ($order1.matcher != trigger.address)
bounce('wrong matcher in order1');
if ($order2.matcher != trigger.address)
bounce('wrong matcher in order2');
if ($order1.aa != this_address)
bounce('wrong aa in order1');
if ($order2.aa != this_address)
bounce('wrong aa in order2');
if ($order1.expiry_ts AND $order1.expiry_ts <= timestamp)
bounce("order1 expired");
if ($order2.expiry_ts AND $order2.expiry_ts <= timestamp)
bounce("order2 expired");
$sell_key1 = 'balance_' || $order1.address || '_' || $order1.sell_asset;
$sell_key2 = 'balance_' || $order2.address || '_' || $order2.sell_asset;
$id1 = sha256($order1.address || $order1.sell_asset || $order1.buy_asset || $order1.sell_amount || $order1.price || ($order1.nonce otherwise '') || (trigger.data.order1.last_ball_unit otherwise '-'));
$id2 = sha256($order2.address || $order2.sell_asset || $order2.buy_asset || $order2.sell_amount || $order2.price || ($order2.nonce otherwise '') || (trigger.data.order2.last_ball_unit otherwise '-'));
if (var['executed_' || $id1])
bounce('order1 already executed');
if (var['executed_' || $id2])
bounce('order2 already executed');
if (var['cancelled_' || $id1])
bounce('order1 already cancelled');
if (var['cancelled_' || $id2])
bounce('order2 already cancelled');
$amount_left1 = var['amount_left_' || $id1] otherwise $order1.sell_amount;
$amount_left2 = var['amount_left_' || $id2] otherwise $order2.sell_amount;
// check balances
if ($amount_left1 > var[$sell_key1] + 0)
bounce('not sufficient balance in sell asset to complete order1');
if ($amount_left2 > var[$sell_key2] + 0)
bounce('not sufficient balance in sell asset to complete order2');
// check if prices match
$maker_price = $order1.price;
$buy_amount1 = round($amount_left1 * $order1.price);
if ($buy_amount1 > $amount_left2){ // order2 is the smaller one
$order_smaller = $order2;
$order_larger = $order1;
$id_smaller = $id2;
$id_larger = $id1;
$amount_left_smaller = $amount_left2;
$amount_left_larger = $amount_left1;
$buy_amount2 = round($amount_left2 / $maker_price); // using maker price instead of our $order2.price
$buy_amount_smaller = $buy_amount2;
$amount_sold2 = $amount_left2;
$amount_sold1 = $buy_amount2;
}
else{ // order1 is the smaller one
$order_smaller = $order1;
$order_larger = $order2;
$id_smaller = $id1;
$id_larger = $id2;
$amount_left_smaller = $amount_left1;
$amount_left_larger = $amount_left2;
$buy_amount_smaller = $buy_amount1;
$amount_sold1 = $amount_left1;
$amount_sold2 = $buy_amount1;
}
// if $order1.price * $order2.price > 1 then you can make a profit by going through two opposite trades or being on both sides of a single trade. This is only possible for market-maker orders, which are not matched.
// order of multiplication is important as it can affect rounding errors
if (round($amount_left_smaller * ($order1.price * $order2.price)) > $amount_left_smaller)
bounce("price mismatch");
$expected_buy_amount_larger = round(($buy_amount_smaller-1) * $order_larger.price); // -1 to account for rounding errors
if ($expected_buy_amount_larger > $amount_left_smaller)
bounce("price mismatch: larger user " || $id_larger || " doesn't like the price, he gets less than expects: " || $amount_left_smaller || " < " || $expected_buy_amount_larger || ", amounts left: " || $amount_left1 || ", " || $amount_left2);
// matcher fees
$max_matcher_fee1 = round($order1.matcher_fee * $amount_sold1/$order1.sell_amount);
$max_matcher_fee2 = round($order2.matcher_fee * $amount_sold2/$order2.sell_amount);
$matcher_fee1 = (!exists(trigger.data.matcher_fee1) OR trigger.data.matcher_fee1 == 'default') ? $max_matcher_fee1 : trigger.data.matcher_fee1;
$matcher_fee2 = (!exists(trigger.data.matcher_fee2) OR trigger.data.matcher_fee2 == 'default') ? $max_matcher_fee2 : trigger.data.matcher_fee2;
// the formula will fail if matcher_fee1/matcher_fee2 is not a number
if ($matcher_fee1 > $max_matcher_fee1)
bounce('matcher_fee1 is too large');
if ($matcher_fee2 > $max_matcher_fee2)
bounce('matcher_fee2 is too large');
// affiliates
if ($order1.affiliate){
if (!$order1.affiliate_fee_asset)
bounce('no affiliate_fee_asset in order1');
if ($order1.affiliate_fee < 0) // will error if none or not a number
bounce('affiliate_fee < 0 in order1');
$affiliate_fee1 = round($order1.affiliate_fee * $amount_sold1/$order1.sell_amount);
}
if ($order2.affiliate){
if (!$order2.affiliate_fee_asset)
bounce('no affiliate_fee_asset in order2');
if ($order2.affiliate_fee < 0) // will error if none or not a number
bounce('affiliate_fee < 0 in order2');
$affiliate_fee2 = round($order2.affiliate_fee * $amount_sold2/$order2.sell_amount);
}
$signer1 = trigger.data.order1.authors[0].address;
$signer2 = trigger.data.order2.authors[0].address;
if ($signer1 != $order1.address AND !var['grant_' || $order1.address || '_to_' || $signer1])
bounce("order1 signer was not authorized to sign");
if ($signer2 != $order2.address AND !var['grant_' || $order2.address || '_to_' || $signer2])
bounce("order2 signer was not authorized to sign");
if (!is_valid_signed_package(trigger.data.order1, $signer1))
bounce('bad signature of order1');
if (!is_valid_signed_package(trigger.data.order2, $signer2))
bounce('bad signature of order2');
true
}",
"messages": [
{
"app": "state",
"state": "{
$buy_key1 = 'balance_' || $order1.address || '_' || $order1.buy_asset;
$buy_key2 = 'balance_' || $order2.address || '_' || $order2.buy_asset;
var[$sell_key1] -= $amount_sold1;
var[$sell_key2] -= $amount_sold2;
var[$buy_key1] += $amount_sold2;
var[$buy_key2] += $amount_sold1;
// matcher fees
$matcher_fee_user_key1 = 'balance_' || $order1.address || '_' || $order1.matcher_fee_asset;
$matcher_fee_user_key2 = 'balance_' || $order2.address || '_' || $order2.matcher_fee_asset;
$matcher_fee_matcher_key1 = 'balance_' || $order1.matcher || '_' || $order1.matcher_fee_asset;
$matcher_fee_matcher_key2 = 'balance_' || $order2.matcher || '_' || $order2.matcher_fee_asset;
var[$matcher_fee_matcher_key1] += $matcher_fee1;
var[$matcher_fee_matcher_key2] += $matcher_fee2;
var[$matcher_fee_user_key1] -= $matcher_fee1;
var[$matcher_fee_user_key2] -= $matcher_fee2;
if (var[$matcher_fee_user_key1] < 0)
bounce("not enough user1 balance for matcher fees");
if (var[$matcher_fee_user_key2] < 0)
bounce("not enough user2 balance for matcher fees");
// fees can be negative
if (var[$matcher_fee_matcher_key1] < 0)
bounce("not enough matcher order1.matcher_fee_asset balance for matcher fees");
if (var[$matcher_fee_matcher_key2] < 0)
bounce("not enough matcher order2.matcher_fee_asset balance for matcher fees");
// affiliate fees
if ($order1.affiliate AND $affiliate_fee1){
$affiliate_fee_user_key1 = 'balance_' || $order1.address || '_' || $order1.affiliate_fee_asset;
$affiliate_fee_affiliate_key1 = 'balance_' || $order1.affiliate || '_' || $order1.affiliate_fee_asset;
var[$affiliate_fee_user_key1] -= $affiliate_fee1;
var[$affiliate_fee_affiliate_key1] += $affiliate_fee1;
if (var[$affiliate_fee_user_key1] < 0)
bounce("not enough user1 balance for affiliate fees");
}
if ($order2.affiliate AND $affiliate_fee2){
$affiliate_fee_user_key2 = 'balance_' || $order2.address || '_' || $order2.affiliate_fee_asset;
$affiliate_fee_affiliate_key2 = 'balance_' || $order2.affiliate || '_' || $order2.affiliate_fee_asset;
var[$affiliate_fee_user_key2] -= $affiliate_fee2;
var[$affiliate_fee_affiliate_key2] += $affiliate_fee2;
if (var[$affiliate_fee_user_key2] < 0)
bounce("not enough user2 balance for affiliate fees");
}
// AA fees
$aa_fee = 1000;
$base_key1 = 'balance_' || $order1.address || '_base';
$base_key2 = 'balance_' || $order2.address || '_base';
var[$base_key1] -= $aa_fee;
var[$base_key2] -= $aa_fee;
if (var[$base_key1] < 0 OR var[$base_key2] < 0)
bounce('not enough balance for AA fees');
// refund the matcher for bounce fees
var['balance_' || trigger.address || '_base'] += trigger.output[[asset=base]];
// update order states
var['executed_' || $id_smaller] = 1;
var['amount_left_' || $id_smaller] = false;
response['executed_' || $id_smaller] = 1;
$new_amount_left_larger = $amount_left_larger - $buy_amount_smaller;
if ($new_amount_left_larger < 0)
bounce("panic: new_amount_left_larger < 0");
if ($new_amount_left_larger){
var['amount_left_' || $id_larger] = $new_amount_left_larger;
response['amount_left_' || $id_larger] = $new_amount_left_larger;
}
else{
var['executed_' || $id_larger] = 1;
var['amount_left_' || $id_larger] = false;
response['executed_' || $id_larger] = 1;
}
// parsable response for transaction log
if ($order1.address != $order2.address){
response[$order1.address || '_' || $order1.sell_asset] = -$amount_sold1;
response[$order2.address || '_' || $order2.buy_asset] = $amount_sold1;
response[$order1.address || '_' || $order1.buy_asset] = $amount_sold2;
response[$order2.address || '_' || $order2.sell_asset] = -$amount_sold2;
}
else{ // self-match
response[$order1.address || '_' || $order1.sell_asset] = 0;
response[$order1.address || '_' || $order1.buy_asset] = 0;
}
response['amount_' || $order1.sell_asset] = $amount_sold1;
response['amount_' || $order1.buy_asset] = $amount_sold2;
response['event'] = 'trade';
}"
}
]
},
{
"if": "{trigger.data.cancel AND trigger.data.order}",
"init": "{
$order = trigger.data.order.signed_message;
if (!$order.sell_asset OR !$order.buy_asset OR !$order.sell_amount OR !$order.price OR !$order.address OR !$order.matcher)
bounce("missing data in order");
if(trigger.address != $CHAINDEX){
if($order.matcher == $CHAINDEX)
bounce('please cancel order through '||$CHAINDEX);
if ($order.address != trigger.address AND !var['grant_' || $order.address || '_to_' || trigger.address])
bounce('not your order');
}
if ($order.aa != this_address)
bounce('wrong aa in order');
if ($order.expiry_ts AND $order.expiry_ts <= timestamp)
bounce("order expired");
$id = sha256($order.address || $order.sell_asset || $order.buy_asset || $order.sell_amount || $order.price || ($order.nonce otherwise '') || trigger.data.order.last_ball_unit);
if (var['executed_' || $id])
bounce('order already executed');
$signer = trigger.data.order.authors[0].address;
if ($signer != $order.address AND !var['grant_' || $order.address || '_to_' || $signer])
bounce("order signer was not authorized to sign");
if (!is_valid_signed_package(trigger.data.order, $signer))
bounce('bad signature of order');
}",
"messages": [
{
"app": "state",
"state": "{
var['cancelled_' || $id] = 1;
response['message'] = 'cancelled order ' || $id;
response['id'] = $id;
response['event'] = 'cancel';
$cancel_fee = 1000;
$key = 'balance_' || ($order.matcher == $CHAINDEX?$CHAINDEX:$order.address) || '_base';
var[$key] += trigger.output[[asset=base]] - $cancel_fee;
if (var[$key] < 0) // received funds can be less than bounce fees if received from an AA
bounce("balance would drop below 0");
}"
}
]
},
{
"if": "{ trigger.data.revoke AND trigger.data.address AND trigger.output[[asset=base]] >= 10000 }",
"init": "{
if (!is_valid_address(trigger.data.address))
bounce("invalid address");
if (trigger.data.address == trigger.address)
bounce("same address");
}",
"messages": [
{
"app": "state",
"state": "{
var['grant_' || trigger.address || '_to_' || trigger.data.address] = false;
response['message'] = 'revoked authorization from ' || trigger.data.address || ' to sign orders for you';
response['address'] = trigger.data.address;
response['event'] = 'revocation';
}"
}
]
},
{
"if": "{ (!trigger.data OR trigger.data.to OR trigger.data.grant AND trigger.data.address) AND trigger.output[[asset=base]] >= 10000 }",
"init": "{
if (trigger.data.grant){
if (!is_valid_address(trigger.data.address))
bounce("invalid address");
if (trigger.data.address == trigger.address)
bounce("same address");
if (trigger.data.to)
bounce("grant and to at the same time");
}
}",
"messages": [
{
"app": "state",
"state": "{
if (trigger.data.grant){
var['grant_' || trigger.address || '_to_' || trigger.data.address] = 1;
$response_grant = 'authorized ' || trigger.data.address || ' to sign orders for you, also ';
response['authorized_address'] = trigger.data.address;
response['event'] = 'grant';
}
$asset = trigger.output[[asset!=base]].asset;
if ($asset == 'ambiguous')
bounce('ambiguous asset');
if (trigger.data.to){
if (!is_valid_address(trigger.data.to))
bounce("invalid deposit address: " || trigger.data.to);
$address = trigger.data.to;
}
else
$address = trigger.address;
$base_key = 'balance_'||$address||'_'||'base';
var[$base_key] = var[$base_key] + trigger.output[[asset=base]];
$response_base = trigger.output[[asset=base]] || ' bytes';
response[$address || '_base'] = trigger.output[[asset=base]];
if ($asset != 'none'){
$asset_key = 'balance_'||$address||'_'||$asset;
var[$asset_key] = var[$asset_key] + trigger.output[[asset=$asset]];
$response_asset = ' and ' || trigger.output[[asset=$asset]] || ' of ' || $asset;
response[$address || '_' || $asset] = trigger.output[[asset=$asset]];
}
response['message'] = ($response_grant otherwise '') || 'accepted coins: ' || $response_base || ($response_asset otherwise '');
response[trigger.data.grant ? 'secondary_event' : 'event'] = 'deposit';
}"
}
]
}
]
}
}
]