Skip to content

Commit

Permalink
e2e(cch): pay btc invoice for ReceiveBTC order
Browse files Browse the repository at this point in the history
  • Loading branch information
doitian committed Jun 18, 2024
1 parent 582c1af commit adfd6df
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 43 deletions.
82 changes: 50 additions & 32 deletions src/cch/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,38 +199,26 @@ impl Actor for CchActor {
}
Ok(())
}
CchMessage::SettleSendBTCOrder(event) => self
.settle_send_btc_order(state, event)
.await
.map_err(Into::into),
CchMessage::SettleSendBTCOrder(event) => {
log::debug!("settle_send_btc_order {:?}", event);
if let Err(err) = self.settle_send_btc_order(state, event).await {
log::error!("settle_send_btc_order failed: {}", err);
}
Ok(())
}
CchMessage::SettleReceiveBTCOrder(event) => {
if event.preimage.is_some() {
log::info!(
"SettleReceiveBTCOrder: payment_hash={}, status={:?}",
event.payment_hash,
event.status
);
// TODO: 1. Create a CKB payment to the payee to get preimage when event.status is Accepted
// TODO: 2. Subscribe to the CKB payment events, once it's settled, use the preimage to settle the BTC payment via invoicesrpc `settle_invoice`.
match state
.orders_db
.update_receive_btc_order(&event.payment_hash, event.preimage, event.status)
.await
{
Err(CchDbError::NotFound(_)) => {
// ignore payments not found in the db
Ok(())
}
result => result.map_err(Into::into),
}
} else {
Ok(())
log::debug!("settle_receive_btc_order {:?}", event);
if let Err(err) = self.settle_receive_btc_order(state, event).await {
log::error!("settle_receive_btc_order failed: {}", err);
}
Ok(())
}
CchMessage::TlcNotification(tlc_notification) => {
if let Err(err) = self.handle_tlc_notification(state, tlc_notification).await {
log::error!("handle_tlc_notification failed: {}", err);
}
Ok(())
}
CchMessage::TlcNotification(tlc_notification) => self
.handle_tlc_notification(state, tlc_notification)
.await
.map_err(Into::into),
}
}
}
Expand Down Expand Up @@ -504,6 +492,35 @@ impl CchActor {

Ok(order)
}

async fn settle_receive_btc_order(
&self,
state: &mut CchState,
event: SettleReceiveBTCOrderEvent,
) -> Result<()> {
if event.preimage.is_some() {
log::info!(
"SettleReceiveBTCOrder: payment_hash={}, status={:?}",
event.payment_hash,
event.status
);
// TODO: 1. Create a CKB payment to the payee to get preimage when event.status is Accepted
// TODO: 2. Subscribe to the CKB payment events, once it's settled, use the preimage to settle the BTC payment via invoicesrpc `settle_invoice`.
match state
.orders_db
.update_receive_btc_order(&event.payment_hash, event.preimage, event.status)
.await
{
Err(CchDbError::NotFound(_)) => {
// ignore payments not found in the db
Ok(())
}
result => result.map_err(Into::into),
}
} else {
Ok(())
}
}
}

