mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-31 02:21:35 +00:00
Logics update: escrow settles exactly at buyer payout time.
This commit is contained in:
parent
bfa0cd84d1
commit
7218b9b0d3
@ -514,8 +514,7 @@ class Logics():
|
||||
|
||||
# Do not gen and kick out the taker if order is older than expiry time
|
||||
if order.expires_at < timezone.now():
|
||||
cls.cancel_bond(order.taker_bond)
|
||||
cls.kick_taker(order)
|
||||
cls.order_expires(order)
|
||||
return False, {'bad_request':'Invoice expired. You did not confirm taking the order in time.'}
|
||||
|
||||
# Do not gen if a taker invoice exist. Do not return if it is already locked. Return the old one if still waiting.
|
||||
@ -580,7 +579,7 @@ class Logics():
|
||||
|
||||
# Do not generate if escrow deposit time has expired
|
||||
if order.expires_at < timezone.now():
|
||||
cls.cancel_order(order,user)
|
||||
cls.order_expires(order)
|
||||
return False, {'bad_request':'Invoice expired. You did not send the escrow in time.'}
|
||||
|
||||
# Do not gen if an escrow invoice exist. Do not return if it is already locked. Return the old one if still waiting.
|
||||
@ -690,12 +689,10 @@ class Logics():
|
||||
|
||||
# If buyer, settle escrow and mark fiat sent
|
||||
if cls.is_buyer(order, user):
|
||||
if cls.settle_escrow(order): ##### !!! KEY LINE - SETTLES THE TRADE ESCROW !!!
|
||||
order.trade_escrow.status = LNPayment.Status.SETLED
|
||||
order.status = Order.Status.FSE
|
||||
order.is_fiat_sent = True
|
||||
order.status = Order.Status.FSE
|
||||
order.is_fiat_sent = True
|
||||
|
||||
# If seller and fiat sent, pay buyer invoice
|
||||
# If seller and fiat was sent, SETTLE ESCRO AND PAY BUYER INVOICE
|
||||
elif cls.is_seller(order, user):
|
||||
if not order.is_fiat_sent:
|
||||
return False, {'bad_request':'You cannot confirm to have received the fiat before it is confirmed to be sent by the buyer.'}
|
||||
@ -704,6 +701,9 @@ class Logics():
|
||||
if order.trade_escrow.num_satoshis <= order.buyer_invoice.num_satoshis:
|
||||
return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'}
|
||||
|
||||
if cls.settle_escrow(order): ##### !!! KEY LINE - SETTLES THE TRADE ESCROW !!!
|
||||
order.trade_escrow.status = LNPayment.Status.SETLED
|
||||
|
||||
# Double check the escrow is settled.
|
||||
if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash):
|
||||
is_payed, context = cls.pay_buyer_invoice(order) ##### !!! KEY LINE - PAYS THE BUYER INVOICE !!!
|
||||
|
@ -15,6 +15,8 @@ class Command(BaseCommand):
|
||||
''' Continuously checks order expiration times for 1 hour. If order
|
||||
has expires, it calls the logics module for expiration handling.'''
|
||||
|
||||
# TODO handle 'database is locked'
|
||||
|
||||
do_nothing = [Order.Status.DEL, Order.Status.UCA,
|
||||
Order.Status.EXP, Order.Status.FSE,
|
||||
Order.Status.DIS, Order.Status.CCA,
|
||||
@ -34,8 +36,17 @@ class Command(BaseCommand):
|
||||
|
||||
for idx, order in enumerate(queryset):
|
||||
context = str(order)+ " was "+ Order.Status(order.status).label
|
||||
if Logics.order_expires(order): # Order send to expire here
|
||||
debug['expired_orders'].append({idx:context})
|
||||
try:
|
||||
if Logics.order_expires(order): # Order send to expire here
|
||||
debug['expired_orders'].append({idx:context})
|
||||
|
||||
# If it cannot locate the hold invoice, make it expire anywway
|
||||
except Exception as e:
|
||||
if 'unable to locate invoice' in str(e):
|
||||
self.stdout.write(str(e))
|
||||
order.status = Order.Status.EXP
|
||||
debug['expired_orders'].append({idx:context})
|
||||
|
||||
|
||||
if debug['num_expired_orders'] > 0:
|
||||
self.stdout.write(str(timezone.now()))
|
||||
|
@ -31,6 +31,8 @@ class Command(BaseCommand):
|
||||
''' Follows and updates LNpayment objects
|
||||
until settled or canceled'''
|
||||
|
||||
# TODO handle 'database is locked'
|
||||
|
||||
lnd_state_to_lnpayment_status = {
|
||||
0: LNPayment.Status.INVGEN, # OPEN
|
||||
1: LNPayment.Status.SETLED, # SETTLED
|
||||
@ -64,6 +66,7 @@ class Command(BaseCommand):
|
||||
# If it fails at finding the invoice it has been canceled.
|
||||
# On RoboSats DB we make a distinction between cancelled and returned (LND does not)
|
||||
if 'unable to locate invoice' in str(e):
|
||||
self.stdout.write('unable to locate invoice')
|
||||
hold_lnpayment.status = LNPayment.Status.CANCEL
|
||||
# LND restarted.
|
||||
if 'wallet locked, unlock it' in str(e):
|
||||
|
@ -70,7 +70,7 @@ def follow_send_payment(lnpayment):
|
||||
order.status = Order.Status.FAI
|
||||
order.save()
|
||||
context = LNNode.payment_failure_context[response.failure_reason]
|
||||
# Call for a retry here
|
||||
# Call a retry here?
|
||||
return False, context
|
||||
|
||||
if response.status == 2 : # Status 2 'SUCCEEDED'
|
||||
|
@ -19,7 +19,7 @@ export default class InfoDialog extends Component {
|
||||
|
||||
<Typography component="h5" variant="h5">How does it work?</Typography>
|
||||
<Typography component="body2" variant="body2">
|
||||
<p>AdequateAlice01 wants to sell bitcoin. She posts a sell order.
|
||||
<p>Anonymous AdequateAlice01 wants to sell bitcoin. She posts a sell order.
|
||||
BafflingBob02 wants to buy bitcoin and he takes Alice's order.
|
||||
Both have to post a small bond using lightning to prove they are real
|
||||
robots. Then, Alice posts the trade collateral also using a lightning
|
||||
@ -51,8 +51,9 @@ export default class InfoDialog extends Component {
|
||||
|
||||
<Typography component="h5" variant="h5">Is <i>RoboSats</i> private?</Typography>
|
||||
<Typography component="body2" variant="body2">
|
||||
<p> RoboSats will never ask you for your name, country or ID. For
|
||||
best anonymity use Tor Browser and access the .onion hidden service. </p>
|
||||
<p> RoboSats will never ask you for your name, country or ID. RoboSats does
|
||||
not custody your funds, and doesn't care who you are. For best anonymity
|
||||
use Tor Browser and access the .onion hidden service. </p>
|
||||
|
||||
<p>Your trading peer is the only one who can potentially guess
|
||||
anything about you. Keep your chat short and concise. Avoid
|
||||
@ -73,29 +74,33 @@ export default class InfoDialog extends Component {
|
||||
<Typography component="h5" variant="h5">What is the trust model?</Typography>
|
||||
<Typography component="body2" variant="body2">
|
||||
<p> The buyer and the seller never have to trust each other.
|
||||
Some trust on <i>RoboSats</i> staff is needed since linking
|
||||
the seller's hold invoice and buyer payment is not atomic (yet).
|
||||
Some trust on <i>RoboSats</i> is needed since linking the
|
||||
seller's hold invoice and buyer payment is not atomic (yet).
|
||||
In addition, disputes are solved by the <i>RoboSats</i> staff.
|
||||
</p>
|
||||
|
||||
<p> While trust requirements are minimized, <i>RoboSats</i> could
|
||||
run away with your satoshis. It could be argued that it is not
|
||||
worth it, as it would instantly destroy <i>RoboSats</i> reputation.
|
||||
<p> Trust requirements are minimized, however there is still one way
|
||||
<i>RoboSats</i> could run away with your satoshis, by not releasing
|
||||
the satoshis to the buyer. It could be argued that such move is not on
|
||||
<i>RoboSats</i> interest as it would damage thereputation for a small payout.
|
||||
However, you should hesitate and only trade small quantities at a
|
||||
time. For large amounts use an onchain escrow service such as <i>Bisq</i>
|
||||
</p>
|
||||
|
||||
<p> You can build more trust on <i>RoboSats</i> by <a href='https://github.com/reckless-satoshi/robosats'>
|
||||
inspecting the source code </a> </p>
|
||||
inspecting the source code. </a> </p>
|
||||
</Typography>
|
||||
|
||||
<Typography component="h5" variant="h5">What happens if <i>RoboSats</i> suddenly disapears?</Typography>
|
||||
<Typography component="body2" variant="body2">
|
||||
<p> Your sats will most likely return to you. Any hold invoice that is not
|
||||
<p> Your sats will return to you. Any hold invoice that is not
|
||||
settled would be automatically returned even if <i>RoboSats</i> goes down
|
||||
forever. This is true for both, locked bonds and trading escrows. However,
|
||||
there is a small window between the buyer confirms FIAT SENT and the moment
|
||||
the seller releases the satoshis when the funds could be lost.
|
||||
there is a small window between the seller confirms FIAT RECEIVED and the moment
|
||||
the buyer receives the satoshis when the funds could be permanentely lost if
|
||||
<i>RoboSats</i> disappears. This window is about 1 second long. Make sure to have enough
|
||||
inbound liquidity to avoid routing failures. If you have any problem, reach out
|
||||
trough the <i>RoboSats</i> public channels.
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@ -116,9 +121,7 @@ export default class InfoDialog extends Component {
|
||||
RoboSats</i> will definitely never ask for your robot token.
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
</DialogContent>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ export default class TradeBox extends Component {
|
||||
size="small"
|
||||
defaultValue={this.props.data.bondInvoice}
|
||||
disabled="true"
|
||||
helperText="This is a hold invoice. It will be charged only if you cancel or lose a dispute."
|
||||
helperText="This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute."
|
||||
color = "secondary"
|
||||
/>
|
||||
</Grid>
|
||||
@ -198,7 +198,7 @@ export default class TradeBox extends Component {
|
||||
size="small"
|
||||
defaultValue={this.props.data.escrowInvoice}
|
||||
disabled="true"
|
||||
helperText="This is a hold invoice. It will be charged once the buyer confirms he sent the fiat."
|
||||
helperText={"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the "+this.props.data.currencyCode+"."}
|
||||
color = "secondary"
|
||||
/>
|
||||
</Grid>
|
||||
|
@ -31,9 +31,9 @@ app.conf.beat_scheduler = 'django_celery_beat.schedulers:DatabaseScheduler'
|
||||
|
||||
# Configure the periodic tasks
|
||||
app.conf.beat_schedule = {
|
||||
'users-cleansing': { # Cleans abandoned users every hour
|
||||
'users-cleansing': { # Cleans abandoned users every 6 hours
|
||||
'task': 'users_cleansing',
|
||||
'schedule': timedelta(hours=1),
|
||||
'schedule': timedelta(hours=6),
|
||||
},
|
||||
'cache-market-prices': { # Cache market prices every minutes for now.
|
||||
'task': 'cache_external_market_prices',
|
||||
|
Loading…
Reference in New Issue
Block a user