Function: spot_limit_order_cancel
Registered at block:
#48244250
Source Code
def _decimal(tick):
dec, _ = get(tick, 'decimal', None)
if dec is None:
dec = 0
return dec
def _insert_order(addr, pair, order_type, order_start, order_new, quote_value, base_value, quote_scale):
assert order_type in ['buy', 'sell']
order_id = order_start
price = - quote_value * quote_scale // base_value
while True:
order, _ = get('spot', f'{pair}_{order_type}', None, str(order_id))
if order is None:
put(addr, 'spot', f'{pair}_{order_type}',
[addr, base_value, quote_value, price, None, None], str(order_new))
order_new += 1
put(addr, 'spot', f'{pair}_{order_type}_new', order_new)
break
if order_type == 'buy':
cond = price > order[3]
else:
cond = price < order[3]
if cond:
next_order_id = order[5]
put(addr, 'spot', f'{pair}_{order_type}',
[addr, base_value, quote_value, price, order_id, next_order_id], str(order_new))
if next_order_id is None:
order_start = order_new
put(addr, 'spot', f'{pair}_{order_type}_start', order_new)
order[5] = order_new
order_new += 1
put(addr, 'spot', f'{pair}_{order_type}_new', order_new)
put(addr, 'spot', f'{pair}_{order_type}', order, str(order_id))
if next_order_id is not None:
next_order, _ = get('spot', f'{pair}_{order_type}', None, str(next_order_id))
if next_order is not None:
next_order[4] = order[5]
put(addr, 'spot', f'{pair}_{order_type}', next_order, str(next_order_id))
break
if order[4] is None:
put(addr, 'spot', f'{pair}_{order_type}',
[addr, base_value, quote_value, price, None, order_id], str(order_new))
put(addr, 'spot', f'{pair}_{order_type}',
[order[0], order[1], order[2], order[3], order_new, order[5]], str(order_id))
order_new += 1
put(addr, 'spot', f'{pair}_{order_type}_new', order_new)
break
order_id = order[4]
return order_start, order_new
def _remove_order(addr, pair, order, order_start, buy_or_sell):
assert buy_or_sell in ['buy', 'sell']
if order[4]:
prev_order, _ = get('spot', f'{pair}_{buy_or_sell}', None, str(order[4]))
prev_order[5] = order[5]
put(prev_order[0], 'spot', f'{pair}_{buy_or_sell}', prev_order, str(order[4]))
if order[5]:
next_order, _ = get('spot', f'{pair}_{buy_or_sell}', None, str(order[5]))
next_order[4] = order[4]
put(next_order[0], 'spot', f'{pair}_{buy_or_sell}', next_order, str(order[5]))
if order[4] is not None and order[5] is None:
order_start = order[4]
put(addr, 'spot', f'{pair}_{buy_or_sell}_start', order_start)
elif order[4] is None and order[5] is None:
order_new, _ = get('spot', f'{pair}_{buy_or_sell}_new', 1)
order_start = order_new
put(addr, 'spot', f'{pair}_{buy_or_sell}_start', order_start)
return order_start
def spot_limit_order(info, args):
assert args['f'] == 'spot_limit_order'
sender = info['sender']
addr = handle_lookup(sender)
base_tick = args['a'][0]
quote_tick = args['a'][2]
assert set(base_tick) <= set(string.ascii_uppercase+'_')
assert set(quote_tick) <= set(string.ascii_uppercase+'_')
pair = '%s_%s' % tuple([base_tick, quote_tick])
quote_scale = 10 ** _decimal(quote_tick)
base_value = int(args['a'][1])
quote_value = int(args['a'][3])
assert base_value * quote_value < 0
spot_buy_start, _ = get('spot', f'{pair}_buy_start', 1)
spot_buy_new, _ = get('spot', f'{pair}_buy_new', 1)
spot_sell_start, _ = get('spot', f'{pair}_sell_start', 1)
spot_sell_new, _ = get('spot', f'{pair}_sell_new', 1)
if base_value < 0 and quote_value > 0:
buy_or_sell = 'sell'
balance, _ = get(base_tick, 'balance', 0, addr)
balance += base_value
make_base = - base_value
assert balance >= 0
put(addr, base_tick, 'balance', balance, addr)
order_id = spot_sell_new
spot_sell_start, spot_sell_new = _insert_order(addr, pair, 'sell', spot_sell_start, spot_sell_new, quote_value, base_value, quote_scale)
elif base_value > 0 and quote_value < 0:
buy_or_sell = 'buy'
balance, _ = get(quote_tick, 'balance', 0, addr)
balance += quote_value
make_base = base_value
assert balance >= 0
put(addr, quote_tick, 'balance', balance, addr)
order_id = spot_buy_new
spot_buy_start, spot_buy_new = _insert_order(addr, pair, 'buy', spot_buy_start, spot_buy_new, quote_value, base_value, quote_scale)
spot_sell_id = spot_sell_start
highest_buy_price = None
# take_amount = 0
take_base = 0
take_quote = 0
while True:
sell, _ = get('spot', f'{pair}_sell', None, str(spot_sell_id))
if not sell:
break
sell_price = sell[3]
if highest_buy_price and sell_price > highest_buy_price:
break
spot_buy_id = spot_buy_start
while True:
buy, _ = get('spot', f'{pair}_buy', None, str(spot_buy_id))
if not buy:
break
buy_price = buy[3]
if highest_buy_price is None:
highest_buy_price = buy_price
if sell_price > buy_price:
spot_buy_id = buy[4]
continue
matched_price = sell_price
dx_base = min(-sell[1], buy[1])
dx_quote = dx_base * matched_price // quote_scale
sell[1] += dx_base
sell[2] -= dx_quote
buy[1] -= dx_base
buy[2] += dx_quote
take_base += dx_base
take_quote += dx_quote
# if buy_or_sell == 'buy':
# take_amount += dx_quote
# else:
# take_amount += dx_base
balance, _ = get(base_tick, 'balance', 0, buy[0])
balance += dx_base
assert balance >= 0
put(buy[0], base_tick, 'balance', balance, buy[0])
balance, _ = get(quote_tick, 'balance', 0, sell[0])
balance += dx_quote
assert balance >= 0
put(sell[0], quote_tick, 'balance', balance, sell[0])
if buy[1] == 0:
spot_buy_start = _remove_order(addr, pair, buy, spot_buy_start, 'buy')
if buy[2] < 0:
balance, _ = get(quote_tick, 'balance', 0, buy[0])
balance -= buy[2]
assert balance >= 0
put(buy[0], quote_tick, 'balance', balance, buy[0])
put(buy[0], 'spot', f'{pair}_buy', None, str(spot_buy_id))
else:
put(buy[0], 'spot', f'{pair}_buy', buy, str(spot_buy_id))
if sell[1] == 0:
break
if buy[4] is None:
break
spot_buy_id = buy[4]
if sell[1] == 0:
spot_sell_start = _remove_order(addr, pair, sell, spot_sell_start, 'sell')
if sell[1] < 0:
balance, _ = get(base_tick, 'balance', 0, sell[0])
balance -= sell[1]
assert balance >= 0
put(sell[0], base_tick, 'balance', balance, sell[0])
put(sell[0], 'spot', f'{pair}_sell', None, str(spot_sell_id))
else:
put(sell[0], 'spot', f'{pair}_sell', sell, str(spot_sell_id))
if sell[4] is None:
break
spot_sell_id = sell[4]
make_base -= take_base
assert make_base >= 0
make_price = - quote_value * quote_scale // base_value
event('SpotLimitMake', [pair, buy_or_sell, addr, make_base, make_price, order_id])
if take_base > 0:
take_price = take_quote * quote_scale // take_base
event('SpotLimitTake', [pair, buy_or_sell, addr, take_base, take_price, order_id])
def spot_market_order(info, args):
assert args['f'] == 'spot_market_order'
sender = info['sender']
addr = handle_lookup(sender)
base_tick = args['a'][0]
quote_tick = args['a'][2]
assert set(base_tick) <= set(string.ascii_uppercase+'_')
assert set(quote_tick) <= set(string.ascii_uppercase+'_')
pair = '%s_%s' % tuple([base_tick, quote_tick])
base_value = args['a'][1]
quote_value = args['a'][3]
quote_scale = 10 ** _decimal(quote_tick)
spot_sell_start, _ = get('spot', f'{pair}_sell_start', 1)
spot_buy_start, _ = get('spot', f'{pair}_buy_start', 1)
take_base = 0
take_quote = 0
if quote_value is None and int(base_value) < 0:
buy_or_sell = 'sell'
base_value = int(args['a'][1])
base_balance, _ = get(base_tick, 'balance', 0, addr)
# base_sum = 0
spot_buy_id = spot_buy_start
while True:
buy, _ = get('spot', f'{pair}_buy', None, str(spot_buy_id))
if buy is None:
break
price = buy[3]
dx_base = min(buy[1], -buy[2] * quote_scale // price, -base_value)
dx_quote = dx_base * price // quote_scale
if dx_base == 0 or dx_quote == 0:
break
if base_balance - dx_base < 0:
break
buy[1] -= dx_base
buy[2] += dx_quote
take_base += dx_base
take_quote += dx_quote
base_balance -= dx_base
# base_sum += dx_base
if buy[1] == 0 or buy[1] // price == 0:
spot_buy_start = _remove_order(addr, pair, buy, spot_buy_start, 'buy')
if buy[2] < 0:
balance, _ = get(quote_tick, 'balance', 0, buy[0])
balance -= buy[2]
assert balance >= 0
put(buy[0], quote_tick, 'balance', balance, buy[0])
put(buy[0], 'spot', f'{pair}_buy', None, str(spot_buy_id))
else:
put(buy[0], 'spot', f'{pair}_buy', buy, str(spot_buy_id))
balance, _ = get(base_tick, 'balance', 0, buy[0])
balance += dx_base
assert balance >= 0
put(addr, base_tick, 'balance', balance, buy[0])
base_value += dx_base
assert base_value <= 0
balance, _ = get(quote_tick, 'balance', 0, addr)
balance += dx_quote
assert balance >= 0
put(addr, quote_tick, 'balance', balance, addr)
if buy[4] is None:
break
spot_buy_id = buy[4]
balance, _ = get(base_tick, 'balance', 0, addr)
balance -= take_base
assert balance >= 0
put(addr, base_tick, 'balance', balance, addr)
elif quote_value is None and int(base_value) > 0:
buy_or_sell = 'buy'
base_value = int(args['a'][1])
quote_balance, _ = get(quote_tick, 'balance', 0, addr)
# quote_sum = 0
spot_sell_id = spot_sell_start
while True:
sell, _ = get('spot', f'{pair}_sell', None, str(spot_sell_id))
if sell is None:
break
price = sell[3]
dx_base = min(-sell[1], quote_balance * quote_scale // price, base_value)
dx_quote = dx_base * price // quote_scale
if dx_base == 0 or dx_quote == 0:
break
if quote_balance - dx_quote < 0:
break
sell[1] += dx_base
sell[2] -= dx_quote
take_base += dx_base
take_quote += dx_quote
quote_balance -= dx_quote
# quote_sum += dx_quote
if sell[1] == 0 or sell[1] // price == 0:
spot_sell_start = _remove_order(addr, pair, sell, spot_sell_start, 'sell')
if sell[1] < 0:
balance, _ = get(base_tick, 'balance', 0, sell[0])
balance -= sell[1]
assert balance >= 0
put(sell[0], base_tick, 'balance', balance, sell[0])
put(sell[0], 'spot', f'{pair}_sell', None, str(spot_sell_id))
else:
put(sell[0], 'spot', f'{pair}_sell', sell, str(spot_sell_id))
balance, _ = get(quote_tick, 'balance', 0, sell[0])
balance += dx_quote
assert balance >= 0
put(addr, quote_tick, 'balance', balance, sell[0])
base_value -= dx_base
assert base_value >= 0
balance, _ = get(base_tick, 'balance', 0, addr)
balance += dx_base
assert balance >= 0
put(addr, base_tick, 'balance', balance, addr)
if sell[4] is None:
break
spot_sell_id = sell[4]
balance, _ = get(quote_tick, 'balance', 0, addr)
balance -= take_quote
assert balance >= 0
put(addr, quote_tick, 'balance', balance, addr)
elif base_value is None and int(quote_value) < 0:
buy_or_sell = 'buy'
quote_value = int(args['a'][3])
quote_balance, _ = get(quote_tick, 'balance', 0, addr)
# quote_sum = 0
spot_sell_id = spot_sell_start
while True:
sell, _ = get('spot', f'{pair}_sell', None, str(spot_sell_id))
if sell is None:
break
price = sell[3]
dx_base = min(-sell[1], -quote_value * quote_scale // price)
dx_quote = dx_base * price // quote_scale
if dx_base == 0 or dx_quote == 0:
break
if quote_balance - dx_quote < 0:
break
sell[1] += dx_base
sell[2] -= dx_quote
take_base += dx_base
take_quote += dx_quote
quote_balance -= dx_quote
# quote_sum += dx_quote
if sell[1] == 0 or sell[1] // price == 0:
spot_sell_start = _remove_order(addr, pair, sell, spot_sell_start, 'sell')
if sell[1] < 0:
balance, _ = get(base_tick, 'balance', 0, sell[0])
balance -= sell[1]
assert balance >= 0
put(sell[0], base_tick, 'balance', balance, sell[0])
put(sell[0], 'spot', f'{pair}_sell', None, str(spot_sell_id))
else:
put(sell[0], 'spot', f'{pair}_sell', sell, str(spot_sell_id))
balance, _ = get(quote_tick, 'balance', 0, sell[0])
balance += dx_quote
assert balance >= 0
put(addr, quote_tick, 'balance', balance, sell[0])
quote_value += dx_quote
assert quote_value <= 0
balance, _ = get(base_tick, 'balance', 0, addr)
balance += dx_base
assert balance >= 0
put(addr, base_tick, 'balance', balance, addr)
if sell[4] is None:
break
spot_sell_id = sell[4]
balance, _ = get(quote_tick, 'balance', 0, addr)
balance -= take_quote
assert balance >= 0
put(addr, quote_tick, 'balance', balance, addr)
elif base_value is None and int(quote_value) > 0:
buy_or_sell = 'sell'
quote_value = int(args['a'][3])
base_balance, _ = get(base_tick, 'balance', 0, addr)
# base_sum = 0
spot_buy_id = spot_buy_start
while True:
buy, _ = get('spot', f'{pair}_buy', None, str(spot_buy_id))
if buy is None:
break
price = buy[3]
dx_base = min(buy[1], base_balance, quote_value * quote_scale // price)
dx_quote = dx_base * price // quote_scale
if dx_base == 0 or dx_quote == 0:
break
if base_balance - dx_base < 0:
break
buy[1] -= dx_base
buy[2] += dx_quote
take_base += dx_base
take_quote += dx_quote
base_balance -= dx_base
# base_sum += dx_base
if buy[1] == 0 or buy[1] // price == 0:
spot_buy_start = _remove_order(addr, pair, buy, spot_buy_start, 'buy')
if buy[2] < 0:
balance, _ = get(quote_tick, 'balance', 0, buy[0])
balance -= buy[2]
assert balance >= 0
put(buy[0], quote_tick, 'balance', balance, buy[0])
put(buy[0], 'spot', f'{pair}_buy', None, str(spot_buy_id))
else:
put(buy[0], 'spot', f'{pair}_buy', buy, str(spot_buy_id))
balance, _ = get(base_tick, 'balance', 0, buy[0])
balance += dx_base
assert balance >= 0
put(addr, base_tick, 'balance', balance, buy[0])
quote_value -= dx_quote
assert quote_value >= 0
balance, _ = get(quote_tick, 'balance', 0, addr)
balance += dx_quote
assert balance >= 0
put(addr, quote_tick, 'balance', balance, addr)
if buy[4] is None:
break
spot_buy_id = buy[4]
balance, _ = get(base_tick, 'balance', 0, addr)
balance -= take_base
assert balance >= 0
put(addr, base_tick, 'balance', balance, addr)
if take_base > 0:
price = take_quote * quote_scale // take_base
event('SpotMarketTake', [pair, buy_or_sell, addr, take_base, price])
def spot_limit_order_cancel(info, args):
assert args['f'] == 'spot_limit_order_cancel'
sender = info['sender']
addr = handle_lookup(sender)
base_tick = args['a'][0]
assert set(base_tick) <= set(string.ascii_uppercase + '_')
quote_tick = args['a'][1]
assert set(quote_tick) <= set(string.ascii_uppercase + '_')
buy_or_sell = args['a'][2]
assert buy_or_sell in ['buy', 'sell']
spot_order_id = int(args['a'][3])
pair = '%s_%s' % (base_tick, quote_tick)
order_key = f'{pair}_{buy_or_sell}'
order, _ = get('spot', order_key, None, str(spot_order_id))
if order is None:
return
assert order[0] == addr, "Sender is not the owner of the order"
prev_order_id = order[4]
next_order_id = order[5]
if prev_order_id is not None:
prev_order, _ = get('spot', order_key, None, str(prev_order_id))
if prev_order:
prev_order[5] = next_order_id
put(prev_order[0], 'spot', order_key, prev_order, str(prev_order_id))
if next_order_id is not None:
next_order, _ = get('spot', order_key, None, str(next_order_id))
if next_order:
next_order[4] = prev_order_id
put(next_order[0], 'spot', order_key, next_order, str(next_order_id))
start_key = f'{pair}_{buy_or_sell}_start'
current_start, _ = get('spot', start_key, 1)
if current_start == spot_order_id:
if prev_order_id is not None:
put(addr, 'spot', start_key, prev_order_id)
else:
new_start_key = f'{pair}_{buy_or_sell}_new'
new_start_val, _ = get('spot', new_start_key, 1)
put(addr, 'spot', start_key, new_start_val)
if buy_or_sell == 'sell':
if order[1] < 0:
balance, _ = get(base_tick, 'balance', 0, addr)
balance -= order[1]
put(addr, base_tick, 'balance', balance, addr)
elif buy_or_sell == 'buy':
if order[2] < 0:
balance, _ = get(quote_tick, 'balance', 0, addr)
balance -= order[2]
put(addr, quote_tick, 'balance', balance, addr)
put(addr, 'spot', order_key, None, str(spot_order_id))
event('SpotOrderCancel', [spot_order_id, buy_or_sell, pair])
def spot_pair_create(info, args):
assert args['f'] == 'spot_pair_create'
sender = info['sender']
addr = handle_lookup(sender)
base_tick = args['a'][0]
quote_tick = args['a'][1]
quote_tokens, _ = get('spot', 'quote_tokens', [])
assert quote_tick in quote_tokens, f"{quote_tick} is not a designated quote token"
owner, _ = get('asset', 'owner', None, base_tick)
assert owner == addr, f"Sender must be the owner of the base token ({base_tick})"
pair = f'{base_tick}_{quote_tick}'
enable, _ = get('spot', f'{pair}_enable', None)
assert enable is None, "Pair already exists"
put(addr, 'spot', f'{pair}_enable', True)
put(addr, 'spot', f'{pair}_buy_start', 1)
put(addr, 'spot', f'{pair}_buy_new', 1)
put(addr, 'spot', f'{pair}_sell_start', 1)
put(addr, 'spot', f'{pair}_sell_new', 1)
def spot_pair_enable(info, args):
assert args['f'] == 'spot_pair_enable'
sender = info['sender']
addr = handle_lookup(sender)
base_tick = args['a'][0]
quote_tick = args['a'][1]
pair = f'{base_tick}_{quote_tick}'
owner, _ = get('asset', 'owner', None, base_tick)
assert owner == addr, f"Sender must be the owner of the base token ({base_tick})"
put(addr, 'spot', f'{pair}_enable', True)
def spot_pair_disable(info, args):
assert args['f'] == 'spot_pair_disable'
sender = info['sender']
addr = handle_lookup(sender)
base_tick = args['a'][0]
quote_tick = args['a'][1]
pair = f'{base_tick}_{quote_tick}'
owner, _ = get('asset', 'owner', None, base_tick)
assert owner == addr, f"Sender must be the owner of the base token ({base_tick})"
put(addr, 'spot', f'{pair}_enable', False)
def spot_set_quote_tokens(info, args):
assert args['f'] == 'spot_set_quote_tokens'
sender = info['sender']
addr = handle_lookup(sender)
manager, _ = get('spot', 'manager', None)
assert manager is not None, "Manager not set"
assert addr == manager, "Only the manager can add quote tokens"
new_tokens = args['a'][0]
assert isinstance(new_tokens, list), "Quote tokens must be a list"
quote_tokens, _ = get('spot', 'quote_tokens', [])
for token in new_tokens:
assert isinstance(token, str), "Token ticker must be a string"
assert set(token) <= set(string.ascii_uppercase+'_'), "Invalid characters in token ticker"
if token not in quote_tokens:
quote_tokens.append(token)
put(addr, 'spot', 'quote_tokens', quote_tokens)
def spot_vote_manager(info, args):
assert args['f'] == 'spot_vote_manager'
sender = info['sender']
addr = handle_lookup(sender)
committee_members, _ = get('committee', 'members', [])
committee_members = set(committee_members)
assert addr in committee_members, "Only committee members can vote"
user = args['a'][0]
assert isinstance(user, str), "User address must be a string"
proposal_key = f'spot_manager:{user}'
votes, _ = get('committee', 'proposal', [], proposal_key)
votes = set(votes)
votes.add(addr)
if len(votes) >= len(committee_members) * 2 // 3:
put(addr, 'spot', 'manager', user)
put(addr, 'committee', 'proposal', [], proposal_key)
else:
put(addr, 'committee', 'proposal', list(votes), proposal_key)
← Back to Functions