Commit graph

1279 commits

Author SHA1 Message Date
Anthony Potdevin
5e116d7359
chore: invoice and payment search
Some checks failed
Test, lint and build / test_lint_build (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
2026-06-24 15:51:01 -06:00
Rajat Khanduri
28d1aa376b
fix(magma): add referrer and verify seller asset-channel support [AMB-2708] (#768)
Some checks are pending
Test, lint and build / test_lint_build (push) Waiting to run
Release Please / release-please (push) Waiting to run
* fix(magma): add referrer and verify seller asset-channel support

* refactor(magma): validate buyer node tapd support instead of seller

* feat(assets): gate asset routes on Taproot Assets capability

The nav already hides the Taproot Assets section for non-tapd nodes, but the
routes themselves were unguarded — a typed URL or bookmark to /trading,
/assets, /asset-channels, /asset-transactions or /asset-tools loaded the
feature regardless. Add a RequireTapd route guard that redirects those to
home when the node lacks the capability, and extract a shared useTapdAvailable
hook so the nav and the guard share one signal. /magma stays ungated (it also
serves BTC channels).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 15:04:05 +02:00
github-actions[bot]
3020a6ec99
chore(master): release 0.18.4 (#766)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-28 21:29:02 -06:00
Rajat Khanduri
6616f2a19c
fix: update buy execution path to not build a route with too little final CLTV headroom (#764)
* chore: update buy execution path

* chore: attempt to find more routes if one fails

---------

Co-authored-by: Anthony Potdevin <31413433+apotdevin@users.noreply.github.com>
2026-05-29 02:36:00 +00:00
Rajat Khanduri
42a4501059
fix(assets): add native display formatting to trading distribution view [AMB-2611] (#765)
* fix(assets): add native display formatting to trading distribution view

* feat(assets): add formatNativeAsset helper and use in trading distribution
2026-05-25 16:24:43 +05:30
github-actions[bot]
7054f0b91f
chore(master): release 0.18.3 (#762)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-16 00:30:01 +02:00
Anthony Potdevin
1abbee4a67
Merge branch 'master' of https://github.com/apotdevin/thunderhub 2026-05-16 00:27:23 +02:00
Anthony Potdevin
826dce3cf1
ci: push flag change 2026-05-16 00:27:17 +02:00
github-actions[bot]
2ae929675d
chore(master): release 0.18.2 (#761)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-15 23:49:29 +02:00
Anthony Potdevin
b9cb8e1f33
Merge branch 'master' of https://github.com/apotdevin/thunderhub 2026-05-15 23:48:27 +02:00
Anthony Potdevin
269e46ca5b
ci: workflow trigger change 2026-05-15 23:48:20 +02:00
Khiet Tam Nguyen
7d9d19713a
fix: otp guardrails min secret bytes 10 (#757) 2026-05-15 23:37:49 +02:00
github-actions[bot]
0f3714abb3
chore(master): release 0.18.1 (#760)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-15 23:28:49 +02:00
Rajat Khanduri
e21c848515
chore(ci): increase docker run timeout to 2hrs (#759) 2026-05-14 20:53:09 +02:00
github-actions[bot]
9d996ffde1
chore(master): release 0.18.0 (#748)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-05 15:18:59 -06:00
Rajat Khanduri
818e82e052
fix(transactions): format trade memo in invoice and payments cards (#754)
* fix(transactions): format trade memo in invoice and payments cards

- Add formatTradeMemo helper to parse th:trade memo JSON
- Use formatted memo for invoice description and message rendering
- Apply formatTradeMemo to decoded payment request description

* fix(transactions): show computed trade memo marker by mode

- Pass tradeDisplayMode from TransactionsPage into InvoiceCard and PaymentsCard
- Add ComputedMarker tooltip component for computed trade memo display
- Refactor tradeMemo usage to use getTradeMemoText/getTradeMemoDisplay with

* feat(transactions): display raw trade memo details in cards

* chore: changes

---------

Co-authored-by: Anthony Potdevin <potdevin.anthony@gmail.com>
2026-05-05 21:17:25 +00:00
Bufo
68d9146135
fix: set asset_id to null for SALE magma orders (#756) 2026-05-05 22:38:02 +05:30
JC Brand
295f6a9a23
feat: show asset balance columns in pending asset channels table (#740)
Adds dynamic asset capacity/local/remote/balance-bar columns to the
pending channels view, matching the display already present for open
channels. Also adds asset_name and asset_precision to the
getPendingChannels query so labels and formatted amounts are correct.
2026-05-04 16:48:49 +02:00
JC Brand
dfc0476e8f
fix: handle channel-open timeout gracefully and reflect in-progress orders (#746)
Three changes:
- setupTradeCapacity: catch the waitForChannelFromPeer timeout and return
    success with channelOpenPending=true instead of throwing; the payment
    is in-flight and the channel will open on Magma's schedule
- SidebarTrade: always refetchReadiness after setup (success or error) so
    the form reflects the actual order state; show a "channel being set up"
    toast when channelOpenPending is true
- fetchPendingOrdersForPeer: drop action_needed filter (role-scoped, excludes
    WAITING_FOR_CHANNEL_OPEN for buyers) and filter client-side against all
    non-terminal statuses so the pending indicator stays visible while Magma
    opens the channel
2026-05-04 13:20:42 +02:00
JC Brand
6f24a8407c
Add Pay/Cancel action buttons for pending Magma orders (#745)
* feat: add Pay/Cancel action buttons for pending Magma orders

When a pending Magma order (WAITING_FOR_BUYER_PAYMENT) exists for a
selected offer, the Get Quote button is disabled and a prominent yellow
action block is shown with "Pay order" and "Cancel order" buttons so
the user knows what to do next.

Disable `Get Quote` button when there is a pending Magma order

* fix: clarify InsufficientBalanceToAttemptPayment as a routing failure

LND's FAILED_INSUFFICIENT_BALANCE maps to this error but it fires when
no funded route exists, not only when wallet balance is low. Surface a
clearer message so the user knows to check inactive channels or HTLCs.

* fix: link pending order warning to Magma order page

* fix: distinguish unpaid, in-progress and ready Magma orders in offer readiness

Post-payment statuses (WAITING_FOR_CHANNEL_OPEN, VALID_CHANNEL_OPENING,
etc.) were treated identically to unpaid statuses, causing the "unpaid
order blocking trading" warning to appear even after the buyer had paid.

Split the status check into unpaidStatuses (hasPending: true) and
inProgressStatuses (hasPending: false, but still return orderId/status).

Expose pending_order_status in the GraphQL type and query, and update
the sidebar UI to show Pay/Cancel only for unpaid orders.
2026-05-04 12:48:13 +02:00
JC Brand
0b84ea04fe
[AMB-2540] feat: enable automatic channel setup for SALE (#737)
* feat: enable SALE transaction type in setupTradePartner [AMB-2540]

Remove the placeholder guard that blocked SALE — the full flow
(sats-denominated order size, HODL invoice payment, outbound asset
channel via fundAssetChannel) was already implemented. Replace the
three "throws not-implemented" spec stubs with real assertions.

* fix: skip asset channel open for SALE when one already exists

Add openAssetChannel flag to SetupTradePartnerInput mirroring the
satsAmount opt-out for PURCHASE. The client passes true only when
hasAssetChannel is false; the server skips fundAssetChannel otherwise.

* chore: rename `openAssetChannel` to `openOutboundAssetChannel`

* fix: pass feeRateSatPerVbyte to fundAssetChannel for SALE

tapd requires an explicit on-chain fee rate when opening an asset
channel. Add optional feeRateSatPerVbyte to SetupTradePartnerInput
and default to 1 sat/vbyte on the server when the caller omits it.
2026-05-04 11:48:17 +02:00
Bufo
7e5fb5cdeb
feat: multi-hop swaps with circular rebalancing (#749)
* feat: multihop swaps

* fix: fee limit

* fix: circular rebalancing

* chore: simplify and fix post-review issues

- magma: guard allChannels against undefined (??= [])
- magma: restore peer filter on btcOpen and btcPending — both were
  accidentally widened to all channels by the multi-hop refactor
- TradingPartners: remove btcChannelPubkeys dead code (filter that used
  it was removed; useMemo and stale dep array entry remain)
- trade: move fullHops array from info to debug log to avoid large
  object serialisation on every rebalance
- trade: fix misleading 'No bitcoin channels found' error when the real
  condition is insufficient outbound liquidity
- test: add debug to mock logger

---------

Co-authored-by: Bufo <bufo24@users.noreply.github.com>
Co-authored-by: Anthony Potdevin <31413433+apotdevin@users.noreply.github.com>
2026-05-02 18:24:23 -06:00
Rajat Khanduri
bd5dda71d3
feat: add fly.toml file (#752) 2026-05-02 18:12:17 -06:00
Kilombino
591e2ef777
fix(database): postgres node-setup wizard query fails with SUBSTR on uuid (#750)
Two related bugs caused the "Connect a Node" setup wizard to error
immediately on startup when using a PostgreSQL backend.

1. Client routing leakage: the Apollo authLink extracts the first URL
   segment as the node slug. On the /node-setup route that segment is
   literally "node-setup", which was forwarded as x-node-slug on every
   GraphQL request from that page.

2. SUBSTR on UUID type: getDbNodeBySlug (and the deleteNode/editNode
   helpers in user.service) used SUBSTR(nodes.id, 1, 8) directly. In
   SQLite nodes.id is stored as TEXT so SUBSTR works. In PostgreSQL
   nodes.id is typed as uuid, and PostgreSQL has no substr(uuid, int,
   int) overload — the query raises a type error regardless of the
   slug value passed in.

Fix:
- client/config/client.tsx: skip the x-node-slug header when the first
  URL segment is a known non-slug public route (login, sso, setup,
  node-setup). Extracted into NON_SLUG_PREFIXES set.
- utils/string.ts: add isValidNodeSlug() — returns true only for exactly
  8 hex characters (the UUID short-prefix format used by the app).
- accounts.service.ts: guard getDbNodeBySlug with isValidNodeSlug()
  before touching the DB; change SUBSTR to SUBSTR(CAST(... AS TEXT), …)
  so it is dialect-safe on PostgreSQL.
- user.service.ts: apply the same CAST fix to deleteNode and editNode.

The server-side CAST fix is independently necessary: even after the
client stops leaking "node-setup", all legitimate slug lookups would
still fail on PostgreSQL without it.

Tested on PostgreSQL 18.3 and SQLite. Full test suite passes (149 tests).

Signed-off-by: Kilombino <kilombino@proton.me>
Co-authored-by: Anthony Potdevin <31413433+apotdevin@users.noreply.github.com>
2026-05-02 18:06:26 -06:00
Anthony Potdevin
e0286fd315
chore: disable mobile drag 2026-05-02 17:56:27 -06:00
Rajat Khanduri
9f06296c44
chore: correct instructions in /node-setup route [AMB-2557] (#747) 2026-04-30 18:41:19 -06:00
github-actions[bot]
1d846602bc
chore(master): release 0.17.0 (#743)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-29 21:37:31 -06:00
Kilombino
f62b48fa24
feat: per-channel notes (inline editing in channels table) (#744)
* feat(db): add channel_notes table with Drizzle schema and migrations

Adds a new `channel_notes` table (SQLite + PG) with composite PK
(account_id, channel_id) to persist per-channel notes scoped to each
ThunderHub account. Includes migration files for both database backends.

* feat(api): add ChannelNotesService with getChannelNotes query and setChannelNote mutation

Introduces ChannelNotesService (Drizzle-backed, account-scoped) with
getNotes/upsertNote methods. Exposes two new GraphQL endpoints on
ChannelsResolver: getChannelNotes (query) and setChannelNote (mutation).

* feat(client): add inline channel notes to channels table and details panel

- Adds NoteCell component to ChannelTable with click-to-edit inline input
  (Enter/✓ to save, Escape to cancel)
- Fetches all notes on load via getChannelNotes query; updates optimistically
- Adds note textarea + Save button in ChannelDetails modal below fee editor
- Notes are persisted server-side and survive page refreshes

* chore: table changes

* chore: schema cleanup

* chore: cleanup table

* chore: more cleanup

* chore: db ondelete

---------

Co-authored-by: Anthony Potdevin <potdevin.anthony@gmail.com>
2026-04-29 21:31:54 -06:00
Anthony Potdevin
fa1de4dd7f
chore: trading partner change 2026-04-29 14:15:25 -06:00
Anthony Potdevin
3b110fc77e
chore: default to buy side order form 2026-04-29 13:03:30 -06:00
github-actions[bot]
87d56852e4
chore(master): release 0.16.2 (#742)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-29 11:34:33 -06:00
Rajat Khanduri
095311402f
chore: fix setup page login input (#741) 2026-04-29 11:28:20 -06:00
github-actions[bot]
6d6e618656
chore(master): release 0.16.1 (#739)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-28 09:26:36 -06:00
Bufo
f5f3b9f5a3
fix: read TA channel cltv/fee from invoice route hint in rebalance (#738)
The circular rebalance for asset channel sat top-up was failing with
IncorrectCltvExpiry because hopCltvDelta was derived from the canonical
TA channel SCID's gossiped policy. The route actually traverses the
peer's tapd virtual SCID alias (e.g. 16000000x0x1), which has its own
gossiped policy that the canonical-SCID lookup does not return.

Switch to the same source the buy flow uses: enable
is_including_private_channels on createInvoice, decode the resulting
BOLT11, and read cltv_delta / base_fee_mtokens / fee_rate from the TA
channel's route hint. Drop both getChannel calls; the canonical lookup
returned the wrong cltv and the BTC channel max was a defensive
fallback that is no longer needed. Disambiguate the hint by
partner_scid_alias when known so multi-hint invoices pick the right
entry.

Co-authored-by: Bufo <bufo24@users.noreply.github.com>
2026-04-28 16:07:31 +02:00
github-actions[bot]
8ef504013b
chore(master): release 0.16.0 (#675)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-28 00:20:52 -06:00
Anthony Potdevin
ca3f3793a7
chore: portfolio widget 2026-04-28 00:16:33 -06:00
Anthony Potdevin
c9c08a0069
chore: switch buy/sell 2026-04-27 22:31:37 -06:00
Anthony Potdevin
d813c21509
chore: balance checks 2026-04-27 19:09:21 -06:00
Anthony Potdevin
2864186318
feat: guided steps (#736) 2026-04-26 21:38:50 -06:00
Anthony Potdevin
f94d881f0e
chore: bump lightning version 2026-04-26 00:35:28 -06:00
Anthony Potdevin
e0b5f3dd46
chore: change lightning package ref 2026-04-25 15:53:07 -06:00
JC Brand
4e41c32dbe
chore: circular rebalance for TA channel sat reserve (#732)
* feat: circular rebalance for TA channel sat reserve

Before executing a sell trade, check whether the TA channel's local sat
balance is below its reserve requirement. If so, run a circular rebalance:
pay a sats invoice to ourselves routing out through the BTC channel and back
in through all TA channels that are below the reserve requirement, topping up
the sat balance with a 50% buffer above the bare deficit so the asset HTLC
anchor can proceed.

* chore: rename id to accountId

* chore: improve variable and parameter naming in trade resolver

- Rename effectiveReserve → minRequiredBalance (it's the floor balance,
  not a modified reserve)
- Rename taChannelPeerAlias → taChannelPartnerScidAlias throughout, and
  peerAlias → partnerScidAlias on the intermediate return object, to
  match the source field partner_scid_alias and make the SCID nature explicit
- Separate empty-channels path from fetch-error path in findTaChannelsForAsset
  so the warning only fires on actual errors

* chore: changes

---------

Co-authored-by: Anthony Potdevin <potdevin.anthony@gmail.com>
2026-04-24 21:49:37 -06:00
Rajat Khanduri
d0db288f86
feat: Filter Magma Orders by node [AMB-2522] (#734) 2026-04-24 02:57:09 +00:00
Rajat Khanduri
7a3cb0a3d3
chore(ui): add a beta tag in Taproot Assets stuff (#733)
* chore(ui): add beta tag in Taproot Assets stuff

* chore(ui): fix hover text background in diff themes

* chore: cleanup

* chore: cleanup

* chore: more stuff

---------

Co-authored-by: Anthony Potdevin <potdevin.anthony@gmail.com>
2026-04-23 20:18:24 -06:00
JC Brand
1686d27ec6
fix: respect word boundaries in toast messages (#731) 2026-04-23 14:25:33 +05:30
Anthony Potdevin
2393f5c460
chore: asset transactions changes 2026-04-22 23:25:12 -06:00
Anthony Potdevin
4bd4a52be3
chore: unify precision number display 2026-04-22 22:47:31 -06:00
Anthony Potdevin
b7bf500b69
chore: asset list toggles 2026-04-22 22:21:01 -06:00
Anthony Potdevin
efb1e9786a
chore: organize taproot asset views 2026-04-22 22:09:09 -06:00
Anthony Potdevin
8760a1ca62
chore: copy text cleanup 2026-04-22 21:09:25 -06:00