EUZ2QB4UHCMGN2D4LEOL5I3DUGP4FDJT
[
"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;
}
// 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 * $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';
}"
}
]
}
]
}
}
]
- MCI: 1190152
- Not bounced
- Response unit:
- Response: {
"responseVars": {
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_base": -1499914000,
"event": "withdrawal"
}
}
- MCI: 1189293
- Bounced
- Response: {
"error": "withdrawal amount too large, balance: 1499914000"
}
- MCI: 1189291
- Not bounced
- Response unit:
- Response: {
"responseVars": {
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_UccpQo12uLmufihkzdK7Kcrb5BlHp8GcMrSEA7NVdNw=": -32819952,
"event": "withdrawal"
}
}
- MCI: 1189255
- Not bounced
- Response unit:
- Response: {
"responseVars": {
"EDMS22PYWN5NE7F34R5CLNTJSVNLLGLS_base": -839982000,
"event": "withdrawal"
}
}
- MCI: 1189252
- Not bounced
- Response unit:
- Response: {
"responseVars": {
"EDMS22PYWN5NE7F34R5CLNTJSVNLLGLS_UccpQo12uLmufihkzdK7Kcrb5BlHp8GcMrSEA7NVdNw=": -16091760,
"event": "withdrawal"
}
}
- MCI: 1189247
- Not bounced
- Response unit:
- Response: {
"responseVars": {
"EJC4A7WQGHEZEKW6RLO7F26SAR4LAQBU_UccpQo12uLmufihkzdK7Kcrb5BlHp8GcMrSEA7NVdNw=": -13813089,
"event": "withdrawal"
}
}
- MCI: 1189239
- Not bounced
- Response unit:
- Response: {
"responseVars": {
"EJC4A7WQGHEZEKW6RLO7F26SAR4LAQBU_base": -359968000,
"event": "withdrawal"
}
}
- MCI: 1188965
- Not bounced
- Response: {
"responseVars": {
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_base": 12299516,
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_UccpQo12uLmufihkzdK7Kcrb5BlHp8GcMrSEA7NVdNw=": -283956,
"event": "trade"
},
"info": "no messages after filtering"
}
- MCI: 1188964
- Not bounced
- Response: {
"responseVars": {
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_base": 47574773,
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_UccpQo12uLmufihkzdK7Kcrb5BlHp8GcMrSEA7NVdNw=": -1098261,
"event": "trade"
},
"info": "no messages after filtering"
}
- MCI: 1188963
- Not bounced
- Response: {
"responseVars": {
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_UccpQo12uLmufihkzdK7Kcrb5BlHp8GcMrSEA7NVdNw=": 459883,
"M7MBGVHP44AN4WN2US2QGF7G4P6HNGQT_base": -19949762,
"event": "trade"
},
"info": "no messages after filtering"
}
Show transactions in assets:
No transactions found, it may be worth changing the filter
Unit ID
Date
From
Direction
To
Amount
19.01.2020 12:29:13
EUZ2QB4UHCMGN2D4LEOL5I3DUGP4FDJT
out
19.01.2020 12:29:13
in
EUZ2QB4UHCMGN2D4LEOL5I3DUGP4FDJT
18.01.2020 21:48:31
in
EUZ2QB4UHCMGN2D4LEOL5I3DUGP4FDJT
18.01.2020 21:47:50
EUZ2QB4UHCMGN2D4LEOL5I3DUGP4FDJT
out
18.01.2020 21:47:50
in
EUZ2QB4UHCMGN2D4LEOL5I3DUGP4FDJT