struct LndPaymentsTracker {
Expand Down Expand Up @@ -698,13 +715,14 @@ impl LndInvoiceTracker {

// Return true to quit the tracker
async fn on_invoice(&self, invoice: lnrpc::Invoice) -> Result<bool> {
log::debug!("[LndPaymentsTracker] invoice: {:?}", invoice);
log::debug!("[LndInvoiceTracker] invoice: {:?}", invoice);
let status = lnrpc::invoice::InvoiceState::try_from(invoice.state)
.map(Into::into)
.unwrap_or(CchOrderStatus::Pending);
let event = CchMessage::SettleReceiveBTCOrder(SettleReceiveBTCOrderEvent {
payment_hash: hex::encode(invoice.r_hash),
preimage: (!invoice.r_preimage.is_empty()).then_some(hex::encode(invoice.r_preimage)),
payment_hash: format!("0x{}", hex::encode(invoice.r_hash)),
preimage: (!invoice.r_preimage.is_empty())
.then(|| format!("0x{}", hex::encode(invoice.r_preimage))),
status,
});
self.cch_actor.cast(event)?;
Expand Down
6 changes: 5 additions & 1 deletion tests/bruno/e2e/cross-chain-hub/01-add-btc-invoice.bru
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ post {
}

body:json {
{"value":5000}
{"value":20000}
}

assert {
res.status: eq 200
}

script:post-response {
Expand Down
5 changes: 5 additions & 0 deletions tests/bruno/e2e/cross-chain-hub/02-create-send-btc-order.bru
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ body:json {
}
}

assert {
res.status: eq 200
res.body.error: isUndefined
}

script:post-response {
if (res.body.result) {
bru.setVar("CKB_PAY_REQ", res.body.result.ckb_pay_req);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ headers {
Accept: application/json
}


body:json {
{
"id": "42",
Expand All @@ -24,7 +23,7 @@ body:json {
"params": [
{
"peer_id": "{{NODE3_PEERID}}",
"funding_amount": "0x2710",
"funding_amount": "0xc350",
"funding_udt_type_script": {
"code_hash": "0xe1e354d6d643ad42724d40967e334984534e0367405c5ae42a9d7d63d77df419",
"hash_type": "data1",
Expand Down
2 changes: 1 addition & 1 deletion tests/bruno/e2e/cross-chain-hub/07-node1-add-tlc.bru
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ body:json {
"params": [
{
"channel_id": "{{N1N3_CHANNEL_ID}}",
"amount": "0x1388",
"amount": "0x4e20",
"payment_hash": "{{PAYMENT_HASH}}",
"expiry": 40
}
Expand Down
10 changes: 5 additions & 5 deletions tests/bruno/e2e/cross-chain-hub/08-check-btc-received.bru
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ vars:post-response {
max_iterations: 10
}

assert {
res.status: eq 200
}

script:pre-request {
if(bru.getVar("iteration") === undefined){
bru.setVar("iteration", 0);
Expand All @@ -27,7 +31,7 @@ script:post-response {
console.log(`Try ${i+1}/${n}`);
}

if (parseInt(res.body.balance, 10) > 0) {
if (parseInt(res.body.local_balance.sat, 10) > 0) {
console.log("Bob has received the payment");
bru.setVar("iteration", 0);
} else if (i+1 < n) {
Expand All @@ -39,7 +43,3 @@ script:post-response {
throw new Error("Bob has not received the payment");
}
}

docs {
BTC user generates an invoice via lnd.
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ body:json {
{
"payment_hash": "{{PAYMENT_HASH}}",
"channel_id": "{{N1N3_CHANNEL_ID}}",
"amount_sats": "0x7d0",
"amount_sats": "0x1",
"final_tlc_expiry": "0x3c"
}
]
}
}

assert {
res.status: eq 200
res.body.error: isUndefined
}

script:pre-request {
const uuid = require('uuid');
const CryptoJS = require("crypto-js");
Expand All @@ -52,5 +57,5 @@ script:post-response {
}

docs {
CKB user sends the received BTC invoice to the cross-chain hub to exchange a CKB invoice.
CKB user requests a BTC invoice to receive BTC from Bitcoin user.
}
47 changes: 47 additions & 0 deletions tests/bruno/e2e/cross-chain-hub/10-pay-btc-invoice.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
meta {
name: 10-pay-btc-invoice
type: http
seq: 10
}

post {
url: {{LND_BOB_RPC_URL}}/v2/router/send
body: json
auth: none
}

body:json {
{
"payment_request": "{{BTC_PAY_REQ}}",
"timeout_seconds": 1
}
}

assert {
res.status: eq 409
}

script:pre-request {
const axios = require('axios');

const url = bru.getEnvVar("LND_BOB_RPC_URL") + "/v2/router/send";
const body = {
payment_request: bru.getVar("BTC_PAY_REQ"),
timeout_seconds: 1
};
console.log(url);
console.log(body);

await axios({
method: 'POST',
url: url,
data: body,
responseType: 'stream'
});
}

docs {
Send payment via lnd RPC https://lightning.engineering/api-docs/api/lnd/router/send-payment-v2.

This is a server-streaming RPC which will block Bruno. The workaround is sending the request in the pre-script so the Bruno request will return 409 because the payment is already sent.
}

0 comments on commit adfd6df

Please sign in to comment.