diff --git a/.github/workflows/bats.yml b/.github/workflows/bats.yml index bd736ddaf3..c1a5f648b8 100644 --- a/.github/workflows/bats.yml +++ b/.github/workflows/bats.yml @@ -21,7 +21,7 @@ jobs: //core/api-keys //apps/dashboard //apps/consent //apps/pay - name: Run bats tests run: | - nix develop -c bats --setup-suite-file bats/ci_setup_suite.bash -t bats/core/** + . ./.env && nix develop -c bats --setup-suite-file bats/ci_setup_suite.bash -t bats/core/** - name: Rename Tilt log if: always() run: mv bats/.e2e-tilt.log bats/e2e-tilt.log diff --git a/core/api/test/bats/ln-receive.bats b/bats/core/api/ln-receive.bats similarity index 90% rename from core/api/test/bats/ln-receive.bats rename to bats/core/api/ln-receive.bats index ca23566a74..fc7790d7d8 100644 --- a/core/api/test/bats/ln-receive.bats +++ b/bats/core/api/ln-receive.bats @@ -1,61 +1,48 @@ #!/usr/bin/env bats -load "helpers/setup-and-teardown" -load "helpers/ln" +load "../../helpers/callback.bash" +load "../../helpers/cli.bash" +load "../../helpers/ledger.bash" +load "../../helpers/ln.bash" +load "../../helpers/onchain.bash" +load "../../helpers/subscriber.bash" +load "../../helpers/trigger.bash" +load "../../helpers/user.bash" -setup_file() { - clear_cache - - bitcoind_init - start_trigger - start_ws_server - start_server - start_exporter - start_callback +ALICE='alice' - lnds_init - - login_user "$ALICE_TOKEN_NAME" "$ALICE_PHONE" "$CODE" - add_callback "$ALICE_TOKEN_NAME" - initialize_user_from_onchain "$ALICE_TOKEN_NAME" "$ALICE_PHONE" "$CODE" +setup_file() { + create_user "$ALICE" + add_callback "$ALICE" + fund_user_onchain "$ALICE" 'btc_wallet' - subscribe_to "$ALICE_TOKEN_NAME" my-updates-sub - sleep 3 + subscribe_to "$ALICE" my-updates-sub + retry 10 1 subscriber_is_up } teardown_file() { - stop_trigger - stop_server - stop_ws_server - stop_exporter stop_subscriber - stop_callback -} - -setup() { - reset_redis } teardown() { if [[ "$(balance_for_check)" != 0 ]]; then fail "Error: balance_for_check failed" fi - } btc_amount=1000 usd_amount=50 @test "ln-receive: settle via ln for BTC wallet, invoice with amount" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" btc_wallet_name="$token_name.btc_wallet_id" # Check callback events before - exec_graphql "$token_name" 'account-details' + exec_graphql "$token_name" 'default-account' account_id="$(graphql_output '.data.me.defaultAccount.id')" [[ "$account_id" != "null" ]] || exit 1 - num_callback_events_before=$(cat .e2e-callback.log | grep "$account_id" | wc -l) + num_callback_events_before=$(cat_callback | grep "$account_id" | wc -l) # Generate invoice variables=$( @@ -135,15 +122,14 @@ usd_amount=50 invoice_status="$(graphql_output '.data.me.defaultAccount.walletById.invoiceByPaymentHash.paymentStatus')" [[ "${invoice_status}" == "PAID" ]] || exit 1 - # Check for callback - num_callback_events_after=$(cat .e2e-callback.log | grep "$account_id" | wc -l) + num_callback_events_after=$(cat_callback | grep "$account_id" | wc -l) [[ "$num_callback_events_after" -gt "$num_callback_events_before" ]] || exit 1 } @test "ln-receive: settle via ln for USD wallet, invoice with amount" { # Generate invoice - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" usd_wallet_name="$token_name.usd_wallet_id" variables=$( @@ -172,7 +158,7 @@ usd_amount=50 } @test "ln-receive: settle via ln for BTC wallet, amountless invoice" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" btc_wallet_name="$token_name.btc_wallet_id" # Generate invoice @@ -202,7 +188,7 @@ usd_amount=50 } @test "ln-receive: handle less-than-1-sat ln payment for BTC wallet" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" btc_wallet_name="$token_name.btc_wallet_id" # Generate amountless invoice @@ -248,7 +234,7 @@ usd_amount=50 @test "ln-receive: settle via ln for USD wallet, amountless invoice" { # Generate invoice - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" usd_wallet_name="$token_name.usd_wallet_id" variables=$( @@ -277,11 +263,12 @@ usd_amount=50 } @test "ln-receive: settles btc-wallet invoices created while trigger down" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" btc_wallet_name="$token_name.btc_wallet_id" # Stop trigger - stop_trigger + touch $TRIGGER_STOP_FILE + retry 10 1 trigger_is_stopped || exit 1 # Generate invoice variables=$( @@ -298,8 +285,8 @@ usd_amount=50 [[ "${payment_hash}" != "null" ]] || exit 1 # Start trigger - start_trigger - sleep 5 + rm $TRIGGER_STOP_FILE + retry 10 1 trigger_is_started # Pay invoice & check for settled lnd_outside_cli payinvoice -f \ @@ -310,11 +297,12 @@ usd_amount=50 } @test "ln-receive: settles usd-wallet invoices created while trigger down" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" usd_wallet_name="$token_name.usd_wallet_id" # Stop trigger - stop_trigger + touch $TRIGGER_STOP_FILE + retry 10 1 trigger_is_stopped || exit 1 # Generate invoice variables=$( @@ -331,8 +319,8 @@ usd_amount=50 [[ "${payment_hash}" != "null" ]] || exit 1 # Start trigger - start_trigger - sleep 5 + rm $TRIGGER_STOP_FILE + retry 10 1 trigger_is_started # Pay invoice & check for settled lnd_outside_cli payinvoice -f \ @@ -343,11 +331,11 @@ usd_amount=50 } @test "ln-receive: settles btc-wallet invoices created & paid while trigger down" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" btc_wallet_name="$token_name.btc_wallet_id" # Stop trigger - stop_trigger + touch $TRIGGER_STOP_FILE # Generate invoice variables=$( @@ -370,18 +358,18 @@ usd_amount=50 & # Start trigger - start_trigger + rm $TRIGGER_STOP_FILE # Check for settled retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" } @test "ln-receive: settles usd-wallet invoices created & paid while trigger down" { - token_name="$ALICE_TOKEN_NAME" + token_name="$ALICE" usd_wallet_name="$token_name.usd_wallet_id" # Stop trigger - stop_trigger + touch $TRIGGER_STOP_FILE # Generate invoice variables=$( @@ -404,7 +392,7 @@ usd_amount=50 & # Start trigger - start_trigger + rm $TRIGGER_STOP_FILE # Check for settled retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" diff --git a/bats/core/api/ln-send.bats b/bats/core/api/ln-send.bats new file mode 100644 index 0000000000..510fc4a2df --- /dev/null +++ b/bats/core/api/ln-send.bats @@ -0,0 +1,621 @@ +#!/usr/bin/env bats + +load "../../helpers/_common.bash" +load "../../helpers/cli.bash" +load "../../helpers/ledger.bash" +load "../../helpers/ln.bash" +load "../../helpers/onchain.bash" +load "../../helpers/user.bash" +load "../../helpers/wallet.bash" + +ALICE='alice' +BOB='bob' + +setup_file() { + clear_cache + + lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + if [[ $lnd1_balance -lt "1000000" ]]; then + create_user 'lnd_funding' + fund_user_lightning 'lnd_funding' 'lnd_funding.btc_wallet_id' '5000000' + fi + + create_user "$ALICE" + user_update_username "$ALICE" + fund_user_onchain "$ALICE" 'btc_wallet' + fund_user_onchain "$ALICE" 'usd_wallet' +} + +teardown() { + if [[ "$(balance_for_check)" != 0 ]]; then + fail "Error: balance_for_check failed" + fi +} + +btc_amount=1000 +usd_amount=50 + +@test "ln-send: lightning settled - lnInvoicePaymentSend from btc" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + + exec_graphql "$token_name" 'ln-invoice-fee-probe' "$variables" + fee_amount="$(graphql_output '.data.lnInvoiceFeeProbe.amount')" + [[ "${fee_amount}" = "0" ]] || exit 1 + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnInvoicePaymentSend from btc, no fee probe" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnInvoicePaymentSend from usd" { + token_name="$ALICE" + usd_wallet_name="$token_name.usd_wallet_id" + + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $usd_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + + exec_graphql "$token_name" 'ln-usd-invoice-fee-probe' "$variables" + fee_amount="$(graphql_output '.data.lnUsdInvoiceFeeProbe.amount')" + [[ "${fee_amount}" = "0" ]] || exit 1 + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnInvoicePaymentSend from usd, no fee probe" { + token_name="$ALICE" + usd_wallet_name="$token_name.usd_wallet_id" + + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $usd_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnNoAmountInvoicePaymentSend" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + --arg amount $btc_amount \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' + ) + + exec_graphql "$token_name" 'ln-no-amount-invoice-fee-probe' "$variables" + fee_amount="$(graphql_output '.data.lnNoAmountInvoiceFeeProbe.amount')" + [[ "${fee_amount}" = "0" ]] || exit 1 + + exec_graphql "$token_name" 'ln-no-amount-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnNoAmountInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnNoAmountInvoicePaymentSend, no fee probe" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + --arg amount $btc_amount \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' + ) + + exec_graphql "$token_name" 'ln-no-amount-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnNoAmountInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnNoAmountUsdInvoicePaymentSend" { + token_name="$ALICE" + usd_wallet_name="$token_name.usd_wallet_id" + + initial_balance="$(balance_for_wallet $token_name 'USD')" + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $usd_wallet_name)" \ + --arg payment_request "$payment_request" \ + --arg amount $usd_amount \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' + ) + + exec_graphql "$token_name" 'ln-no-amount-usd-invoice-fee-probe' "$variables" + fee_amount="$(graphql_output '.data.lnNoAmountUsdInvoiceFeeProbe.amount')" + [[ "${fee_amount}" = "0" ]] || exit 1 + + exec_graphql "$token_name" 'ln-no-amount-usd-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnNoAmountUsdInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_balance="$(balance_for_wallet $token_name 'USD')" + wallet_diff="$(( $initial_balance - $final_balance ))" + [[ "$wallet_diff" == "$usd_amount" ]] || exit 1 + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" -gt "0" ]] || exit 1 +} + +@test "ln-send: lightning settled - lnNoAmountUsdInvoicePaymentSend, no fee probe" { + token_name="$ALICE" + usd_wallet_name="$token_name.usd_wallet_id" + + initial_balance="$(balance_for_wallet $token_name 'USD')" + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + invoice_response="$(lnd_outside_cli addinvoice)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $usd_wallet_name)" \ + --arg payment_request "$payment_request" \ + --arg amount $usd_amount \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' + ) + + exec_graphql "$token_name" 'ln-no-amount-usd-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnNoAmountUsdInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + + final_balance="$(balance_for_wallet $token_name 'USD')" + wallet_diff="$(( $initial_balance - $final_balance ))" + [[ "$wallet_diff" == "$usd_amount" ]] || exit 1 + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" -gt "0" ]] || exit 1 +} + +@test "ln-send: intraledger settled - lnInvoicePaymentSend from btc to btc, with contacts check" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + create_user "$BOB" + user_update_username "$BOB" + bob_btc_wallet_name="$BOB.btc_wallet_id" + + initial_balance="$(balance_for_wallet $token_name 'BTC')" + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + # Check is not contact before send + run is_contact "$token_name" "$BOB" + [[ "$status" -ne "0" ]] || exit 1 + run is_contact "$BOB" "$token_name" + [[ "$status" -ne "0" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $bob_btc_wallet_name)" \ + --arg amount "$btc_amount" \ + '{input: {walletId: $wallet_id, amount: $amount}}' + ) + exec_graphql "$BOB" 'ln-invoice-create' "$variables" + invoice="$(graphql_output '.data.lnInvoiceCreate.invoice')" + + payment_request="$(echo $invoice | jq -r '.paymentRequest')" + [[ "${payment_request}" != "null" ]] || exit 1 + payment_hash="$(echo $invoice | jq -r '.paymentHash')" + [[ "${payment_hash}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + check_for_ln_initiated_settled "$BOB" "$payment_hash" + + final_balance="$(balance_for_wallet $token_name 'BTC')" + wallet_diff="$(( $initial_balance - $final_balance ))" + [[ "$wallet_diff" == "$btc_amount" ]] || exit 1 + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "0" ]] || exit 1 + + # Check is contact after send + run is_contact "$token_name" "$BOB" + [[ "$status" == "0" ]] || exit 1 + run is_contact "$BOB" "$token_name" + [[ "$status" == "0" ]] || exit 1 +} + +@test "ln-send: intraledger settled - lnInvoicePaymentSend from usd to btc" { + token_name="$ALICE" + usd_wallet_name="$token_name.usd_wallet_id" + + create_user "$BOB" + user_update_username "$BOB" + bob_btc_wallet_name="$BOB.btc_wallet_id" + + initial_recipient_balance="$(balance_for_wallet $BOB 'BTC')" + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $bob_btc_wallet_name)" \ + --arg amount "$btc_amount" \ + '{input: {walletId: $wallet_id, amount: $amount}}' + ) + exec_graphql "$BOB" 'ln-invoice-create' "$variables" + invoice="$(graphql_output '.data.lnInvoiceCreate.invoice')" + + payment_request="$(echo $invoice | jq -r '.paymentRequest')" + [[ "${payment_request}" != "null" ]] || exit 1 + payment_hash="$(echo $invoice | jq -r '.paymentHash')" + [[ "${payment_hash}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $usd_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + + exec_graphql "$token_name" 'ln-usd-invoice-fee-probe' "$variables" + fee_amount="$(graphql_output '.data.lnUsdInvoiceFeeProbe.amount')" + [[ "${fee_amount}" = "0" ]] || exit 1 + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + check_for_ln_initiated_settled "$BOB" "$payment_hash" + + final_recipient_balance="$(balance_for_wallet $BOB 'BTC')" + recipient_wallet_diff="$(( $final_recipient_balance - $initial_recipient_balance ))" + [[ "$recipient_wallet_diff" == "$btc_amount" ]] || exit 1 + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "0" ]] || exit 1 +} + +@test "ln-send: intraledger settled - lnNoAmountInvoicePaymentSend from btc to usd" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + create_user "$BOB" + user_update_username "$BOB" + bob_usd_wallet_name="$BOB.usd_wallet_id" + + initial_balance="$(balance_for_wallet $token_name 'BTC')" + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $bob_usd_wallet_name)" \ + '{input: {walletId: $wallet_id}}' + ) + exec_graphql "$BOB" 'ln-no-amount-invoice-create' "$variables" + invoice="$(graphql_output '.data.lnNoAmountInvoiceCreate.invoice')" + + payment_request="$(echo $invoice | jq -r '.paymentRequest')" + [[ "${payment_request}" != "null" ]] || exit 1 + payment_hash="$(echo $invoice | jq -r '.paymentHash')" + [[ "${payment_hash}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + --arg amount $btc_amount \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' + ) + + exec_graphql "$token_name" 'ln-no-amount-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnNoAmountInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + check_for_ln_initiated_settled "$BOB" "$payment_hash" + + final_balance="$(balance_for_wallet $token_name 'BTC')" + wallet_diff="$(( $initial_balance - $final_balance ))" + [[ "$wallet_diff" == "$btc_amount" ]] || exit 1 + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "0" ]] || exit 1 +} + +@test "ln-send: intraledger settled - lnNoAmountUsdInvoicePaymentSend from usd to usd" { + token_name="$ALICE" + usd_wallet_name="$token_name.usd_wallet_id" + + create_user "$BOB" + user_update_username "$BOB" + bob_usd_wallet_name="$BOB.usd_wallet_id" + + initial_balance="$(balance_for_wallet $token_name 'USD')" + initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $bob_usd_wallet_name)" \ + '{input: {walletId: $wallet_id}}' + ) + exec_graphql "$BOB" 'ln-no-amount-invoice-create' "$variables" + invoice="$(graphql_output '.data.lnNoAmountInvoiceCreate.invoice')" + + payment_request="$(echo $invoice | jq -r '.paymentRequest')" + [[ "${payment_request}" != "null" ]] || exit 1 + payment_hash="$(echo $invoice | jq -r '.paymentHash')" + [[ "${payment_hash}" != "null" ]] || exit 1 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $usd_wallet_name)" \ + --arg payment_request "$payment_request" \ + --arg amount $usd_amount \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' + ) + + exec_graphql "$token_name" 'ln-no-amount-usd-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnNoAmountUsdInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + # Check for settled + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" + check_for_ln_initiated_settled "$BOB" "$payment_hash" + + final_balance="$(balance_for_wallet $token_name 'USD')" + wallet_diff="$(( $initial_balance - $final_balance ))" + [[ "$wallet_diff" == "$usd_amount" ]] || exit 1 + + final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') + lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" + [[ "$lnd1_diff" == "0" ]] || exit 1 +} + +@test "ln-send: ln settled - settle failed and then successful payment" { + token_name="$ALICE" + btc_wallet_name="$token_name.btc_wallet_id" + + threshold_amount=150000 + invoice_response="$(lnd_outside_2_cli addinvoice --amt $threshold_amount)" + payment_request="$(echo $invoice_response | jq -r '.payment_request')" + payment_hash=$(echo $invoice_response | jq -r '.r_hash') + [[ "${payment_request}" != "null" ]] || exit 1 + + check_num_txns() { + expected_num="$1" + + num_txns="$(num_txns_for_hash "$token_name" "$payment_hash")" + [[ "$num_txns" == "$expected_num" ]] || exit 1 + } + + # Rebalance last hop so payment will fail + rebalance_channel lnd_outside_cli lnd_outside_2_cli "$(( $threshold_amount - 1 ))" + + # Try payment and check for fail + initial_balance="$(balance_for_wallet $token_name 'BTC')" + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' + ) + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + error_msg="$(graphql_output '.data.lnInvoicePaymentSend.errors[0].message')" + [[ "${send_status}" = "FAILURE" ]] || exit 1 + [[ "${error_msg}" == "Unable to find a route for payment." ]] || exit 1 + + # Check for txns + retry 15 1 check_num_txns "2" + balance_after_fail="$(balance_for_wallet $token_name 'BTC')" + [[ "$initial_balance" == "$balance_after_fail" ]] || exit 1 + + # Rebalance last hop so same payment will succeed + rebalance_channel lnd_outside_cli lnd_outside_2_cli "$(( $threshold_amount * 2 ))" + lnd_cli resetmc + + # Retry payment and check for success + exec_graphql "$token_name" 'ln-invoice-fee-probe' "$variables" + num_errors="$(graphql_output '.data.lnInvoiceFeeProbe.errors | length')" + fee_amount="$(graphql_output '.data.lnInvoiceFeeProbe.amount')" + [[ "$num_errors" == "0" ]] || exit 1 + [[ "${fee_amount}" -gt "0" ]] || exit 1 + + exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" + send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" + [[ "${send_status}" = "SUCCESS" ]] || exit 1 + + transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" + [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 + + transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" + [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 + + # Check for txns + retry 15 1 check_num_txns "3" + balance_after_success="$(balance_for_wallet $token_name 'BTC')" + [[ "$balance_after_success" -lt "$initial_balance" ]] || exit 1 +} diff --git a/bats/gql/callback-endpoint-add.gql b/bats/gql/callback-endpoint-add.gql new file mode 100644 index 0000000000..0b5f7ee9b0 --- /dev/null +++ b/bats/gql/callback-endpoint-add.gql @@ -0,0 +1,8 @@ +mutation callbackEndpointAdd($input: CallbackEndpointAddInput!) { + callbackEndpointAdd(input: $input) { + errors { + message + } + id + } +} diff --git a/bats/gql/invoice-for-wallet-by-payment-hash.gql b/bats/gql/invoice-for-wallet-by-payment-hash.gql new file mode 100644 index 0000000000..147bb65714 --- /dev/null +++ b/bats/gql/invoice-for-wallet-by-payment-hash.gql @@ -0,0 +1,17 @@ +query me($walletId: WalletId!, $paymentHash: PaymentHash!) { + me { + defaultAccount { + id + walletById(walletId: $walletId) { + id + invoiceByPaymentHash(paymentHash: $paymentHash) { + paymentHash + paymentStatus + ... on LnInvoice { + satoshis + } + } + } + } + } +} diff --git a/bats/gql/ln-invoice-create.gql b/bats/gql/ln-invoice-create.gql new file mode 100644 index 0000000000..3e3a27d0a0 --- /dev/null +++ b/bats/gql/ln-invoice-create.gql @@ -0,0 +1,11 @@ +mutation lnInvoiceCreateInput($input: LnInvoiceCreateInput!) { + lnInvoiceCreate(input: $input) { + invoice { + paymentRequest + paymentHash + } + errors { + message + } + } +} diff --git a/bats/gql/ln-invoice-fee-probe.gql b/bats/gql/ln-invoice-fee-probe.gql new file mode 100644 index 0000000000..3064f585df --- /dev/null +++ b/bats/gql/ln-invoice-fee-probe.gql @@ -0,0 +1,8 @@ +mutation LnInvoiceFeeProbe($input: LnInvoiceFeeProbeInput!) { + lnInvoiceFeeProbe(input: $input) { + errors { + message + } + amount + } +} diff --git a/bats/gql/ln-invoice-payment-send.gql b/bats/gql/ln-invoice-payment-send.gql new file mode 100644 index 0000000000..b34a5ab400 --- /dev/null +++ b/bats/gql/ln-invoice-payment-send.gql @@ -0,0 +1,16 @@ +mutation lnInvoicePaymentSend($input: LnInvoicePaymentInput!) { + lnInvoicePaymentSend(input: $input) { + errors { + message + } + status + transaction { + initiationVia { + ... on InitiationViaLn { + paymentHash + paymentRequest + } + } + } + } +} diff --git a/bats/gql/ln-no-amount-invoice-create.gql b/bats/gql/ln-no-amount-invoice-create.gql new file mode 100644 index 0000000000..ac03667394 --- /dev/null +++ b/bats/gql/ln-no-amount-invoice-create.gql @@ -0,0 +1,11 @@ +mutation lnNoAmountInvoiceCreate($input: LnNoAmountInvoiceCreateInput!) { + lnNoAmountInvoiceCreate(input: $input) { + invoice { + paymentRequest + paymentHash + } + errors { + message + } + } +} diff --git a/bats/gql/ln-no-amount-invoice-fee-probe.gql b/bats/gql/ln-no-amount-invoice-fee-probe.gql new file mode 100644 index 0000000000..cbd12026ac --- /dev/null +++ b/bats/gql/ln-no-amount-invoice-fee-probe.gql @@ -0,0 +1,8 @@ +mutation lnNoAmountInvoiceFeeProbe($input: LnNoAmountInvoiceFeeProbeInput!) { + lnNoAmountInvoiceFeeProbe(input: $input) { + errors { + message + } + amount + } +} diff --git a/bats/gql/ln-no-amount-invoice-payment-send.gql b/bats/gql/ln-no-amount-invoice-payment-send.gql new file mode 100644 index 0000000000..7131b589b4 --- /dev/null +++ b/bats/gql/ln-no-amount-invoice-payment-send.gql @@ -0,0 +1,8 @@ +mutation lnNoAmountInvoicePaymentSend($input: LnNoAmountInvoicePaymentInput!) { + lnNoAmountInvoicePaymentSend(input: $input) { + errors { + message + } + status + } +} diff --git a/bats/gql/ln-no-amount-usd-invoice-fee-probe.gql b/bats/gql/ln-no-amount-usd-invoice-fee-probe.gql new file mode 100644 index 0000000000..00bde20e62 --- /dev/null +++ b/bats/gql/ln-no-amount-usd-invoice-fee-probe.gql @@ -0,0 +1,8 @@ +mutation lnNoAmountUsdInvoiceFeeProbe($input: LnNoAmountUsdInvoiceFeeProbeInput!) { + lnNoAmountUsdInvoiceFeeProbe(input: $input) { + errors { + message + } + amount + } +} diff --git a/bats/gql/ln-no-amount-usd-invoice-payment-send.gql b/bats/gql/ln-no-amount-usd-invoice-payment-send.gql new file mode 100644 index 0000000000..a34ccee880 --- /dev/null +++ b/bats/gql/ln-no-amount-usd-invoice-payment-send.gql @@ -0,0 +1,8 @@ +mutation lnNoAmountUsdInvoicePaymentSend($input: LnNoAmountUsdInvoicePaymentInput!) { + lnNoAmountUsdInvoicePaymentSend(input: $input) { + errors { + message + } + status + } +} diff --git a/bats/gql/ln-usd-invoice-create.gql b/bats/gql/ln-usd-invoice-create.gql new file mode 100644 index 0000000000..270e9ef009 --- /dev/null +++ b/bats/gql/ln-usd-invoice-create.gql @@ -0,0 +1,11 @@ +mutation lnUsdInvoiceCreate($input: LnUsdInvoiceCreateInput!) { + lnUsdInvoiceCreate(input: $input) { + invoice { + paymentRequest + paymentHash + } + errors { + message + } + } +} diff --git a/bats/gql/ln-usd-invoice-fee-probe.gql b/bats/gql/ln-usd-invoice-fee-probe.gql new file mode 100644 index 0000000000..1508e144aa --- /dev/null +++ b/bats/gql/ln-usd-invoice-fee-probe.gql @@ -0,0 +1,8 @@ +mutation lnUsdInvoiceFeeProbe($input: LnUsdInvoiceFeeProbeInput!) { + lnUsdInvoiceFeeProbe(input: $input) { + errors { + message + } + amount + } +} diff --git a/bats/gql/transaction-for-wallet-by-id.gql b/bats/gql/transaction-for-wallet-by-id.gql new file mode 100644 index 0000000000..2fbf247a24 --- /dev/null +++ b/bats/gql/transaction-for-wallet-by-id.gql @@ -0,0 +1,55 @@ +query transactionForWalletById($walletId: WalletId!, $transactionId: ID!) { + me { + defaultAccount { + id + displayCurrency + walletById(walletId: $walletId) { + transactionById(transactionId: $transactionId) { + __typename + id + status + direction + memo + createdAt + settlementAmount + settlementFee + settlementDisplayAmount + settlementDisplayFee + settlementDisplayCurrency + settlementCurrency + settlementPrice { + base + offset + } + initiationVia { + __typename + ... on InitiationViaIntraLedger { + counterPartyWalletId + counterPartyUsername + } + ... on InitiationViaLn { + paymentHash + paymentRequest + } + ... on InitiationViaOnChain { + address + } + } + settlementVia { + __typename + ... on SettlementViaIntraLedger { + counterPartyWalletId + counterPartyUsername + } + ... on SettlementViaLn { + preImage + } + ... on SettlementViaOnChain { + transactionHash + } + } + } + } + } + } +} diff --git a/bats/gql/transactions-for-wallet-by-payment-hash.gql b/bats/gql/transactions-for-wallet-by-payment-hash.gql new file mode 100644 index 0000000000..f90d1c7af9 --- /dev/null +++ b/bats/gql/transactions-for-wallet-by-payment-hash.gql @@ -0,0 +1,58 @@ +query transactionsForWalletByPaymentHash( + $walletId: WalletId! + $paymentHash: PaymentHash! +) { + me { + defaultAccount { + displayCurrency + walletById(walletId: $walletId) { + id + transactionsByPaymentHash(paymentHash: $paymentHash) { + __typename + id + status + direction + memo + createdAt + settlementAmount + settlementFee + settlementDisplayAmount + settlementDisplayFee + settlementDisplayCurrency + settlementCurrency + settlementPrice { + base + offset + } + initiationVia { + __typename + ... on InitiationViaIntraLedger { + counterPartyWalletId + counterPartyUsername + } + ... on InitiationViaLn { + paymentHash + paymentRequest + } + ... on InitiationViaOnChain { + address + } + } + settlementVia { + __typename + ... on SettlementViaIntraLedger { + counterPartyWalletId + counterPartyUsername + } + ... on SettlementViaLn { + preImage + } + ... on SettlementViaOnChain { + transactionHash + } + } + } + } + } + } +} diff --git a/bats/helpers/_common.bash b/bats/helpers/_common.bash index bc5cb1a930..60dce70142 100644 --- a/bats/helpers/_common.bash +++ b/bats/helpers/_common.bash @@ -4,6 +4,8 @@ export BATS_ROOT_DIR="${REPO_ROOT}/bats" CACHE_DIR=${BATS_TMPDIR:-tmp/bats}/galoy-bats-cache mkdir -p "$CACHE_DIR" +TILT_LOG_FILE="${REPO_ROOT}/bats/.e2e-tilt.log" + OATHKEEPER_PROXY=${OATHKEEPER_PROXY:-localhost:4455} if ! type fail &>/dev/null; then @@ -135,3 +137,8 @@ cache_value() { read_value() { cat ${CACHE_DIR}/$1 } + +clear_cache() { + rm -r ${CACHE_DIR} + mkdir -p ${CACHE_DIR} +} diff --git a/bats/helpers/callback.bash b/bats/helpers/callback.bash new file mode 100644 index 0000000000..1eb6e89b94 --- /dev/null +++ b/bats/helpers/callback.bash @@ -0,0 +1,17 @@ +CURRENT_FILE=${BASH_SOURCE:-bats/helpers/.} +source "$(dirname "$CURRENT_FILE")/_common.bash" + +add_callback() { + local token_name=$1 + + local variables=$( + jq -n \ + --arg url "$SVIX_CALLBACK_URL" \ + '{input: {url: $url}}' + ) + exec_graphql "$token_name" 'callback-endpoint-add' "$variables" +} + +cat_callback() { + cat "$TILT_LOG_FILE" | grep 'callback │ ' +} diff --git a/bats/helpers/callback/BUCK b/bats/helpers/callback/BUCK new file mode 100644 index 0000000000..3b3edbff06 --- /dev/null +++ b/bats/helpers/callback/BUCK @@ -0,0 +1,9 @@ +load( + "@toolchains//workspace-pnpm:macros.bzl", + "dev_pnpm_task_binary", +) + +dev_pnpm_task_binary( + name = "run", + command = "callback", +) diff --git a/bats/helpers/callback/index.ts b/bats/helpers/callback/index.ts new file mode 100644 index 0000000000..41b793102b --- /dev/null +++ b/bats/helpers/callback/index.ts @@ -0,0 +1,22 @@ +import http from "http" + +const PORT: number = 8080 + +const server: http.Server = http.createServer( + (req: http.IncomingMessage, res: http.ServerResponse) => { + let body: Buffer[] = [] + req + .on("data", (chunk: Buffer) => { + body.push(chunk) + }) + .on("end", () => { + const parsedBody: string = Buffer.concat(body).toString() + console.log(parsedBody) + res.end("Received") + }) + }, +) + +server.listen(PORT, () => { + console.error(`Server listening on port ${PORT}`) +}) diff --git a/bats/helpers/callback/package.json b/bats/helpers/callback/package.json new file mode 100644 index 0000000000..86731e64cd --- /dev/null +++ b/bats/helpers/callback/package.json @@ -0,0 +1,10 @@ +{ + "name": "callback", + "scripts": { + "callback": "tsx index.ts" + }, + "devDependencies": { + "@types/node": "^20.8.7", + "tsx": "^4.2.0" + } +} diff --git a/bats/helpers/callback/pnpm-lock.yaml b/bats/helpers/callback/pnpm-lock.yaml new file mode 100644 index 0000000000..2d6062e6f0 --- /dev/null +++ b/bats/helpers/callback/pnpm-lock.yaml @@ -0,0 +1,285 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@types/node': + specifier: ^20.8.7 + version: 20.10.4 + tsx: + specifier: ^4.2.0 + version: 4.6.2 + +packages: + + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@types/node@20.10.4: + resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==} + dependencies: + undici-types: 5.26.5 + dev: true + + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /tsx@4.6.2: + resolution: {integrity: sha512-QPpBdJo+ZDtqZgAnq86iY/PD2KYCUPSUGIunHdGwyII99GKH+f3z3FZ8XNFLSGQIA4I365ui8wnQpl8OKLqcsg==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.18.20 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true diff --git a/bats/helpers/callback/pnpm-workspace.yaml b/bats/helpers/callback/pnpm-workspace.yaml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/bats/helpers/callback/pnpm-workspace.yaml @@ -0,0 +1 @@ +--- diff --git a/bats/helpers/callback/prettier.config.js b/bats/helpers/callback/prettier.config.js new file mode 100644 index 0000000000..e6236cf0be --- /dev/null +++ b/bats/helpers/callback/prettier.config.js @@ -0,0 +1,15 @@ +module.exports = { + // Custom: + semi: false, + trailingComma: "all", + printWidth: 90, + quoteProps: "consistent", + // Defaults: + singleQuote: false, + tabWidth: 2, + useTabs: false, + bracketSpacing: true, + arrowParens: "always", + proseWrap: "preserve", + endOfLine: "lf", +} diff --git a/bats/helpers/cli.bash b/bats/helpers/cli.bash index fecdc9fec7..28032c6ca9 100644 --- a/bats/helpers/cli.bash +++ b/bats/helpers/cli.bash @@ -1,3 +1,5 @@ +LNDS_REST_LOG=".e2e-lnds-rest.log" + bitcoin_cli() { docker exec "${COMPOSE_PROJECT_NAME}-bitcoind-1" bitcoin-cli $@ } @@ -10,6 +12,42 @@ lnd_cli() { $@ } +lnd_outside_cli() { + docker exec "${COMPOSE_PROJECT_NAME}-lnd-outside-1-1" \ + lncli \ + --macaroonpath /root/.lnd/admin.macaroon \ + --tlscertpath /root/.lnd/tls.cert \ + $@ +} + +lnd_outside_rest() { + local route=$1 + local endpoint="https://localhost:8080/$route" + + local data=$2 + + local macaroon_hex=$( + docker exec "${COMPOSE_PROJECT_NAME}-lnd-outside-1-1" \ + xxd -p -c 10000 /root/.lnd/admin.macaroon + ) + + docker exec "${COMPOSE_PROJECT_NAME}-lnd-outside-1-1" \ + curl -s \ + --cacert /root/.lnd/tls.cert \ + -H "Grpc-Metadata-macaroon: $macaroon_hex" \ + ${data:+ -X POST -d $data} \ + "$endpoint" \ + > "$LNDS_REST_LOG" +} + +lnd_outside_2_cli() { + docker exec "${COMPOSE_PROJECT_NAME}-lnd-outside-2-1" \ + lncli \ + --macaroonpath /root/.lnd/admin.macaroon \ + --tlscertpath /root/.lnd/tls.cert \ + $@ +} + bria_cli() { docker exec "${COMPOSE_PROJECT_NAME}-bria-1" bria $@ } @@ -21,3 +59,7 @@ tilt_cli() { mongo_cli() { docker exec "${COMPOSE_PROJECT_NAME}-mongodb-1" mongosh --quiet mongodb://localhost:27017/galoy --eval $@ } + +redis_cli() { + docker exec "${COMPOSE_PROJECT_NAME}-redis-1" redis-cli $@ +} diff --git a/bats/helpers/ln.bash b/bats/helpers/ln.bash index e068c3859c..3cf7569118 100644 --- a/bats/helpers/ln.bash +++ b/bats/helpers/ln.bash @@ -2,6 +2,8 @@ CURRENT_FILE=${BASH_SOURCE:-bats/helpers/.} source "$(dirname "$CURRENT_FILE")/_common.bash" source "$(dirname "$CURRENT_FILE")/cli.bash" +export SUBSCRIBER_LOG_FILE="${BATS_ROOT_DIR}/.e2e-subscriber.log" + create_new_lnd_onchain_address() { local wallet_name=$1 local wallet_id=$(read_value $wallet_name) @@ -31,3 +33,159 @@ create_new_lnd_onchain_address() { echo $address } + +get_from_transaction_by_ln_hash_and_status() { + payment_hash="$1" + expected_status="$2" + property_query="$3" + + jq_query=' + .data.me.defaultAccount.transactions.edges[] + | select(.node.initiationVia.paymentHash == $payment_hash) + | select(.node.status == $expected_status) + .node' + + echo $output \ + | jq -r \ + --arg payment_hash "$payment_hash" \ + --arg expected_status "$expected_status" \ + "$jq_query" \ + | jq -r "$property_query" \ + | head -n 1 +} + +check_for_ln_initiated_status() { + local expected_status=$1 + local token_name=$2 + local payment_hash=$3 + local first=${4:-"2"} + + variables=$( + jq -n \ + --argjson first "$first" \ + '{"first": $first}' + ) + exec_graphql "$token_name" 'transactions' "$variables" + + status="$(get_from_transaction_by_ln_hash_and_status $payment_hash $expected_status '.status')" + [[ "${status}" == "${expected_status}" ]] || return 1 +} + +check_for_ln_initiated_settled() { + check_for_ln_initiated_status "SUCCESS" "$@" +} + +check_for_ln_update() { + payment_hash=$1 + + retry 10 1 \ + grep "Data.*LnUpdate.*$payment_hash" "$SUBSCRIBER_LOG_FILE" \ + | awk '{print $2}' \ + | jq -r --arg hash "$payment_hash" 'select(.data.myUpdates.update.paymentHash == $hash)' \ + || exit 1 + + paid_status=$( \ + grep 'Data.*LnUpdate' "$SUBSCRIBER_LOG_FILE" \ + | awk '{print $2}' \ + | jq -r --arg hash "$payment_hash" 'select(.data.myUpdates.update.paymentHash == $hash) .data.myUpdates.update.status' + ) + + [[ "$paid_status" == "PAID" ]] || exit 1 +} + +fund_user_lightning() { + local token_name=$1 + local wallet_id_name=$2 + local amount=$3 + + variables=$( + jq -n \ + --arg wallet_id "$(read_value $wallet_id_name)" \ + '{input: {walletId: $wallet_id}}' + ) + exec_graphql "$token_name" 'ln-no-amount-invoice-create' "$variables" + invoice="$(graphql_output '.data.lnNoAmountInvoiceCreate.invoice')" + + payment_request="$(echo $invoice | jq -r '.paymentRequest')" + [[ "${payment_request}" != "null" ]] + payment_hash="$(echo $invoice | jq -r '.paymentHash')" + [[ "${payment_hash}" != "null" ]] + + lnd_outside_cli payinvoice -f \ + --pay_req "$payment_request" \ + --amt "$amount" + + retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" +} + +run_with_lnd() { + local func_name="$1" + shift # This will shift away the function name, so $1 becomes the next argument + + if [[ "$func_name" == "lnd_cli" ]]; then + lnd_cli "$@" + elif [[ "$func_name" == "lnd_outside_cli" ]]; then + lnd_outside_cli "$@" + elif [[ "$func_name" == "lnd_outside_2_cli" ]]; then + lnd_outside_2_cli "$@" + else + echo "Invalid function name passed!" && return 1 + fi +} + +rebalance_channel() { + lnd_cli_value="$1" + lnd_partner_cli_value="$2" + target_local_balance="$3" + + local_pubkey="$(run_with_lnd $lnd_cli_value getinfo | jq -r '.identity_pubkey')" + remote_pubkey="$(run_with_lnd $lnd_partner_cli_value getinfo | jq -r '.identity_pubkey')" + + partner_channel_filter=' + [ + .channels[]? + | select(.remote_pubkey == $remote_pubkey) + ] | first + ' + + channel=$( + run_with_lnd "$lnd_cli_value" listchannels \ + | jq -r \ + --arg remote_pubkey "$remote_pubkey" \ + "$partner_channel_filter" + ) + [[ "$channel" != "null" ]] + + actual_local_balance=$(echo $channel | jq -r '.local_balance') + diff="$(( $actual_local_balance - $target_local_balance ))" + if [[ "$diff" -gt 0 ]]; then + run_with_lnd "$lnd_cli_value" sendpayment --dest=$remote_pubkey --amt=$diff --keysend + elif [[ "$diff" -lt 0 ]]; then + run_with_lnd "$lnd_partner_cli_value" sendpayment --dest=$local_pubkey --amt="$(abs $diff)" --keysend + fi +} + +num_txns_for_hash() { + token_name="$1" + payment_hash="$2" + + first=20 + txn_variables=$( + jq -n \ + --argjson first "$first" \ + '{"first": $first}' + ) + exec_graphql "$token_name" 'transactions' "$txn_variables" > /dev/null + + jq_query=' + [ + .data.me.defaultAccount.transactions.edges[] + | select(.node.initiationVia.paymentHash == $payment_hash) + ] + | length + ' + echo $output \ + | jq -r \ + --arg payment_hash "$payment_hash" \ + "$jq_query" +} diff --git a/bats/helpers/subscriber.bash b/bats/helpers/subscriber.bash index 2b2c54d599..622b3f0270 100644 --- a/bats/helpers/subscriber.bash +++ b/bats/helpers/subscriber.bash @@ -29,3 +29,7 @@ stop_subscriber() { [[ -f "$SUBSCRIBER_PID_FILE" ]] && kill $(cat $SUBSCRIBER_PID_FILE) > /dev/null || true } +subscriber_is_up() { + grep "Data:" "$SUBSCRIBER_LOG_FILE" + return "$?" +} diff --git a/bats/helpers/trigger.bash b/bats/helpers/trigger.bash new file mode 100644 index 0000000000..d7be8bdd69 --- /dev/null +++ b/bats/helpers/trigger.bash @@ -0,0 +1,26 @@ +CURRENT_FILE=${BASH_SOURCE:-bats/helpers/.} +source "$(dirname "$CURRENT_FILE")/_common.bash" + +TRIGGER_STOP_FILE="$BATS_ROOT_DIR/.stop_trigger" + +trigger_is_stopped() { + local NUM_LINES=2 + cat $TILT_LOG_FILE | grep 'api-trigger │' \ + | tail -n $NUM_LINES \ + | grep "Successfully stopped trigger" + + return "$?" +} + +trigger_is_started() { + local NUM_LINES=18 + cat $TILT_LOG_FILE | grep 'api-trigger │' \ + | tail -n $NUM_LINES \ + | grep "Successfully stopped trigger" + + if [[ "$?" == "0" ]]; then + return 1 + else + return 0 + fi +} diff --git a/core/api/test/bats/ln-send.bats b/core/api/test/bats/ln-send.bats index 5b9d29ea89..2cd0f30982 100644 --- a/core/api/test/bats/ln-send.bats +++ b/core/api/test/bats/ln-send.bats @@ -33,624 +33,9 @@ teardown() { fi } -amount_sent_for_ln_txn_by_hash() { - token_name="$1" - payment_hash="$2" - - first=20 - txn_variables=$( - jq -n \ - --argjson first "$first" \ - '{"first": $first}' - ) - exec_graphql "$token_name" 'transactions' "$txn_variables" > /dev/null - - jq_query=' - [ - .data.me.defaultAccount.transactions.edges[] - | select(.node.initiationVia.paymentHash == $payment_hash) - | select(.node.direction == "SEND") - ] - | first .node.settlementAmount - ' - local amount=$(echo $output \ - | jq -r \ - --arg payment_hash "$payment_hash" \ - "$jq_query" - ) - abs $amount -} - btc_amount=1000 usd_amount=50 -@test "ln-send: lightning settled - lnInvoicePaymentSend from btc" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - - exec_graphql "$token_name" 'ln-invoice-fee-probe' "$variables" - fee_amount="$(graphql_output '.data.lnInvoiceFeeProbe.amount')" - [[ "${fee_amount}" = "0" ]] || exit 1 - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnInvoicePaymentSend from btc, no fee probe" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnInvoicePaymentSend from usd" { - token_name="$ALICE_TOKEN_NAME" - usd_wallet_name="$token_name.usd_wallet_id" - - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - - exec_graphql "$token_name" 'ln-usd-invoice-fee-probe' "$variables" - fee_amount="$(graphql_output '.data.lnUsdInvoiceFeeProbe.amount')" - [[ "${fee_amount}" = "0" ]] || exit 1 - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnInvoicePaymentSend from usd, no fee probe" { - token_name="$ALICE_TOKEN_NAME" - usd_wallet_name="$token_name.usd_wallet_id" - - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice --amt $btc_amount)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnNoAmountInvoicePaymentSend" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - --arg amount $btc_amount \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' - ) - - exec_graphql "$token_name" 'ln-no-amount-invoice-fee-probe' "$variables" - fee_amount="$(graphql_output '.data.lnNoAmountInvoiceFeeProbe.amount')" - [[ "${fee_amount}" = "0" ]] || exit 1 - - exec_graphql "$token_name" 'ln-no-amount-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnNoAmountInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnNoAmountInvoicePaymentSend, no fee probe" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - --arg amount $btc_amount \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' - ) - - exec_graphql "$token_name" 'ln-no-amount-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnNoAmountInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "$btc_amount" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnNoAmountUsdInvoicePaymentSend" { - token_name="$ALICE_TOKEN_NAME" - usd_wallet_name="$token_name.usd_wallet_id" - - initial_balance="$(balance_for_wallet $token_name 'USD')" - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_wallet_name)" \ - --arg payment_request "$payment_request" \ - --arg amount $usd_amount \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' - ) - - exec_graphql "$token_name" 'ln-no-amount-usd-invoice-fee-probe' "$variables" - fee_amount="$(graphql_output '.data.lnNoAmountUsdInvoiceFeeProbe.amount')" - [[ "${fee_amount}" = "0" ]] || exit 1 - - exec_graphql "$token_name" 'ln-no-amount-usd-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnNoAmountUsdInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_balance="$(balance_for_wallet $token_name 'USD')" - wallet_diff="$(( $initial_balance - $final_balance ))" - [[ "$wallet_diff" == "$usd_amount" ]] || exit 1 - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" -gt "0" ]] || exit 1 -} - -@test "ln-send: lightning settled - lnNoAmountUsdInvoicePaymentSend, no fee probe" { - token_name="$ALICE_TOKEN_NAME" - usd_wallet_name="$token_name.usd_wallet_id" - - initial_balance="$(balance_for_wallet $token_name 'USD')" - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - invoice_response="$(lnd_outside_cli addinvoice)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_wallet_name)" \ - --arg payment_request "$payment_request" \ - --arg amount $usd_amount \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' - ) - - exec_graphql "$token_name" 'ln-no-amount-usd-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnNoAmountUsdInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - - final_balance="$(balance_for_wallet $token_name 'USD')" - wallet_diff="$(( $initial_balance - $final_balance ))" - [[ "$wallet_diff" == "$usd_amount" ]] || exit 1 - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" -gt "0" ]] || exit 1 -} - -@test "ln-send: intraledger settled - lnInvoicePaymentSend from btc to btc, with contacts check" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - recipient_token_name="user_$RANDOM" - recipient_phone="$(random_phone)" - login_user \ - "$recipient_token_name" \ - "$recipient_phone" \ - "$CODE" - user_update_username "$recipient_token_name" - btc_recipient_wallet_name="$recipient_token_name.btc_wallet_id" - - initial_balance="$(balance_for_wallet $token_name 'BTC')" - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - # Check is not contact before send - run is_contact "$token_name" "$recipient_token_name" - [[ "$status" -ne "0" ]] || exit 1 - run is_contact "$recipient_token_name" "$token_name" - [[ "$status" -ne "0" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_recipient_wallet_name)" \ - --arg amount "$btc_amount" \ - '{input: {walletId: $wallet_id, amount: $amount}}' - ) - exec_graphql "$recipient_token_name" 'ln-invoice-create' "$variables" - invoice="$(graphql_output '.data.lnInvoiceCreate.invoice')" - - payment_request="$(echo $invoice | jq -r '.paymentRequest')" - [[ "${payment_request}" != "null" ]] || exit 1 - payment_hash="$(echo $invoice | jq -r '.paymentHash')" - [[ "${payment_hash}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - check_for_ln_initiated_settled "$recipient_token_name" "$payment_hash" - - final_balance="$(balance_for_wallet $token_name 'BTC')" - wallet_diff="$(( $initial_balance - $final_balance ))" - [[ "$wallet_diff" == "$btc_amount" ]] || exit 1 - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "0" ]] || exit 1 - - # Check is contact after send - run is_contact "$token_name" "$recipient_token_name" - [[ "$status" == "0" ]] || exit 1 - run is_contact "$recipient_token_name" "$token_name" - [[ "$status" == "0" ]] || exit 1 -} - -@test "ln-send: intraledger settled - lnInvoicePaymentSend from usd to btc" { - token_name="$ALICE_TOKEN_NAME" - usd_wallet_name="$token_name.usd_wallet_id" - - recipient_token_name="$BOB_TOKEN_NAME" - btc_recipient_wallet_name="$recipient_token_name.btc_wallet_id" - - initial_recipient_balance="$(balance_for_wallet $recipient_token_name 'BTC')" - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_recipient_wallet_name)" \ - --arg amount "$btc_amount" \ - '{input: {walletId: $wallet_id, amount: $amount}}' - ) - exec_graphql "$recipient_token_name" 'ln-invoice-create' "$variables" - invoice="$(graphql_output '.data.lnInvoiceCreate.invoice')" - - payment_request="$(echo $invoice | jq -r '.paymentRequest')" - [[ "${payment_request}" != "null" ]] || exit 1 - payment_hash="$(echo $invoice | jq -r '.paymentHash')" - [[ "${payment_hash}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - - exec_graphql "$token_name" 'ln-usd-invoice-fee-probe' "$variables" - fee_amount="$(graphql_output '.data.lnUsdInvoiceFeeProbe.amount')" - [[ "${fee_amount}" = "0" ]] || exit 1 - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - check_for_ln_initiated_settled "$recipient_token_name" "$payment_hash" - - final_recipient_balance="$(balance_for_wallet $recipient_token_name 'BTC')" - recipient_wallet_diff="$(( $final_recipient_balance - $initial_recipient_balance ))" - [[ "$recipient_wallet_diff" == "$btc_amount" ]] || exit 1 - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "0" ]] || exit 1 -} - -@test "ln-send: intraledger settled - lnNoAmountInvoicePaymentSend from btc to usd" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - recipient_token_name="$BOB_TOKEN_NAME" - usd_recipient_wallet_name="$recipient_token_name.usd_wallet_id" - - initial_balance="$(balance_for_wallet $token_name 'BTC')" - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_recipient_wallet_name)" \ - '{input: {walletId: $wallet_id}}' - ) - exec_graphql "$recipient_token_name" 'ln-no-amount-invoice-create' "$variables" - invoice="$(graphql_output '.data.lnNoAmountInvoiceCreate.invoice')" - - payment_request="$(echo $invoice | jq -r '.paymentRequest')" - [[ "${payment_request}" != "null" ]] || exit 1 - payment_hash="$(echo $invoice | jq -r '.paymentHash')" - [[ "${payment_hash}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - --arg amount $btc_amount \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' - ) - - exec_graphql "$token_name" 'ln-no-amount-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnNoAmountInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - check_for_ln_initiated_settled "$recipient_token_name" "$payment_hash" - - final_balance="$(balance_for_wallet $token_name 'BTC')" - wallet_diff="$(( $initial_balance - $final_balance ))" - [[ "$wallet_diff" == "$btc_amount" ]] || exit 1 - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "0" ]] || exit 1 -} - -@test "ln-send: intraledger settled - lnNoAmountUsdInvoicePaymentSend from usd to usd" { - token_name="$ALICE_TOKEN_NAME" - usd_wallet_name="$token_name.usd_wallet_id" - - recipient_token_name="$BOB_TOKEN_NAME" - usd_recipient_wallet_name="$recipient_token_name.usd_wallet_id" - - initial_balance="$(balance_for_wallet $token_name 'USD')" - initial_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_recipient_wallet_name)" \ - '{input: {walletId: $wallet_id}}' - ) - exec_graphql "$recipient_token_name" 'ln-no-amount-invoice-create' "$variables" - invoice="$(graphql_output '.data.lnNoAmountInvoiceCreate.invoice')" - - payment_request="$(echo $invoice | jq -r '.paymentRequest')" - [[ "${payment_request}" != "null" ]] || exit 1 - payment_hash="$(echo $invoice | jq -r '.paymentHash')" - [[ "${payment_hash}" != "null" ]] || exit 1 - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $usd_wallet_name)" \ - --arg payment_request "$payment_request" \ - --arg amount $usd_amount \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request, amount: $amount}}' - ) - - exec_graphql "$token_name" 'ln-no-amount-usd-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnNoAmountUsdInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - # Check for settled - retry 15 1 check_for_ln_initiated_settled "$token_name" "$payment_hash" - check_for_ln_initiated_settled "$recipient_token_name" "$payment_hash" - - final_balance="$(balance_for_wallet $token_name 'USD')" - wallet_diff="$(( $initial_balance - $final_balance ))" - [[ "$wallet_diff" == "$usd_amount" ]] || exit 1 - - final_lnd1_balance=$(lnd_cli channelbalance | jq -r '.balance') - lnd1_diff="$(( $initial_lnd1_balance - $final_lnd1_balance ))" - [[ "$lnd1_diff" == "0" ]] || exit 1 -} - -@test "ln-send: ln settled - settle failed and then successful payment" { - token_name="$ALICE_TOKEN_NAME" - btc_wallet_name="$token_name.btc_wallet_id" - - threshold_amount=150000 - invoice_response="$(lnd_outside_2_cli addinvoice --amt $threshold_amount)" - payment_request="$(echo $invoice_response | jq -r '.payment_request')" - payment_hash=$(echo $invoice_response | jq -r '.r_hash') - [[ "${payment_request}" != "null" ]] || exit 1 - - check_num_txns() { - expected_num="$1" - - num_txns="$(num_txns_for_hash "$token_name" "$payment_hash")" - [[ "$num_txns" == "$expected_num" ]] || exit 1 - } - - # Rebalance last hop so payment will fail - rebalance_channel lnd_outside_cli lnd_outside_2_cli "$(( $threshold_amount - 1 ))" - - # Try payment and check for fail - initial_balance="$(balance_for_wallet $token_name 'BTC')" - - variables=$( - jq -n \ - --arg wallet_id "$(read_value $btc_wallet_name)" \ - --arg payment_request "$payment_request" \ - '{input: {walletId: $wallet_id, paymentRequest: $payment_request}}' - ) - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - error_msg="$(graphql_output '.data.lnInvoicePaymentSend.errors[0].message')" - [[ "${send_status}" = "FAILURE" ]] || exit 1 - [[ "${error_msg}" == "Unable to find a route for payment." ]] || exit 1 - - # Check for txns - retry 15 1 check_num_txns "2" - balance_after_fail="$(balance_for_wallet $token_name 'BTC')" - [[ "$initial_balance" == "$balance_after_fail" ]] || exit 1 - - # Rebalance last hop so same payment will succeed - rebalance_channel lnd_outside_cli lnd_outside_2_cli "$(( $threshold_amount * 2 ))" - lnd_cli resetmc - - # Retry payment and check for success - exec_graphql "$token_name" 'ln-invoice-fee-probe' "$variables" - num_errors="$(graphql_output '.data.lnInvoiceFeeProbe.errors | length')" - fee_amount="$(graphql_output '.data.lnInvoiceFeeProbe.amount')" - [[ "$num_errors" == "0" ]] || exit 1 - [[ "${fee_amount}" -gt "0" ]] || exit 1 - - exec_graphql "$token_name" 'ln-invoice-payment-send' "$variables" - send_status="$(graphql_output '.data.lnInvoicePaymentSend.status')" - [[ "${send_status}" = "SUCCESS" ]] || exit 1 - - transaction_payment_hash="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentHash')" - [[ "${transaction_payment_hash}" == "${payment_hash}" ]] || exit 1 - - transaction_payment_request="$(graphql_output '.data.lnInvoicePaymentSend.transaction.initiationVia.paymentRequest')" - [[ "${transaction_payment_request}" == "${payment_request}" ]] || exit 1 - - # Check for txns - retry 15 1 check_num_txns "3" - balance_after_success="$(balance_for_wallet $token_name 'BTC')" - [[ "$balance_after_success" -lt "$initial_balance" ]] || exit 1 -} - @test "ln-send: ln settled - settle failed and then pending-to-failed payment" { skip "missing xxd dep, failing on concourse" diff --git a/dev/BUCK b/dev/BUCK index d70e2b09e6..648fd4593b 100644 --- a/dev/BUCK +++ b/dev/BUCK @@ -80,3 +80,8 @@ sh_binary( name = "setup-hydra-client", main = "bin/setup-hydra-client.sh", ) + +sh_binary( + name = "stoppable-trigger", + main = "bin/run-stoppable-trigger.sh", +) diff --git a/dev/Tiltfile b/dev/Tiltfile index 6668618092..47f09039de 100644 --- a/dev/Tiltfile +++ b/dev/Tiltfile @@ -234,9 +234,19 @@ core_serve_env = { "LND1_TYPE": "offchain,onchain", "SVIX_SECRET": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2OTE2NzIwMTQsImV4cCI6MjAwNzAzMjAxNCwibmJmIjoxNjkxNjcyMDE0LCJpc3MiOiJzdml4LXNlcnZlciIsInN1YiI6Im9yZ18yM3JiOFlkR3FNVDBxSXpwZ0d3ZFhmSGlyTXUifQ.b9s0aWSisNdUNki4edabBEToLNSwjC9-AiJQr4J3y4E", "SVIX_ENDPOINT": "http://localhost:8071", + "SVIX_CALLBACK_URL": "http://bats-tests:8080/webhook/", "EXPORTER_PORT": "3003" } +callback_target = "//bats/helpers/callback:run" +local_resource( + "callback", + labels = ["test"], + serve_cmd = "buck2 run {}".format(callback_target), + allow_parallel = True, + deps = _buck2_dep_inputs(callback_target), +) + api_target = "//core/api:dev" if is_ci: api_target = "//core/api:api" @@ -257,10 +267,12 @@ local_resource( deps = _buck2_dep_inputs(api_target), resource_deps = [ "init-onchain", + "init-lightning", "lnd1", "redis", "mongodb", "oathkeeper", + "svix", ] ) @@ -271,7 +283,7 @@ local_resource( "api-trigger", labels = ["core"], cmd = "buck2 build {}".format(api_trigger_target), - serve_cmd = "buck2 run {}".format(api_trigger_target), + serve_cmd = "buck2 run //dev:stoppable-trigger {}".format(api_trigger_target), serve_env = core_serve_env, allow_parallel = True, readiness_probe = probe( diff --git a/dev/bin/init-lightning.sh b/dev/bin/init-lightning.sh index a77eb6526b..377d9e22f5 100755 --- a/dev/bin/init-lightning.sh +++ b/dev/bin/init-lightning.sh @@ -24,6 +24,37 @@ retry() { false } +run_with_lnd() { + local func_name="$1" + shift # This will shift away the function name, so $1 becomes the next argument + + if [[ "$func_name" == "lnd_cli" ]]; then + lnd_cli "$@" + elif [[ "$func_name" == "lnd_outside_cli" ]]; then + lnd_outside_cli "$@" + elif [[ "$func_name" == "lnd_outside_2_cli" ]]; then + lnd_outside_2_cli "$@" + else + echo "Invalid function name passed!" && return 1 + fi +} + +lnd_is_ready() { + lnd_cli_cmd="$1" + echo "Checking $lnd_cli_cmd is ready..." + run_with_lnd "$lnd_cli_cmd" getinfo > /dev/null 2>&1 + return "$?" +} + +lnd_outside_connect_with_retry() { + connection_string="$1" + connected=$(lnd_outside_cli connect "$connection_string" 2>&1) + connected_success="$?" + if [[ "$connected_success" == "0" ]]; then return 0; fi + if [[ "$connected" =~ "already connected" ]]; then return 0; fi + return 1 +} + mempool_not_empty() { echo "Waiting for txn to show up in mempool..." local txid="$(bitcoin_cli getrawmempool | jq -r ".[0]")" @@ -56,6 +87,7 @@ bitcoin_cli -generate "${block_rewards}" > /dev/null 2>&1 echo "Funded with "${block_rewards}" block rewards" echo "Funding 'lndOutside1' node..." +retry 30 1 lnd_is_ready lnd_outside_cli amount="1" address="$(lnd_outside_cli newaddress p2wkh | jq -r '.address')" local_amount="10000000" @@ -66,9 +98,10 @@ echo "Funded with txid: ${funded_txid}" # Open channel from lndoutside1 -> lnd1 echo "Opening channel: lndoutside1 -> lnd1..." +retry 30 1 lnd_is_ready lnd_cli pubkey_lnd1="$(lnd_cli getinfo | jq -r '.identity_pubkey')" endpoint_lnd1="${COMPOSE_PROJECT_NAME}-lnd1-1:9735" -lnd_outside_cli connect "${pubkey_lnd1}@${endpoint_lnd1}" > /dev/null 2>&1 || true +retry 10 1 lnd_outside_connect_with_retry "${pubkey_lnd1}@${endpoint_lnd1}" retry 10 1 synced_to_graph funding_txid=$(lnd_outside_cli openchannel \ --node_key "$pubkey_lnd1" \ @@ -87,9 +120,10 @@ echo "Channel ${funding_txid} confirmed" # Open channel with push from lndoutside1 -> lndoutside2 echo "Opening balanced channel: lndoutside1 -> lndoutside2..." +retry 30 1 lnd_is_ready lnd_outside_2_cli pubkey_lnd_outside_2="$(lnd_outside_2_cli getinfo | jq -r '.identity_pubkey')" endpoint_lnd_outside_2="${COMPOSE_PROJECT_NAME}-lnd-outside-2-1:9735" -lnd_outside_cli connect "${pubkey_lnd_outside_2}@${endpoint_lnd_outside_2}" > /dev/null 2>&1 || true +retry 10 1 lnd_outside_connect_with_retry "${pubkey_lnd_outside_2}@${endpoint_lnd_outside_2}" retry 10 1 synced_to_graph funding_txid=$(lnd_outside_cli openchannel \ --node_key "$pubkey_lnd_outside_2" \ diff --git a/dev/bin/run-stoppable-trigger.sh b/dev/bin/run-stoppable-trigger.sh new file mode 100755 index 0000000000..b70799f94c --- /dev/null +++ b/dev/bin/run-stoppable-trigger.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +buck_target="$1" + +REPO_ROOT=$(git rev-parse --show-toplevel) +BATS_DIR="${REPO_ROOT}/bats" + +TRIGGER_PID_FILE="$BATS_DIR/.trigger_pid" + +CONTROL_FILE="$BATS_DIR/.stop_trigger" +rm "$CONTROL_FILE" + +start_trigger() { + buck2 run "$buck_target" & + echo "$!" > "$TRIGGER_PID_FILE" +} + +trigger_is_running() { + SERVER_PID=$(head -n 1 "$TRIGGER_PID_FILE") + if ps -p "$SERVER_PID" > /dev/null; then + return 0 + fi + return 1 +} + +while true; do + if [[ -f "$CONTROL_FILE" ]]; then + if trigger_is_running > /dev/null; then + echo "Stopping server..." + kill -15 $SERVER_PID + if [[ "$?" == "0" ]]; then + echo "Successfully stopped trigger" + else + echo "Could not stop trigger, exiting..." + exit 1 + fi + fi + else + if ! trigger_is_running > /dev/null; then + start_trigger + fi + fi + sleep 2 +done diff --git a/dev/docker-compose.deps.yml b/dev/docker-compose.deps.yml index 21ecd0c12d..466de6e93a 100644 --- a/dev/docker-compose.deps.yml +++ b/dev/docker-compose.deps.yml @@ -308,7 +308,7 @@ services: ports: - 8071:8071 extra_hosts: - - dockerhost-alias:host-gateway + - bats-tests:host-gateway svix-pg: image: postgres:14.1 environment: