Unit ID
GImItT17k/J4pA24NaCI4LwBpyeqP9dox6u2Zyaj+SA=
Received
05.12.2019 14:24:45
Confirmation delay (full node)
4 minutes 29 seconds
Confirmation delay (light node)
7 minutes 37 seconds
Messages
Definition
Definition: [ "autonomous agent", { "messages": { "cases": [ { "if": "{trigger.data.withdraw AND trigger.data.asset AND trigger.data.amount}", "init": "{ $key = 'balance_'||trigger.address||'_'||trigger.data.asset; $balance = var[$key] + 0; if (trigger.data.to){ if (!is_valid_address(trigger.data.to)) bounce("invalid withdrawal address: " || trigger.data.to); $address = trigger.data.to; } else $address = trigger.address; 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[$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.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); $id2 = sha256($order2.address || $order2.sell_asset || $order2.buy_asset || $order2.sell_amount || $order2.price || ($order2.nonce otherwise '') || trigger.data.order2.last_ball_unit); if (var['executed_' || $id1]) bounce('order1 already executed'); if (var['executed_' || $id2]) bounce('order2 already executed'); $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; } // 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 * $order_larger.price); if ($expected_buy_amount_larger > $amount_left_smaller) bounce("price mismatch: larger user doesn't like the price, he gets less than expects"); // 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 = (typeof(trigger.data.matcher_fee1) == 'boolean' AND !trigger.data.matcher_fee1 OR trigger.data.matcher_fee1 == 'default') ? $max_matcher_fee1 : trigger.data.matcher_fee1; $matcher_fee2 = (typeof(trigger.data.matcher_fee2) == 'boolean' AND !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); } if (!is_valid_signed_package(trigger.data.order1, $order1.address)) bounce('bad signature of order1'); if (!is_valid_signed_package(trigger.data.order2, $order2.address)) 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'); var['executed_' || $id_smaller] = 1; var['amount_left_' || $id_smaller] = false; $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; else{ var['executed_' || $id_larger] = 1; var['amount_left_' || $id_larger] = false; } // parsable response for transaction log 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; response['event'] = 'trade'; }" } ] }, { "if": "{!trigger.data OR trigger.data.to}", "messages": [ { "app": "state", "state": "{ $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'] = 'accepted coins: ' || $response_base || ($response_asset otherwise ''); response['event'] = 'deposit'; }" } ] } ] } } ]
Technical information
Fees:
11,396 bytes
(353 headers, 11043 payload)
Level:1155103
Witnessed level:1155096
Main chain index:1153840
Latest included mc index:1153839
Status:stable/confirmed/final