Compare commits
93 commits
master
...
feature/ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a574a5b817 | ||
|
|
81f199a18a | ||
|
|
e3ec8676fb | ||
|
|
b115712c87 | ||
|
|
51ce89234e | ||
|
|
f048e71821 | ||
|
|
b2dbcd6a20 | ||
|
|
48bfc45bcf | ||
|
|
6725d4620b | ||
|
|
680cca6852 | ||
|
|
b08e7c134a | ||
|
|
adb581a018 | ||
|
|
21e3fc6ac0 | ||
|
|
7ef33441e3 | ||
|
|
0466ee673b | ||
|
|
72c9872b23 | ||
|
|
5e5e30c7a2 | ||
|
|
611eb4fc04 | ||
|
|
6512e10f08 | ||
|
|
e9b5dacb3b | ||
|
|
a2b7ac1673 | ||
|
|
70544bd551 | ||
|
|
74513a1412 | ||
|
|
266f526453 | ||
|
|
169284021f | ||
|
|
67f9dfde8b | ||
|
|
7c8cca0a55 | ||
|
|
0a30cf537f | ||
|
|
595e5bb257 | ||
|
|
8576a1d138 | ||
|
|
c18b79dc50 | ||
|
|
bfa71f7439 | ||
|
|
a0b77ec1ca | ||
|
|
cfb7dd1e6e | ||
|
|
be6f48427f | ||
|
|
21cb960c2e | ||
|
|
7af841c330 | ||
|
|
71b55c06d4 | ||
|
|
432f9d0b42 | ||
|
|
574f229cee | ||
|
|
f0418fb389 | ||
|
|
dcfa9250fe | ||
|
|
ef14ec9ddf | ||
|
|
2c8d57dd6e | ||
|
|
f8fe946b40 | ||
|
|
e411b7aa7f | ||
|
|
d949addb16 | ||
|
|
9e66f7d72e | ||
|
|
ae3b39ee04 | ||
|
|
c83028c419 | ||
|
|
c146d46c59 | ||
|
|
6aa90d63ba | ||
|
|
8ada2ac165 | ||
|
|
6e8a181d34 | ||
|
|
875d1274de | ||
|
|
791a5756a7 | ||
|
|
305b268d73 | ||
|
|
6da8434073 | ||
|
|
c85968ce2f | ||
|
|
e32dff939e | ||
|
|
97de703feb | ||
|
|
a10cf126b3 | ||
|
|
edbbbd4aec | ||
|
|
f4b302ed43 | ||
|
|
c3e3f99c7d | ||
|
|
e271d35c2d | ||
|
|
3389045de7 | ||
|
|
9fe681d73b | ||
|
|
ecf7c43416 | ||
|
|
81f7400748 | ||
|
|
c1bcda5654 | ||
|
|
3a6b22cff8 | ||
|
|
a362cb4b91 | ||
|
|
0a2556d0d4 | ||
|
|
3046e73464 | ||
|
|
e24fa4f055 | ||
|
|
d9ec58165f | ||
|
|
7b81a90c1a | ||
|
|
1f09bcc679 | ||
|
|
070aa758d8 | ||
|
|
23156986b1 | ||
|
|
f262d46d1f | ||
|
|
02d3580613 | ||
|
|
ae4a5cb5d0 | ||
|
|
f5eb1f3253 | ||
|
|
3255730ae2 | ||
|
|
e15668b442 | ||
|
|
3b827626a6 | ||
|
|
e71f631993 | ||
|
|
d120ad7f99 | ||
|
|
44c55f3baa | ||
|
|
03792f3111 | ||
|
|
a596e186fe |
90 changed files with 14694 additions and 5911 deletions
|
|
@ -2,3 +2,21 @@
|
||||||
.github
|
.github
|
||||||
build
|
build
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
# Runtime state files (should not be baked into image)
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite-journal
|
||||||
|
*.sqlite-wal
|
||||||
|
*.sqlite-shm
|
||||||
|
*.db
|
||||||
|
admin.connect
|
||||||
|
admin.enroll
|
||||||
|
admin.npub
|
||||||
|
app.nprofile
|
||||||
|
.jwt_secret
|
||||||
|
|
||||||
|
# Runtime data directories
|
||||||
|
metric_cache/
|
||||||
|
metric_events/
|
||||||
|
bundler_events/
|
||||||
|
logs/
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
FROM node:18
|
FROM node:20
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
/**
|
||||||
|
* TypeORM DataSource used only by the TypeORM CLI (e.g. migration:generate).
|
||||||
|
*
|
||||||
|
* Migrations at runtime are run from src/services/storage/migrations/runner.ts (allMigrations),
|
||||||
|
* not from this file. The app never uses this DataSource to run migrations.
|
||||||
|
*
|
||||||
|
* Workflow: update the migrations array in this file *before* running
|
||||||
|
* migration:generate, so TypeORM knows the current schema (entities + existing migrations).
|
||||||
|
* We do not update this file immediately after adding a new migration; update it when you
|
||||||
|
* are about to generate the next migration.
|
||||||
|
*/
|
||||||
import { DataSource } from "typeorm"
|
import { DataSource } from "typeorm"
|
||||||
import { User } from "./build/src/services/storage/entity/User.js"
|
import { User } from "./build/src/services/storage/entity/User.js"
|
||||||
import { UserReceivingInvoice } from "./build/src/services/storage/entity/UserReceivingInvoice.js"
|
import { UserReceivingInvoice } from "./build/src/services/storage/entity/UserReceivingInvoice.js"
|
||||||
|
|
@ -22,11 +33,13 @@ import { AppUserDevice } from "./build/src/services/storage/entity/AppUserDevice
|
||||||
import { UserAccess } from "./build/src/services/storage/entity/UserAccess.js"
|
import { UserAccess } from "./build/src/services/storage/entity/UserAccess.js"
|
||||||
import { AdminSettings } from "./build/src/services/storage/entity/AdminSettings.js"
|
import { AdminSettings } from "./build/src/services/storage/entity/AdminSettings.js"
|
||||||
import { TransactionSwap } from "./build/src/services/storage/entity/TransactionSwap.js"
|
import { TransactionSwap } from "./build/src/services/storage/entity/TransactionSwap.js"
|
||||||
|
import { InvoiceSwap } from "./build/src/services/storage/entity/InvoiceSwap.js"
|
||||||
|
|
||||||
import { Initial1703170309875 } from './build/src/services/storage/migrations/1703170309875-initial.js'
|
import { Initial1703170309875 } from './build/src/services/storage/migrations/1703170309875-initial.js'
|
||||||
import { LspOrder1718387847693 } from './build/src/services/storage/migrations/1718387847693-lsp_order.js'
|
import { LspOrder1718387847693 } from './build/src/services/storage/migrations/1718387847693-lsp_order.js'
|
||||||
import { LndNodeInfo1720187506189 } from './build/src/services/storage/migrations/1720187506189-lnd_node_info.js'
|
|
||||||
import { LiquidityProvider1719335699480 } from './build/src/services/storage/migrations/1719335699480-liquidity_provider.js'
|
import { LiquidityProvider1719335699480 } from './build/src/services/storage/migrations/1719335699480-liquidity_provider.js'
|
||||||
|
import { LndNodeInfo1720187506189 } from './build/src/services/storage/migrations/1720187506189-lnd_node_info.js'
|
||||||
|
import { TrackedProvider1720814323679 } from './build/src/services/storage/migrations/1720814323679-tracked_provider.js'
|
||||||
import { CreateInviteTokenTable1721751414878 } from './build/src/services/storage/migrations/1721751414878-create_invite_token_table.js'
|
import { CreateInviteTokenTable1721751414878 } from './build/src/services/storage/migrations/1721751414878-create_invite_token_table.js'
|
||||||
import { PaymentIndex1721760297610 } from './build/src/services/storage/migrations/1721760297610-payment_index.js'
|
import { PaymentIndex1721760297610 } from './build/src/services/storage/migrations/1721760297610-payment_index.js'
|
||||||
import { DebitAccess1726496225078 } from './build/src/services/storage/migrations/1726496225078-debit_access.js'
|
import { DebitAccess1726496225078 } from './build/src/services/storage/migrations/1726496225078-debit_access.js'
|
||||||
|
|
@ -35,6 +48,7 @@ import { DebitToPub1727105758354 } from './build/src/services/storage/migrations
|
||||||
import { UserCbUrl1727112281043 } from './build/src/services/storage/migrations/1727112281043-user_cb_url.js'
|
import { UserCbUrl1727112281043 } from './build/src/services/storage/migrations/1727112281043-user_cb_url.js'
|
||||||
import { UserOffer1733502626042 } from './build/src/services/storage/migrations/1733502626042-user_offer.js'
|
import { UserOffer1733502626042 } from './build/src/services/storage/migrations/1733502626042-user_offer.js'
|
||||||
import { ManagementGrant1751307732346 } from './build/src/services/storage/migrations/1751307732346-management_grant.js'
|
import { ManagementGrant1751307732346 } from './build/src/services/storage/migrations/1751307732346-management_grant.js'
|
||||||
|
import { ManagementGrantBanned1751989251513 } from './build/src/services/storage/migrations/1751989251513-management_grant_banned.js'
|
||||||
import { InvoiceCallbackUrls1752425992291 } from './build/src/services/storage/migrations/1752425992291-invoice_callback_urls.js'
|
import { InvoiceCallbackUrls1752425992291 } from './build/src/services/storage/migrations/1752425992291-invoice_callback_urls.js'
|
||||||
import { OldSomethingLeftover1753106599604 } from './build/src/services/storage/migrations/1753106599604-old_something_leftover.js'
|
import { OldSomethingLeftover1753106599604 } from './build/src/services/storage/migrations/1753106599604-old_something_leftover.js'
|
||||||
import { UserReceivingInvoiceIdx1753109184611 } from './build/src/services/storage/migrations/1753109184611-user_receiving_invoice_idx.js'
|
import { UserReceivingInvoiceIdx1753109184611 } from './build/src/services/storage/migrations/1753109184611-user_receiving_invoice_idx.js'
|
||||||
|
|
@ -47,20 +61,34 @@ import { TxSwap1762890527098 } from './build/src/services/storage/migrations/176
|
||||||
import { TxSwapAddress1764779178945 } from './build/src/services/storage/migrations/1764779178945-tx_swap_address.js'
|
import { TxSwapAddress1764779178945 } from './build/src/services/storage/migrations/1764779178945-tx_swap_address.js'
|
||||||
import { ClinkRequester1765497600000 } from './build/src/services/storage/migrations/1765497600000-clink_requester.js'
|
import { ClinkRequester1765497600000 } from './build/src/services/storage/migrations/1765497600000-clink_requester.js'
|
||||||
import { TrackedProviderHeight1766504040000 } from './build/src/services/storage/migrations/1766504040000-tracked_provider_height.js'
|
import { TrackedProviderHeight1766504040000 } from './build/src/services/storage/migrations/1766504040000-tracked_provider_height.js'
|
||||||
|
import { SwapsServiceUrl1768413055036 } from './build/src/services/storage/migrations/1768413055036-swaps_service_url.js'
|
||||||
|
import { InvoiceSwaps1769529793283 } from './build/src/services/storage/migrations/1769529793283-invoice_swaps.js'
|
||||||
|
import { InvoiceSwapsFixes1769805357459 } from './build/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.js'
|
||||||
|
import { ApplicationUserTopicId1770038768784 } from './build/src/services/storage/migrations/1770038768784-application_user_topic_id.js'
|
||||||
|
import { SwapTimestamps1771347307798 } from './build/src/services/storage/migrations/1771347307798-swap_timestamps.js'
|
||||||
|
import { TxSwapTimestamps1771878683383 } from './build/src/services/storage/migrations/1771878683383-tx_swap_timestamps.js'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default new DataSource({
|
export default new DataSource({
|
||||||
type: "better-sqlite3",
|
type: "better-sqlite3",
|
||||||
database: "db.sqlite",
|
database: "db.sqlite",
|
||||||
// logging: true,
|
// logging: true,
|
||||||
migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, CreateInviteTokenTable1721751414878,
|
migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189,
|
||||||
PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043,
|
TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264,
|
||||||
UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611,
|
DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513,
|
||||||
AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098,
|
InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175,
|
||||||
TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000],
|
UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098,
|
||||||
|
TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036,
|
||||||
|
InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798,
|
||||||
|
TxSwapTimestamps1771878683383
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
|
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
|
||||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo,
|
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo,
|
||||||
TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap],
|
TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap, InvoiceSwap],
|
||||||
// synchronize: true,
|
// synchronize: true,
|
||||||
})
|
})
|
||||||
//npx typeorm migration:generate ./src/services/storage/migrations/swaps_service_url -d ./datasource.js
|
//npx typeorm migration:generate ./src/services/storage/migrations/refund_swap_info -d ./datasource.js
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
/**
|
||||||
|
* TypeORM DataSource used only by the TypeORM CLI (e.g. migration:generate).
|
||||||
|
*
|
||||||
|
* Migrations at runtime are run from src/services/storage/migrations/runner.ts (allMigrations),
|
||||||
|
* not from this file. The app never uses this DataSource to run migrations.
|
||||||
|
*
|
||||||
|
* Workflow: update the migrations array in this file *before* running
|
||||||
|
* migration:generate, so TypeORM knows the current schema (entities + existing migrations).
|
||||||
|
* We do not update this file immediately after adding a new migration; update it when you
|
||||||
|
* are about to generate the next migration.
|
||||||
|
*/
|
||||||
import { DataSource } from "typeorm"
|
import { DataSource } from "typeorm"
|
||||||
import { BalanceEvent } from "./build/src/services/storage/entity/BalanceEvent.js"
|
import { BalanceEvent } from "./build/src/services/storage/entity/BalanceEvent.js"
|
||||||
import { ChannelBalanceEvent } from "./build/src/services/storage/entity/ChannelsBalanceEvent.js"
|
import { ChannelBalanceEvent } from "./build/src/services/storage/entity/ChannelsBalanceEvent.js"
|
||||||
|
|
@ -8,12 +19,16 @@ import { LndMetrics1703170330183 } from './build/src/services/storage/migrations
|
||||||
import { ChannelRouting1709316653538 } from './build/src/services/storage/migrations/1709316653538-channel_routing.js'
|
import { ChannelRouting1709316653538 } from './build/src/services/storage/migrations/1709316653538-channel_routing.js'
|
||||||
import { HtlcCount1724266887195 } from './build/src/services/storage/migrations/1724266887195-htlc_count.js'
|
import { HtlcCount1724266887195 } from './build/src/services/storage/migrations/1724266887195-htlc_count.js'
|
||||||
import { BalanceEvents1724860966825 } from './build/src/services/storage/migrations/1724860966825-balance_events.js'
|
import { BalanceEvents1724860966825 } from './build/src/services/storage/migrations/1724860966825-balance_events.js'
|
||||||
|
import { RootOps1732566440447 } from './build/src/services/storage/migrations/1732566440447-root_ops.js'
|
||||||
|
import { RootOpsTime1745428134124 } from './build/src/services/storage/migrations/1745428134124-root_ops_time.js'
|
||||||
|
import { ChannelEvents1750777346411 } from './build/src/services/storage/migrations/1750777346411-channel_events.js'
|
||||||
|
import { RootOpPending1771524665409 } from './build/src/services/storage/migrations/1771524665409-root_op_pending.js'
|
||||||
export default new DataSource({
|
export default new DataSource({
|
||||||
type: "better-sqlite3",
|
type: "better-sqlite3",
|
||||||
database: "metrics.sqlite",
|
database: "metrics.sqlite",
|
||||||
entities: [BalanceEvent, ChannelBalanceEvent, ChannelRouting, RootOperation, ChannelEvent],
|
entities: [BalanceEvent, ChannelBalanceEvent, ChannelRouting, RootOperation, ChannelEvent],
|
||||||
migrations: [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825]
|
migrations: [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825,
|
||||||
|
RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411, RootOpPending1771524665409]
|
||||||
});
|
});
|
||||||
|
|
||||||
//npx typeorm migration:generate ./src/services/storage/migrations/channel_events -d ./metricsDatasource.js
|
//npx typeorm migration:generate ./src/services/storage/migrations/root_op_pending -d ./metricsDatasource.js
|
||||||
2926
package-lock.json
generated
2926
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -77,6 +77,7 @@
|
||||||
"zip-a-folder": "^3.1.9"
|
"zip-a-folder": "^3.1.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/better-sqlite3": "^7.6.13",
|
||||||
"@types/chai": "^4.3.4",
|
"@types/chai": "^4.3.4",
|
||||||
"@types/chai-string": "^1.4.5",
|
"@types/chai-string": "^1.4.5",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- BumpTx
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [BumpTx](#BumpTx)
|
||||||
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- CloseChannel
|
- CloseChannel
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- input: [CloseChannelRequest](#CloseChannelRequest)
|
- input: [CloseChannelRequest](#CloseChannelRequest)
|
||||||
|
|
@ -93,6 +98,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [MessagingToken](#MessagingToken)
|
- input: [MessagingToken](#MessagingToken)
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- GetAdminInvoiceSwapQuotes
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [InvoiceSwapRequest](#InvoiceSwapRequest)
|
||||||
|
- output: [InvoiceSwapQuoteList](#InvoiceSwapQuoteList)
|
||||||
|
|
||||||
- GetAdminTransactionSwapQuotes
|
- GetAdminTransactionSwapQuotes
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- input: [TransactionSwapRequest](#TransactionSwapRequest)
|
- input: [TransactionSwapRequest](#TransactionSwapRequest)
|
||||||
|
|
@ -103,6 +113,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
||||||
- output: [AppsMetrics](#AppsMetrics)
|
- output: [AppsMetrics](#AppsMetrics)
|
||||||
|
|
||||||
|
- GetAssetsAndLiabilities
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [AssetsAndLiabilitiesReq](#AssetsAndLiabilitiesReq)
|
||||||
|
- output: [AssetsAndLiabilities](#AssetsAndLiabilities)
|
||||||
|
|
||||||
- GetBundleMetrics
|
- GetBundleMetrics
|
||||||
- auth type: __Metrics__
|
- auth type: __Metrics__
|
||||||
- input: [LatestBundleMetricReq](#LatestBundleMetricReq)
|
- input: [LatestBundleMetricReq](#LatestBundleMetricReq)
|
||||||
|
|
@ -243,20 +258,25 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- ListAdminSwaps
|
- ListAdminInvoiceSwaps
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [SwapsList](#SwapsList)
|
- output: [InvoiceSwapsList](#InvoiceSwapsList)
|
||||||
|
|
||||||
|
- ListAdminTxSwaps
|
||||||
|
- auth type: __Admin__
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [TxSwapsList](#TxSwapsList)
|
||||||
|
|
||||||
- ListChannels
|
- ListChannels
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [LndChannels](#LndChannels)
|
- output: [LndChannels](#LndChannels)
|
||||||
|
|
||||||
- ListSwaps
|
- ListTxSwaps
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [SwapsList](#SwapsList)
|
- output: [TxSwapsList](#TxSwapsList)
|
||||||
|
|
||||||
- LndGetInfo
|
- LndGetInfo
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
|
|
@ -290,10 +310,15 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [PayAddressRequest](#PayAddressRequest)
|
- input: [PayAddressRequest](#PayAddressRequest)
|
||||||
- output: [PayAddressResponse](#PayAddressResponse)
|
- output: [PayAddressResponse](#PayAddressResponse)
|
||||||
|
|
||||||
|
- PayAdminInvoiceSwap
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [PayAdminInvoiceSwapRequest](#PayAdminInvoiceSwapRequest)
|
||||||
|
- output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse)
|
||||||
|
|
||||||
- PayAdminTransactionSwap
|
- PayAdminTransactionSwap
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- input: [PayAdminTransactionSwapRequest](#PayAdminTransactionSwapRequest)
|
- input: [PayAdminTransactionSwapRequest](#PayAdminTransactionSwapRequest)
|
||||||
- output: [AdminSwapResponse](#AdminSwapResponse)
|
- output: [AdminTxSwapResponse](#AdminTxSwapResponse)
|
||||||
|
|
||||||
- PayInvoice
|
- PayInvoice
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
|
|
@ -305,6 +330,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- RefundAdminInvoiceSwap
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [RefundAdminInvoiceSwapRequest](#RefundAdminInvoiceSwapRequest)
|
||||||
|
- output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse)
|
||||||
|
|
||||||
- ResetDebit
|
- ResetDebit
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- input: [DebitOperation](#DebitOperation)
|
- input: [DebitOperation](#DebitOperation)
|
||||||
|
|
@ -484,6 +514,13 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- BumpTx
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/tx/bump__
|
||||||
|
- input: [BumpTx](#BumpTx)
|
||||||
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- CloseChannel
|
- CloseChannel
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
|
|
@ -540,6 +577,13 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [MessagingToken](#MessagingToken)
|
- input: [MessagingToken](#MessagingToken)
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- GetAdminInvoiceSwapQuotes
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/swap/invoice/quote__
|
||||||
|
- input: [InvoiceSwapRequest](#InvoiceSwapRequest)
|
||||||
|
- output: [InvoiceSwapQuoteList](#InvoiceSwapQuoteList)
|
||||||
|
|
||||||
- GetAdminTransactionSwapQuotes
|
- GetAdminTransactionSwapQuotes
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
|
|
@ -575,6 +619,13 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
||||||
- output: [AppsMetrics](#AppsMetrics)
|
- output: [AppsMetrics](#AppsMetrics)
|
||||||
|
|
||||||
|
- GetAssetsAndLiabilities
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/assets/liabilities__
|
||||||
|
- input: [AssetsAndLiabilitiesReq](#AssetsAndLiabilitiesReq)
|
||||||
|
- output: [AssetsAndLiabilities](#AssetsAndLiabilities)
|
||||||
|
|
||||||
- GetBundleMetrics
|
- GetBundleMetrics
|
||||||
- auth type: __Metrics__
|
- auth type: __Metrics__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
|
|
@ -743,7 +794,7 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- GetTransactionSwapQuotes
|
- GetTransactionSwapQuotes
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/api/user/swap/quote__
|
- http route: __/api/user/swap/transaction/quote__
|
||||||
- input: [TransactionSwapRequest](#TransactionSwapRequest)
|
- input: [TransactionSwapRequest](#TransactionSwapRequest)
|
||||||
- output: [TransactionSwapQuoteList](#TransactionSwapQuoteList)
|
- output: [TransactionSwapQuoteList](#TransactionSwapQuoteList)
|
||||||
|
|
||||||
|
|
@ -834,12 +885,19 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- ListAdminSwaps
|
- ListAdminInvoiceSwaps
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/api/admin/swap/list__
|
- http route: __/api/admin/swap/invoice/list__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [SwapsList](#SwapsList)
|
- output: [InvoiceSwapsList](#InvoiceSwapsList)
|
||||||
|
|
||||||
|
- ListAdminTxSwaps
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/swap/transaction/list__
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [TxSwapsList](#TxSwapsList)
|
||||||
|
|
||||||
- ListChannels
|
- ListChannels
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
|
|
@ -848,12 +906,12 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [LndChannels](#LndChannels)
|
- output: [LndChannels](#LndChannels)
|
||||||
|
|
||||||
- ListSwaps
|
- ListTxSwaps
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/api/user/swap/list__
|
- http route: __/api/user/swap/transaction/list__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [SwapsList](#SwapsList)
|
- output: [TxSwapsList](#TxSwapsList)
|
||||||
|
|
||||||
- LndGetInfo
|
- LndGetInfo
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
|
|
@ -899,12 +957,19 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [PayAddressRequest](#PayAddressRequest)
|
- input: [PayAddressRequest](#PayAddressRequest)
|
||||||
- output: [PayAddressResponse](#PayAddressResponse)
|
- output: [PayAddressResponse](#PayAddressResponse)
|
||||||
|
|
||||||
|
- PayAdminInvoiceSwap
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/swap/invoice/pay__
|
||||||
|
- input: [PayAdminInvoiceSwapRequest](#PayAdminInvoiceSwapRequest)
|
||||||
|
- output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse)
|
||||||
|
|
||||||
- PayAdminTransactionSwap
|
- PayAdminTransactionSwap
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/api/admin/swap/transaction/pay__
|
- http route: __/api/admin/swap/transaction/pay__
|
||||||
- input: [PayAdminTransactionSwapRequest](#PayAdminTransactionSwapRequest)
|
- input: [PayAdminTransactionSwapRequest](#PayAdminTransactionSwapRequest)
|
||||||
- output: [AdminSwapResponse](#AdminSwapResponse)
|
- output: [AdminTxSwapResponse](#AdminTxSwapResponse)
|
||||||
|
|
||||||
- PayAppUserInvoice
|
- PayAppUserInvoice
|
||||||
- auth type: __App__
|
- auth type: __App__
|
||||||
|
|
@ -927,6 +992,13 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- RefundAdminInvoiceSwap
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/swap/invoice/refund__
|
||||||
|
- input: [RefundAdminInvoiceSwapRequest](#RefundAdminInvoiceSwapRequest)
|
||||||
|
- output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse)
|
||||||
|
|
||||||
- RequestNPubLinkingToken
|
- RequestNPubLinkingToken
|
||||||
- auth type: __App__
|
- auth type: __App__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
|
|
@ -1098,7 +1170,10 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __name__: _string_
|
- __name__: _string_
|
||||||
- __price_sats__: _number_
|
- __price_sats__: _number_
|
||||||
|
|
||||||
### AdminSwapResponse
|
### AdminInvoiceSwapResponse
|
||||||
|
- __tx_id__: _string_
|
||||||
|
|
||||||
|
### AdminTxSwapResponse
|
||||||
- __network_fee__: _number_
|
- __network_fee__: _number_
|
||||||
- __tx_id__: _string_
|
- __tx_id__: _string_
|
||||||
|
|
||||||
|
|
@ -1135,6 +1210,21 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __include_operations__: _boolean_ *this field is optional
|
- __include_operations__: _boolean_ *this field is optional
|
||||||
- __to_unix__: _number_ *this field is optional
|
- __to_unix__: _number_ *this field is optional
|
||||||
|
|
||||||
|
### AssetOperation
|
||||||
|
- __amount__: _number_
|
||||||
|
- __tracked__: _[TrackedOperation](#TrackedOperation)_ *this field is optional
|
||||||
|
- __ts__: _number_
|
||||||
|
|
||||||
|
### AssetsAndLiabilities
|
||||||
|
- __liquidity_providers__: ARRAY of: _[LiquidityAssetProvider](#LiquidityAssetProvider)_
|
||||||
|
- __lnds__: ARRAY of: _[LndAssetProvider](#LndAssetProvider)_
|
||||||
|
- __users_balance__: _number_
|
||||||
|
|
||||||
|
### AssetsAndLiabilitiesReq
|
||||||
|
- __limit_invoices__: _number_ *this field is optional
|
||||||
|
- __limit_payments__: _number_ *this field is optional
|
||||||
|
- __limit_providers__: _number_ *this field is optional
|
||||||
|
|
||||||
### AuthApp
|
### AuthApp
|
||||||
- __app__: _[Application](#Application)_
|
- __app__: _[Application](#Application)_
|
||||||
- __auth_token__: _string_
|
- __auth_token__: _string_
|
||||||
|
|
@ -1163,6 +1253,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __nextRelay__: _string_ *this field is optional
|
- __nextRelay__: _string_ *this field is optional
|
||||||
- __type__: _string_
|
- __type__: _string_
|
||||||
|
|
||||||
|
### BumpTx
|
||||||
|
- __output_index__: _number_
|
||||||
|
- __sat_per_vbyte__: _number_
|
||||||
|
- __txid__: _string_
|
||||||
|
|
||||||
### BundleData
|
### BundleData
|
||||||
- __available_chunks__: ARRAY of: _number_
|
- __available_chunks__: ARRAY of: _number_
|
||||||
- __base_64_data__: ARRAY of: _string_
|
- __base_64_data__: ARRAY of: _string_
|
||||||
|
|
@ -1331,6 +1426,39 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __token__: _string_
|
- __token__: _string_
|
||||||
- __url__: _string_
|
- __url__: _string_
|
||||||
|
|
||||||
|
### InvoiceSwapOperation
|
||||||
|
- __completed_at_unix__: _number_ *this field is optional
|
||||||
|
- __failure_reason__: _string_ *this field is optional
|
||||||
|
- __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional
|
||||||
|
- __quote__: _[InvoiceSwapQuote](#InvoiceSwapQuote)_
|
||||||
|
- __refund_address__: _string_ *this field is optional
|
||||||
|
- __refund_at_unix__: _number_ *this field is optional
|
||||||
|
- __refund_tx_id__: _string_ *this field is optional
|
||||||
|
|
||||||
|
### InvoiceSwapQuote
|
||||||
|
- __address__: _string_
|
||||||
|
- __chain_fee_sats__: _number_
|
||||||
|
- __expires_at_block_height__: _number_
|
||||||
|
- __invoice__: _string_
|
||||||
|
- __invoice_amount_sats__: _number_
|
||||||
|
- __paid_at_unix__: _number_
|
||||||
|
- __service_fee_sats__: _number_
|
||||||
|
- __service_url__: _string_
|
||||||
|
- __swap_fee_sats__: _number_
|
||||||
|
- __swap_operation_id__: _string_
|
||||||
|
- __transaction_amount_sats__: _number_
|
||||||
|
- __tx_id__: _string_
|
||||||
|
|
||||||
|
### InvoiceSwapQuoteList
|
||||||
|
- __quotes__: ARRAY of: _[InvoiceSwapQuote](#InvoiceSwapQuote)_
|
||||||
|
|
||||||
|
### InvoiceSwapRequest
|
||||||
|
- __amount_sats__: _number_
|
||||||
|
|
||||||
|
### InvoiceSwapsList
|
||||||
|
- __current_block_height__: _number_
|
||||||
|
- __swaps__: ARRAY of: _[InvoiceSwapOperation](#InvoiceSwapOperation)_
|
||||||
|
|
||||||
### LatestBundleMetricReq
|
### LatestBundleMetricReq
|
||||||
- __limit__: _number_ *this field is optional
|
- __limit__: _number_ *this field is optional
|
||||||
|
|
||||||
|
|
@ -1340,6 +1468,10 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
### LinkNPubThroughTokenRequest
|
### LinkNPubThroughTokenRequest
|
||||||
- __token__: _string_
|
- __token__: _string_
|
||||||
|
|
||||||
|
### LiquidityAssetProvider
|
||||||
|
- __pubkey__: _string_
|
||||||
|
- __tracked__: _[TrackedLiquidityProvider](#TrackedLiquidityProvider)_ *this field is optional
|
||||||
|
|
||||||
### LiveDebitRequest
|
### LiveDebitRequest
|
||||||
- __debit__: _[LiveDebitRequest_debit](#LiveDebitRequest_debit)_
|
- __debit__: _[LiveDebitRequest_debit](#LiveDebitRequest_debit)_
|
||||||
- __npub__: _string_
|
- __npub__: _string_
|
||||||
|
|
@ -1353,6 +1485,10 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __latest_balance__: _number_
|
- __latest_balance__: _number_
|
||||||
- __operation__: _[UserOperation](#UserOperation)_
|
- __operation__: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### LndAssetProvider
|
||||||
|
- __pubkey__: _string_
|
||||||
|
- __tracked__: _[TrackedLndProvider](#TrackedLndProvider)_ *this field is optional
|
||||||
|
|
||||||
### LndChannels
|
### LndChannels
|
||||||
- __open_channels__: ARRAY of: _[OpenChannel](#OpenChannel)_
|
- __open_channels__: ARRAY of: _[OpenChannel](#OpenChannel)_
|
||||||
|
|
||||||
|
|
@ -1534,6 +1670,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __service_fee__: _number_
|
- __service_fee__: _number_
|
||||||
- __txId__: _string_
|
- __txId__: _string_
|
||||||
|
|
||||||
|
### PayAdminInvoiceSwapRequest
|
||||||
|
- __no_claim__: _boolean_ *this field is optional
|
||||||
|
- __sat_per_v_byte__: _number_
|
||||||
|
- __swap_operation_id__: _string_
|
||||||
|
|
||||||
### PayAdminTransactionSwapRequest
|
### PayAdminTransactionSwapRequest
|
||||||
- __address__: _string_
|
- __address__: _string_
|
||||||
- __swap_operation_id__: _string_
|
- __swap_operation_id__: _string_
|
||||||
|
|
@ -1584,6 +1725,18 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
### ProvidersDisruption
|
### ProvidersDisruption
|
||||||
- __disruptions__: ARRAY of: _[ProviderDisruption](#ProviderDisruption)_
|
- __disruptions__: ARRAY of: _[ProviderDisruption](#ProviderDisruption)_
|
||||||
|
|
||||||
|
### PushNotificationEnvelope
|
||||||
|
- __app_npub_hex__: _string_
|
||||||
|
- __encrypted_payload__: _string_
|
||||||
|
- __topic_id__: _string_
|
||||||
|
|
||||||
|
### PushNotificationPayload
|
||||||
|
- __data__: _[PushNotificationPayload_data](#PushNotificationPayload_data)_
|
||||||
|
|
||||||
|
### RefundAdminInvoiceSwapRequest
|
||||||
|
- __sat_per_v_byte__: _number_
|
||||||
|
- __swap_operation_id__: _string_
|
||||||
|
|
||||||
### RelaysMigration
|
### RelaysMigration
|
||||||
- __relays__: ARRAY of: _string_
|
- __relays__: ARRAY of: _string_
|
||||||
|
|
||||||
|
|
@ -1640,19 +1793,31 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __page__: _number_
|
- __page__: _number_
|
||||||
- __request_id__: _number_ *this field is optional
|
- __request_id__: _number_ *this field is optional
|
||||||
|
|
||||||
### SwapOperation
|
### TrackedLiquidityProvider
|
||||||
- __address_paid__: _string_
|
- __balance__: _number_
|
||||||
- __failure_reason__: _string_ *this field is optional
|
- __invoices__: ARRAY of: _[AssetOperation](#AssetOperation)_
|
||||||
- __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional
|
- __payments__: ARRAY of: _[AssetOperation](#AssetOperation)_
|
||||||
- __swap_operation_id__: _string_
|
|
||||||
|
|
||||||
### SwapsList
|
### TrackedLndProvider
|
||||||
- __quotes__: ARRAY of: _[TransactionSwapQuote](#TransactionSwapQuote)_
|
- __channels_balance__: _number_
|
||||||
- __swaps__: ARRAY of: _[SwapOperation](#SwapOperation)_
|
- __confirmed_balance__: _number_
|
||||||
|
- __incoming_tx__: ARRAY of: _[AssetOperation](#AssetOperation)_
|
||||||
|
- __invoices__: ARRAY of: _[AssetOperation](#AssetOperation)_
|
||||||
|
- __outgoing_tx__: ARRAY of: _[AssetOperation](#AssetOperation)_
|
||||||
|
- __payments__: ARRAY of: _[AssetOperation](#AssetOperation)_
|
||||||
|
- __unconfirmed_balance__: _number_
|
||||||
|
|
||||||
|
### TrackedOperation
|
||||||
|
- __amount__: _number_
|
||||||
|
- __ts__: _number_
|
||||||
|
- __type__: _[TrackedOperationType](#TrackedOperationType)_
|
||||||
|
|
||||||
### TransactionSwapQuote
|
### TransactionSwapQuote
|
||||||
- __chain_fee_sats__: _number_
|
- __chain_fee_sats__: _number_
|
||||||
|
- __completed_at_unix__: _number_
|
||||||
|
- __expires_at_block_height__: _number_
|
||||||
- __invoice_amount_sats__: _number_
|
- __invoice_amount_sats__: _number_
|
||||||
|
- __paid_at_unix__: _number_
|
||||||
- __service_fee_sats__: _number_
|
- __service_fee_sats__: _number_
|
||||||
- __service_url__: _string_
|
- __service_url__: _string_
|
||||||
- __swap_fee_sats__: _number_
|
- __swap_fee_sats__: _number_
|
||||||
|
|
@ -1665,6 +1830,16 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
### TransactionSwapRequest
|
### TransactionSwapRequest
|
||||||
- __transaction_amount_sats__: _number_
|
- __transaction_amount_sats__: _number_
|
||||||
|
|
||||||
|
### TxSwapOperation
|
||||||
|
- __address_paid__: _string_ *this field is optional
|
||||||
|
- __failure_reason__: _string_ *this field is optional
|
||||||
|
- __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional
|
||||||
|
- __quote__: _[TransactionSwapQuote](#TransactionSwapQuote)_
|
||||||
|
- __tx_id__: _string_ *this field is optional
|
||||||
|
|
||||||
|
### TxSwapsList
|
||||||
|
- __swaps__: ARRAY of: _[TxSwapOperation](#TxSwapOperation)_
|
||||||
|
|
||||||
### UpdateChannelPolicyRequest
|
### UpdateChannelPolicyRequest
|
||||||
- __policy__: _[ChannelPolicy](#ChannelPolicy)_
|
- __policy__: _[ChannelPolicy](#ChannelPolicy)_
|
||||||
- __update__: _[UpdateChannelPolicyRequest_update](#UpdateChannelPolicyRequest_update)_
|
- __update__: _[UpdateChannelPolicyRequest_update](#UpdateChannelPolicyRequest_update)_
|
||||||
|
|
@ -1707,6 +1882,7 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __nmanage__: _string_
|
- __nmanage__: _string_
|
||||||
- __noffer__: _string_
|
- __noffer__: _string_
|
||||||
- __service_fee_bps__: _number_
|
- __service_fee_bps__: _number_
|
||||||
|
- __topic_id__: _string_
|
||||||
- __userId__: _string_
|
- __userId__: _string_
|
||||||
- __user_identifier__: _string_
|
- __user_identifier__: _string_
|
||||||
|
|
||||||
|
|
@ -1771,6 +1947,10 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __BUNDLE_METRIC__
|
- __BUNDLE_METRIC__
|
||||||
- __USAGE_METRIC__
|
- __USAGE_METRIC__
|
||||||
|
|
||||||
|
### TrackedOperationType
|
||||||
|
- __ROOT__
|
||||||
|
- __USER__
|
||||||
|
|
||||||
### UserOperationType
|
### UserOperationType
|
||||||
- __INCOMING_INVOICE__
|
- __INCOMING_INVOICE__
|
||||||
- __INCOMING_TX__
|
- __INCOMING_TX__
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ type Client struct {
|
||||||
BanDebit func(req DebitOperation) error
|
BanDebit func(req DebitOperation) error
|
||||||
BanUser func(req BanUserRequest) (*BanUserResponse, error)
|
BanUser func(req BanUserRequest) (*BanUserResponse, error)
|
||||||
// batching method: BatchUser not implemented
|
// batching method: BatchUser not implemented
|
||||||
|
BumpTx func(req BumpTx) error
|
||||||
CloseChannel func(req CloseChannelRequest) (*CloseChannelResponse, error)
|
CloseChannel func(req CloseChannelRequest) (*CloseChannelResponse, error)
|
||||||
CreateOneTimeInviteLink func(req CreateOneTimeInviteLinkRequest) (*CreateOneTimeInviteLinkResponse, error)
|
CreateOneTimeInviteLink func(req CreateOneTimeInviteLinkRequest) (*CreateOneTimeInviteLinkResponse, error)
|
||||||
DecodeInvoice func(req DecodeInvoiceRequest) (*DecodeInvoiceResponse, error)
|
DecodeInvoice func(req DecodeInvoiceRequest) (*DecodeInvoiceResponse, error)
|
||||||
|
|
@ -74,11 +75,13 @@ type Client struct {
|
||||||
EncryptionExchange func(req EncryptionExchangeRequest) error
|
EncryptionExchange func(req EncryptionExchangeRequest) error
|
||||||
EnrollAdminToken func(req EnrollAdminTokenRequest) error
|
EnrollAdminToken func(req EnrollAdminTokenRequest) error
|
||||||
EnrollMessagingToken func(req MessagingToken) error
|
EnrollMessagingToken func(req MessagingToken) error
|
||||||
|
GetAdminInvoiceSwapQuotes func(req InvoiceSwapRequest) (*InvoiceSwapQuoteList, error)
|
||||||
GetAdminTransactionSwapQuotes func(req TransactionSwapRequest) (*TransactionSwapQuoteList, error)
|
GetAdminTransactionSwapQuotes func(req TransactionSwapRequest) (*TransactionSwapQuoteList, error)
|
||||||
GetApp func() (*Application, error)
|
GetApp func() (*Application, error)
|
||||||
GetAppUser func(req GetAppUserRequest) (*AppUser, error)
|
GetAppUser func(req GetAppUserRequest) (*AppUser, error)
|
||||||
GetAppUserLNURLInfo func(req GetAppUserLNURLInfoRequest) (*LnurlPayInfoResponse, error)
|
GetAppUserLNURLInfo func(req GetAppUserLNURLInfoRequest) (*LnurlPayInfoResponse, error)
|
||||||
GetAppsMetrics func(req AppsMetricsRequest) (*AppsMetrics, error)
|
GetAppsMetrics func(req AppsMetricsRequest) (*AppsMetrics, error)
|
||||||
|
GetAssetsAndLiabilities func(req AssetsAndLiabilitiesReq) (*AssetsAndLiabilities, error)
|
||||||
GetBundleMetrics func(req LatestBundleMetricReq) (*BundleMetrics, error)
|
GetBundleMetrics func(req LatestBundleMetricReq) (*BundleMetrics, error)
|
||||||
GetDebitAuthorizations func() (*DebitAuthorizations, error)
|
GetDebitAuthorizations func() (*DebitAuthorizations, error)
|
||||||
GetErrorStats func() (*ErrorStats, error)
|
GetErrorStats func() (*ErrorStats, error)
|
||||||
|
|
@ -114,19 +117,22 @@ type Client struct {
|
||||||
HandleLnurlWithdraw func(query HandleLnurlWithdraw_Query) error
|
HandleLnurlWithdraw func(query HandleLnurlWithdraw_Query) error
|
||||||
Health func() error
|
Health func() error
|
||||||
LinkNPubThroughToken func(req LinkNPubThroughTokenRequest) error
|
LinkNPubThroughToken func(req LinkNPubThroughTokenRequest) error
|
||||||
ListAdminSwaps func() (*SwapsList, error)
|
ListAdminInvoiceSwaps func() (*InvoiceSwapsList, error)
|
||||||
|
ListAdminTxSwaps func() (*TxSwapsList, error)
|
||||||
ListChannels func() (*LndChannels, error)
|
ListChannels func() (*LndChannels, error)
|
||||||
ListSwaps func() (*SwapsList, error)
|
ListTxSwaps func() (*TxSwapsList, error)
|
||||||
LndGetInfo func(req LndGetInfoRequest) (*LndGetInfoResponse, error)
|
LndGetInfo func(req LndGetInfoRequest) (*LndGetInfoResponse, error)
|
||||||
NewAddress func(req NewAddressRequest) (*NewAddressResponse, error)
|
NewAddress func(req NewAddressRequest) (*NewAddressResponse, error)
|
||||||
NewInvoice func(req NewInvoiceRequest) (*NewInvoiceResponse, error)
|
NewInvoice func(req NewInvoiceRequest) (*NewInvoiceResponse, error)
|
||||||
NewProductInvoice func(query NewProductInvoice_Query) (*NewInvoiceResponse, error)
|
NewProductInvoice func(query NewProductInvoice_Query) (*NewInvoiceResponse, error)
|
||||||
OpenChannel func(req OpenChannelRequest) (*OpenChannelResponse, error)
|
OpenChannel func(req OpenChannelRequest) (*OpenChannelResponse, error)
|
||||||
PayAddress func(req PayAddressRequest) (*PayAddressResponse, error)
|
PayAddress func(req PayAddressRequest) (*PayAddressResponse, error)
|
||||||
PayAdminTransactionSwap func(req PayAdminTransactionSwapRequest) (*AdminSwapResponse, error)
|
PayAdminInvoiceSwap func(req PayAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error)
|
||||||
|
PayAdminTransactionSwap func(req PayAdminTransactionSwapRequest) (*AdminTxSwapResponse, error)
|
||||||
PayAppUserInvoice func(req PayAppUserInvoiceRequest) (*PayInvoiceResponse, error)
|
PayAppUserInvoice func(req PayAppUserInvoiceRequest) (*PayInvoiceResponse, error)
|
||||||
PayInvoice func(req PayInvoiceRequest) (*PayInvoiceResponse, error)
|
PayInvoice func(req PayInvoiceRequest) (*PayInvoiceResponse, error)
|
||||||
PingSubProcesses func() error
|
PingSubProcesses func() error
|
||||||
|
RefundAdminInvoiceSwap func(req RefundAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error)
|
||||||
RequestNPubLinkingToken func(req RequestNPubLinkingTokenRequest) (*RequestNPubLinkingTokenResponse, error)
|
RequestNPubLinkingToken func(req RequestNPubLinkingTokenRequest) (*RequestNPubLinkingTokenResponse, error)
|
||||||
ResetDebit func(req DebitOperation) error
|
ResetDebit func(req DebitOperation) error
|
||||||
ResetManage func(req ManageOperation) error
|
ResetManage func(req ManageOperation) error
|
||||||
|
|
@ -460,6 +466,30 @@ func NewClient(params ClientParams) *Client {
|
||||||
return &res, nil
|
return &res, nil
|
||||||
},
|
},
|
||||||
// batching method: BatchUser not implemented
|
// batching method: BatchUser not implemented
|
||||||
|
BumpTx: func(req BumpTx) error {
|
||||||
|
auth, err := params.RetrieveAdminAuth()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/admin/tx/bump"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
CloseChannel: func(req CloseChannelRequest) (*CloseChannelResponse, error) {
|
CloseChannel: func(req CloseChannelRequest) (*CloseChannelResponse, error) {
|
||||||
auth, err := params.RetrieveAdminAuth()
|
auth, err := params.RetrieveAdminAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -667,6 +697,35 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
GetAdminInvoiceSwapQuotes: func(req InvoiceSwapRequest) (*InvoiceSwapQuoteList, error) {
|
||||||
|
auth, err := params.RetrieveAdminAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/admin/swap/invoice/quote"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := InvoiceSwapQuoteList{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
GetAdminTransactionSwapQuotes: func(req TransactionSwapRequest) (*TransactionSwapQuoteList, error) {
|
GetAdminTransactionSwapQuotes: func(req TransactionSwapRequest) (*TransactionSwapQuoteList, error) {
|
||||||
auth, err := params.RetrieveAdminAuth()
|
auth, err := params.RetrieveAdminAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -809,6 +868,35 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return &res, nil
|
return &res, nil
|
||||||
},
|
},
|
||||||
|
GetAssetsAndLiabilities: func(req AssetsAndLiabilitiesReq) (*AssetsAndLiabilities, error) {
|
||||||
|
auth, err := params.RetrieveAdminAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/admin/assets/liabilities"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := AssetsAndLiabilities{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
GetBundleMetrics: func(req LatestBundleMetricReq) (*BundleMetrics, error) {
|
GetBundleMetrics: func(req LatestBundleMetricReq) (*BundleMetrics, error) {
|
||||||
auth, err := params.RetrieveMetricsAuth()
|
auth, err := params.RetrieveMetricsAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1324,7 +1412,7 @@ func NewClient(params ClientParams) *Client {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
finalRoute := "/api/user/swap/quote"
|
finalRoute := "/api/user/swap/transaction/quote"
|
||||||
body, err := json.Marshal(req)
|
body, err := json.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1643,12 +1731,12 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ListAdminSwaps: func() (*SwapsList, error) {
|
ListAdminInvoiceSwaps: func() (*InvoiceSwapsList, error) {
|
||||||
auth, err := params.RetrieveAdminAuth()
|
auth, err := params.RetrieveAdminAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
finalRoute := "/api/admin/swap/list"
|
finalRoute := "/api/admin/swap/invoice/list"
|
||||||
body := []byte{}
|
body := []byte{}
|
||||||
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1662,7 +1750,33 @@ func NewClient(params ClientParams) *Client {
|
||||||
if result.Status == "ERROR" {
|
if result.Status == "ERROR" {
|
||||||
return nil, fmt.Errorf(result.Reason)
|
return nil, fmt.Errorf(result.Reason)
|
||||||
}
|
}
|
||||||
res := SwapsList{}
|
res := InvoiceSwapsList{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
|
ListAdminTxSwaps: func() (*TxSwapsList, error) {
|
||||||
|
auth, err := params.RetrieveAdminAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/admin/swap/transaction/list"
|
||||||
|
body := []byte{}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := TxSwapsList{}
|
||||||
err = json.Unmarshal(resBody, &res)
|
err = json.Unmarshal(resBody, &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1691,12 +1805,12 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return &res, nil
|
return &res, nil
|
||||||
},
|
},
|
||||||
ListSwaps: func() (*SwapsList, error) {
|
ListTxSwaps: func() (*TxSwapsList, error) {
|
||||||
auth, err := params.RetrieveUserAuth()
|
auth, err := params.RetrieveUserAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
finalRoute := "/api/user/swap/list"
|
finalRoute := "/api/user/swap/transaction/list"
|
||||||
body := []byte{}
|
body := []byte{}
|
||||||
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1710,7 +1824,7 @@ func NewClient(params ClientParams) *Client {
|
||||||
if result.Status == "ERROR" {
|
if result.Status == "ERROR" {
|
||||||
return nil, fmt.Errorf(result.Reason)
|
return nil, fmt.Errorf(result.Reason)
|
||||||
}
|
}
|
||||||
res := SwapsList{}
|
res := TxSwapsList{}
|
||||||
err = json.Unmarshal(resBody, &res)
|
err = json.Unmarshal(resBody, &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1892,7 +2006,36 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return &res, nil
|
return &res, nil
|
||||||
},
|
},
|
||||||
PayAdminTransactionSwap: func(req PayAdminTransactionSwapRequest) (*AdminSwapResponse, error) {
|
PayAdminInvoiceSwap: func(req PayAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error) {
|
||||||
|
auth, err := params.RetrieveAdminAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/admin/swap/invoice/pay"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := AdminInvoiceSwapResponse{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
|
PayAdminTransactionSwap: func(req PayAdminTransactionSwapRequest) (*AdminTxSwapResponse, error) {
|
||||||
auth, err := params.RetrieveAdminAuth()
|
auth, err := params.RetrieveAdminAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1914,7 +2057,7 @@ func NewClient(params ClientParams) *Client {
|
||||||
if result.Status == "ERROR" {
|
if result.Status == "ERROR" {
|
||||||
return nil, fmt.Errorf(result.Reason)
|
return nil, fmt.Errorf(result.Reason)
|
||||||
}
|
}
|
||||||
res := AdminSwapResponse{}
|
res := AdminTxSwapResponse{}
|
||||||
err = json.Unmarshal(resBody, &res)
|
err = json.Unmarshal(resBody, &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -2000,6 +2143,35 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
RefundAdminInvoiceSwap: func(req RefundAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error) {
|
||||||
|
auth, err := params.RetrieveAdminAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/admin/swap/invoice/refund"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := AdminInvoiceSwapResponse{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
RequestNPubLinkingToken: func(req RequestNPubLinkingTokenRequest) (*RequestNPubLinkingTokenResponse, error) {
|
RequestNPubLinkingToken: func(req RequestNPubLinkingTokenRequest) (*RequestNPubLinkingTokenResponse, error) {
|
||||||
auth, err := params.RetrieveAppAuth()
|
auth, err := params.RetrieveAppAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,13 @@ const (
|
||||||
USAGE_METRIC SingleMetricType = "USAGE_METRIC"
|
USAGE_METRIC SingleMetricType = "USAGE_METRIC"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TrackedOperationType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ROOT TrackedOperationType = "ROOT"
|
||||||
|
USER TrackedOperationType = "USER"
|
||||||
|
)
|
||||||
|
|
||||||
type UserOperationType string
|
type UserOperationType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -123,7 +130,10 @@ type AddProductRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Price_sats int64 `json:"price_sats"`
|
Price_sats int64 `json:"price_sats"`
|
||||||
}
|
}
|
||||||
type AdminSwapResponse struct {
|
type AdminInvoiceSwapResponse struct {
|
||||||
|
Tx_id string `json:"tx_id"`
|
||||||
|
}
|
||||||
|
type AdminTxSwapResponse struct {
|
||||||
Network_fee int64 `json:"network_fee"`
|
Network_fee int64 `json:"network_fee"`
|
||||||
Tx_id string `json:"tx_id"`
|
Tx_id string `json:"tx_id"`
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +170,21 @@ type AppsMetricsRequest struct {
|
||||||
Include_operations bool `json:"include_operations"`
|
Include_operations bool `json:"include_operations"`
|
||||||
To_unix int64 `json:"to_unix"`
|
To_unix int64 `json:"to_unix"`
|
||||||
}
|
}
|
||||||
|
type AssetOperation struct {
|
||||||
|
Amount int64 `json:"amount"`
|
||||||
|
Tracked *TrackedOperation `json:"tracked"`
|
||||||
|
Ts int64 `json:"ts"`
|
||||||
|
}
|
||||||
|
type AssetsAndLiabilities struct {
|
||||||
|
Liquidity_providers []LiquidityAssetProvider `json:"liquidity_providers"`
|
||||||
|
Lnds []LndAssetProvider `json:"lnds"`
|
||||||
|
Users_balance int64 `json:"users_balance"`
|
||||||
|
}
|
||||||
|
type AssetsAndLiabilitiesReq struct {
|
||||||
|
Limit_invoices int64 `json:"limit_invoices"`
|
||||||
|
Limit_payments int64 `json:"limit_payments"`
|
||||||
|
Limit_providers int64 `json:"limit_providers"`
|
||||||
|
}
|
||||||
type AuthApp struct {
|
type AuthApp struct {
|
||||||
App *Application `json:"app"`
|
App *Application `json:"app"`
|
||||||
Auth_token string `json:"auth_token"`
|
Auth_token string `json:"auth_token"`
|
||||||
|
|
@ -188,6 +213,11 @@ type BeaconData struct {
|
||||||
Nextrelay string `json:"nextRelay"`
|
Nextrelay string `json:"nextRelay"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
type BumpTx struct {
|
||||||
|
Output_index int64 `json:"output_index"`
|
||||||
|
Sat_per_vbyte int64 `json:"sat_per_vbyte"`
|
||||||
|
Txid string `json:"txid"`
|
||||||
|
}
|
||||||
type BundleData struct {
|
type BundleData struct {
|
||||||
Available_chunks []int64 `json:"available_chunks"`
|
Available_chunks []int64 `json:"available_chunks"`
|
||||||
Base_64_data []string `json:"base_64_data"`
|
Base_64_data []string `json:"base_64_data"`
|
||||||
|
|
@ -356,6 +386,39 @@ type HttpCreds struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
}
|
}
|
||||||
|
type InvoiceSwapOperation struct {
|
||||||
|
Completed_at_unix int64 `json:"completed_at_unix"`
|
||||||
|
Failure_reason string `json:"failure_reason"`
|
||||||
|
Operation_payment *UserOperation `json:"operation_payment"`
|
||||||
|
Quote *InvoiceSwapQuote `json:"quote"`
|
||||||
|
Refund_address string `json:"refund_address"`
|
||||||
|
Refund_at_unix int64 `json:"refund_at_unix"`
|
||||||
|
Refund_tx_id string `json:"refund_tx_id"`
|
||||||
|
}
|
||||||
|
type InvoiceSwapQuote struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
Chain_fee_sats int64 `json:"chain_fee_sats"`
|
||||||
|
Expires_at_block_height int64 `json:"expires_at_block_height"`
|
||||||
|
Invoice string `json:"invoice"`
|
||||||
|
Invoice_amount_sats int64 `json:"invoice_amount_sats"`
|
||||||
|
Paid_at_unix int64 `json:"paid_at_unix"`
|
||||||
|
Service_fee_sats int64 `json:"service_fee_sats"`
|
||||||
|
Service_url string `json:"service_url"`
|
||||||
|
Swap_fee_sats int64 `json:"swap_fee_sats"`
|
||||||
|
Swap_operation_id string `json:"swap_operation_id"`
|
||||||
|
Transaction_amount_sats int64 `json:"transaction_amount_sats"`
|
||||||
|
Tx_id string `json:"tx_id"`
|
||||||
|
}
|
||||||
|
type InvoiceSwapQuoteList struct {
|
||||||
|
Quotes []InvoiceSwapQuote `json:"quotes"`
|
||||||
|
}
|
||||||
|
type InvoiceSwapRequest struct {
|
||||||
|
Amount_sats int64 `json:"amount_sats"`
|
||||||
|
}
|
||||||
|
type InvoiceSwapsList struct {
|
||||||
|
Current_block_height int64 `json:"current_block_height"`
|
||||||
|
Swaps []InvoiceSwapOperation `json:"swaps"`
|
||||||
|
}
|
||||||
type LatestBundleMetricReq struct {
|
type LatestBundleMetricReq struct {
|
||||||
Limit int64 `json:"limit"`
|
Limit int64 `json:"limit"`
|
||||||
}
|
}
|
||||||
|
|
@ -365,6 +428,10 @@ type LatestUsageMetricReq struct {
|
||||||
type LinkNPubThroughTokenRequest struct {
|
type LinkNPubThroughTokenRequest struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
type LiquidityAssetProvider struct {
|
||||||
|
Pubkey string `json:"pubkey"`
|
||||||
|
Tracked *TrackedLiquidityProvider `json:"tracked"`
|
||||||
|
}
|
||||||
type LiveDebitRequest struct {
|
type LiveDebitRequest struct {
|
||||||
Debit *LiveDebitRequest_debit `json:"debit"`
|
Debit *LiveDebitRequest_debit `json:"debit"`
|
||||||
Npub string `json:"npub"`
|
Npub string `json:"npub"`
|
||||||
|
|
@ -378,6 +445,10 @@ type LiveUserOperation struct {
|
||||||
Latest_balance int64 `json:"latest_balance"`
|
Latest_balance int64 `json:"latest_balance"`
|
||||||
Operation *UserOperation `json:"operation"`
|
Operation *UserOperation `json:"operation"`
|
||||||
}
|
}
|
||||||
|
type LndAssetProvider struct {
|
||||||
|
Pubkey string `json:"pubkey"`
|
||||||
|
Tracked *TrackedLndProvider `json:"tracked"`
|
||||||
|
}
|
||||||
type LndChannels struct {
|
type LndChannels struct {
|
||||||
Open_channels []OpenChannel `json:"open_channels"`
|
Open_channels []OpenChannel `json:"open_channels"`
|
||||||
}
|
}
|
||||||
|
|
@ -559,6 +630,11 @@ type PayAddressResponse struct {
|
||||||
Service_fee int64 `json:"service_fee"`
|
Service_fee int64 `json:"service_fee"`
|
||||||
Txid string `json:"txId"`
|
Txid string `json:"txId"`
|
||||||
}
|
}
|
||||||
|
type PayAdminInvoiceSwapRequest struct {
|
||||||
|
No_claim bool `json:"no_claim"`
|
||||||
|
Sat_per_v_byte int64 `json:"sat_per_v_byte"`
|
||||||
|
Swap_operation_id string `json:"swap_operation_id"`
|
||||||
|
}
|
||||||
type PayAdminTransactionSwapRequest struct {
|
type PayAdminTransactionSwapRequest struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Swap_operation_id string `json:"swap_operation_id"`
|
Swap_operation_id string `json:"swap_operation_id"`
|
||||||
|
|
@ -609,6 +685,18 @@ type ProviderDisruption struct {
|
||||||
type ProvidersDisruption struct {
|
type ProvidersDisruption struct {
|
||||||
Disruptions []ProviderDisruption `json:"disruptions"`
|
Disruptions []ProviderDisruption `json:"disruptions"`
|
||||||
}
|
}
|
||||||
|
type PushNotificationEnvelope struct {
|
||||||
|
App_npub_hex string `json:"app_npub_hex"`
|
||||||
|
Encrypted_payload string `json:"encrypted_payload"`
|
||||||
|
Topic_id string `json:"topic_id"`
|
||||||
|
}
|
||||||
|
type PushNotificationPayload struct {
|
||||||
|
Data *PushNotificationPayload_data `json:"data"`
|
||||||
|
}
|
||||||
|
type RefundAdminInvoiceSwapRequest struct {
|
||||||
|
Sat_per_v_byte int64 `json:"sat_per_v_byte"`
|
||||||
|
Swap_operation_id string `json:"swap_operation_id"`
|
||||||
|
}
|
||||||
type RelaysMigration struct {
|
type RelaysMigration struct {
|
||||||
Relays []string `json:"relays"`
|
Relays []string `json:"relays"`
|
||||||
}
|
}
|
||||||
|
|
@ -665,19 +753,31 @@ type SingleMetricReq struct {
|
||||||
Page int64 `json:"page"`
|
Page int64 `json:"page"`
|
||||||
Request_id int64 `json:"request_id"`
|
Request_id int64 `json:"request_id"`
|
||||||
}
|
}
|
||||||
type SwapOperation struct {
|
type TrackedLiquidityProvider struct {
|
||||||
Address_paid string `json:"address_paid"`
|
Balance int64 `json:"balance"`
|
||||||
Failure_reason string `json:"failure_reason"`
|
Invoices []AssetOperation `json:"invoices"`
|
||||||
Operation_payment *UserOperation `json:"operation_payment"`
|
Payments []AssetOperation `json:"payments"`
|
||||||
Swap_operation_id string `json:"swap_operation_id"`
|
|
||||||
}
|
}
|
||||||
type SwapsList struct {
|
type TrackedLndProvider struct {
|
||||||
Quotes []TransactionSwapQuote `json:"quotes"`
|
Channels_balance int64 `json:"channels_balance"`
|
||||||
Swaps []SwapOperation `json:"swaps"`
|
Confirmed_balance int64 `json:"confirmed_balance"`
|
||||||
|
Incoming_tx []AssetOperation `json:"incoming_tx"`
|
||||||
|
Invoices []AssetOperation `json:"invoices"`
|
||||||
|
Outgoing_tx []AssetOperation `json:"outgoing_tx"`
|
||||||
|
Payments []AssetOperation `json:"payments"`
|
||||||
|
Unconfirmed_balance int64 `json:"unconfirmed_balance"`
|
||||||
|
}
|
||||||
|
type TrackedOperation struct {
|
||||||
|
Amount int64 `json:"amount"`
|
||||||
|
Ts int64 `json:"ts"`
|
||||||
|
Type TrackedOperationType `json:"type"`
|
||||||
}
|
}
|
||||||
type TransactionSwapQuote struct {
|
type TransactionSwapQuote struct {
|
||||||
Chain_fee_sats int64 `json:"chain_fee_sats"`
|
Chain_fee_sats int64 `json:"chain_fee_sats"`
|
||||||
|
Completed_at_unix int64 `json:"completed_at_unix"`
|
||||||
|
Expires_at_block_height int64 `json:"expires_at_block_height"`
|
||||||
Invoice_amount_sats int64 `json:"invoice_amount_sats"`
|
Invoice_amount_sats int64 `json:"invoice_amount_sats"`
|
||||||
|
Paid_at_unix int64 `json:"paid_at_unix"`
|
||||||
Service_fee_sats int64 `json:"service_fee_sats"`
|
Service_fee_sats int64 `json:"service_fee_sats"`
|
||||||
Service_url string `json:"service_url"`
|
Service_url string `json:"service_url"`
|
||||||
Swap_fee_sats int64 `json:"swap_fee_sats"`
|
Swap_fee_sats int64 `json:"swap_fee_sats"`
|
||||||
|
|
@ -690,6 +790,16 @@ type TransactionSwapQuoteList struct {
|
||||||
type TransactionSwapRequest struct {
|
type TransactionSwapRequest struct {
|
||||||
Transaction_amount_sats int64 `json:"transaction_amount_sats"`
|
Transaction_amount_sats int64 `json:"transaction_amount_sats"`
|
||||||
}
|
}
|
||||||
|
type TxSwapOperation struct {
|
||||||
|
Address_paid string `json:"address_paid"`
|
||||||
|
Failure_reason string `json:"failure_reason"`
|
||||||
|
Operation_payment *UserOperation `json:"operation_payment"`
|
||||||
|
Quote *TransactionSwapQuote `json:"quote"`
|
||||||
|
Tx_id string `json:"tx_id"`
|
||||||
|
}
|
||||||
|
type TxSwapsList struct {
|
||||||
|
Swaps []TxSwapOperation `json:"swaps"`
|
||||||
|
}
|
||||||
type UpdateChannelPolicyRequest struct {
|
type UpdateChannelPolicyRequest struct {
|
||||||
Policy *ChannelPolicy `json:"policy"`
|
Policy *ChannelPolicy `json:"policy"`
|
||||||
Update *UpdateChannelPolicyRequest_update `json:"update"`
|
Update *UpdateChannelPolicyRequest_update `json:"update"`
|
||||||
|
|
@ -732,6 +842,7 @@ type UserInfo struct {
|
||||||
Nmanage string `json:"nmanage"`
|
Nmanage string `json:"nmanage"`
|
||||||
Noffer string `json:"noffer"`
|
Noffer string `json:"noffer"`
|
||||||
Service_fee_bps int64 `json:"service_fee_bps"`
|
Service_fee_bps int64 `json:"service_fee_bps"`
|
||||||
|
Topic_id string `json:"topic_id"`
|
||||||
Userid string `json:"userId"`
|
Userid string `json:"userId"`
|
||||||
User_identifier string `json:"user_identifier"`
|
User_identifier string `json:"user_identifier"`
|
||||||
}
|
}
|
||||||
|
|
@ -830,6 +941,18 @@ type NPubLinking_state struct {
|
||||||
Linking_token *string `json:"linking_token"`
|
Linking_token *string `json:"linking_token"`
|
||||||
Unlinked *Empty `json:"unlinked"`
|
Unlinked *Empty `json:"unlinked"`
|
||||||
}
|
}
|
||||||
|
type PushNotificationPayload_data_type string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RECEIVED_OPERATION PushNotificationPayload_data_type = "received_operation"
|
||||||
|
SENT_OPERATION PushNotificationPayload_data_type = "sent_operation"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushNotificationPayload_data struct {
|
||||||
|
Type PushNotificationPayload_data_type `json:"type"`
|
||||||
|
Received_operation *UserOperation `json:"received_operation"`
|
||||||
|
Sent_operation *UserOperation `json:"sent_operation"`
|
||||||
|
}
|
||||||
type UpdateChannelPolicyRequest_update_type string
|
type UpdateChannelPolicyRequest_update_type string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
|
|
@ -545,12 +545,12 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'ListSwaps':
|
case 'ListTxSwaps':
|
||||||
if (!methods.ListSwaps) {
|
if (!methods.ListTxSwaps) {
|
||||||
throw new Error('method ListSwaps not found' )
|
throw new Error('method ListTxSwaps not found' )
|
||||||
} else {
|
} else {
|
||||||
opStats.validate = opStats.guard
|
opStats.validate = opStats.guard
|
||||||
const res = await methods.ListSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
const res = await methods.ListTxSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
||||||
opStats.handle = process.hrtime.bigint()
|
opStats.handle = process.hrtime.bigint()
|
||||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
}
|
}
|
||||||
|
|
@ -693,6 +693,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...ctx }, ...callsMetrics])
|
opts.metricsCallback([{ ...info, ...stats, ...ctx }, ...callsMetrics])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.BumpTx) throw new Error('method: BumpTx is not implemented')
|
||||||
|
app.post('/api/admin/tx/bump', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'BumpTx', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.BumpTx) throw new Error('method: BumpTx is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.BumpTxValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
await methods.BumpTx({rpcName:'BumpTx', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK'})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.CloseChannel) throw new Error('method: CloseChannel is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.CloseChannel) throw new Error('method: CloseChannel is not implemented')
|
||||||
app.post('/api/admin/channel/close', async (req, res) => {
|
app.post('/api/admin/channel/close', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'CloseChannel', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'CloseChannel', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -869,6 +891,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.GetAdminInvoiceSwapQuotes) throw new Error('method: GetAdminInvoiceSwapQuotes is not implemented')
|
||||||
|
app.post('/api/admin/swap/invoice/quote', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'GetAdminInvoiceSwapQuotes', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.GetAdminInvoiceSwapQuotes) throw new Error('method: GetAdminInvoiceSwapQuotes is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.InvoiceSwapRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.GetAdminInvoiceSwapQuotes({rpcName:'GetAdminInvoiceSwapQuotes', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.GetAdminTransactionSwapQuotes) throw new Error('method: GetAdminTransactionSwapQuotes is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetAdminTransactionSwapQuotes) throw new Error('method: GetAdminTransactionSwapQuotes is not implemented')
|
||||||
app.post('/api/admin/swap/transaction/quote', async (req, res) => {
|
app.post('/api/admin/swap/transaction/quote', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetAdminTransactionSwapQuotes', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetAdminTransactionSwapQuotes', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -976,6 +1020,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.GetAssetsAndLiabilities) throw new Error('method: GetAssetsAndLiabilities is not implemented')
|
||||||
|
app.post('/api/admin/assets/liabilities', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'GetAssetsAndLiabilities', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.GetAssetsAndLiabilities) throw new Error('method: GetAssetsAndLiabilities is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AssetsAndLiabilitiesReqValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.GetAssetsAndLiabilities({rpcName:'GetAssetsAndLiabilities', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.GetBundleMetrics) throw new Error('method: GetBundleMetrics is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetBundleMetrics) throw new Error('method: GetBundleMetrics is not implemented')
|
||||||
app.post('/api/reports/bundle', async (req, res) => {
|
app.post('/api/reports/bundle', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetBundleMetrics', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetBundleMetrics', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -1362,7 +1428,7 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.GetTransactionSwapQuotes) throw new Error('method: GetTransactionSwapQuotes is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetTransactionSwapQuotes) throw new Error('method: GetTransactionSwapQuotes is not implemented')
|
||||||
app.post('/api/user/swap/quote', async (req, res) => {
|
app.post('/api/user/swap/transaction/quote', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetTransactionSwapQuotes', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetTransactionSwapQuotes', batch: false, nostr: false, batchSize: 0}
|
||||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
let authCtx: Types.AuthContext = {}
|
let authCtx: Types.AuthContext = {}
|
||||||
|
|
@ -1607,20 +1673,39 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.ListAdminSwaps) throw new Error('method: ListAdminSwaps is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.ListAdminInvoiceSwaps) throw new Error('method: ListAdminInvoiceSwaps is not implemented')
|
||||||
app.post('/api/admin/swap/list', async (req, res) => {
|
app.post('/api/admin/swap/invoice/list', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'ListAdminSwaps', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'ListAdminInvoiceSwaps', batch: false, nostr: false, batchSize: 0}
|
||||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
let authCtx: Types.AuthContext = {}
|
let authCtx: Types.AuthContext = {}
|
||||||
try {
|
try {
|
||||||
if (!methods.ListAdminSwaps) throw new Error('method: ListAdminSwaps is not implemented')
|
if (!methods.ListAdminInvoiceSwaps) throw new Error('method: ListAdminInvoiceSwaps is not implemented')
|
||||||
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
stats.validate = stats.guard
|
stats.validate = stats.guard
|
||||||
const query = req.query
|
const query = req.query
|
||||||
const params = req.params
|
const params = req.params
|
||||||
const response = await methods.ListAdminSwaps({rpcName:'ListAdminSwaps', ctx:authContext })
|
const response = await methods.ListAdminInvoiceSwaps({rpcName:'ListAdminInvoiceSwaps', ctx:authContext })
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.ListAdminTxSwaps) throw new Error('method: ListAdminTxSwaps is not implemented')
|
||||||
|
app.post('/api/admin/swap/transaction/list', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'ListAdminTxSwaps', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.ListAdminTxSwaps) throw new Error('method: ListAdminTxSwaps is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
stats.validate = stats.guard
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.ListAdminTxSwaps({rpcName:'ListAdminTxSwaps', ctx:authContext })
|
||||||
stats.handle = process.hrtime.bigint()
|
stats.handle = process.hrtime.bigint()
|
||||||
res.json({status: 'OK', ...response})
|
res.json({status: 'OK', ...response})
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
|
@ -1645,20 +1730,20 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.ListSwaps) throw new Error('method: ListSwaps is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.ListTxSwaps) throw new Error('method: ListTxSwaps is not implemented')
|
||||||
app.post('/api/user/swap/list', async (req, res) => {
|
app.post('/api/user/swap/transaction/list', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'ListSwaps', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'ListTxSwaps', batch: false, nostr: false, batchSize: 0}
|
||||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
let authCtx: Types.AuthContext = {}
|
let authCtx: Types.AuthContext = {}
|
||||||
try {
|
try {
|
||||||
if (!methods.ListSwaps) throw new Error('method: ListSwaps is not implemented')
|
if (!methods.ListTxSwaps) throw new Error('method: ListTxSwaps is not implemented')
|
||||||
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
stats.validate = stats.guard
|
stats.validate = stats.guard
|
||||||
const query = req.query
|
const query = req.query
|
||||||
const params = req.params
|
const params = req.params
|
||||||
const response = await methods.ListSwaps({rpcName:'ListSwaps', ctx:authContext })
|
const response = await methods.ListTxSwaps({rpcName:'ListTxSwaps', ctx:authContext })
|
||||||
stats.handle = process.hrtime.bigint()
|
stats.handle = process.hrtime.bigint()
|
||||||
res.json({status: 'OK', ...response})
|
res.json({status: 'OK', ...response})
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
|
@ -1793,6 +1878,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.PayAdminInvoiceSwap) throw new Error('method: PayAdminInvoiceSwap is not implemented')
|
||||||
|
app.post('/api/admin/swap/invoice/pay', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'PayAdminInvoiceSwap', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.PayAdminInvoiceSwap) throw new Error('method: PayAdminInvoiceSwap is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.PayAdminInvoiceSwapRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.PayAdminInvoiceSwap({rpcName:'PayAdminInvoiceSwap', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.PayAdminTransactionSwap) throw new Error('method: PayAdminTransactionSwap is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.PayAdminTransactionSwap) throw new Error('method: PayAdminTransactionSwap is not implemented')
|
||||||
app.post('/api/admin/swap/transaction/pay', async (req, res) => {
|
app.post('/api/admin/swap/transaction/pay', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'PayAdminTransactionSwap', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'PayAdminTransactionSwap', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -1878,6 +1985,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.RefundAdminInvoiceSwap) throw new Error('method: RefundAdminInvoiceSwap is not implemented')
|
||||||
|
app.post('/api/admin/swap/invoice/refund', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'RefundAdminInvoiceSwap', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.RefundAdminInvoiceSwap) throw new Error('method: RefundAdminInvoiceSwap is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.RefundAdminInvoiceSwapRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.RefundAdminInvoiceSwap({rpcName:'RefundAdminInvoiceSwap', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.RequestNPubLinkingToken) throw new Error('method: RequestNPubLinkingToken is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.RequestNPubLinkingToken) throw new Error('method: RequestNPubLinkingToken is not implemented')
|
||||||
app.post('/api/app/user/npub/token', async (req, res) => {
|
app.post('/api/app/user/npub/token', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'RequestNPubLinkingToken', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'RequestNPubLinkingToken', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,17 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
BumpTx: async (request: Types.BumpTx): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/tx/bump'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
CloseChannel: async (request: Types.CloseChannelRequest): Promise<ResultError | ({ status: 'OK' }& Types.CloseChannelResponse)> => {
|
CloseChannel: async (request: Types.CloseChannelRequest): Promise<ResultError | ({ status: 'OK' }& Types.CloseChannelResponse)> => {
|
||||||
const auth = await params.retrieveAdminAuth()
|
const auth = await params.retrieveAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
|
@ -273,6 +284,20 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
GetAdminInvoiceSwapQuotes: async (request: Types.InvoiceSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.InvoiceSwapQuoteList)> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/swap/invoice/quote'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.InvoiceSwapQuoteListValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetAdminTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.TransactionSwapQuoteList)> => {
|
GetAdminTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.TransactionSwapQuoteList)> => {
|
||||||
const auth = await params.retrieveAdminAuth()
|
const auth = await params.retrieveAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
|
@ -343,6 +368,20 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
GetAssetsAndLiabilities: async (request: Types.AssetsAndLiabilitiesReq): Promise<ResultError | ({ status: 'OK' }& Types.AssetsAndLiabilities)> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/assets/liabilities'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AssetsAndLiabilitiesValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetBundleMetrics: async (request: Types.LatestBundleMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.BundleMetrics)> => {
|
GetBundleMetrics: async (request: Types.LatestBundleMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.BundleMetrics)> => {
|
||||||
const auth = await params.retrieveMetricsAuth()
|
const auth = await params.retrieveMetricsAuth()
|
||||||
if (auth === null) throw new Error('retrieveMetricsAuth() returned null')
|
if (auth === null) throw new Error('retrieveMetricsAuth() returned null')
|
||||||
|
|
@ -620,7 +659,7 @@ export default (params: ClientParams) => ({
|
||||||
GetTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.TransactionSwapQuoteList)> => {
|
GetTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.TransactionSwapQuoteList)> => {
|
||||||
const auth = await params.retrieveUserAuth()
|
const auth = await params.retrieveUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||||
let finalRoute = '/api/user/swap/quote'
|
let finalRoute = '/api/user/swap/transaction/quote'
|
||||||
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
|
|
@ -781,16 +820,30 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
ListAdminSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.SwapsList)> => {
|
ListAdminInvoiceSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.InvoiceSwapsList)> => {
|
||||||
const auth = await params.retrieveAdminAuth()
|
const auth = await params.retrieveAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
let finalRoute = '/api/admin/swap/list'
|
let finalRoute = '/api/admin/swap/invoice/list'
|
||||||
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
||||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.SwapsListValidate(result)
|
const error = Types.InvoiceSwapsListValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
ListAdminTxSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.TxSwapsList)> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/swap/transaction/list'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.TxSwapsListValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
@ -809,16 +862,16 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
ListSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.SwapsList)> => {
|
ListTxSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.TxSwapsList)> => {
|
||||||
const auth = await params.retrieveUserAuth()
|
const auth = await params.retrieveUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||||
let finalRoute = '/api/user/swap/list'
|
let finalRoute = '/api/user/swap/transaction/list'
|
||||||
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
||||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.SwapsListValidate(result)
|
const error = Types.TxSwapsListValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
@ -909,7 +962,21 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminSwapResponse)> => {
|
PayAdminInvoiceSwap: async (request: Types.PayAdminInvoiceSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminInvoiceSwapResponse)> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/swap/invoice/pay'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AdminInvoiceSwapResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminTxSwapResponse)> => {
|
||||||
const auth = await params.retrieveAdminAuth()
|
const auth = await params.retrieveAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
let finalRoute = '/api/admin/swap/transaction/pay'
|
let finalRoute = '/api/admin/swap/transaction/pay'
|
||||||
|
|
@ -918,7 +985,7 @@ export default (params: ClientParams) => ({
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.AdminSwapResponseValidate(result)
|
const error = Types.AdminTxSwapResponseValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
@ -962,6 +1029,20 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
RefundAdminInvoiceSwap: async (request: Types.RefundAdminInvoiceSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminInvoiceSwapResponse)> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/swap/invoice/refund'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AdminInvoiceSwapResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
RequestNPubLinkingToken: async (request: Types.RequestNPubLinkingTokenRequest): Promise<ResultError | ({ status: 'OK' }& Types.RequestNPubLinkingTokenResponse)> => {
|
RequestNPubLinkingToken: async (request: Types.RequestNPubLinkingTokenRequest): Promise<ResultError | ({ status: 'OK' }& Types.RequestNPubLinkingTokenResponse)> => {
|
||||||
const auth = await params.retrieveAppAuth()
|
const auth = await params.retrieveAppAuth()
|
||||||
if (auth === null) throw new Error('retrieveAppAuth() returned null')
|
if (auth === null) throw new Error('retrieveAppAuth() returned null')
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,18 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
BumpTx: async (request: Types.BumpTx): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'BumpTx',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
CloseChannel: async (request: Types.CloseChannelRequest): Promise<ResultError | ({ status: 'OK' }& Types.CloseChannelResponse)> => {
|
CloseChannel: async (request: Types.CloseChannelRequest): Promise<ResultError | ({ status: 'OK' }& Types.CloseChannelResponse)> => {
|
||||||
const auth = await params.retrieveNostrAdminAuth()
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
|
@ -230,6 +242,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
GetAdminInvoiceSwapQuotes: async (request: Types.InvoiceSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.InvoiceSwapQuoteList)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'GetAdminInvoiceSwapQuotes',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.InvoiceSwapQuoteListValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetAdminTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.TransactionSwapQuoteList)> => {
|
GetAdminTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.TransactionSwapQuoteList)> => {
|
||||||
const auth = await params.retrieveNostrAdminAuth()
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
|
@ -260,6 +287,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
GetAssetsAndLiabilities: async (request: Types.AssetsAndLiabilitiesReq): Promise<ResultError | ({ status: 'OK' }& Types.AssetsAndLiabilities)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'GetAssetsAndLiabilities',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AssetsAndLiabilitiesValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetBundleMetrics: async (request: Types.LatestBundleMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.BundleMetrics)> => {
|
GetBundleMetrics: async (request: Types.LatestBundleMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.BundleMetrics)> => {
|
||||||
const auth = await params.retrieveNostrMetricsAuth()
|
const auth = await params.retrieveNostrMetricsAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||||
|
|
@ -666,16 +708,30 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
ListAdminSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.SwapsList)> => {
|
ListAdminInvoiceSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.InvoiceSwapsList)> => {
|
||||||
const auth = await params.retrieveNostrAdminAuth()
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
const nostrRequest: NostrRequest = {}
|
const nostrRequest: NostrRequest = {}
|
||||||
const data = await send(params.pubDestination, {rpcName:'ListAdminSwaps',authIdentifier:auth, ...nostrRequest })
|
const data = await send(params.pubDestination, {rpcName:'ListAdminInvoiceSwaps',authIdentifier:auth, ...nostrRequest })
|
||||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.SwapsListValidate(result)
|
const error = Types.InvoiceSwapsListValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
ListAdminTxSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.TxSwapsList)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'ListAdminTxSwaps',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.TxSwapsListValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
@ -694,16 +750,16 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
ListSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.SwapsList)> => {
|
ListTxSwaps: async (): Promise<ResultError | ({ status: 'OK' }& Types.TxSwapsList)> => {
|
||||||
const auth = await params.retrieveNostrUserAuth()
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
const nostrRequest: NostrRequest = {}
|
const nostrRequest: NostrRequest = {}
|
||||||
const data = await send(params.pubDestination, {rpcName:'ListSwaps',authIdentifier:auth, ...nostrRequest })
|
const data = await send(params.pubDestination, {rpcName:'ListTxSwaps',authIdentifier:auth, ...nostrRequest })
|
||||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.SwapsListValidate(result)
|
const error = Types.TxSwapsListValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
@ -798,7 +854,22 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminSwapResponse)> => {
|
PayAdminInvoiceSwap: async (request: Types.PayAdminInvoiceSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminInvoiceSwapResponse)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'PayAdminInvoiceSwap',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AdminInvoiceSwapResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminTxSwapResponse)> => {
|
||||||
const auth = await params.retrieveNostrAdminAuth()
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
const nostrRequest: NostrRequest = {}
|
const nostrRequest: NostrRequest = {}
|
||||||
|
|
@ -808,7 +879,7 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.AdminSwapResponseValidate(result)
|
const error = Types.AdminTxSwapResponseValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
@ -839,6 +910,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
RefundAdminInvoiceSwap: async (request: Types.RefundAdminInvoiceSwapRequest): Promise<ResultError | ({ status: 'OK' }& Types.AdminInvoiceSwapResponse)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'RefundAdminInvoiceSwap',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AdminInvoiceSwapResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
ResetDebit: async (request: Types.DebitOperation): Promise<ResultError | ({ status: 'OK' })> => {
|
ResetDebit: async (request: Types.DebitOperation): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
const auth = await params.retrieveNostrUserAuth()
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
|
|
||||||
|
|
@ -427,12 +427,12 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'ListSwaps':
|
case 'ListTxSwaps':
|
||||||
if (!methods.ListSwaps) {
|
if (!methods.ListTxSwaps) {
|
||||||
throw new Error('method not defined: ListSwaps')
|
throw new Error('method not defined: ListTxSwaps')
|
||||||
} else {
|
} else {
|
||||||
opStats.validate = opStats.guard
|
opStats.validate = opStats.guard
|
||||||
const res = await methods.ListSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
const res = await methods.ListTxSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
||||||
opStats.handle = process.hrtime.bigint()
|
opStats.handle = process.hrtime.bigint()
|
||||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
}
|
}
|
||||||
|
|
@ -575,6 +575,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...ctx }, ...callsMetrics])
|
opts.metricsCallback([{ ...info, ...stats, ...ctx }, ...callsMetrics])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
|
case 'BumpTx':
|
||||||
|
try {
|
||||||
|
if (!methods.BumpTx) throw new Error('method: BumpTx is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.BumpTxValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
await methods.BumpTx({rpcName:'BumpTx', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK'})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
case 'CloseChannel':
|
case 'CloseChannel':
|
||||||
try {
|
try {
|
||||||
if (!methods.CloseChannel) throw new Error('method: CloseChannel is not implemented')
|
if (!methods.CloseChannel) throw new Error('method: CloseChannel is not implemented')
|
||||||
|
|
@ -687,6 +703,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
|
case 'GetAdminInvoiceSwapQuotes':
|
||||||
|
try {
|
||||||
|
if (!methods.GetAdminInvoiceSwapQuotes) throw new Error('method: GetAdminInvoiceSwapQuotes is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.InvoiceSwapRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.GetAdminInvoiceSwapQuotes({rpcName:'GetAdminInvoiceSwapQuotes', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
case 'GetAdminTransactionSwapQuotes':
|
case 'GetAdminTransactionSwapQuotes':
|
||||||
try {
|
try {
|
||||||
if (!methods.GetAdminTransactionSwapQuotes) throw new Error('method: GetAdminTransactionSwapQuotes is not implemented')
|
if (!methods.GetAdminTransactionSwapQuotes) throw new Error('method: GetAdminTransactionSwapQuotes is not implemented')
|
||||||
|
|
@ -719,6 +751,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
|
case 'GetAssetsAndLiabilities':
|
||||||
|
try {
|
||||||
|
if (!methods.GetAssetsAndLiabilities) throw new Error('method: GetAssetsAndLiabilities is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AssetsAndLiabilitiesReqValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.GetAssetsAndLiabilities({rpcName:'GetAssetsAndLiabilities', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
case 'GetBundleMetrics':
|
case 'GetBundleMetrics':
|
||||||
try {
|
try {
|
||||||
if (!methods.GetBundleMetrics) throw new Error('method: GetBundleMetrics is not implemented')
|
if (!methods.GetBundleMetrics) throw new Error('method: GetBundleMetrics is not implemented')
|
||||||
|
|
@ -1122,14 +1170,27 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
case 'ListAdminSwaps':
|
case 'ListAdminInvoiceSwaps':
|
||||||
try {
|
try {
|
||||||
if (!methods.ListAdminSwaps) throw new Error('method: ListAdminSwaps is not implemented')
|
if (!methods.ListAdminInvoiceSwaps) throw new Error('method: ListAdminInvoiceSwaps is not implemented')
|
||||||
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.validate = stats.guard
|
stats.validate = stats.guard
|
||||||
const response = await methods.ListAdminSwaps({rpcName:'ListAdminSwaps', ctx:authContext })
|
const response = await methods.ListAdminInvoiceSwaps({rpcName:'ListAdminInvoiceSwaps', ctx:authContext })
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
|
case 'ListAdminTxSwaps':
|
||||||
|
try {
|
||||||
|
if (!methods.ListAdminTxSwaps) throw new Error('method: ListAdminTxSwaps is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
stats.validate = stats.guard
|
||||||
|
const response = await methods.ListAdminTxSwaps({rpcName:'ListAdminTxSwaps', ctx:authContext })
|
||||||
stats.handle = process.hrtime.bigint()
|
stats.handle = process.hrtime.bigint()
|
||||||
res({status: 'OK', ...response})
|
res({status: 'OK', ...response})
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
|
@ -1148,14 +1209,14 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
case 'ListSwaps':
|
case 'ListTxSwaps':
|
||||||
try {
|
try {
|
||||||
if (!methods.ListSwaps) throw new Error('method: ListSwaps is not implemented')
|
if (!methods.ListTxSwaps) throw new Error('method: ListTxSwaps is not implemented')
|
||||||
const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier)
|
const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier)
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.validate = stats.guard
|
stats.validate = stats.guard
|
||||||
const response = await methods.ListSwaps({rpcName:'ListSwaps', ctx:authContext })
|
const response = await methods.ListTxSwaps({rpcName:'ListTxSwaps', ctx:authContext })
|
||||||
stats.handle = process.hrtime.bigint()
|
stats.handle = process.hrtime.bigint()
|
||||||
res({status: 'OK', ...response})
|
res({status: 'OK', ...response})
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
|
@ -1254,6 +1315,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
|
case 'PayAdminInvoiceSwap':
|
||||||
|
try {
|
||||||
|
if (!methods.PayAdminInvoiceSwap) throw new Error('method: PayAdminInvoiceSwap is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.PayAdminInvoiceSwapRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.PayAdminInvoiceSwap({rpcName:'PayAdminInvoiceSwap', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
case 'PayAdminTransactionSwap':
|
case 'PayAdminTransactionSwap':
|
||||||
try {
|
try {
|
||||||
if (!methods.PayAdminTransactionSwap) throw new Error('method: PayAdminTransactionSwap is not implemented')
|
if (!methods.PayAdminTransactionSwap) throw new Error('method: PayAdminTransactionSwap is not implemented')
|
||||||
|
|
@ -1299,6 +1376,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
|
case 'RefundAdminInvoiceSwap':
|
||||||
|
try {
|
||||||
|
if (!methods.RefundAdminInvoiceSwap) throw new Error('method: RefundAdminInvoiceSwap is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.RefundAdminInvoiceSwapRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.RefundAdminInvoiceSwap({rpcName:'RefundAdminInvoiceSwap', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
case 'ResetDebit':
|
case 'ResetDebit':
|
||||||
try {
|
try {
|
||||||
if (!methods.ResetDebit) throw new Error('method: ResetDebit is not implemented')
|
if (!methods.ResetDebit) throw new Error('method: ResetDebit is not implemented')
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3)
|
// @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||||
|
|
@ -31,7 +31,7 @@ export interface IChainNotifierClient {
|
||||||
* a notification is sent once the output script confirms in the given
|
* a notification is sent once the output script confirms in the given
|
||||||
* transaction.
|
* transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RegisterConfirmationsNtfn(chainrpc.ConfRequest) returns (stream chainrpc.ConfEvent);
|
* @generated from protobuf rpc: RegisterConfirmationsNtfn
|
||||||
*/
|
*/
|
||||||
registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall<ConfRequest, ConfEvent>;
|
registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall<ConfRequest, ConfEvent>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,7 +43,7 @@ export interface IChainNotifierClient {
|
||||||
* A client can specify whether the spend request should be for a particular
|
* A client can specify whether the spend request should be for a particular
|
||||||
* outpoint or for an output script by specifying a zero outpoint.
|
* outpoint or for an output script by specifying a zero outpoint.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RegisterSpendNtfn(chainrpc.SpendRequest) returns (stream chainrpc.SpendEvent);
|
* @generated from protobuf rpc: RegisterSpendNtfn
|
||||||
*/
|
*/
|
||||||
registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall<SpendRequest, SpendEvent>;
|
registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall<SpendRequest, SpendEvent>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -58,7 +58,7 @@ export interface IChainNotifierClient {
|
||||||
* point. This allows clients to be idempotent by ensuring that they do not
|
* point. This allows clients to be idempotent by ensuring that they do not
|
||||||
* missing processing a single block within the chain.
|
* missing processing a single block within the chain.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RegisterBlockEpochNtfn(chainrpc.BlockEpoch) returns (stream chainrpc.BlockEpoch);
|
* @generated from protobuf rpc: RegisterBlockEpochNtfn
|
||||||
*/
|
*/
|
||||||
registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall<BlockEpoch, BlockEpoch>;
|
registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall<BlockEpoch, BlockEpoch>;
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +86,7 @@ export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo {
|
||||||
* a notification is sent once the output script confirms in the given
|
* a notification is sent once the output script confirms in the given
|
||||||
* transaction.
|
* transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RegisterConfirmationsNtfn(chainrpc.ConfRequest) returns (stream chainrpc.ConfEvent);
|
* @generated from protobuf rpc: RegisterConfirmationsNtfn
|
||||||
*/
|
*/
|
||||||
registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall<ConfRequest, ConfEvent> {
|
registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall<ConfRequest, ConfEvent> {
|
||||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -101,7 +101,7 @@ export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo {
|
||||||
* A client can specify whether the spend request should be for a particular
|
* A client can specify whether the spend request should be for a particular
|
||||||
* outpoint or for an output script by specifying a zero outpoint.
|
* outpoint or for an output script by specifying a zero outpoint.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RegisterSpendNtfn(chainrpc.SpendRequest) returns (stream chainrpc.SpendEvent);
|
* @generated from protobuf rpc: RegisterSpendNtfn
|
||||||
*/
|
*/
|
||||||
registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall<SpendRequest, SpendEvent> {
|
registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall<SpendRequest, SpendEvent> {
|
||||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -119,7 +119,7 @@ export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo {
|
||||||
* point. This allows clients to be idempotent by ensuring that they do not
|
* point. This allows clients to be idempotent by ensuring that they do not
|
||||||
* missing processing a single block within the chain.
|
* missing processing a single block within the chain.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RegisterBlockEpochNtfn(chainrpc.BlockEpoch) returns (stream chainrpc.BlockEpoch);
|
* @generated from protobuf rpc: RegisterBlockEpochNtfn
|
||||||
*/
|
*/
|
||||||
registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall<BlockEpoch, BlockEpoch> {
|
registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall<BlockEpoch, BlockEpoch> {
|
||||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3)
|
// @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
||||||
|
|
@ -10,7 +10,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime";
|
||||||
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
||||||
import type { PartialMessage } from "@protobuf-ts/runtime";
|
import type { PartialMessage } from "@protobuf-ts/runtime";
|
||||||
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
||||||
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
|
|
||||||
import { MessageType } from "@protobuf-ts/runtime";
|
import { MessageType } from "@protobuf-ts/runtime";
|
||||||
/**
|
/**
|
||||||
* @generated from protobuf message chainrpc.ConfRequest
|
* @generated from protobuf message chainrpc.ConfRequest
|
||||||
|
|
@ -22,7 +21,7 @@ export interface ConfRequest {
|
||||||
* for. If set to a hash of all zeros, then the confirmation notification will
|
* for. If set to a hash of all zeros, then the confirmation notification will
|
||||||
* be requested for the script instead.
|
* be requested for the script instead.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes txid = 1;
|
* @generated from protobuf field: bytes txid = 1
|
||||||
*/
|
*/
|
||||||
txid: Uint8Array;
|
txid: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,7 +31,7 @@ export interface ConfRequest {
|
||||||
* hash of all zeros, then a confirmation notification will be requested for
|
* hash of all zeros, then a confirmation notification will be requested for
|
||||||
* this script instead.
|
* this script instead.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes script = 2;
|
* @generated from protobuf field: bytes script = 2
|
||||||
*/
|
*/
|
||||||
script: Uint8Array;
|
script: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,7 +39,7 @@ export interface ConfRequest {
|
||||||
* The number of desired confirmations the transaction/output script should
|
* The number of desired confirmations the transaction/output script should
|
||||||
* reach before dispatching a confirmation notification.
|
* reach before dispatching a confirmation notification.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 num_confs = 3;
|
* @generated from protobuf field: uint32 num_confs = 3
|
||||||
*/
|
*/
|
||||||
numConfs: number;
|
numConfs: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -49,7 +48,7 @@ export interface ConfRequest {
|
||||||
* could have been included in a block. This should in most cases be set to the
|
* could have been included in a block. This should in most cases be set to the
|
||||||
* broadcast height of the transaction/output script.
|
* broadcast height of the transaction/output script.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 height_hint = 4;
|
* @generated from protobuf field: uint32 height_hint = 4
|
||||||
*/
|
*/
|
||||||
heightHint: number;
|
heightHint: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,7 +56,7 @@ export interface ConfRequest {
|
||||||
* If true, then the block that mines the specified txid/script will be
|
* If true, then the block that mines the specified txid/script will be
|
||||||
* included in eventual the notification event.
|
* included in eventual the notification event.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bool include_block = 5;
|
* @generated from protobuf field: bool include_block = 5
|
||||||
*/
|
*/
|
||||||
includeBlock: boolean;
|
includeBlock: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -68,26 +67,26 @@ export interface ConfDetails {
|
||||||
/**
|
/**
|
||||||
* The raw bytes of the confirmed transaction.
|
* The raw bytes of the confirmed transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes raw_tx = 1;
|
* @generated from protobuf field: bytes raw_tx = 1
|
||||||
*/
|
*/
|
||||||
rawTx: Uint8Array;
|
rawTx: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* The hash of the block in which the confirmed transaction was included in.
|
* The hash of the block in which the confirmed transaction was included in.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes block_hash = 2;
|
* @generated from protobuf field: bytes block_hash = 2
|
||||||
*/
|
*/
|
||||||
blockHash: Uint8Array;
|
blockHash: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* The height of the block in which the confirmed transaction was included
|
* The height of the block in which the confirmed transaction was included
|
||||||
* in.
|
* in.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 block_height = 3;
|
* @generated from protobuf field: uint32 block_height = 3
|
||||||
*/
|
*/
|
||||||
blockHeight: number;
|
blockHeight: number;
|
||||||
/**
|
/**
|
||||||
* The index of the confirmed transaction within the block.
|
* The index of the confirmed transaction within the block.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 tx_index = 4;
|
* @generated from protobuf field: uint32 tx_index = 4
|
||||||
*/
|
*/
|
||||||
txIndex: number;
|
txIndex: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -95,7 +94,7 @@ export interface ConfDetails {
|
||||||
* The raw bytes of the block that mined the transaction. Only included if
|
* The raw bytes of the block that mined the transaction. Only included if
|
||||||
* include_block was set in the request.
|
* include_block was set in the request.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes raw_block = 5;
|
* @generated from protobuf field: bytes raw_block = 5
|
||||||
*/
|
*/
|
||||||
rawBlock: Uint8Array;
|
rawBlock: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +119,7 @@ export interface ConfEvent {
|
||||||
* An event that includes the confirmation details of the request
|
* An event that includes the confirmation details of the request
|
||||||
* (txid/ouput script).
|
* (txid/ouput script).
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: chainrpc.ConfDetails conf = 1;
|
* @generated from protobuf field: chainrpc.ConfDetails conf = 1
|
||||||
*/
|
*/
|
||||||
conf: ConfDetails;
|
conf: ConfDetails;
|
||||||
} | {
|
} | {
|
||||||
|
|
@ -130,7 +129,7 @@ export interface ConfEvent {
|
||||||
* An event send when the transaction of the request is reorged out of the
|
* An event send when the transaction of the request is reorged out of the
|
||||||
* chain.
|
* chain.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: chainrpc.Reorg reorg = 2;
|
* @generated from protobuf field: chainrpc.Reorg reorg = 2
|
||||||
*/
|
*/
|
||||||
reorg: Reorg;
|
reorg: Reorg;
|
||||||
} | {
|
} | {
|
||||||
|
|
@ -144,13 +143,13 @@ export interface Outpoint {
|
||||||
/**
|
/**
|
||||||
* The hash of the transaction.
|
* The hash of the transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes hash = 1;
|
* @generated from protobuf field: bytes hash = 1
|
||||||
*/
|
*/
|
||||||
hash: Uint8Array;
|
hash: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* The index of the output within the transaction.
|
* The index of the output within the transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 index = 2;
|
* @generated from protobuf field: uint32 index = 2
|
||||||
*/
|
*/
|
||||||
index: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +167,7 @@ export interface SpendRequest {
|
||||||
* So an outpoint must _always_ be specified when registering a spend
|
* So an outpoint must _always_ be specified when registering a spend
|
||||||
* notification for a Taproot output.
|
* notification for a Taproot output.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: chainrpc.Outpoint outpoint = 1;
|
* @generated from protobuf field: chainrpc.Outpoint outpoint = 1
|
||||||
*/
|
*/
|
||||||
outpoint?: Outpoint;
|
outpoint?: Outpoint;
|
||||||
/**
|
/**
|
||||||
|
|
@ -177,7 +176,7 @@ export interface SpendRequest {
|
||||||
* to match block filters. If the outpoint is set to a zero outpoint, then a
|
* to match block filters. If the outpoint is set to a zero outpoint, then a
|
||||||
* spend notification will be requested for this script instead.
|
* spend notification will be requested for this script instead.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes script = 2;
|
* @generated from protobuf field: bytes script = 2
|
||||||
*/
|
*/
|
||||||
script: Uint8Array;
|
script: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -186,7 +185,7 @@ export interface SpendRequest {
|
||||||
* have been spent. This should in most cases be set to the broadcast height of
|
* have been spent. This should in most cases be set to the broadcast height of
|
||||||
* the outpoint/output script.
|
* the outpoint/output script.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 height_hint = 3;
|
* @generated from protobuf field: uint32 height_hint = 3
|
||||||
*/
|
*/
|
||||||
heightHint: number;
|
heightHint: number;
|
||||||
}
|
}
|
||||||
|
|
@ -197,31 +196,31 @@ export interface SpendDetails {
|
||||||
/**
|
/**
|
||||||
* The outpoint was that spent.
|
* The outpoint was that spent.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: chainrpc.Outpoint spending_outpoint = 1;
|
* @generated from protobuf field: chainrpc.Outpoint spending_outpoint = 1
|
||||||
*/
|
*/
|
||||||
spendingOutpoint?: Outpoint;
|
spendingOutpoint?: Outpoint;
|
||||||
/**
|
/**
|
||||||
* The raw bytes of the spending transaction.
|
* The raw bytes of the spending transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes raw_spending_tx = 2;
|
* @generated from protobuf field: bytes raw_spending_tx = 2
|
||||||
*/
|
*/
|
||||||
rawSpendingTx: Uint8Array;
|
rawSpendingTx: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* The hash of the spending transaction.
|
* The hash of the spending transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes spending_tx_hash = 3;
|
* @generated from protobuf field: bytes spending_tx_hash = 3
|
||||||
*/
|
*/
|
||||||
spendingTxHash: Uint8Array;
|
spendingTxHash: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* The input of the spending transaction that fulfilled the spend request.
|
* The input of the spending transaction that fulfilled the spend request.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 spending_input_index = 4;
|
* @generated from protobuf field: uint32 spending_input_index = 4
|
||||||
*/
|
*/
|
||||||
spendingInputIndex: number;
|
spendingInputIndex: number;
|
||||||
/**
|
/**
|
||||||
* The height at which the spending transaction was included in a block.
|
* The height at which the spending transaction was included in a block.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 spending_height = 5;
|
* @generated from protobuf field: uint32 spending_height = 5
|
||||||
*/
|
*/
|
||||||
spendingHeight: number;
|
spendingHeight: number;
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +238,7 @@ export interface SpendEvent {
|
||||||
* An event that includes the details of the spending transaction of the
|
* An event that includes the details of the spending transaction of the
|
||||||
* request (outpoint/output script).
|
* request (outpoint/output script).
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: chainrpc.SpendDetails spend = 1;
|
* @generated from protobuf field: chainrpc.SpendDetails spend = 1
|
||||||
*/
|
*/
|
||||||
spend: SpendDetails;
|
spend: SpendDetails;
|
||||||
} | {
|
} | {
|
||||||
|
|
@ -249,7 +248,7 @@ export interface SpendEvent {
|
||||||
* An event sent when the spending transaction of the request was
|
* An event sent when the spending transaction of the request was
|
||||||
* reorged out of the chain.
|
* reorged out of the chain.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: chainrpc.Reorg reorg = 2;
|
* @generated from protobuf field: chainrpc.Reorg reorg = 2
|
||||||
*/
|
*/
|
||||||
reorg: Reorg;
|
reorg: Reorg;
|
||||||
} | {
|
} | {
|
||||||
|
|
@ -263,13 +262,13 @@ export interface BlockEpoch {
|
||||||
/**
|
/**
|
||||||
* The hash of the block.
|
* The hash of the block.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes hash = 1;
|
* @generated from protobuf field: bytes hash = 1
|
||||||
*/
|
*/
|
||||||
hash: Uint8Array;
|
hash: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* The height of the block.
|
* The height of the block.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 height = 2;
|
* @generated from protobuf field: uint32 height = 2
|
||||||
*/
|
*/
|
||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
@ -285,8 +284,12 @@ class ConfRequest$Type extends MessageType<ConfRequest> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<ConfRequest>): ConfRequest {
|
create(value?: PartialMessage<ConfRequest>): ConfRequest {
|
||||||
const message = { txid: new Uint8Array(0), script: new Uint8Array(0), numConfs: 0, heightHint: 0, includeBlock: false };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.txid = new Uint8Array(0);
|
||||||
|
message.script = new Uint8Array(0);
|
||||||
|
message.numConfs = 0;
|
||||||
|
message.heightHint = 0;
|
||||||
|
message.includeBlock = false;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<ConfRequest>(this, message, value);
|
reflectionMergePartial<ConfRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -360,8 +363,12 @@ class ConfDetails$Type extends MessageType<ConfDetails> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<ConfDetails>): ConfDetails {
|
create(value?: PartialMessage<ConfDetails>): ConfDetails {
|
||||||
const message = { rawTx: new Uint8Array(0), blockHash: new Uint8Array(0), blockHeight: 0, txIndex: 0, rawBlock: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.rawTx = new Uint8Array(0);
|
||||||
|
message.blockHash = new Uint8Array(0);
|
||||||
|
message.blockHeight = 0;
|
||||||
|
message.txIndex = 0;
|
||||||
|
message.rawBlock = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<ConfDetails>(this, message, value);
|
reflectionMergePartial<ConfDetails>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -429,14 +436,26 @@ class Reorg$Type extends MessageType<Reorg> {
|
||||||
super("chainrpc.Reorg", []);
|
super("chainrpc.Reorg", []);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<Reorg>): Reorg {
|
create(value?: PartialMessage<Reorg>): Reorg {
|
||||||
const message = {};
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<Reorg>(this, message, value);
|
reflectionMergePartial<Reorg>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Reorg): Reorg {
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Reorg): Reorg {
|
||||||
return target ?? this.create();
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryWrite(message: Reorg, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
internalBinaryWrite(message: Reorg, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
let u = options.writeUnknownFields;
|
let u = options.writeUnknownFields;
|
||||||
|
|
@ -458,8 +477,8 @@ class ConfEvent$Type extends MessageType<ConfEvent> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<ConfEvent>): ConfEvent {
|
create(value?: PartialMessage<ConfEvent>): ConfEvent {
|
||||||
const message = { event: { oneofKind: undefined } };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.event = { oneofKind: undefined };
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<ConfEvent>(this, message, value);
|
reflectionMergePartial<ConfEvent>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -518,8 +537,9 @@ class Outpoint$Type extends MessageType<Outpoint> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<Outpoint>): Outpoint {
|
create(value?: PartialMessage<Outpoint>): Outpoint {
|
||||||
const message = { hash: new Uint8Array(0), index: 0 };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.hash = new Uint8Array(0);
|
||||||
|
message.index = 0;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<Outpoint>(this, message, value);
|
reflectionMergePartial<Outpoint>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -573,8 +593,9 @@ class SpendRequest$Type extends MessageType<SpendRequest> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<SpendRequest>): SpendRequest {
|
create(value?: PartialMessage<SpendRequest>): SpendRequest {
|
||||||
const message = { script: new Uint8Array(0), heightHint: 0 };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.script = new Uint8Array(0);
|
||||||
|
message.heightHint = 0;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<SpendRequest>(this, message, value);
|
reflectionMergePartial<SpendRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -636,8 +657,11 @@ class SpendDetails$Type extends MessageType<SpendDetails> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<SpendDetails>): SpendDetails {
|
create(value?: PartialMessage<SpendDetails>): SpendDetails {
|
||||||
const message = { rawSpendingTx: new Uint8Array(0), spendingTxHash: new Uint8Array(0), spendingInputIndex: 0, spendingHeight: 0 };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.rawSpendingTx = new Uint8Array(0);
|
||||||
|
message.spendingTxHash = new Uint8Array(0);
|
||||||
|
message.spendingInputIndex = 0;
|
||||||
|
message.spendingHeight = 0;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<SpendDetails>(this, message, value);
|
reflectionMergePartial<SpendDetails>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -708,8 +732,8 @@ class SpendEvent$Type extends MessageType<SpendEvent> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<SpendEvent>): SpendEvent {
|
create(value?: PartialMessage<SpendEvent>): SpendEvent {
|
||||||
const message = { event: { oneofKind: undefined } };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.event = { oneofKind: undefined };
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<SpendEvent>(this, message, value);
|
reflectionMergePartial<SpendEvent>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -768,8 +792,9 @@ class BlockEpoch$Type extends MessageType<BlockEpoch> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<BlockEpoch>): BlockEpoch {
|
create(value?: PartialMessage<BlockEpoch>): BlockEpoch {
|
||||||
const message = { hash: new Uint8Array(0), height: 0 };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.hash = new Uint8Array(0);
|
||||||
|
message.height = 0;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<BlockEpoch>(this, message, value);
|
reflectionMergePartial<BlockEpoch>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "invoices.proto" (package "invoicesrpc", syntax proto3)
|
// @generated from protobuf file "invoices.proto" (package "invoicesrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||||
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
|
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
|
||||||
import { Invoices } from "./invoices.js";
|
import { Invoices } from "./invoices.js";
|
||||||
|
import type { HtlcModifyRequest } from "./invoices.js";
|
||||||
|
import type { HtlcModifyResponse } from "./invoices.js";
|
||||||
|
import type { DuplexStreamingCall } from "@protobuf-ts/runtime-rpc";
|
||||||
import type { LookupInvoiceMsg } from "./invoices.js";
|
import type { LookupInvoiceMsg } from "./invoices.js";
|
||||||
import type { SettleInvoiceResp } from "./invoices.js";
|
import type { SettleInvoiceResp } from "./invoices.js";
|
||||||
import type { SettleInvoiceMsg } from "./invoices.js";
|
import type { SettleInvoiceMsg } from "./invoices.js";
|
||||||
|
|
@ -17,6 +20,23 @@ import type { Invoice } from "./lightning.js";
|
||||||
import type { SubscribeSingleInvoiceRequest } from "./invoices.js";
|
import type { SubscribeSingleInvoiceRequest } from "./invoices.js";
|
||||||
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
|
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
|
||||||
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
|
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
|
||||||
|
//
|
||||||
|
// Comments in this file will be directly parsed into the API
|
||||||
|
// Documentation as descriptions of the associated method, message, or field.
|
||||||
|
// These descriptions should go right above the definition of the object, and
|
||||||
|
// can be in either block or // comment format.
|
||||||
|
//
|
||||||
|
// An RPC method can be matched to an lncli command by placing a line in the
|
||||||
|
// beginning of the description in exactly the following format:
|
||||||
|
// lncli: `methodname`
|
||||||
|
//
|
||||||
|
// Failure to specify the exact name of the command will cause documentation
|
||||||
|
// generation to fail.
|
||||||
|
//
|
||||||
|
// More information on how exactly the gRPC documentation is generated from
|
||||||
|
// this proto file can be found here:
|
||||||
|
// https://github.com/lightninglabs/lightning-api
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoices is a service that can be used to create, accept, settle and cancel
|
* Invoices is a service that can be used to create, accept, settle and cancel
|
||||||
* invoices.
|
* invoices.
|
||||||
|
|
@ -30,43 +50,70 @@ export interface IInvoicesClient {
|
||||||
* to notify the client of state transitions of the specified invoice.
|
* to notify the client of state transitions of the specified invoice.
|
||||||
* Initially the current invoice state is always sent out.
|
* Initially the current invoice state is always sent out.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SubscribeSingleInvoice(invoicesrpc.SubscribeSingleInvoiceRequest) returns (stream lnrpc.Invoice);
|
* @generated from protobuf rpc: SubscribeSingleInvoice
|
||||||
*/
|
*/
|
||||||
subscribeSingleInvoice(input: SubscribeSingleInvoiceRequest, options?: RpcOptions): ServerStreamingCall<SubscribeSingleInvoiceRequest, Invoice>;
|
subscribeSingleInvoice(input: SubscribeSingleInvoiceRequest, options?: RpcOptions): ServerStreamingCall<SubscribeSingleInvoiceRequest, Invoice>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `cancelinvoice`
|
||||||
* CancelInvoice cancels a currently open invoice. If the invoice is already
|
* CancelInvoice cancels a currently open invoice. If the invoice is already
|
||||||
* canceled, this call will succeed. If the invoice is already settled, it will
|
* canceled, this call will succeed. If the invoice is already settled, it will
|
||||||
* fail.
|
* fail.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: CancelInvoice(invoicesrpc.CancelInvoiceMsg) returns (invoicesrpc.CancelInvoiceResp);
|
* @generated from protobuf rpc: CancelInvoice
|
||||||
*/
|
*/
|
||||||
cancelInvoice(input: CancelInvoiceMsg, options?: RpcOptions): UnaryCall<CancelInvoiceMsg, CancelInvoiceResp>;
|
cancelInvoice(input: CancelInvoiceMsg, options?: RpcOptions): UnaryCall<CancelInvoiceMsg, CancelInvoiceResp>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `addholdinvoice`
|
||||||
* AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
* AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
||||||
* supplied in the request.
|
* supplied in the request.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: AddHoldInvoice(invoicesrpc.AddHoldInvoiceRequest) returns (invoicesrpc.AddHoldInvoiceResp);
|
* @generated from protobuf rpc: AddHoldInvoice
|
||||||
*/
|
*/
|
||||||
addHoldInvoice(input: AddHoldInvoiceRequest, options?: RpcOptions): UnaryCall<AddHoldInvoiceRequest, AddHoldInvoiceResp>;
|
addHoldInvoice(input: AddHoldInvoiceRequest, options?: RpcOptions): UnaryCall<AddHoldInvoiceRequest, AddHoldInvoiceResp>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `settleinvoice`
|
||||||
* SettleInvoice settles an accepted invoice. If the invoice is already
|
* SettleInvoice settles an accepted invoice. If the invoice is already
|
||||||
* settled, this call will succeed.
|
* settled, this call will succeed.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SettleInvoice(invoicesrpc.SettleInvoiceMsg) returns (invoicesrpc.SettleInvoiceResp);
|
* @generated from protobuf rpc: SettleInvoice
|
||||||
*/
|
*/
|
||||||
settleInvoice(input: SettleInvoiceMsg, options?: RpcOptions): UnaryCall<SettleInvoiceMsg, SettleInvoiceResp>;
|
settleInvoice(input: SettleInvoiceMsg, options?: RpcOptions): UnaryCall<SettleInvoiceMsg, SettleInvoiceResp>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced
|
* LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced
|
||||||
* using either its payment hash, payment address, or set ID.
|
* using either its payment hash, payment address, or set ID.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: LookupInvoiceV2(invoicesrpc.LookupInvoiceMsg) returns (lnrpc.Invoice);
|
* @generated from protobuf rpc: LookupInvoiceV2
|
||||||
*/
|
*/
|
||||||
lookupInvoiceV2(input: LookupInvoiceMsg, options?: RpcOptions): UnaryCall<LookupInvoiceMsg, Invoice>;
|
lookupInvoiceV2(input: LookupInvoiceMsg, options?: RpcOptions): UnaryCall<LookupInvoiceMsg, Invoice>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* HtlcModifier is a bidirectional streaming RPC that allows a client to
|
||||||
|
* intercept and modify the HTLCs that attempt to settle the given invoice. The
|
||||||
|
* server will send HTLCs of invoices to the client and the client can modify
|
||||||
|
* some aspects of the HTLC in order to pass the invoice acceptance tests.
|
||||||
|
*
|
||||||
|
* @generated from protobuf rpc: HtlcModifier
|
||||||
|
*/
|
||||||
|
htlcModifier(options?: RpcOptions): DuplexStreamingCall<HtlcModifyResponse, HtlcModifyRequest>;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Comments in this file will be directly parsed into the API
|
||||||
|
// Documentation as descriptions of the associated method, message, or field.
|
||||||
|
// These descriptions should go right above the definition of the object, and
|
||||||
|
// can be in either block or // comment format.
|
||||||
|
//
|
||||||
|
// An RPC method can be matched to an lncli command by placing a line in the
|
||||||
|
// beginning of the description in exactly the following format:
|
||||||
|
// lncli: `methodname`
|
||||||
|
//
|
||||||
|
// Failure to specify the exact name of the command will cause documentation
|
||||||
|
// generation to fail.
|
||||||
|
//
|
||||||
|
// More information on how exactly the gRPC documentation is generated from
|
||||||
|
// this proto file can be found here:
|
||||||
|
// https://github.com/lightninglabs/lightning-api
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoices is a service that can be used to create, accept, settle and cancel
|
* Invoices is a service that can be used to create, accept, settle and cancel
|
||||||
* invoices.
|
* invoices.
|
||||||
|
|
@ -85,41 +132,41 @@ export class InvoicesClient implements IInvoicesClient, ServiceInfo {
|
||||||
* to notify the client of state transitions of the specified invoice.
|
* to notify the client of state transitions of the specified invoice.
|
||||||
* Initially the current invoice state is always sent out.
|
* Initially the current invoice state is always sent out.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SubscribeSingleInvoice(invoicesrpc.SubscribeSingleInvoiceRequest) returns (stream lnrpc.Invoice);
|
* @generated from protobuf rpc: SubscribeSingleInvoice
|
||||||
*/
|
*/
|
||||||
subscribeSingleInvoice(input: SubscribeSingleInvoiceRequest, options?: RpcOptions): ServerStreamingCall<SubscribeSingleInvoiceRequest, Invoice> {
|
subscribeSingleInvoice(input: SubscribeSingleInvoiceRequest, options?: RpcOptions): ServerStreamingCall<SubscribeSingleInvoiceRequest, Invoice> {
|
||||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<SubscribeSingleInvoiceRequest, Invoice>("serverStreaming", this._transport, method, opt, input);
|
return stackIntercept<SubscribeSingleInvoiceRequest, Invoice>("serverStreaming", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `cancelinvoice`
|
||||||
* CancelInvoice cancels a currently open invoice. If the invoice is already
|
* CancelInvoice cancels a currently open invoice. If the invoice is already
|
||||||
* canceled, this call will succeed. If the invoice is already settled, it will
|
* canceled, this call will succeed. If the invoice is already settled, it will
|
||||||
* fail.
|
* fail.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: CancelInvoice(invoicesrpc.CancelInvoiceMsg) returns (invoicesrpc.CancelInvoiceResp);
|
* @generated from protobuf rpc: CancelInvoice
|
||||||
*/
|
*/
|
||||||
cancelInvoice(input: CancelInvoiceMsg, options?: RpcOptions): UnaryCall<CancelInvoiceMsg, CancelInvoiceResp> {
|
cancelInvoice(input: CancelInvoiceMsg, options?: RpcOptions): UnaryCall<CancelInvoiceMsg, CancelInvoiceResp> {
|
||||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<CancelInvoiceMsg, CancelInvoiceResp>("unary", this._transport, method, opt, input);
|
return stackIntercept<CancelInvoiceMsg, CancelInvoiceResp>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `addholdinvoice`
|
||||||
* AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
* AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
||||||
* supplied in the request.
|
* supplied in the request.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: AddHoldInvoice(invoicesrpc.AddHoldInvoiceRequest) returns (invoicesrpc.AddHoldInvoiceResp);
|
* @generated from protobuf rpc: AddHoldInvoice
|
||||||
*/
|
*/
|
||||||
addHoldInvoice(input: AddHoldInvoiceRequest, options?: RpcOptions): UnaryCall<AddHoldInvoiceRequest, AddHoldInvoiceResp> {
|
addHoldInvoice(input: AddHoldInvoiceRequest, options?: RpcOptions): UnaryCall<AddHoldInvoiceRequest, AddHoldInvoiceResp> {
|
||||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<AddHoldInvoiceRequest, AddHoldInvoiceResp>("unary", this._transport, method, opt, input);
|
return stackIntercept<AddHoldInvoiceRequest, AddHoldInvoiceResp>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `settleinvoice`
|
||||||
* SettleInvoice settles an accepted invoice. If the invoice is already
|
* SettleInvoice settles an accepted invoice. If the invoice is already
|
||||||
* settled, this call will succeed.
|
* settled, this call will succeed.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SettleInvoice(invoicesrpc.SettleInvoiceMsg) returns (invoicesrpc.SettleInvoiceResp);
|
* @generated from protobuf rpc: SettleInvoice
|
||||||
*/
|
*/
|
||||||
settleInvoice(input: SettleInvoiceMsg, options?: RpcOptions): UnaryCall<SettleInvoiceMsg, SettleInvoiceResp> {
|
settleInvoice(input: SettleInvoiceMsg, options?: RpcOptions): UnaryCall<SettleInvoiceMsg, SettleInvoiceResp> {
|
||||||
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -127,13 +174,26 @@ export class InvoicesClient implements IInvoicesClient, ServiceInfo {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced
|
* LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced
|
||||||
* using either its payment hash, payment address, or set ID.
|
* using either its payment hash, payment address, or set ID.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: LookupInvoiceV2(invoicesrpc.LookupInvoiceMsg) returns (lnrpc.Invoice);
|
* @generated from protobuf rpc: LookupInvoiceV2
|
||||||
*/
|
*/
|
||||||
lookupInvoiceV2(input: LookupInvoiceMsg, options?: RpcOptions): UnaryCall<LookupInvoiceMsg, Invoice> {
|
lookupInvoiceV2(input: LookupInvoiceMsg, options?: RpcOptions): UnaryCall<LookupInvoiceMsg, Invoice> {
|
||||||
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<LookupInvoiceMsg, Invoice>("unary", this._transport, method, opt, input);
|
return stackIntercept<LookupInvoiceMsg, Invoice>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* HtlcModifier is a bidirectional streaming RPC that allows a client to
|
||||||
|
* intercept and modify the HTLCs that attempt to settle the given invoice. The
|
||||||
|
* server will send HTLCs of invoices to the client and the client can modify
|
||||||
|
* some aspects of the HTLC in order to pass the invoice acceptance tests.
|
||||||
|
*
|
||||||
|
* @generated from protobuf rpc: HtlcModifier
|
||||||
|
*/
|
||||||
|
htlcModifier(options?: RpcOptions): DuplexStreamingCall<HtlcModifyResponse, HtlcModifyRequest> {
|
||||||
|
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
||||||
|
return stackIntercept<HtlcModifyResponse, HtlcModifyRequest>("duplex", this._transport, method, opt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "invoices.proto" (package "invoicesrpc", syntax proto3)
|
// @generated from protobuf file "invoices.proto" (package "invoicesrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import { Invoice } from "./lightning.js";
|
|
||||||
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
||||||
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
|
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
|
||||||
import type { IBinaryWriter } from "@protobuf-ts/runtime";
|
import type { IBinaryWriter } from "@protobuf-ts/runtime";
|
||||||
|
|
@ -11,8 +10,8 @@ import type { IBinaryReader } from "@protobuf-ts/runtime";
|
||||||
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
||||||
import type { PartialMessage } from "@protobuf-ts/runtime";
|
import type { PartialMessage } from "@protobuf-ts/runtime";
|
||||||
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
||||||
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
|
|
||||||
import { MessageType } from "@protobuf-ts/runtime";
|
import { MessageType } from "@protobuf-ts/runtime";
|
||||||
|
import { Invoice } from "./lightning.js";
|
||||||
import { RouteHint } from "./lightning.js";
|
import { RouteHint } from "./lightning.js";
|
||||||
/**
|
/**
|
||||||
* @generated from protobuf message invoicesrpc.CancelInvoiceMsg
|
* @generated from protobuf message invoicesrpc.CancelInvoiceMsg
|
||||||
|
|
@ -22,7 +21,7 @@ export interface CancelInvoiceMsg {
|
||||||
* Hash corresponding to the (hold) invoice to cancel. When using
|
* Hash corresponding to the (hold) invoice to cancel. When using
|
||||||
* REST, this field must be encoded as base64.
|
* REST, this field must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes payment_hash = 1;
|
* @generated from protobuf field: bytes payment_hash = 1
|
||||||
*/
|
*/
|
||||||
paymentHash: Uint8Array;
|
paymentHash: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -42,13 +41,13 @@ export interface AddHoldInvoiceRequest {
|
||||||
* field of the encoded payment request if the description_hash field is not
|
* field of the encoded payment request if the description_hash field is not
|
||||||
* being used.
|
* being used.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: string memo = 1;
|
* @generated from protobuf field: string memo = 1
|
||||||
*/
|
*/
|
||||||
memo: string;
|
memo: string;
|
||||||
/**
|
/**
|
||||||
* The hash of the preimage
|
* The hash of the preimage
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes hash = 2;
|
* @generated from protobuf field: bytes hash = 2
|
||||||
*/
|
*/
|
||||||
hash: Uint8Array;
|
hash: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,7 +56,7 @@ export interface AddHoldInvoiceRequest {
|
||||||
*
|
*
|
||||||
* The fields value and value_msat are mutually exclusive.
|
* The fields value and value_msat are mutually exclusive.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: int64 value = 3;
|
* @generated from protobuf field: int64 value = 3
|
||||||
*/
|
*/
|
||||||
value: bigint;
|
value: bigint;
|
||||||
/**
|
/**
|
||||||
|
|
@ -66,7 +65,7 @@ export interface AddHoldInvoiceRequest {
|
||||||
*
|
*
|
||||||
* The fields value and value_msat are mutually exclusive.
|
* The fields value and value_msat are mutually exclusive.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: int64 value_msat = 10;
|
* @generated from protobuf field: int64 value_msat = 10
|
||||||
*/
|
*/
|
||||||
valueMsat: bigint;
|
valueMsat: bigint;
|
||||||
/**
|
/**
|
||||||
|
|
@ -75,25 +74,25 @@ export interface AddHoldInvoiceRequest {
|
||||||
* payment (memo) is too long to naturally fit within the description field
|
* payment (memo) is too long to naturally fit within the description field
|
||||||
* of an encoded payment request.
|
* of an encoded payment request.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes description_hash = 4;
|
* @generated from protobuf field: bytes description_hash = 4
|
||||||
*/
|
*/
|
||||||
descriptionHash: Uint8Array;
|
descriptionHash: Uint8Array;
|
||||||
/**
|
/**
|
||||||
* Payment request expiry time in seconds. Default is 3600 (1 hour).
|
* Payment request expiry time in seconds. Default is 86400 (24 hours).
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: int64 expiry = 5;
|
* @generated from protobuf field: int64 expiry = 5
|
||||||
*/
|
*/
|
||||||
expiry: bigint;
|
expiry: bigint;
|
||||||
/**
|
/**
|
||||||
* Fallback on-chain address.
|
* Fallback on-chain address.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: string fallback_addr = 6;
|
* @generated from protobuf field: string fallback_addr = 6
|
||||||
*/
|
*/
|
||||||
fallbackAddr: string;
|
fallbackAddr: string;
|
||||||
/**
|
/**
|
||||||
* Delta to use for the time-lock of the CLTV extended to the final hop.
|
* Delta to use for the time-lock of the CLTV extended to the final hop.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint64 cltv_expiry = 7;
|
* @generated from protobuf field: uint64 cltv_expiry = 7
|
||||||
*/
|
*/
|
||||||
cltvExpiry: bigint;
|
cltvExpiry: bigint;
|
||||||
/**
|
/**
|
||||||
|
|
@ -101,13 +100,13 @@ export interface AddHoldInvoiceRequest {
|
||||||
* Route hints that can each be individually used to assist in reaching the
|
* Route hints that can each be individually used to assist in reaching the
|
||||||
* invoice's destination.
|
* invoice's destination.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 8;
|
* @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 8
|
||||||
*/
|
*/
|
||||||
routeHints: RouteHint[];
|
routeHints: RouteHint[];
|
||||||
/**
|
/**
|
||||||
* Whether this invoice should include routing hints for private channels.
|
* Whether this invoice should include routing hints for private channels.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bool private = 9;
|
* @generated from protobuf field: bool private = 9
|
||||||
*/
|
*/
|
||||||
private: boolean;
|
private: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +120,7 @@ export interface AddHoldInvoiceResp {
|
||||||
* details of the invoice, the sender has all the data necessary to send a
|
* details of the invoice, the sender has all the data necessary to send a
|
||||||
* payment to the recipient.
|
* payment to the recipient.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: string payment_request = 1;
|
* @generated from protobuf field: string payment_request = 1
|
||||||
*/
|
*/
|
||||||
paymentRequest: string;
|
paymentRequest: string;
|
||||||
/**
|
/**
|
||||||
|
|
@ -131,16 +130,17 @@ export interface AddHoldInvoiceResp {
|
||||||
* SubscribeInvoices call can use this to instantly get notified of all added
|
* SubscribeInvoices call can use this to instantly get notified of all added
|
||||||
* invoices with an add_index greater than this one.
|
* invoices with an add_index greater than this one.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint64 add_index = 2;
|
* @generated from protobuf field: uint64 add_index = 2
|
||||||
*/
|
*/
|
||||||
addIndex: bigint;
|
addIndex: bigint;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The payment address of the generated invoice. This value should be used
|
* The payment address of the generated invoice. This is also called
|
||||||
* in all payments for this invoice as we require it for end to end
|
* the payment secret in specifications (e.g. BOLT 11). This value should
|
||||||
|
* be used in all payments for this invoice as we require it for end to end
|
||||||
* security.
|
* security.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes payment_addr = 3;
|
* @generated from protobuf field: bytes payment_addr = 3
|
||||||
*/
|
*/
|
||||||
paymentAddr: Uint8Array;
|
paymentAddr: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +152,7 @@ export interface SettleInvoiceMsg {
|
||||||
* Externally discovered pre-image that should be used to settle the hold
|
* Externally discovered pre-image that should be used to settle the hold
|
||||||
* invoice.
|
* invoice.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes preimage = 1;
|
* @generated from protobuf field: bytes preimage = 1
|
||||||
*/
|
*/
|
||||||
preimage: Uint8Array;
|
preimage: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +169,7 @@ export interface SubscribeSingleInvoiceRequest {
|
||||||
* Hash corresponding to the (hold) invoice to subscribe to. When using
|
* Hash corresponding to the (hold) invoice to subscribe to. When using
|
||||||
* REST, this field must be encoded as base64url.
|
* REST, this field must be encoded as base64url.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes r_hash = 2;
|
* @generated from protobuf field: bytes r_hash = 2
|
||||||
*/
|
*/
|
||||||
rHash: Uint8Array;
|
rHash: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -185,29 +185,122 @@ export interface LookupInvoiceMsg {
|
||||||
/**
|
/**
|
||||||
* When using REST, this field must be encoded as base64.
|
* When using REST, this field must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes payment_hash = 1;
|
* @generated from protobuf field: bytes payment_hash = 1
|
||||||
*/
|
*/
|
||||||
paymentHash: Uint8Array;
|
paymentHash: Uint8Array;
|
||||||
} | {
|
} | {
|
||||||
oneofKind: "paymentAddr";
|
oneofKind: "paymentAddr";
|
||||||
/**
|
/**
|
||||||
* @generated from protobuf field: bytes payment_addr = 2;
|
* @generated from protobuf field: bytes payment_addr = 2
|
||||||
*/
|
*/
|
||||||
paymentAddr: Uint8Array;
|
paymentAddr: Uint8Array;
|
||||||
} | {
|
} | {
|
||||||
oneofKind: "setId";
|
oneofKind: "setId";
|
||||||
/**
|
/**
|
||||||
* @generated from protobuf field: bytes set_id = 3;
|
* @generated from protobuf field: bytes set_id = 3
|
||||||
*/
|
*/
|
||||||
setId: Uint8Array;
|
setId: Uint8Array;
|
||||||
} | {
|
} | {
|
||||||
oneofKind: undefined;
|
oneofKind: undefined;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @generated from protobuf field: invoicesrpc.LookupModifier lookup_modifier = 4;
|
* @generated from protobuf field: invoicesrpc.LookupModifier lookup_modifier = 4
|
||||||
*/
|
*/
|
||||||
lookupModifier: LookupModifier;
|
lookupModifier: LookupModifier;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* CircuitKey is a unique identifier for an HTLC.
|
||||||
|
*
|
||||||
|
* @generated from protobuf message invoicesrpc.CircuitKey
|
||||||
|
*/
|
||||||
|
export interface CircuitKey {
|
||||||
|
/**
|
||||||
|
* The id of the channel that the is part of this circuit.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: uint64 chan_id = 1
|
||||||
|
*/
|
||||||
|
chanId: bigint;
|
||||||
|
/**
|
||||||
|
* The index of the incoming htlc in the incoming channel.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: uint64 htlc_id = 2
|
||||||
|
*/
|
||||||
|
htlcId: bigint;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @generated from protobuf message invoicesrpc.HtlcModifyRequest
|
||||||
|
*/
|
||||||
|
export interface HtlcModifyRequest {
|
||||||
|
/**
|
||||||
|
* The invoice the intercepted HTLC is attempting to settle. The HTLCs in
|
||||||
|
* the invoice are only HTLCs that have already been accepted or settled,
|
||||||
|
* not including the current intercepted HTLC.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: lnrpc.Invoice invoice = 1
|
||||||
|
*/
|
||||||
|
invoice?: Invoice;
|
||||||
|
/**
|
||||||
|
* The unique identifier of the HTLC of this intercepted HTLC.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: invoicesrpc.CircuitKey exit_htlc_circuit_key = 2
|
||||||
|
*/
|
||||||
|
exitHtlcCircuitKey?: CircuitKey;
|
||||||
|
/**
|
||||||
|
* The amount in milli-satoshi that the exit HTLC is attempting to pay.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: uint64 exit_htlc_amt = 3
|
||||||
|
*/
|
||||||
|
exitHtlcAmt: bigint;
|
||||||
|
/**
|
||||||
|
* The absolute expiry height of the exit HTLC.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: uint32 exit_htlc_expiry = 4
|
||||||
|
*/
|
||||||
|
exitHtlcExpiry: number;
|
||||||
|
/**
|
||||||
|
* The current block height.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: uint32 current_height = 5
|
||||||
|
*/
|
||||||
|
currentHeight: number;
|
||||||
|
/**
|
||||||
|
* The wire message custom records of the exit HTLC.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: map<uint64, bytes> exit_htlc_wire_custom_records = 6
|
||||||
|
*/
|
||||||
|
exitHtlcWireCustomRecords: {
|
||||||
|
[key: string]: Uint8Array;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @generated from protobuf message invoicesrpc.HtlcModifyResponse
|
||||||
|
*/
|
||||||
|
export interface HtlcModifyResponse {
|
||||||
|
/**
|
||||||
|
* The circuit key of the HTLC that the client wants to modify.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: invoicesrpc.CircuitKey circuit_key = 1
|
||||||
|
*/
|
||||||
|
circuitKey?: CircuitKey;
|
||||||
|
/**
|
||||||
|
* The modified amount in milli-satoshi that the exit HTLC is paying. This
|
||||||
|
* value can be different from the actual on-chain HTLC amount, in case the
|
||||||
|
* HTLC carries other valuable items, as can be the case with custom channel
|
||||||
|
* types.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: optional uint64 amt_paid = 2
|
||||||
|
*/
|
||||||
|
amtPaid?: bigint;
|
||||||
|
/**
|
||||||
|
* This flag indicates whether the HTLCs associated with the invoices should
|
||||||
|
* be cancelled. The interceptor client may set this field if some
|
||||||
|
* unexpected behavior is encountered. Setting this will ignore the amt_paid
|
||||||
|
* field.
|
||||||
|
*
|
||||||
|
* @generated from protobuf field: bool cancel_set = 3
|
||||||
|
*/
|
||||||
|
cancelSet: boolean;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @generated from protobuf enum invoicesrpc.LookupModifier
|
* @generated from protobuf enum invoicesrpc.LookupModifier
|
||||||
*/
|
*/
|
||||||
|
|
@ -245,8 +338,8 @@ class CancelInvoiceMsg$Type extends MessageType<CancelInvoiceMsg> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<CancelInvoiceMsg>): CancelInvoiceMsg {
|
create(value?: PartialMessage<CancelInvoiceMsg>): CancelInvoiceMsg {
|
||||||
const message = { paymentHash: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.paymentHash = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<CancelInvoiceMsg>(this, message, value);
|
reflectionMergePartial<CancelInvoiceMsg>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -290,14 +383,26 @@ class CancelInvoiceResp$Type extends MessageType<CancelInvoiceResp> {
|
||||||
super("invoicesrpc.CancelInvoiceResp", []);
|
super("invoicesrpc.CancelInvoiceResp", []);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<CancelInvoiceResp>): CancelInvoiceResp {
|
create(value?: PartialMessage<CancelInvoiceResp>): CancelInvoiceResp {
|
||||||
const message = {};
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<CancelInvoiceResp>(this, message, value);
|
reflectionMergePartial<CancelInvoiceResp>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CancelInvoiceResp): CancelInvoiceResp {
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CancelInvoiceResp): CancelInvoiceResp {
|
||||||
return target ?? this.create();
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryWrite(message: CancelInvoiceResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
internalBinaryWrite(message: CancelInvoiceResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
let u = options.writeUnknownFields;
|
let u = options.writeUnknownFields;
|
||||||
|
|
@ -322,13 +427,22 @@ class AddHoldInvoiceRequest$Type extends MessageType<AddHoldInvoiceRequest> {
|
||||||
{ no: 5, name: "expiry", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
|
{ no: 5, name: "expiry", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||||
{ no: 6, name: "fallback_addr", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
{ no: 6, name: "fallback_addr", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||||
{ no: 7, name: "cltv_expiry", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
{ no: 7, name: "cltv_expiry", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||||
{ no: 8, name: "route_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => RouteHint },
|
{ no: 8, name: "route_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => RouteHint },
|
||||||
{ no: 9, name: "private", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
|
{ no: 9, name: "private", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<AddHoldInvoiceRequest>): AddHoldInvoiceRequest {
|
create(value?: PartialMessage<AddHoldInvoiceRequest>): AddHoldInvoiceRequest {
|
||||||
const message = { memo: "", hash: new Uint8Array(0), value: 0n, valueMsat: 0n, descriptionHash: new Uint8Array(0), expiry: 0n, fallbackAddr: "", cltvExpiry: 0n, routeHints: [], private: false };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.memo = "";
|
||||||
|
message.hash = new Uint8Array(0);
|
||||||
|
message.value = 0n;
|
||||||
|
message.valueMsat = 0n;
|
||||||
|
message.descriptionHash = new Uint8Array(0);
|
||||||
|
message.expiry = 0n;
|
||||||
|
message.fallbackAddr = "";
|
||||||
|
message.cltvExpiry = 0n;
|
||||||
|
message.routeHints = [];
|
||||||
|
message.private = false;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<AddHoldInvoiceRequest>(this, message, value);
|
reflectionMergePartial<AddHoldInvoiceRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -389,9 +503,6 @@ class AddHoldInvoiceRequest$Type extends MessageType<AddHoldInvoiceRequest> {
|
||||||
/* int64 value = 3; */
|
/* int64 value = 3; */
|
||||||
if (message.value !== 0n)
|
if (message.value !== 0n)
|
||||||
writer.tag(3, WireType.Varint).int64(message.value);
|
writer.tag(3, WireType.Varint).int64(message.value);
|
||||||
/* int64 value_msat = 10; */
|
|
||||||
if (message.valueMsat !== 0n)
|
|
||||||
writer.tag(10, WireType.Varint).int64(message.valueMsat);
|
|
||||||
/* bytes description_hash = 4; */
|
/* bytes description_hash = 4; */
|
||||||
if (message.descriptionHash.length)
|
if (message.descriptionHash.length)
|
||||||
writer.tag(4, WireType.LengthDelimited).bytes(message.descriptionHash);
|
writer.tag(4, WireType.LengthDelimited).bytes(message.descriptionHash);
|
||||||
|
|
@ -410,6 +521,9 @@ class AddHoldInvoiceRequest$Type extends MessageType<AddHoldInvoiceRequest> {
|
||||||
/* bool private = 9; */
|
/* bool private = 9; */
|
||||||
if (message.private !== false)
|
if (message.private !== false)
|
||||||
writer.tag(9, WireType.Varint).bool(message.private);
|
writer.tag(9, WireType.Varint).bool(message.private);
|
||||||
|
/* int64 value_msat = 10; */
|
||||||
|
if (message.valueMsat !== 0n)
|
||||||
|
writer.tag(10, WireType.Varint).int64(message.valueMsat);
|
||||||
let u = options.writeUnknownFields;
|
let u = options.writeUnknownFields;
|
||||||
if (u !== false)
|
if (u !== false)
|
||||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||||
|
|
@ -430,8 +544,10 @@ class AddHoldInvoiceResp$Type extends MessageType<AddHoldInvoiceResp> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<AddHoldInvoiceResp>): AddHoldInvoiceResp {
|
create(value?: PartialMessage<AddHoldInvoiceResp>): AddHoldInvoiceResp {
|
||||||
const message = { paymentRequest: "", addIndex: 0n, paymentAddr: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.paymentRequest = "";
|
||||||
|
message.addIndex = 0n;
|
||||||
|
message.paymentAddr = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<AddHoldInvoiceResp>(this, message, value);
|
reflectionMergePartial<AddHoldInvoiceResp>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -489,8 +605,8 @@ class SettleInvoiceMsg$Type extends MessageType<SettleInvoiceMsg> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<SettleInvoiceMsg>): SettleInvoiceMsg {
|
create(value?: PartialMessage<SettleInvoiceMsg>): SettleInvoiceMsg {
|
||||||
const message = { preimage: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.preimage = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<SettleInvoiceMsg>(this, message, value);
|
reflectionMergePartial<SettleInvoiceMsg>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -534,14 +650,26 @@ class SettleInvoiceResp$Type extends MessageType<SettleInvoiceResp> {
|
||||||
super("invoicesrpc.SettleInvoiceResp", []);
|
super("invoicesrpc.SettleInvoiceResp", []);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<SettleInvoiceResp>): SettleInvoiceResp {
|
create(value?: PartialMessage<SettleInvoiceResp>): SettleInvoiceResp {
|
||||||
const message = {};
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<SettleInvoiceResp>(this, message, value);
|
reflectionMergePartial<SettleInvoiceResp>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SettleInvoiceResp): SettleInvoiceResp {
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SettleInvoiceResp): SettleInvoiceResp {
|
||||||
return target ?? this.create();
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryWrite(message: SettleInvoiceResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
internalBinaryWrite(message: SettleInvoiceResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
let u = options.writeUnknownFields;
|
let u = options.writeUnknownFields;
|
||||||
|
|
@ -562,8 +690,8 @@ class SubscribeSingleInvoiceRequest$Type extends MessageType<SubscribeSingleInvo
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<SubscribeSingleInvoiceRequest>): SubscribeSingleInvoiceRequest {
|
create(value?: PartialMessage<SubscribeSingleInvoiceRequest>): SubscribeSingleInvoiceRequest {
|
||||||
const message = { rHash: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.rHash = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<SubscribeSingleInvoiceRequest>(this, message, value);
|
reflectionMergePartial<SubscribeSingleInvoiceRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -612,8 +740,9 @@ class LookupInvoiceMsg$Type extends MessageType<LookupInvoiceMsg> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<LookupInvoiceMsg>): LookupInvoiceMsg {
|
create(value?: PartialMessage<LookupInvoiceMsg>): LookupInvoiceMsg {
|
||||||
const message = { invoiceRef: { oneofKind: undefined }, lookupModifier: 0 };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.invoiceRef = { oneofKind: undefined };
|
||||||
|
message.lookupModifier = 0;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<LookupInvoiceMsg>(this, message, value);
|
reflectionMergePartial<LookupInvoiceMsg>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -678,6 +807,223 @@ class LookupInvoiceMsg$Type extends MessageType<LookupInvoiceMsg> {
|
||||||
* @generated MessageType for protobuf message invoicesrpc.LookupInvoiceMsg
|
* @generated MessageType for protobuf message invoicesrpc.LookupInvoiceMsg
|
||||||
*/
|
*/
|
||||||
export const LookupInvoiceMsg = new LookupInvoiceMsg$Type();
|
export const LookupInvoiceMsg = new LookupInvoiceMsg$Type();
|
||||||
|
// @generated message type with reflection information, may provide speed optimized methods
|
||||||
|
class CircuitKey$Type extends MessageType<CircuitKey> {
|
||||||
|
constructor() {
|
||||||
|
super("invoicesrpc.CircuitKey", [
|
||||||
|
{ no: 1, name: "chan_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||||
|
{ no: 2, name: "htlc_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
create(value?: PartialMessage<CircuitKey>): CircuitKey {
|
||||||
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
|
message.chanId = 0n;
|
||||||
|
message.htlcId = 0n;
|
||||||
|
if (value !== undefined)
|
||||||
|
reflectionMergePartial<CircuitKey>(this, message, value);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CircuitKey): CircuitKey {
|
||||||
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
case /* uint64 chan_id */ 1:
|
||||||
|
message.chanId = reader.uint64().toBigInt();
|
||||||
|
break;
|
||||||
|
case /* uint64 htlc_id */ 2:
|
||||||
|
message.htlcId = reader.uint64().toBigInt();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
internalBinaryWrite(message: CircuitKey, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
|
/* uint64 chan_id = 1; */
|
||||||
|
if (message.chanId !== 0n)
|
||||||
|
writer.tag(1, WireType.Varint).uint64(message.chanId);
|
||||||
|
/* uint64 htlc_id = 2; */
|
||||||
|
if (message.htlcId !== 0n)
|
||||||
|
writer.tag(2, WireType.Varint).uint64(message.htlcId);
|
||||||
|
let u = options.writeUnknownFields;
|
||||||
|
if (u !== false)
|
||||||
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @generated MessageType for protobuf message invoicesrpc.CircuitKey
|
||||||
|
*/
|
||||||
|
export const CircuitKey = new CircuitKey$Type();
|
||||||
|
// @generated message type with reflection information, may provide speed optimized methods
|
||||||
|
class HtlcModifyRequest$Type extends MessageType<HtlcModifyRequest> {
|
||||||
|
constructor() {
|
||||||
|
super("invoicesrpc.HtlcModifyRequest", [
|
||||||
|
{ no: 1, name: "invoice", kind: "message", T: () => Invoice },
|
||||||
|
{ no: 2, name: "exit_htlc_circuit_key", kind: "message", T: () => CircuitKey },
|
||||||
|
{ no: 3, name: "exit_htlc_amt", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||||
|
{ no: 4, name: "exit_htlc_expiry", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||||
|
{ no: 5, name: "current_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||||
|
{ no: 6, name: "exit_htlc_wire_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
create(value?: PartialMessage<HtlcModifyRequest>): HtlcModifyRequest {
|
||||||
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
|
message.exitHtlcAmt = 0n;
|
||||||
|
message.exitHtlcExpiry = 0;
|
||||||
|
message.currentHeight = 0;
|
||||||
|
message.exitHtlcWireCustomRecords = {};
|
||||||
|
if (value !== undefined)
|
||||||
|
reflectionMergePartial<HtlcModifyRequest>(this, message, value);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: HtlcModifyRequest): HtlcModifyRequest {
|
||||||
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
case /* lnrpc.Invoice invoice */ 1:
|
||||||
|
message.invoice = Invoice.internalBinaryRead(reader, reader.uint32(), options, message.invoice);
|
||||||
|
break;
|
||||||
|
case /* invoicesrpc.CircuitKey exit_htlc_circuit_key */ 2:
|
||||||
|
message.exitHtlcCircuitKey = CircuitKey.internalBinaryRead(reader, reader.uint32(), options, message.exitHtlcCircuitKey);
|
||||||
|
break;
|
||||||
|
case /* uint64 exit_htlc_amt */ 3:
|
||||||
|
message.exitHtlcAmt = reader.uint64().toBigInt();
|
||||||
|
break;
|
||||||
|
case /* uint32 exit_htlc_expiry */ 4:
|
||||||
|
message.exitHtlcExpiry = reader.uint32();
|
||||||
|
break;
|
||||||
|
case /* uint32 current_height */ 5:
|
||||||
|
message.currentHeight = reader.uint32();
|
||||||
|
break;
|
||||||
|
case /* map<uint64, bytes> exit_htlc_wire_custom_records */ 6:
|
||||||
|
this.binaryReadMap6(message.exitHtlcWireCustomRecords, reader, options);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
private binaryReadMap6(map: HtlcModifyRequest["exitHtlcWireCustomRecords"], reader: IBinaryReader, options: BinaryReadOptions): void {
|
||||||
|
let len = reader.uint32(), end = reader.pos + len, key: keyof HtlcModifyRequest["exitHtlcWireCustomRecords"] | undefined, val: HtlcModifyRequest["exitHtlcWireCustomRecords"][any] | undefined;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
case 1:
|
||||||
|
key = reader.uint64().toString();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
val = reader.bytes();
|
||||||
|
break;
|
||||||
|
default: throw new globalThis.Error("unknown map entry field for invoicesrpc.HtlcModifyRequest.exit_htlc_wire_custom_records");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map[key ?? "0"] = val ?? new Uint8Array(0);
|
||||||
|
}
|
||||||
|
internalBinaryWrite(message: HtlcModifyRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
|
/* lnrpc.Invoice invoice = 1; */
|
||||||
|
if (message.invoice)
|
||||||
|
Invoice.internalBinaryWrite(message.invoice, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||||
|
/* invoicesrpc.CircuitKey exit_htlc_circuit_key = 2; */
|
||||||
|
if (message.exitHtlcCircuitKey)
|
||||||
|
CircuitKey.internalBinaryWrite(message.exitHtlcCircuitKey, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
||||||
|
/* uint64 exit_htlc_amt = 3; */
|
||||||
|
if (message.exitHtlcAmt !== 0n)
|
||||||
|
writer.tag(3, WireType.Varint).uint64(message.exitHtlcAmt);
|
||||||
|
/* uint32 exit_htlc_expiry = 4; */
|
||||||
|
if (message.exitHtlcExpiry !== 0)
|
||||||
|
writer.tag(4, WireType.Varint).uint32(message.exitHtlcExpiry);
|
||||||
|
/* uint32 current_height = 5; */
|
||||||
|
if (message.currentHeight !== 0)
|
||||||
|
writer.tag(5, WireType.Varint).uint32(message.currentHeight);
|
||||||
|
/* map<uint64, bytes> exit_htlc_wire_custom_records = 6; */
|
||||||
|
for (let k of globalThis.Object.keys(message.exitHtlcWireCustomRecords))
|
||||||
|
writer.tag(6, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.exitHtlcWireCustomRecords[k]).join();
|
||||||
|
let u = options.writeUnknownFields;
|
||||||
|
if (u !== false)
|
||||||
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @generated MessageType for protobuf message invoicesrpc.HtlcModifyRequest
|
||||||
|
*/
|
||||||
|
export const HtlcModifyRequest = new HtlcModifyRequest$Type();
|
||||||
|
// @generated message type with reflection information, may provide speed optimized methods
|
||||||
|
class HtlcModifyResponse$Type extends MessageType<HtlcModifyResponse> {
|
||||||
|
constructor() {
|
||||||
|
super("invoicesrpc.HtlcModifyResponse", [
|
||||||
|
{ no: 1, name: "circuit_key", kind: "message", T: () => CircuitKey },
|
||||||
|
{ no: 2, name: "amt_paid", kind: "scalar", opt: true, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||||
|
{ no: 3, name: "cancel_set", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
create(value?: PartialMessage<HtlcModifyResponse>): HtlcModifyResponse {
|
||||||
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
|
message.cancelSet = false;
|
||||||
|
if (value !== undefined)
|
||||||
|
reflectionMergePartial<HtlcModifyResponse>(this, message, value);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: HtlcModifyResponse): HtlcModifyResponse {
|
||||||
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
case /* invoicesrpc.CircuitKey circuit_key */ 1:
|
||||||
|
message.circuitKey = CircuitKey.internalBinaryRead(reader, reader.uint32(), options, message.circuitKey);
|
||||||
|
break;
|
||||||
|
case /* optional uint64 amt_paid */ 2:
|
||||||
|
message.amtPaid = reader.uint64().toBigInt();
|
||||||
|
break;
|
||||||
|
case /* bool cancel_set */ 3:
|
||||||
|
message.cancelSet = reader.bool();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
internalBinaryWrite(message: HtlcModifyResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
|
/* invoicesrpc.CircuitKey circuit_key = 1; */
|
||||||
|
if (message.circuitKey)
|
||||||
|
CircuitKey.internalBinaryWrite(message.circuitKey, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||||
|
/* optional uint64 amt_paid = 2; */
|
||||||
|
if (message.amtPaid !== undefined)
|
||||||
|
writer.tag(2, WireType.Varint).uint64(message.amtPaid);
|
||||||
|
/* bool cancel_set = 3; */
|
||||||
|
if (message.cancelSet !== false)
|
||||||
|
writer.tag(3, WireType.Varint).bool(message.cancelSet);
|
||||||
|
let u = options.writeUnknownFields;
|
||||||
|
if (u !== false)
|
||||||
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @generated MessageType for protobuf message invoicesrpc.HtlcModifyResponse
|
||||||
|
*/
|
||||||
|
export const HtlcModifyResponse = new HtlcModifyResponse$Type();
|
||||||
/**
|
/**
|
||||||
* @generated ServiceType for protobuf service invoicesrpc.Invoices
|
* @generated ServiceType for protobuf service invoicesrpc.Invoices
|
||||||
*/
|
*/
|
||||||
|
|
@ -686,5 +1032,6 @@ export const Invoices = new ServiceType("invoicesrpc.Invoices", [
|
||||||
{ name: "CancelInvoice", options: {}, I: CancelInvoiceMsg, O: CancelInvoiceResp },
|
{ name: "CancelInvoice", options: {}, I: CancelInvoiceMsg, O: CancelInvoiceResp },
|
||||||
{ name: "AddHoldInvoice", options: {}, I: AddHoldInvoiceRequest, O: AddHoldInvoiceResp },
|
{ name: "AddHoldInvoice", options: {}, I: AddHoldInvoiceRequest, O: AddHoldInvoiceResp },
|
||||||
{ name: "SettleInvoice", options: {}, I: SettleInvoiceMsg, O: SettleInvoiceResp },
|
{ name: "SettleInvoice", options: {}, I: SettleInvoiceMsg, O: SettleInvoiceResp },
|
||||||
{ name: "LookupInvoiceV2", options: {}, I: LookupInvoiceMsg, O: Invoice }
|
{ name: "LookupInvoiceV2", options: {}, I: LookupInvoiceMsg, O: Invoice },
|
||||||
|
{ name: "HtlcModifier", serverStreaming: true, clientStreaming: true, options: {}, I: HtlcModifyResponse, O: HtlcModifyRequest }
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,13 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "router.proto" (package "routerrpc", syntax proto3)
|
// @generated from protobuf file "router.proto" (package "routerrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||||
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
|
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
|
||||||
import { Router } from "./router.js";
|
import { Router } from "./router.js";
|
||||||
|
import type { DeleteAliasesResponse } from "./router.js";
|
||||||
|
import type { DeleteAliasesRequest } from "./router.js";
|
||||||
|
import type { AddAliasesResponse } from "./router.js";
|
||||||
|
import type { AddAliasesRequest } from "./router.js";
|
||||||
import type { UpdateChanStatusResponse } from "./router.js";
|
import type { UpdateChanStatusResponse } from "./router.js";
|
||||||
import type { UpdateChanStatusRequest } from "./router.js";
|
import type { UpdateChanStatusRequest } from "./router.js";
|
||||||
import type { ForwardHtlcInterceptRequest } from "./router.js";
|
import type { ForwardHtlcInterceptRequest } from "./router.js";
|
||||||
|
|
@ -39,6 +43,23 @@ import type { Payment } from "./lightning.js";
|
||||||
import type { SendPaymentRequest } from "./router.js";
|
import type { SendPaymentRequest } from "./router.js";
|
||||||
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
|
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
|
||||||
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
|
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
|
||||||
|
//
|
||||||
|
// Comments in this file will be directly parsed into the API
|
||||||
|
// Documentation as descriptions of the associated method, message, or field.
|
||||||
|
// These descriptions should go right above the definition of the object, and
|
||||||
|
// can be in either block or // comment format.
|
||||||
|
//
|
||||||
|
// An RPC method can be matched to an lncli command by placing a line in the
|
||||||
|
// beginning of the description in exactly the following format:
|
||||||
|
// lncli: `methodname`
|
||||||
|
//
|
||||||
|
// Failure to specify the exact name of the command will cause documentation
|
||||||
|
// generation to fail.
|
||||||
|
//
|
||||||
|
// More information on how exactly the gRPC documentation is generated from
|
||||||
|
// this proto file can be found here:
|
||||||
|
// https://github.com/lightninglabs/lightning-api
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router is a service that offers advanced interaction with the router
|
* Router is a service that offers advanced interaction with the router
|
||||||
* subsystem of the daemon.
|
* subsystem of the daemon.
|
||||||
|
|
@ -50,17 +71,20 @@ export interface IRouterClient {
|
||||||
*
|
*
|
||||||
* SendPaymentV2 attempts to route a payment described by the passed
|
* SendPaymentV2 attempts to route a payment described by the passed
|
||||||
* PaymentRequest to the final destination. The call returns a stream of
|
* PaymentRequest to the final destination. The call returns a stream of
|
||||||
* payment updates.
|
* payment updates. When using this RPC, make sure to set a fee limit, as the
|
||||||
|
* default routing fee limit is 0 sats. Without a non-zero fee limit only
|
||||||
|
* routes without fees will be attempted which often fails with
|
||||||
|
* FAILURE_REASON_NO_ROUTE.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SendPaymentV2(routerrpc.SendPaymentRequest) returns (stream lnrpc.Payment);
|
* @generated from protobuf rpc: SendPaymentV2
|
||||||
*/
|
*/
|
||||||
sendPaymentV2(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, Payment>;
|
sendPaymentV2(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, Payment>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `trackpayment`
|
||||||
* TrackPaymentV2 returns an update stream for the payment identified by the
|
* TrackPaymentV2 returns an update stream for the payment identified by the
|
||||||
* payment hash.
|
* payment hash.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: TrackPaymentV2(routerrpc.TrackPaymentRequest) returns (stream lnrpc.Payment);
|
* @generated from protobuf rpc: TrackPaymentV2
|
||||||
*/
|
*/
|
||||||
trackPaymentV2(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, Payment>;
|
trackPaymentV2(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, Payment>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,7 +96,7 @@ export interface IRouterClient {
|
||||||
* payment attempt make sure to subscribe to this method before initiating any
|
* payment attempt make sure to subscribe to this method before initiating any
|
||||||
* payments.
|
* payments.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: TrackPayments(routerrpc.TrackPaymentsRequest) returns (stream lnrpc.Payment);
|
* @generated from protobuf rpc: TrackPayments
|
||||||
*/
|
*/
|
||||||
trackPayments(input: TrackPaymentsRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentsRequest, Payment>;
|
trackPayments(input: TrackPaymentsRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentsRequest, Payment>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -80,7 +104,7 @@ export interface IRouterClient {
|
||||||
* EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it
|
* EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it
|
||||||
* may cost to send an HTLC to the target end destination.
|
* may cost to send an HTLC to the target end destination.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: EstimateRouteFee(routerrpc.RouteFeeRequest) returns (routerrpc.RouteFeeResponse);
|
* @generated from protobuf rpc: EstimateRouteFee
|
||||||
*/
|
*/
|
||||||
estimateRouteFee(input: RouteFeeRequest, options?: RpcOptions): UnaryCall<RouteFeeRequest, RouteFeeResponse>;
|
estimateRouteFee(input: RouteFeeRequest, options?: RpcOptions): UnaryCall<RouteFeeRequest, RouteFeeResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -92,7 +116,7 @@ export interface IRouterClient {
|
||||||
* SendToRouteV2 in that it doesn't return the full HTLC information.
|
* SendToRouteV2 in that it doesn't return the full HTLC information.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @generated from protobuf rpc: SendToRoute(routerrpc.SendToRouteRequest) returns (routerrpc.SendToRouteResponse);
|
* @generated from protobuf rpc: SendToRoute
|
||||||
*/
|
*/
|
||||||
sendToRoute(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, SendToRouteResponse>;
|
sendToRoute(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, SendToRouteResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,65 +126,71 @@ export interface IRouterClient {
|
||||||
* route manually. This can be used for things like rebalancing, and atomic
|
* route manually. This can be used for things like rebalancing, and atomic
|
||||||
* swaps.
|
* swaps.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SendToRouteV2(routerrpc.SendToRouteRequest) returns (lnrpc.HTLCAttempt);
|
* @generated from protobuf rpc: SendToRouteV2
|
||||||
*/
|
*/
|
||||||
sendToRouteV2(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, HTLCAttempt>;
|
sendToRouteV2(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, HTLCAttempt>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `resetmc`
|
||||||
* ResetMissionControl clears all mission control state and starts with a clean
|
* ResetMissionControl clears all mission control state and starts with a clean
|
||||||
* slate.
|
* slate.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ResetMissionControl(routerrpc.ResetMissionControlRequest) returns (routerrpc.ResetMissionControlResponse);
|
* @generated from protobuf rpc: ResetMissionControl
|
||||||
*/
|
*/
|
||||||
resetMissionControl(input: ResetMissionControlRequest, options?: RpcOptions): UnaryCall<ResetMissionControlRequest, ResetMissionControlResponse>;
|
resetMissionControl(input: ResetMissionControlRequest, options?: RpcOptions): UnaryCall<ResetMissionControlRequest, ResetMissionControlResponse>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `querymc`
|
||||||
* QueryMissionControl exposes the internal mission control state to callers.
|
* QueryMissionControl exposes the internal mission control state to callers.
|
||||||
* It is a development feature.
|
* It is a development feature.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: QueryMissionControl(routerrpc.QueryMissionControlRequest) returns (routerrpc.QueryMissionControlResponse);
|
* @generated from protobuf rpc: QueryMissionControl
|
||||||
*/
|
*/
|
||||||
queryMissionControl(input: QueryMissionControlRequest, options?: RpcOptions): UnaryCall<QueryMissionControlRequest, QueryMissionControlResponse>;
|
queryMissionControl(input: QueryMissionControlRequest, options?: RpcOptions): UnaryCall<QueryMissionControlRequest, QueryMissionControlResponse>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `importmc`
|
||||||
* XImportMissionControl is an experimental API that imports the state provided
|
* XImportMissionControl is an experimental API that imports the state provided
|
||||||
* to the internal mission control's state, using all results which are more
|
* to the internal mission control's state, using all results which are more
|
||||||
* recent than our existing values. These values will only be imported
|
* recent than our existing values. These values will only be imported
|
||||||
* in-memory, and will not be persisted across restarts.
|
* in-memory, and will not be persisted across restarts.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: XImportMissionControl(routerrpc.XImportMissionControlRequest) returns (routerrpc.XImportMissionControlResponse);
|
* @generated from protobuf rpc: XImportMissionControl
|
||||||
*/
|
*/
|
||||||
xImportMissionControl(input: XImportMissionControlRequest, options?: RpcOptions): UnaryCall<XImportMissionControlRequest, XImportMissionControlResponse>;
|
xImportMissionControl(input: XImportMissionControlRequest, options?: RpcOptions): UnaryCall<XImportMissionControlRequest, XImportMissionControlResponse>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `getmccfg`
|
||||||
* GetMissionControlConfig returns mission control's current config.
|
* GetMissionControlConfig returns mission control's current config.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: GetMissionControlConfig(routerrpc.GetMissionControlConfigRequest) returns (routerrpc.GetMissionControlConfigResponse);
|
* @generated from protobuf rpc: GetMissionControlConfig
|
||||||
*/
|
*/
|
||||||
getMissionControlConfig(input: GetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<GetMissionControlConfigRequest, GetMissionControlConfigResponse>;
|
getMissionControlConfig(input: GetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<GetMissionControlConfigRequest, GetMissionControlConfigResponse>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `setmccfg`
|
||||||
* SetMissionControlConfig will set mission control's config, if the config
|
* SetMissionControlConfig will set mission control's config, if the config
|
||||||
* provided is valid.
|
* provided is valid.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SetMissionControlConfig(routerrpc.SetMissionControlConfigRequest) returns (routerrpc.SetMissionControlConfigResponse);
|
* @generated from protobuf rpc: SetMissionControlConfig
|
||||||
*/
|
*/
|
||||||
setMissionControlConfig(input: SetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<SetMissionControlConfigRequest, SetMissionControlConfigResponse>;
|
setMissionControlConfig(input: SetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<SetMissionControlConfigRequest, SetMissionControlConfigResponse>;
|
||||||
/**
|
/**
|
||||||
|
* lncli: `queryprob`
|
||||||
|
* Deprecated. QueryProbability returns the current success probability
|
||||||
|
* estimate for a given node pair and amount. The call returns a zero success
|
||||||
|
* probability if no channel is available or if the amount violates min/max
|
||||||
|
* HTLC constraints.
|
||||||
*
|
*
|
||||||
* QueryProbability returns the current success probability estimate for a
|
* @generated from protobuf rpc: QueryProbability
|
||||||
* given node pair and amount.
|
|
||||||
*
|
|
||||||
* @generated from protobuf rpc: QueryProbability(routerrpc.QueryProbabilityRequest) returns (routerrpc.QueryProbabilityResponse);
|
|
||||||
*/
|
*/
|
||||||
queryProbability(input: QueryProbabilityRequest, options?: RpcOptions): UnaryCall<QueryProbabilityRequest, QueryProbabilityResponse>;
|
queryProbability(input: QueryProbabilityRequest, options?: RpcOptions): UnaryCall<QueryProbabilityRequest, QueryProbabilityResponse>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `buildroute`
|
||||||
* BuildRoute builds a fully specified route based on a list of hop public
|
* BuildRoute builds a fully specified route based on a list of hop public
|
||||||
* keys. It retrieves the relevant channel policies from the graph in order to
|
* keys. It retrieves the relevant channel policies from the graph in order to
|
||||||
* calculate the correct fees and time locks.
|
* calculate the correct fees and time locks.
|
||||||
|
* Note that LND will use its default final_cltv_delta if no value is supplied.
|
||||||
|
* Make sure to add the correct final_cltv_delta depending on the invoice
|
||||||
|
* restriction. Moreover the caller has to make sure to provide the
|
||||||
|
* payment_addr if the route is paying an invoice which signaled it.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: BuildRoute(routerrpc.BuildRouteRequest) returns (routerrpc.BuildRouteResponse);
|
* @generated from protobuf rpc: BuildRoute
|
||||||
*/
|
*/
|
||||||
buildRoute(input: BuildRouteRequest, options?: RpcOptions): UnaryCall<BuildRouteRequest, BuildRouteResponse>;
|
buildRoute(input: BuildRouteRequest, options?: RpcOptions): UnaryCall<BuildRouteRequest, BuildRouteResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -168,7 +198,7 @@ export interface IRouterClient {
|
||||||
* SubscribeHtlcEvents creates a uni-directional stream from the server to
|
* SubscribeHtlcEvents creates a uni-directional stream from the server to
|
||||||
* the client which delivers a stream of htlc events.
|
* the client which delivers a stream of htlc events.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SubscribeHtlcEvents(routerrpc.SubscribeHtlcEventsRequest) returns (stream routerrpc.HtlcEvent);
|
* @generated from protobuf rpc: SubscribeHtlcEvents
|
||||||
*/
|
*/
|
||||||
subscribeHtlcEvents(input: SubscribeHtlcEventsRequest, options?: RpcOptions): ServerStreamingCall<SubscribeHtlcEventsRequest, HtlcEvent>;
|
subscribeHtlcEvents(input: SubscribeHtlcEventsRequest, options?: RpcOptions): ServerStreamingCall<SubscribeHtlcEventsRequest, HtlcEvent>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -178,7 +208,7 @@ export interface IRouterClient {
|
||||||
* returns a stream of payment status updates.
|
* returns a stream of payment status updates.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @generated from protobuf rpc: SendPayment(routerrpc.SendPaymentRequest) returns (stream routerrpc.PaymentStatus);
|
* @generated from protobuf rpc: SendPayment
|
||||||
*/
|
*/
|
||||||
sendPayment(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, PaymentStatus>;
|
sendPayment(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, PaymentStatus>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -187,7 +217,7 @@ export interface IRouterClient {
|
||||||
* the payment identified by the payment hash.
|
* the payment identified by the payment hash.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @generated from protobuf rpc: TrackPayment(routerrpc.TrackPaymentRequest) returns (stream routerrpc.PaymentStatus);
|
* @generated from protobuf rpc: TrackPayment
|
||||||
*/
|
*/
|
||||||
trackPayment(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, PaymentStatus>;
|
trackPayment(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, PaymentStatus>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -198,20 +228,59 @@ export interface IRouterClient {
|
||||||
* In case of interception, the htlc can be either settled, cancelled or
|
* In case of interception, the htlc can be either settled, cancelled or
|
||||||
* resumed later by using the ResolveHoldForward endpoint.
|
* resumed later by using the ResolveHoldForward endpoint.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: HtlcInterceptor(stream routerrpc.ForwardHtlcInterceptResponse) returns (stream routerrpc.ForwardHtlcInterceptRequest);
|
* @generated from protobuf rpc: HtlcInterceptor
|
||||||
*/
|
*/
|
||||||
htlcInterceptor(options?: RpcOptions): DuplexStreamingCall<ForwardHtlcInterceptResponse, ForwardHtlcInterceptRequest>;
|
htlcInterceptor(options?: RpcOptions): DuplexStreamingCall<ForwardHtlcInterceptResponse, ForwardHtlcInterceptRequest>;
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `updatechanstatus`
|
||||||
* UpdateChanStatus attempts to manually set the state of a channel
|
* UpdateChanStatus attempts to manually set the state of a channel
|
||||||
* (enabled, disabled, or auto). A manual "disable" request will cause the
|
* (enabled, disabled, or auto). A manual "disable" request will cause the
|
||||||
* channel to stay disabled until a subsequent manual request of either
|
* channel to stay disabled until a subsequent manual request of either
|
||||||
* "enable" or "auto".
|
* "enable" or "auto".
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: UpdateChanStatus(routerrpc.UpdateChanStatusRequest) returns (routerrpc.UpdateChanStatusResponse);
|
* @generated from protobuf rpc: UpdateChanStatus
|
||||||
*/
|
*/
|
||||||
updateChanStatus(input: UpdateChanStatusRequest, options?: RpcOptions): UnaryCall<UpdateChanStatusRequest, UpdateChanStatusResponse>;
|
updateChanStatus(input: UpdateChanStatusRequest, options?: RpcOptions): UnaryCall<UpdateChanStatusRequest, UpdateChanStatusResponse>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* XAddLocalChanAliases is an experimental API that creates a set of new
|
||||||
|
* channel SCID alias mappings. The final total set of aliases in the manager
|
||||||
|
* after the add operation is returned. This is only a locally stored alias,
|
||||||
|
* and will not be communicated to the channel peer via any message. Therefore,
|
||||||
|
* routing over such an alias will only work if the peer also calls this same
|
||||||
|
* RPC on their end. If an alias already exists, an error is returned
|
||||||
|
*
|
||||||
|
* @generated from protobuf rpc: XAddLocalChanAliases
|
||||||
|
*/
|
||||||
|
xAddLocalChanAliases(input: AddAliasesRequest, options?: RpcOptions): UnaryCall<AddAliasesRequest, AddAliasesResponse>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* XDeleteLocalChanAliases is an experimental API that deletes a set of alias
|
||||||
|
* mappings. The final total set of aliases in the manager after the delete
|
||||||
|
* operation is returned. The deletion will not be communicated to the channel
|
||||||
|
* peer via any message.
|
||||||
|
*
|
||||||
|
* @generated from protobuf rpc: XDeleteLocalChanAliases
|
||||||
|
*/
|
||||||
|
xDeleteLocalChanAliases(input: DeleteAliasesRequest, options?: RpcOptions): UnaryCall<DeleteAliasesRequest, DeleteAliasesResponse>;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Comments in this file will be directly parsed into the API
|
||||||
|
// Documentation as descriptions of the associated method, message, or field.
|
||||||
|
// These descriptions should go right above the definition of the object, and
|
||||||
|
// can be in either block or // comment format.
|
||||||
|
//
|
||||||
|
// An RPC method can be matched to an lncli command by placing a line in the
|
||||||
|
// beginning of the description in exactly the following format:
|
||||||
|
// lncli: `methodname`
|
||||||
|
//
|
||||||
|
// Failure to specify the exact name of the command will cause documentation
|
||||||
|
// generation to fail.
|
||||||
|
//
|
||||||
|
// More information on how exactly the gRPC documentation is generated from
|
||||||
|
// this proto file can be found here:
|
||||||
|
// https://github.com/lightninglabs/lightning-api
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router is a service that offers advanced interaction with the router
|
* Router is a service that offers advanced interaction with the router
|
||||||
* subsystem of the daemon.
|
* subsystem of the daemon.
|
||||||
|
|
@ -228,20 +297,23 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
*
|
*
|
||||||
* SendPaymentV2 attempts to route a payment described by the passed
|
* SendPaymentV2 attempts to route a payment described by the passed
|
||||||
* PaymentRequest to the final destination. The call returns a stream of
|
* PaymentRequest to the final destination. The call returns a stream of
|
||||||
* payment updates.
|
* payment updates. When using this RPC, make sure to set a fee limit, as the
|
||||||
|
* default routing fee limit is 0 sats. Without a non-zero fee limit only
|
||||||
|
* routes without fees will be attempted which often fails with
|
||||||
|
* FAILURE_REASON_NO_ROUTE.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SendPaymentV2(routerrpc.SendPaymentRequest) returns (stream lnrpc.Payment);
|
* @generated from protobuf rpc: SendPaymentV2
|
||||||
*/
|
*/
|
||||||
sendPaymentV2(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, Payment> {
|
sendPaymentV2(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, Payment> {
|
||||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<SendPaymentRequest, Payment>("serverStreaming", this._transport, method, opt, input);
|
return stackIntercept<SendPaymentRequest, Payment>("serverStreaming", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `trackpayment`
|
||||||
* TrackPaymentV2 returns an update stream for the payment identified by the
|
* TrackPaymentV2 returns an update stream for the payment identified by the
|
||||||
* payment hash.
|
* payment hash.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: TrackPaymentV2(routerrpc.TrackPaymentRequest) returns (stream lnrpc.Payment);
|
* @generated from protobuf rpc: TrackPaymentV2
|
||||||
*/
|
*/
|
||||||
trackPaymentV2(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, Payment> {
|
trackPaymentV2(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, Payment> {
|
||||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -256,7 +328,7 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* payment attempt make sure to subscribe to this method before initiating any
|
* payment attempt make sure to subscribe to this method before initiating any
|
||||||
* payments.
|
* payments.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: TrackPayments(routerrpc.TrackPaymentsRequest) returns (stream lnrpc.Payment);
|
* @generated from protobuf rpc: TrackPayments
|
||||||
*/
|
*/
|
||||||
trackPayments(input: TrackPaymentsRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentsRequest, Payment> {
|
trackPayments(input: TrackPaymentsRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentsRequest, Payment> {
|
||||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -267,7 +339,7 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it
|
* EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it
|
||||||
* may cost to send an HTLC to the target end destination.
|
* may cost to send an HTLC to the target end destination.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: EstimateRouteFee(routerrpc.RouteFeeRequest) returns (routerrpc.RouteFeeResponse);
|
* @generated from protobuf rpc: EstimateRouteFee
|
||||||
*/
|
*/
|
||||||
estimateRouteFee(input: RouteFeeRequest, options?: RpcOptions): UnaryCall<RouteFeeRequest, RouteFeeResponse> {
|
estimateRouteFee(input: RouteFeeRequest, options?: RpcOptions): UnaryCall<RouteFeeRequest, RouteFeeResponse> {
|
||||||
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -282,7 +354,7 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* SendToRouteV2 in that it doesn't return the full HTLC information.
|
* SendToRouteV2 in that it doesn't return the full HTLC information.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @generated from protobuf rpc: SendToRoute(routerrpc.SendToRouteRequest) returns (routerrpc.SendToRouteResponse);
|
* @generated from protobuf rpc: SendToRoute
|
||||||
*/
|
*/
|
||||||
sendToRoute(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, SendToRouteResponse> {
|
sendToRoute(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, SendToRouteResponse> {
|
||||||
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -295,86 +367,92 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* route manually. This can be used for things like rebalancing, and atomic
|
* route manually. This can be used for things like rebalancing, and atomic
|
||||||
* swaps.
|
* swaps.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SendToRouteV2(routerrpc.SendToRouteRequest) returns (lnrpc.HTLCAttempt);
|
* @generated from protobuf rpc: SendToRouteV2
|
||||||
*/
|
*/
|
||||||
sendToRouteV2(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, HTLCAttempt> {
|
sendToRouteV2(input: SendToRouteRequest, options?: RpcOptions): UnaryCall<SendToRouteRequest, HTLCAttempt> {
|
||||||
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<SendToRouteRequest, HTLCAttempt>("unary", this._transport, method, opt, input);
|
return stackIntercept<SendToRouteRequest, HTLCAttempt>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `resetmc`
|
||||||
* ResetMissionControl clears all mission control state and starts with a clean
|
* ResetMissionControl clears all mission control state and starts with a clean
|
||||||
* slate.
|
* slate.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ResetMissionControl(routerrpc.ResetMissionControlRequest) returns (routerrpc.ResetMissionControlResponse);
|
* @generated from protobuf rpc: ResetMissionControl
|
||||||
*/
|
*/
|
||||||
resetMissionControl(input: ResetMissionControlRequest, options?: RpcOptions): UnaryCall<ResetMissionControlRequest, ResetMissionControlResponse> {
|
resetMissionControl(input: ResetMissionControlRequest, options?: RpcOptions): UnaryCall<ResetMissionControlRequest, ResetMissionControlResponse> {
|
||||||
const method = this.methods[6], opt = this._transport.mergeOptions(options);
|
const method = this.methods[6], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<ResetMissionControlRequest, ResetMissionControlResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<ResetMissionControlRequest, ResetMissionControlResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `querymc`
|
||||||
* QueryMissionControl exposes the internal mission control state to callers.
|
* QueryMissionControl exposes the internal mission control state to callers.
|
||||||
* It is a development feature.
|
* It is a development feature.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: QueryMissionControl(routerrpc.QueryMissionControlRequest) returns (routerrpc.QueryMissionControlResponse);
|
* @generated from protobuf rpc: QueryMissionControl
|
||||||
*/
|
*/
|
||||||
queryMissionControl(input: QueryMissionControlRequest, options?: RpcOptions): UnaryCall<QueryMissionControlRequest, QueryMissionControlResponse> {
|
queryMissionControl(input: QueryMissionControlRequest, options?: RpcOptions): UnaryCall<QueryMissionControlRequest, QueryMissionControlResponse> {
|
||||||
const method = this.methods[7], opt = this._transport.mergeOptions(options);
|
const method = this.methods[7], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<QueryMissionControlRequest, QueryMissionControlResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<QueryMissionControlRequest, QueryMissionControlResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `importmc`
|
||||||
* XImportMissionControl is an experimental API that imports the state provided
|
* XImportMissionControl is an experimental API that imports the state provided
|
||||||
* to the internal mission control's state, using all results which are more
|
* to the internal mission control's state, using all results which are more
|
||||||
* recent than our existing values. These values will only be imported
|
* recent than our existing values. These values will only be imported
|
||||||
* in-memory, and will not be persisted across restarts.
|
* in-memory, and will not be persisted across restarts.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: XImportMissionControl(routerrpc.XImportMissionControlRequest) returns (routerrpc.XImportMissionControlResponse);
|
* @generated from protobuf rpc: XImportMissionControl
|
||||||
*/
|
*/
|
||||||
xImportMissionControl(input: XImportMissionControlRequest, options?: RpcOptions): UnaryCall<XImportMissionControlRequest, XImportMissionControlResponse> {
|
xImportMissionControl(input: XImportMissionControlRequest, options?: RpcOptions): UnaryCall<XImportMissionControlRequest, XImportMissionControlResponse> {
|
||||||
const method = this.methods[8], opt = this._transport.mergeOptions(options);
|
const method = this.methods[8], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<XImportMissionControlRequest, XImportMissionControlResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<XImportMissionControlRequest, XImportMissionControlResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `getmccfg`
|
||||||
* GetMissionControlConfig returns mission control's current config.
|
* GetMissionControlConfig returns mission control's current config.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: GetMissionControlConfig(routerrpc.GetMissionControlConfigRequest) returns (routerrpc.GetMissionControlConfigResponse);
|
* @generated from protobuf rpc: GetMissionControlConfig
|
||||||
*/
|
*/
|
||||||
getMissionControlConfig(input: GetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<GetMissionControlConfigRequest, GetMissionControlConfigResponse> {
|
getMissionControlConfig(input: GetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<GetMissionControlConfigRequest, GetMissionControlConfigResponse> {
|
||||||
const method = this.methods[9], opt = this._transport.mergeOptions(options);
|
const method = this.methods[9], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<GetMissionControlConfigRequest, GetMissionControlConfigResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<GetMissionControlConfigRequest, GetMissionControlConfigResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `setmccfg`
|
||||||
* SetMissionControlConfig will set mission control's config, if the config
|
* SetMissionControlConfig will set mission control's config, if the config
|
||||||
* provided is valid.
|
* provided is valid.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SetMissionControlConfig(routerrpc.SetMissionControlConfigRequest) returns (routerrpc.SetMissionControlConfigResponse);
|
* @generated from protobuf rpc: SetMissionControlConfig
|
||||||
*/
|
*/
|
||||||
setMissionControlConfig(input: SetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<SetMissionControlConfigRequest, SetMissionControlConfigResponse> {
|
setMissionControlConfig(input: SetMissionControlConfigRequest, options?: RpcOptions): UnaryCall<SetMissionControlConfigRequest, SetMissionControlConfigResponse> {
|
||||||
const method = this.methods[10], opt = this._transport.mergeOptions(options);
|
const method = this.methods[10], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<SetMissionControlConfigRequest, SetMissionControlConfigResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<SetMissionControlConfigRequest, SetMissionControlConfigResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* lncli: `queryprob`
|
||||||
|
* Deprecated. QueryProbability returns the current success probability
|
||||||
|
* estimate for a given node pair and amount. The call returns a zero success
|
||||||
|
* probability if no channel is available or if the amount violates min/max
|
||||||
|
* HTLC constraints.
|
||||||
*
|
*
|
||||||
* QueryProbability returns the current success probability estimate for a
|
* @generated from protobuf rpc: QueryProbability
|
||||||
* given node pair and amount.
|
|
||||||
*
|
|
||||||
* @generated from protobuf rpc: QueryProbability(routerrpc.QueryProbabilityRequest) returns (routerrpc.QueryProbabilityResponse);
|
|
||||||
*/
|
*/
|
||||||
queryProbability(input: QueryProbabilityRequest, options?: RpcOptions): UnaryCall<QueryProbabilityRequest, QueryProbabilityResponse> {
|
queryProbability(input: QueryProbabilityRequest, options?: RpcOptions): UnaryCall<QueryProbabilityRequest, QueryProbabilityResponse> {
|
||||||
const method = this.methods[11], opt = this._transport.mergeOptions(options);
|
const method = this.methods[11], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<QueryProbabilityRequest, QueryProbabilityResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<QueryProbabilityRequest, QueryProbabilityResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `buildroute`
|
||||||
* BuildRoute builds a fully specified route based on a list of hop public
|
* BuildRoute builds a fully specified route based on a list of hop public
|
||||||
* keys. It retrieves the relevant channel policies from the graph in order to
|
* keys. It retrieves the relevant channel policies from the graph in order to
|
||||||
* calculate the correct fees and time locks.
|
* calculate the correct fees and time locks.
|
||||||
|
* Note that LND will use its default final_cltv_delta if no value is supplied.
|
||||||
|
* Make sure to add the correct final_cltv_delta depending on the invoice
|
||||||
|
* restriction. Moreover the caller has to make sure to provide the
|
||||||
|
* payment_addr if the route is paying an invoice which signaled it.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: BuildRoute(routerrpc.BuildRouteRequest) returns (routerrpc.BuildRouteResponse);
|
* @generated from protobuf rpc: BuildRoute
|
||||||
*/
|
*/
|
||||||
buildRoute(input: BuildRouteRequest, options?: RpcOptions): UnaryCall<BuildRouteRequest, BuildRouteResponse> {
|
buildRoute(input: BuildRouteRequest, options?: RpcOptions): UnaryCall<BuildRouteRequest, BuildRouteResponse> {
|
||||||
const method = this.methods[12], opt = this._transport.mergeOptions(options);
|
const method = this.methods[12], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -385,7 +463,7 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* SubscribeHtlcEvents creates a uni-directional stream from the server to
|
* SubscribeHtlcEvents creates a uni-directional stream from the server to
|
||||||
* the client which delivers a stream of htlc events.
|
* the client which delivers a stream of htlc events.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SubscribeHtlcEvents(routerrpc.SubscribeHtlcEventsRequest) returns (stream routerrpc.HtlcEvent);
|
* @generated from protobuf rpc: SubscribeHtlcEvents
|
||||||
*/
|
*/
|
||||||
subscribeHtlcEvents(input: SubscribeHtlcEventsRequest, options?: RpcOptions): ServerStreamingCall<SubscribeHtlcEventsRequest, HtlcEvent> {
|
subscribeHtlcEvents(input: SubscribeHtlcEventsRequest, options?: RpcOptions): ServerStreamingCall<SubscribeHtlcEventsRequest, HtlcEvent> {
|
||||||
const method = this.methods[13], opt = this._transport.mergeOptions(options);
|
const method = this.methods[13], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -398,7 +476,7 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* returns a stream of payment status updates.
|
* returns a stream of payment status updates.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @generated from protobuf rpc: SendPayment(routerrpc.SendPaymentRequest) returns (stream routerrpc.PaymentStatus);
|
* @generated from protobuf rpc: SendPayment
|
||||||
*/
|
*/
|
||||||
sendPayment(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, PaymentStatus> {
|
sendPayment(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall<SendPaymentRequest, PaymentStatus> {
|
||||||
const method = this.methods[14], opt = this._transport.mergeOptions(options);
|
const method = this.methods[14], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -410,7 +488,7 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* the payment identified by the payment hash.
|
* the payment identified by the payment hash.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @generated from protobuf rpc: TrackPayment(routerrpc.TrackPaymentRequest) returns (stream routerrpc.PaymentStatus);
|
* @generated from protobuf rpc: TrackPayment
|
||||||
*/
|
*/
|
||||||
trackPayment(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, PaymentStatus> {
|
trackPayment(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall<TrackPaymentRequest, PaymentStatus> {
|
||||||
const method = this.methods[15], opt = this._transport.mergeOptions(options);
|
const method = this.methods[15], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -424,23 +502,51 @@ export class RouterClient implements IRouterClient, ServiceInfo {
|
||||||
* In case of interception, the htlc can be either settled, cancelled or
|
* In case of interception, the htlc can be either settled, cancelled or
|
||||||
* resumed later by using the ResolveHoldForward endpoint.
|
* resumed later by using the ResolveHoldForward endpoint.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: HtlcInterceptor(stream routerrpc.ForwardHtlcInterceptResponse) returns (stream routerrpc.ForwardHtlcInterceptRequest);
|
* @generated from protobuf rpc: HtlcInterceptor
|
||||||
*/
|
*/
|
||||||
htlcInterceptor(options?: RpcOptions): DuplexStreamingCall<ForwardHtlcInterceptResponse, ForwardHtlcInterceptRequest> {
|
htlcInterceptor(options?: RpcOptions): DuplexStreamingCall<ForwardHtlcInterceptResponse, ForwardHtlcInterceptRequest> {
|
||||||
const method = this.methods[16], opt = this._transport.mergeOptions(options);
|
const method = this.methods[16], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<ForwardHtlcInterceptResponse, ForwardHtlcInterceptRequest>("duplex", this._transport, method, opt);
|
return stackIntercept<ForwardHtlcInterceptResponse, ForwardHtlcInterceptRequest>("duplex", this._transport, method, opt);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
* lncli: `updatechanstatus`
|
||||||
* UpdateChanStatus attempts to manually set the state of a channel
|
* UpdateChanStatus attempts to manually set the state of a channel
|
||||||
* (enabled, disabled, or auto). A manual "disable" request will cause the
|
* (enabled, disabled, or auto). A manual "disable" request will cause the
|
||||||
* channel to stay disabled until a subsequent manual request of either
|
* channel to stay disabled until a subsequent manual request of either
|
||||||
* "enable" or "auto".
|
* "enable" or "auto".
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: UpdateChanStatus(routerrpc.UpdateChanStatusRequest) returns (routerrpc.UpdateChanStatusResponse);
|
* @generated from protobuf rpc: UpdateChanStatus
|
||||||
*/
|
*/
|
||||||
updateChanStatus(input: UpdateChanStatusRequest, options?: RpcOptions): UnaryCall<UpdateChanStatusRequest, UpdateChanStatusResponse> {
|
updateChanStatus(input: UpdateChanStatusRequest, options?: RpcOptions): UnaryCall<UpdateChanStatusRequest, UpdateChanStatusResponse> {
|
||||||
const method = this.methods[17], opt = this._transport.mergeOptions(options);
|
const method = this.methods[17], opt = this._transport.mergeOptions(options);
|
||||||
return stackIntercept<UpdateChanStatusRequest, UpdateChanStatusResponse>("unary", this._transport, method, opt, input);
|
return stackIntercept<UpdateChanStatusRequest, UpdateChanStatusResponse>("unary", this._transport, method, opt, input);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* XAddLocalChanAliases is an experimental API that creates a set of new
|
||||||
|
* channel SCID alias mappings. The final total set of aliases in the manager
|
||||||
|
* after the add operation is returned. This is only a locally stored alias,
|
||||||
|
* and will not be communicated to the channel peer via any message. Therefore,
|
||||||
|
* routing over such an alias will only work if the peer also calls this same
|
||||||
|
* RPC on their end. If an alias already exists, an error is returned
|
||||||
|
*
|
||||||
|
* @generated from protobuf rpc: XAddLocalChanAliases
|
||||||
|
*/
|
||||||
|
xAddLocalChanAliases(input: AddAliasesRequest, options?: RpcOptions): UnaryCall<AddAliasesRequest, AddAliasesResponse> {
|
||||||
|
const method = this.methods[18], opt = this._transport.mergeOptions(options);
|
||||||
|
return stackIntercept<AddAliasesRequest, AddAliasesResponse>("unary", this._transport, method, opt, input);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* XDeleteLocalChanAliases is an experimental API that deletes a set of alias
|
||||||
|
* mappings. The final total set of aliases in the manager after the delete
|
||||||
|
* operation is returned. The deletion will not be communicated to the channel
|
||||||
|
* peer via any message.
|
||||||
|
*
|
||||||
|
* @generated from protobuf rpc: XDeleteLocalChanAliases
|
||||||
|
*/
|
||||||
|
xDeleteLocalChanAliases(input: DeleteAliasesRequest, options?: RpcOptions): UnaryCall<DeleteAliasesRequest, DeleteAliasesResponse> {
|
||||||
|
const method = this.methods[19], opt = this._transport.mergeOptions(options);
|
||||||
|
return stackIntercept<DeleteAliasesRequest, DeleteAliasesResponse>("unary", this._transport, method, opt, input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1690
proto/lnd/router.ts
1690
proto/lnd/router.ts
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "signer.proto" (package "signrpc", syntax proto3)
|
// @generated from protobuf file "signer.proto" (package "signrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||||
|
|
@ -46,7 +46,7 @@ export interface ISignerClient {
|
||||||
* If we are unable to sign using the specified keys, then an error will be
|
* If we are unable to sign using the specified keys, then an error will be
|
||||||
* returned.
|
* returned.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignOutputRaw(signrpc.SignReq) returns (signrpc.SignResp);
|
* @generated from protobuf rpc: SignOutputRaw
|
||||||
*/
|
*/
|
||||||
signOutputRaw(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, SignResp>;
|
signOutputRaw(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, SignResp>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -62,7 +62,7 @@ export interface ISignerClient {
|
||||||
* in the TxOut field, the value in that same field, and finally the input
|
* in the TxOut field, the value in that same field, and finally the input
|
||||||
* index.
|
* index.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ComputeInputScript(signrpc.SignReq) returns (signrpc.InputScriptResp);
|
* @generated from protobuf rpc: ComputeInputScript
|
||||||
*/
|
*/
|
||||||
computeInputScript(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, InputScriptResp>;
|
computeInputScript(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, InputScriptResp>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,7 +73,7 @@ export interface ISignerClient {
|
||||||
* The main difference to SignMessage in the main RPC is that a specific key is
|
* The main difference to SignMessage in the main RPC is that a specific key is
|
||||||
* used to sign the message instead of the node identity private key.
|
* used to sign the message instead of the node identity private key.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignMessage(signrpc.SignMessageReq) returns (signrpc.SignMessageResp);
|
* @generated from protobuf rpc: SignMessage
|
||||||
*/
|
*/
|
||||||
signMessage(input: SignMessageReq, options?: RpcOptions): UnaryCall<SignMessageReq, SignMessageResp>;
|
signMessage(input: SignMessageReq, options?: RpcOptions): UnaryCall<SignMessageReq, SignMessageResp>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -84,7 +84,7 @@ export interface ISignerClient {
|
||||||
* The main difference to VerifyMessage in the main RPC is that the public key
|
* The main difference to VerifyMessage in the main RPC is that the public key
|
||||||
* used to sign the message does not have to be a node known to the network.
|
* used to sign the message does not have to be a node known to the network.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: VerifyMessage(signrpc.VerifyMessageReq) returns (signrpc.VerifyMessageResp);
|
* @generated from protobuf rpc: VerifyMessage
|
||||||
*/
|
*/
|
||||||
verifyMessage(input: VerifyMessageReq, options?: RpcOptions): UnaryCall<VerifyMessageReq, VerifyMessageResp>;
|
verifyMessage(input: VerifyMessageReq, options?: RpcOptions): UnaryCall<VerifyMessageReq, VerifyMessageResp>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -98,7 +98,7 @@ export interface ISignerClient {
|
||||||
* The resulting shared public key is serialized in the compressed format and
|
* The resulting shared public key is serialized in the compressed format and
|
||||||
* hashed with sha256, resulting in the final key length of 256bit.
|
* hashed with sha256, resulting in the final key length of 256bit.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: DeriveSharedKey(signrpc.SharedKeyRequest) returns (signrpc.SharedKeyResponse);
|
* @generated from protobuf rpc: DeriveSharedKey
|
||||||
*/
|
*/
|
||||||
deriveSharedKey(input: SharedKeyRequest, options?: RpcOptions): UnaryCall<SharedKeyRequest, SharedKeyResponse>;
|
deriveSharedKey(input: SharedKeyRequest, options?: RpcOptions): UnaryCall<SharedKeyRequest, SharedKeyResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -115,7 +115,7 @@ export interface ISignerClient {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2CombineKeys(signrpc.MuSig2CombineKeysRequest) returns (signrpc.MuSig2CombineKeysResponse);
|
* @generated from protobuf rpc: MuSig2CombineKeys
|
||||||
*/
|
*/
|
||||||
muSig2CombineKeys(input: MuSig2CombineKeysRequest, options?: RpcOptions): UnaryCall<MuSig2CombineKeysRequest, MuSig2CombineKeysResponse>;
|
muSig2CombineKeys(input: MuSig2CombineKeysRequest, options?: RpcOptions): UnaryCall<MuSig2CombineKeysRequest, MuSig2CombineKeysResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -131,7 +131,7 @@ export interface ISignerClient {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2CreateSession(signrpc.MuSig2SessionRequest) returns (signrpc.MuSig2SessionResponse);
|
* @generated from protobuf rpc: MuSig2CreateSession
|
||||||
*/
|
*/
|
||||||
muSig2CreateSession(input: MuSig2SessionRequest, options?: RpcOptions): UnaryCall<MuSig2SessionRequest, MuSig2SessionResponse>;
|
muSig2CreateSession(input: MuSig2SessionRequest, options?: RpcOptions): UnaryCall<MuSig2SessionRequest, MuSig2SessionResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -144,7 +144,7 @@ export interface ISignerClient {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2RegisterNonces(signrpc.MuSig2RegisterNoncesRequest) returns (signrpc.MuSig2RegisterNoncesResponse);
|
* @generated from protobuf rpc: MuSig2RegisterNonces
|
||||||
*/
|
*/
|
||||||
muSig2RegisterNonces(input: MuSig2RegisterNoncesRequest, options?: RpcOptions): UnaryCall<MuSig2RegisterNoncesRequest, MuSig2RegisterNoncesResponse>;
|
muSig2RegisterNonces(input: MuSig2RegisterNoncesRequest, options?: RpcOptions): UnaryCall<MuSig2RegisterNoncesRequest, MuSig2RegisterNoncesResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -160,7 +160,7 @@ export interface ISignerClient {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2Sign(signrpc.MuSig2SignRequest) returns (signrpc.MuSig2SignResponse);
|
* @generated from protobuf rpc: MuSig2Sign
|
||||||
*/
|
*/
|
||||||
muSig2Sign(input: MuSig2SignRequest, options?: RpcOptions): UnaryCall<MuSig2SignRequest, MuSig2SignResponse>;
|
muSig2Sign(input: MuSig2SignRequest, options?: RpcOptions): UnaryCall<MuSig2SignRequest, MuSig2SignResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -174,7 +174,7 @@ export interface ISignerClient {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2CombineSig(signrpc.MuSig2CombineSigRequest) returns (signrpc.MuSig2CombineSigResponse);
|
* @generated from protobuf rpc: MuSig2CombineSig
|
||||||
*/
|
*/
|
||||||
muSig2CombineSig(input: MuSig2CombineSigRequest, options?: RpcOptions): UnaryCall<MuSig2CombineSigRequest, MuSig2CombineSigResponse>;
|
muSig2CombineSig(input: MuSig2CombineSigRequest, options?: RpcOptions): UnaryCall<MuSig2CombineSigRequest, MuSig2CombineSigResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -187,7 +187,7 @@ export interface ISignerClient {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2Cleanup(signrpc.MuSig2CleanupRequest) returns (signrpc.MuSig2CleanupResponse);
|
* @generated from protobuf rpc: MuSig2Cleanup
|
||||||
*/
|
*/
|
||||||
muSig2Cleanup(input: MuSig2CleanupRequest, options?: RpcOptions): UnaryCall<MuSig2CleanupRequest, MuSig2CleanupResponse>;
|
muSig2Cleanup(input: MuSig2CleanupRequest, options?: RpcOptions): UnaryCall<MuSig2CleanupRequest, MuSig2CleanupResponse>;
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +214,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* If we are unable to sign using the specified keys, then an error will be
|
* If we are unable to sign using the specified keys, then an error will be
|
||||||
* returned.
|
* returned.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignOutputRaw(signrpc.SignReq) returns (signrpc.SignResp);
|
* @generated from protobuf rpc: SignOutputRaw
|
||||||
*/
|
*/
|
||||||
signOutputRaw(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, SignResp> {
|
signOutputRaw(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, SignResp> {
|
||||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -233,7 +233,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* in the TxOut field, the value in that same field, and finally the input
|
* in the TxOut field, the value in that same field, and finally the input
|
||||||
* index.
|
* index.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ComputeInputScript(signrpc.SignReq) returns (signrpc.InputScriptResp);
|
* @generated from protobuf rpc: ComputeInputScript
|
||||||
*/
|
*/
|
||||||
computeInputScript(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, InputScriptResp> {
|
computeInputScript(input: SignReq, options?: RpcOptions): UnaryCall<SignReq, InputScriptResp> {
|
||||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -247,7 +247,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* The main difference to SignMessage in the main RPC is that a specific key is
|
* The main difference to SignMessage in the main RPC is that a specific key is
|
||||||
* used to sign the message instead of the node identity private key.
|
* used to sign the message instead of the node identity private key.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignMessage(signrpc.SignMessageReq) returns (signrpc.SignMessageResp);
|
* @generated from protobuf rpc: SignMessage
|
||||||
*/
|
*/
|
||||||
signMessage(input: SignMessageReq, options?: RpcOptions): UnaryCall<SignMessageReq, SignMessageResp> {
|
signMessage(input: SignMessageReq, options?: RpcOptions): UnaryCall<SignMessageReq, SignMessageResp> {
|
||||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -261,7 +261,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* The main difference to VerifyMessage in the main RPC is that the public key
|
* The main difference to VerifyMessage in the main RPC is that the public key
|
||||||
* used to sign the message does not have to be a node known to the network.
|
* used to sign the message does not have to be a node known to the network.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: VerifyMessage(signrpc.VerifyMessageReq) returns (signrpc.VerifyMessageResp);
|
* @generated from protobuf rpc: VerifyMessage
|
||||||
*/
|
*/
|
||||||
verifyMessage(input: VerifyMessageReq, options?: RpcOptions): UnaryCall<VerifyMessageReq, VerifyMessageResp> {
|
verifyMessage(input: VerifyMessageReq, options?: RpcOptions): UnaryCall<VerifyMessageReq, VerifyMessageResp> {
|
||||||
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -278,7 +278,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* The resulting shared public key is serialized in the compressed format and
|
* The resulting shared public key is serialized in the compressed format and
|
||||||
* hashed with sha256, resulting in the final key length of 256bit.
|
* hashed with sha256, resulting in the final key length of 256bit.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: DeriveSharedKey(signrpc.SharedKeyRequest) returns (signrpc.SharedKeyResponse);
|
* @generated from protobuf rpc: DeriveSharedKey
|
||||||
*/
|
*/
|
||||||
deriveSharedKey(input: SharedKeyRequest, options?: RpcOptions): UnaryCall<SharedKeyRequest, SharedKeyResponse> {
|
deriveSharedKey(input: SharedKeyRequest, options?: RpcOptions): UnaryCall<SharedKeyRequest, SharedKeyResponse> {
|
||||||
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -298,7 +298,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2CombineKeys(signrpc.MuSig2CombineKeysRequest) returns (signrpc.MuSig2CombineKeysResponse);
|
* @generated from protobuf rpc: MuSig2CombineKeys
|
||||||
*/
|
*/
|
||||||
muSig2CombineKeys(input: MuSig2CombineKeysRequest, options?: RpcOptions): UnaryCall<MuSig2CombineKeysRequest, MuSig2CombineKeysResponse> {
|
muSig2CombineKeys(input: MuSig2CombineKeysRequest, options?: RpcOptions): UnaryCall<MuSig2CombineKeysRequest, MuSig2CombineKeysResponse> {
|
||||||
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -317,7 +317,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2CreateSession(signrpc.MuSig2SessionRequest) returns (signrpc.MuSig2SessionResponse);
|
* @generated from protobuf rpc: MuSig2CreateSession
|
||||||
*/
|
*/
|
||||||
muSig2CreateSession(input: MuSig2SessionRequest, options?: RpcOptions): UnaryCall<MuSig2SessionRequest, MuSig2SessionResponse> {
|
muSig2CreateSession(input: MuSig2SessionRequest, options?: RpcOptions): UnaryCall<MuSig2SessionRequest, MuSig2SessionResponse> {
|
||||||
const method = this.methods[6], opt = this._transport.mergeOptions(options);
|
const method = this.methods[6], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -333,7 +333,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2RegisterNonces(signrpc.MuSig2RegisterNoncesRequest) returns (signrpc.MuSig2RegisterNoncesResponse);
|
* @generated from protobuf rpc: MuSig2RegisterNonces
|
||||||
*/
|
*/
|
||||||
muSig2RegisterNonces(input: MuSig2RegisterNoncesRequest, options?: RpcOptions): UnaryCall<MuSig2RegisterNoncesRequest, MuSig2RegisterNoncesResponse> {
|
muSig2RegisterNonces(input: MuSig2RegisterNoncesRequest, options?: RpcOptions): UnaryCall<MuSig2RegisterNoncesRequest, MuSig2RegisterNoncesResponse> {
|
||||||
const method = this.methods[7], opt = this._transport.mergeOptions(options);
|
const method = this.methods[7], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -352,7 +352,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2Sign(signrpc.MuSig2SignRequest) returns (signrpc.MuSig2SignResponse);
|
* @generated from protobuf rpc: MuSig2Sign
|
||||||
*/
|
*/
|
||||||
muSig2Sign(input: MuSig2SignRequest, options?: RpcOptions): UnaryCall<MuSig2SignRequest, MuSig2SignResponse> {
|
muSig2Sign(input: MuSig2SignRequest, options?: RpcOptions): UnaryCall<MuSig2SignRequest, MuSig2SignResponse> {
|
||||||
const method = this.methods[8], opt = this._transport.mergeOptions(options);
|
const method = this.methods[8], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -369,7 +369,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2CombineSig(signrpc.MuSig2CombineSigRequest) returns (signrpc.MuSig2CombineSigResponse);
|
* @generated from protobuf rpc: MuSig2CombineSig
|
||||||
*/
|
*/
|
||||||
muSig2CombineSig(input: MuSig2CombineSigRequest, options?: RpcOptions): UnaryCall<MuSig2CombineSigRequest, MuSig2CombineSigResponse> {
|
muSig2CombineSig(input: MuSig2CombineSigRequest, options?: RpcOptions): UnaryCall<MuSig2CombineSigRequest, MuSig2CombineSigResponse> {
|
||||||
const method = this.methods[9], opt = this._transport.mergeOptions(options);
|
const method = this.methods[9], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -385,7 +385,7 @@ export class SignerClient implements ISignerClient, ServiceInfo {
|
||||||
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
* considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||||
* releases. Backward compatibility is not guaranteed!
|
* releases. Backward compatibility is not guaranteed!
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: MuSig2Cleanup(signrpc.MuSig2CleanupRequest) returns (signrpc.MuSig2CleanupResponse);
|
* @generated from protobuf rpc: MuSig2Cleanup
|
||||||
*/
|
*/
|
||||||
muSig2Cleanup(input: MuSig2CleanupRequest, options?: RpcOptions): UnaryCall<MuSig2CleanupRequest, MuSig2CleanupResponse> {
|
muSig2Cleanup(input: MuSig2CleanupRequest, options?: RpcOptions): UnaryCall<MuSig2CleanupRequest, MuSig2CleanupResponse> {
|
||||||
const method = this.methods[10], opt = this._transport.mergeOptions(options);
|
const method = this.methods[10], opt = this._transport.mergeOptions(options);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "walletkit.proto" (package "walletrpc", syntax proto3)
|
// @generated from protobuf file "walletkit.proto" (package "walletrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||||
|
|
@ -43,7 +43,7 @@ import type { RequiredReserveResponse } from "./walletkit.js";
|
||||||
import type { RequiredReserveRequest } from "./walletkit.js";
|
import type { RequiredReserveRequest } from "./walletkit.js";
|
||||||
import type { ListAccountsResponse } from "./walletkit.js";
|
import type { ListAccountsResponse } from "./walletkit.js";
|
||||||
import type { ListAccountsRequest } from "./walletkit.js";
|
import type { ListAccountsRequest } from "./walletkit.js";
|
||||||
import type { Transaction } from "./lightning";
|
import type { Transaction } from "./lightning.js";
|
||||||
import type { GetTransactionRequest } from "./walletkit.js";
|
import type { GetTransactionRequest } from "./walletkit.js";
|
||||||
import type { AddrResponse } from "./walletkit.js";
|
import type { AddrResponse } from "./walletkit.js";
|
||||||
import type { AddrRequest } from "./walletkit.js";
|
import type { AddrRequest } from "./walletkit.js";
|
||||||
|
|
@ -92,7 +92,7 @@ export interface IWalletKitClient {
|
||||||
* default, all utxos are listed. To list only the unconfirmed utxos, set
|
* default, all utxos are listed. To list only the unconfirmed utxos, set
|
||||||
* the unconfirmed_only to true.
|
* the unconfirmed_only to true.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListUnspent(walletrpc.ListUnspentRequest) returns (walletrpc.ListUnspentResponse);
|
* @generated from protobuf rpc: ListUnspent
|
||||||
*/
|
*/
|
||||||
listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall<ListUnspentRequest, ListUnspentResponse>;
|
listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall<ListUnspentRequest, ListUnspentResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -103,7 +103,7 @@ export interface IWalletKitClient {
|
||||||
* successive invocations of this RPC. Outputs can be unlocked before their
|
* successive invocations of this RPC. Outputs can be unlocked before their
|
||||||
* expiration through `ReleaseOutput`.
|
* expiration through `ReleaseOutput`.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: LeaseOutput(walletrpc.LeaseOutputRequest) returns (walletrpc.LeaseOutputResponse);
|
* @generated from protobuf rpc: LeaseOutput
|
||||||
*/
|
*/
|
||||||
leaseOutput(input: LeaseOutputRequest, options?: RpcOptions): UnaryCall<LeaseOutputRequest, LeaseOutputResponse>;
|
leaseOutput(input: LeaseOutputRequest, options?: RpcOptions): UnaryCall<LeaseOutputRequest, LeaseOutputResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -112,14 +112,14 @@ export interface IWalletKitClient {
|
||||||
* selection if it remains unspent. The ID should match the one used to
|
* selection if it remains unspent. The ID should match the one used to
|
||||||
* originally lock the output.
|
* originally lock the output.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ReleaseOutput(walletrpc.ReleaseOutputRequest) returns (walletrpc.ReleaseOutputResponse);
|
* @generated from protobuf rpc: ReleaseOutput
|
||||||
*/
|
*/
|
||||||
releaseOutput(input: ReleaseOutputRequest, options?: RpcOptions): UnaryCall<ReleaseOutputRequest, ReleaseOutputResponse>;
|
releaseOutput(input: ReleaseOutputRequest, options?: RpcOptions): UnaryCall<ReleaseOutputRequest, ReleaseOutputResponse>;
|
||||||
/**
|
/**
|
||||||
* lncli: `wallet listleases`
|
* lncli: `wallet listleases`
|
||||||
* ListLeases lists all currently locked utxos.
|
* ListLeases lists all currently locked utxos.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListLeases(walletrpc.ListLeasesRequest) returns (walletrpc.ListLeasesResponse);
|
* @generated from protobuf rpc: ListLeases
|
||||||
*/
|
*/
|
||||||
listLeases(input: ListLeasesRequest, options?: RpcOptions): UnaryCall<ListLeasesRequest, ListLeasesResponse>;
|
listLeases(input: ListLeasesRequest, options?: RpcOptions): UnaryCall<ListLeasesRequest, ListLeasesResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -128,7 +128,7 @@ export interface IWalletKitClient {
|
||||||
* (account in BIP43) specified. This method should return the next external
|
* (account in BIP43) specified. This method should return the next external
|
||||||
* child within this branch.
|
* child within this branch.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: DeriveNextKey(walletrpc.KeyReq) returns (signrpc.KeyDescriptor);
|
* @generated from protobuf rpc: DeriveNextKey
|
||||||
*/
|
*/
|
||||||
deriveNextKey(input: KeyReq, options?: RpcOptions): UnaryCall<KeyReq, KeyDescriptor>;
|
deriveNextKey(input: KeyReq, options?: RpcOptions): UnaryCall<KeyReq, KeyDescriptor>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -136,21 +136,21 @@ export interface IWalletKitClient {
|
||||||
* DeriveKey attempts to derive an arbitrary key specified by the passed
|
* DeriveKey attempts to derive an arbitrary key specified by the passed
|
||||||
* KeyLocator.
|
* KeyLocator.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: DeriveKey(signrpc.KeyLocator) returns (signrpc.KeyDescriptor);
|
* @generated from protobuf rpc: DeriveKey
|
||||||
*/
|
*/
|
||||||
deriveKey(input: KeyLocator, options?: RpcOptions): UnaryCall<KeyLocator, KeyDescriptor>;
|
deriveKey(input: KeyLocator, options?: RpcOptions): UnaryCall<KeyLocator, KeyDescriptor>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* NextAddr returns the next unused address within the wallet.
|
* NextAddr returns the next unused address within the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: NextAddr(walletrpc.AddrRequest) returns (walletrpc.AddrResponse);
|
* @generated from protobuf rpc: NextAddr
|
||||||
*/
|
*/
|
||||||
nextAddr(input: AddrRequest, options?: RpcOptions): UnaryCall<AddrRequest, AddrResponse>;
|
nextAddr(input: AddrRequest, options?: RpcOptions): UnaryCall<AddrRequest, AddrResponse>;
|
||||||
/**
|
/**
|
||||||
* lncli: `wallet gettx`
|
* lncli: `wallet gettx`
|
||||||
* GetTransaction returns details for a transaction found in the wallet.
|
* GetTransaction returns details for a transaction found in the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: GetTransaction(walletrpc.GetTransactionRequest) returns (lnrpc.Transaction);
|
* @generated from protobuf rpc: GetTransaction
|
||||||
*/
|
*/
|
||||||
getTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, Transaction>;
|
getTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, Transaction>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -159,7 +159,7 @@ export interface IWalletKitClient {
|
||||||
* name and key scope filter can be provided to filter through all of the
|
* name and key scope filter can be provided to filter through all of the
|
||||||
* wallet accounts and return only those matching.
|
* wallet accounts and return only those matching.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListAccounts(walletrpc.ListAccountsRequest) returns (walletrpc.ListAccountsResponse);
|
* @generated from protobuf rpc: ListAccounts
|
||||||
*/
|
*/
|
||||||
listAccounts(input: ListAccountsRequest, options?: RpcOptions): UnaryCall<ListAccountsRequest, ListAccountsResponse>;
|
listAccounts(input: ListAccountsRequest, options?: RpcOptions): UnaryCall<ListAccountsRequest, ListAccountsResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -168,7 +168,7 @@ export interface IWalletKitClient {
|
||||||
* in the wallet in order to fee bump anchor channels if necessary. The value
|
* in the wallet in order to fee bump anchor channels if necessary. The value
|
||||||
* scales with the number of public anchor channels but is capped at a maximum.
|
* scales with the number of public anchor channels but is capped at a maximum.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RequiredReserve(walletrpc.RequiredReserveRequest) returns (walletrpc.RequiredReserveResponse);
|
* @generated from protobuf rpc: RequiredReserve
|
||||||
*/
|
*/
|
||||||
requiredReserve(input: RequiredReserveRequest, options?: RpcOptions): UnaryCall<RequiredReserveRequest, RequiredReserveResponse>;
|
requiredReserve(input: RequiredReserveRequest, options?: RpcOptions): UnaryCall<RequiredReserveRequest, RequiredReserveResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -177,7 +177,7 @@ export interface IWalletKitClient {
|
||||||
* account name filter can be provided to filter through all of the
|
* account name filter can be provided to filter through all of the
|
||||||
* wallet accounts and return the addresses of only those matching.
|
* wallet accounts and return the addresses of only those matching.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListAddresses(walletrpc.ListAddressesRequest) returns (walletrpc.ListAddressesResponse);
|
* @generated from protobuf rpc: ListAddresses
|
||||||
*/
|
*/
|
||||||
listAddresses(input: ListAddressesRequest, options?: RpcOptions): UnaryCall<ListAddressesRequest, ListAddressesResponse>;
|
listAddresses(input: ListAddressesRequest, options?: RpcOptions): UnaryCall<ListAddressesRequest, ListAddressesResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -195,7 +195,7 @@ export interface IWalletKitClient {
|
||||||
* For P2TR addresses this represents a special case. ECDSA is used to create
|
* For P2TR addresses this represents a special case. ECDSA is used to create
|
||||||
* a compact signature which makes the public key of the signature recoverable.
|
* a compact signature which makes the public key of the signature recoverable.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignMessageWithAddr(walletrpc.SignMessageWithAddrRequest) returns (walletrpc.SignMessageWithAddrResponse);
|
* @generated from protobuf rpc: SignMessageWithAddr
|
||||||
*/
|
*/
|
||||||
signMessageWithAddr(input: SignMessageWithAddrRequest, options?: RpcOptions): UnaryCall<SignMessageWithAddrRequest, SignMessageWithAddrResponse>;
|
signMessageWithAddr(input: SignMessageWithAddrRequest, options?: RpcOptions): UnaryCall<SignMessageWithAddrRequest, SignMessageWithAddrResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -220,7 +220,7 @@ export interface IWalletKitClient {
|
||||||
* taproot key. The compact ECDSA signature format was used because there
|
* taproot key. The compact ECDSA signature format was used because there
|
||||||
* are still no known compact signature schemes for schnorr signatures.
|
* are still no known compact signature schemes for schnorr signatures.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: VerifyMessageWithAddr(walletrpc.VerifyMessageWithAddrRequest) returns (walletrpc.VerifyMessageWithAddrResponse);
|
* @generated from protobuf rpc: VerifyMessageWithAddr
|
||||||
*/
|
*/
|
||||||
verifyMessageWithAddr(input: VerifyMessageWithAddrRequest, options?: RpcOptions): UnaryCall<VerifyMessageWithAddrRequest, VerifyMessageWithAddrResponse>;
|
verifyMessageWithAddr(input: VerifyMessageWithAddrRequest, options?: RpcOptions): UnaryCall<VerifyMessageWithAddrRequest, VerifyMessageWithAddrResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -249,7 +249,7 @@ export interface IWalletKitClient {
|
||||||
* detected by lnd if they happen after the import. Rescans to detect past
|
* detected by lnd if they happen after the import. Rescans to detect past
|
||||||
* events will be supported later on.
|
* events will be supported later on.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ImportAccount(walletrpc.ImportAccountRequest) returns (walletrpc.ImportAccountResponse);
|
* @generated from protobuf rpc: ImportAccount
|
||||||
*/
|
*/
|
||||||
importAccount(input: ImportAccountRequest, options?: RpcOptions): UnaryCall<ImportAccountRequest, ImportAccountResponse>;
|
importAccount(input: ImportAccountRequest, options?: RpcOptions): UnaryCall<ImportAccountRequest, ImportAccountResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -264,7 +264,7 @@ export interface IWalletKitClient {
|
||||||
* they happen after the import. Rescans to detect past events will be
|
* they happen after the import. Rescans to detect past events will be
|
||||||
* supported later on.
|
* supported later on.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ImportPublicKey(walletrpc.ImportPublicKeyRequest) returns (walletrpc.ImportPublicKeyResponse);
|
* @generated from protobuf rpc: ImportPublicKey
|
||||||
*/
|
*/
|
||||||
importPublicKey(input: ImportPublicKeyRequest, options?: RpcOptions): UnaryCall<ImportPublicKeyRequest, ImportPublicKeyResponse>;
|
importPublicKey(input: ImportPublicKeyRequest, options?: RpcOptions): UnaryCall<ImportPublicKeyRequest, ImportPublicKeyResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -281,7 +281,7 @@ export interface IWalletKitClient {
|
||||||
* NOTE: Taproot keys imported through this RPC currently _cannot_ be used for
|
* NOTE: Taproot keys imported through this RPC currently _cannot_ be used for
|
||||||
* funding PSBTs. Only tracking the balance and UTXOs is currently supported.
|
* funding PSBTs. Only tracking the balance and UTXOs is currently supported.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ImportTapscript(walletrpc.ImportTapscriptRequest) returns (walletrpc.ImportTapscriptResponse);
|
* @generated from protobuf rpc: ImportTapscript
|
||||||
*/
|
*/
|
||||||
importTapscript(input: ImportTapscriptRequest, options?: RpcOptions): UnaryCall<ImportTapscriptRequest, ImportTapscriptResponse>;
|
importTapscript(input: ImportTapscriptRequest, options?: RpcOptions): UnaryCall<ImportTapscriptRequest, ImportTapscriptResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -291,7 +291,7 @@ export interface IWalletKitClient {
|
||||||
* attempt to re-broadcast the transaction on start up, until it enters the
|
* attempt to re-broadcast the transaction on start up, until it enters the
|
||||||
* chain.
|
* chain.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: PublishTransaction(walletrpc.Transaction) returns (walletrpc.PublishResponse);
|
* @generated from protobuf rpc: PublishTransaction
|
||||||
*/
|
*/
|
||||||
publishTransaction(input: Transaction$, options?: RpcOptions): UnaryCall<Transaction$, PublishResponse>;
|
publishTransaction(input: Transaction$, options?: RpcOptions): UnaryCall<Transaction$, PublishResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -299,7 +299,7 @@ export interface IWalletKitClient {
|
||||||
* RemoveTransaction attempts to remove the provided transaction from the
|
* RemoveTransaction attempts to remove the provided transaction from the
|
||||||
* internal transaction store of the wallet.
|
* internal transaction store of the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RemoveTransaction(walletrpc.GetTransactionRequest) returns (walletrpc.RemoveTransactionResponse);
|
* @generated from protobuf rpc: RemoveTransaction
|
||||||
*/
|
*/
|
||||||
removeTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, RemoveTransactionResponse>;
|
removeTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, RemoveTransactionResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -308,7 +308,7 @@ export interface IWalletKitClient {
|
||||||
* allows the caller to create a transaction that sends to several outputs at
|
* allows the caller to create a transaction that sends to several outputs at
|
||||||
* once. This is ideal when wanting to batch create a set of transactions.
|
* once. This is ideal when wanting to batch create a set of transactions.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SendOutputs(walletrpc.SendOutputsRequest) returns (walletrpc.SendOutputsResponse);
|
* @generated from protobuf rpc: SendOutputs
|
||||||
*/
|
*/
|
||||||
sendOutputs(input: SendOutputsRequest, options?: RpcOptions): UnaryCall<SendOutputsRequest, SendOutputsResponse>;
|
sendOutputs(input: SendOutputsRequest, options?: RpcOptions): UnaryCall<SendOutputsRequest, SendOutputsResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -317,7 +317,7 @@ export interface IWalletKitClient {
|
||||||
* determine the fee (in sat/kw) to attach to a transaction in order to
|
* determine the fee (in sat/kw) to attach to a transaction in order to
|
||||||
* achieve the confirmation target.
|
* achieve the confirmation target.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: EstimateFee(walletrpc.EstimateFeeRequest) returns (walletrpc.EstimateFeeResponse);
|
* @generated from protobuf rpc: EstimateFee
|
||||||
*/
|
*/
|
||||||
estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall<EstimateFeeRequest, EstimateFeeResponse>;
|
estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall<EstimateFeeRequest, EstimateFeeResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -331,7 +331,7 @@ export interface IWalletKitClient {
|
||||||
* remain supported. This is an advanced API that depends on the internals of
|
* remain supported. This is an advanced API that depends on the internals of
|
||||||
* the UtxoSweeper, so things may change.
|
* the UtxoSweeper, so things may change.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: PendingSweeps(walletrpc.PendingSweepsRequest) returns (walletrpc.PendingSweepsResponse);
|
* @generated from protobuf rpc: PendingSweeps
|
||||||
*/
|
*/
|
||||||
pendingSweeps(input: PendingSweepsRequest, options?: RpcOptions): UnaryCall<PendingSweepsRequest, PendingSweepsResponse>;
|
pendingSweeps(input: PendingSweepsRequest, options?: RpcOptions): UnaryCall<PendingSweepsRequest, PendingSweepsResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -365,7 +365,7 @@ export interface IWalletKitClient {
|
||||||
* done by specifying an outpoint within the low fee transaction that is under
|
* done by specifying an outpoint within the low fee transaction that is under
|
||||||
* the control of the wallet.
|
* the control of the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: BumpFee(walletrpc.BumpFeeRequest) returns (walletrpc.BumpFeeResponse);
|
* @generated from protobuf rpc: BumpFee
|
||||||
*/
|
*/
|
||||||
bumpFee(input: BumpFeeRequest, options?: RpcOptions): UnaryCall<BumpFeeRequest, BumpFeeResponse>;
|
bumpFee(input: BumpFeeRequest, options?: RpcOptions): UnaryCall<BumpFeeRequest, BumpFeeResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -373,7 +373,7 @@ export interface IWalletKitClient {
|
||||||
* BumpForceCloseFee is an endpoint that allows users to bump the fee of a
|
* BumpForceCloseFee is an endpoint that allows users to bump the fee of a
|
||||||
* channel force close. This only works for channels with option_anchors.
|
* channel force close. This only works for channels with option_anchors.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: BumpForceCloseFee(walletrpc.BumpForceCloseFeeRequest) returns (walletrpc.BumpForceCloseFeeResponse);
|
* @generated from protobuf rpc: BumpForceCloseFee
|
||||||
*/
|
*/
|
||||||
bumpForceCloseFee(input: BumpForceCloseFeeRequest, options?: RpcOptions): UnaryCall<BumpForceCloseFeeRequest, BumpForceCloseFeeResponse>;
|
bumpForceCloseFee(input: BumpForceCloseFeeRequest, options?: RpcOptions): UnaryCall<BumpForceCloseFeeRequest, BumpForceCloseFeeResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -382,7 +382,7 @@ export interface IWalletKitClient {
|
||||||
* Note that these sweeps may not be confirmed yet, as we record sweeps on
|
* Note that these sweeps may not be confirmed yet, as we record sweeps on
|
||||||
* broadcast, not confirmation.
|
* broadcast, not confirmation.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListSweeps(walletrpc.ListSweepsRequest) returns (walletrpc.ListSweepsResponse);
|
* @generated from protobuf rpc: ListSweeps
|
||||||
*/
|
*/
|
||||||
listSweeps(input: ListSweepsRequest, options?: RpcOptions): UnaryCall<ListSweepsRequest, ListSweepsResponse>;
|
listSweeps(input: ListSweepsRequest, options?: RpcOptions): UnaryCall<ListSweepsRequest, ListSweepsResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -392,7 +392,7 @@ export interface IWalletKitClient {
|
||||||
* overwrite the existing transaction label. Labels must not be empty, and
|
* overwrite the existing transaction label. Labels must not be empty, and
|
||||||
* cannot exceed 500 characters.
|
* cannot exceed 500 characters.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: LabelTransaction(walletrpc.LabelTransactionRequest) returns (walletrpc.LabelTransactionResponse);
|
* @generated from protobuf rpc: LabelTransaction
|
||||||
*/
|
*/
|
||||||
labelTransaction(input: LabelTransactionRequest, options?: RpcOptions): UnaryCall<LabelTransactionRequest, LabelTransactionResponse>;
|
labelTransaction(input: LabelTransactionRequest, options?: RpcOptions): UnaryCall<LabelTransactionRequest, LabelTransactionResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -426,7 +426,7 @@ export interface IWalletKitClient {
|
||||||
* publishing the transaction) or to unlock/release the locked UTXOs in case of
|
* publishing the transaction) or to unlock/release the locked UTXOs in case of
|
||||||
* an error on the caller's side.
|
* an error on the caller's side.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: FundPsbt(walletrpc.FundPsbtRequest) returns (walletrpc.FundPsbtResponse);
|
* @generated from protobuf rpc: FundPsbt
|
||||||
*/
|
*/
|
||||||
fundPsbt(input: FundPsbtRequest, options?: RpcOptions): UnaryCall<FundPsbtRequest, FundPsbtResponse>;
|
fundPsbt(input: FundPsbtRequest, options?: RpcOptions): UnaryCall<FundPsbtRequest, FundPsbtResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -443,7 +443,7 @@ export interface IWalletKitClient {
|
||||||
* input/output/fee value validation, PSBT finalization). Any input that is
|
* input/output/fee value validation, PSBT finalization). Any input that is
|
||||||
* incomplete will be skipped.
|
* incomplete will be skipped.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignPsbt(walletrpc.SignPsbtRequest) returns (walletrpc.SignPsbtResponse);
|
* @generated from protobuf rpc: SignPsbt
|
||||||
*/
|
*/
|
||||||
signPsbt(input: SignPsbtRequest, options?: RpcOptions): UnaryCall<SignPsbtRequest, SignPsbtResponse>;
|
signPsbt(input: SignPsbtRequest, options?: RpcOptions): UnaryCall<SignPsbtRequest, SignPsbtResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -460,7 +460,7 @@ export interface IWalletKitClient {
|
||||||
* caller's responsibility to either publish the transaction on success or
|
* caller's responsibility to either publish the transaction on success or
|
||||||
* unlock/release any locked UTXOs in case of an error in this method.
|
* unlock/release any locked UTXOs in case of an error in this method.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: FinalizePsbt(walletrpc.FinalizePsbtRequest) returns (walletrpc.FinalizePsbtResponse);
|
* @generated from protobuf rpc: FinalizePsbt
|
||||||
*/
|
*/
|
||||||
finalizePsbt(input: FinalizePsbtRequest, options?: RpcOptions): UnaryCall<FinalizePsbtRequest, FinalizePsbtResponse>;
|
finalizePsbt(input: FinalizePsbtRequest, options?: RpcOptions): UnaryCall<FinalizePsbtRequest, FinalizePsbtResponse>;
|
||||||
}
|
}
|
||||||
|
|
@ -500,7 +500,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* default, all utxos are listed. To list only the unconfirmed utxos, set
|
* default, all utxos are listed. To list only the unconfirmed utxos, set
|
||||||
* the unconfirmed_only to true.
|
* the unconfirmed_only to true.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListUnspent(walletrpc.ListUnspentRequest) returns (walletrpc.ListUnspentResponse);
|
* @generated from protobuf rpc: ListUnspent
|
||||||
*/
|
*/
|
||||||
listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall<ListUnspentRequest, ListUnspentResponse> {
|
listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall<ListUnspentRequest, ListUnspentResponse> {
|
||||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -514,7 +514,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* successive invocations of this RPC. Outputs can be unlocked before their
|
* successive invocations of this RPC. Outputs can be unlocked before their
|
||||||
* expiration through `ReleaseOutput`.
|
* expiration through `ReleaseOutput`.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: LeaseOutput(walletrpc.LeaseOutputRequest) returns (walletrpc.LeaseOutputResponse);
|
* @generated from protobuf rpc: LeaseOutput
|
||||||
*/
|
*/
|
||||||
leaseOutput(input: LeaseOutputRequest, options?: RpcOptions): UnaryCall<LeaseOutputRequest, LeaseOutputResponse> {
|
leaseOutput(input: LeaseOutputRequest, options?: RpcOptions): UnaryCall<LeaseOutputRequest, LeaseOutputResponse> {
|
||||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -526,7 +526,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* selection if it remains unspent. The ID should match the one used to
|
* selection if it remains unspent. The ID should match the one used to
|
||||||
* originally lock the output.
|
* originally lock the output.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ReleaseOutput(walletrpc.ReleaseOutputRequest) returns (walletrpc.ReleaseOutputResponse);
|
* @generated from protobuf rpc: ReleaseOutput
|
||||||
*/
|
*/
|
||||||
releaseOutput(input: ReleaseOutputRequest, options?: RpcOptions): UnaryCall<ReleaseOutputRequest, ReleaseOutputResponse> {
|
releaseOutput(input: ReleaseOutputRequest, options?: RpcOptions): UnaryCall<ReleaseOutputRequest, ReleaseOutputResponse> {
|
||||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -536,7 +536,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* lncli: `wallet listleases`
|
* lncli: `wallet listleases`
|
||||||
* ListLeases lists all currently locked utxos.
|
* ListLeases lists all currently locked utxos.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListLeases(walletrpc.ListLeasesRequest) returns (walletrpc.ListLeasesResponse);
|
* @generated from protobuf rpc: ListLeases
|
||||||
*/
|
*/
|
||||||
listLeases(input: ListLeasesRequest, options?: RpcOptions): UnaryCall<ListLeasesRequest, ListLeasesResponse> {
|
listLeases(input: ListLeasesRequest, options?: RpcOptions): UnaryCall<ListLeasesRequest, ListLeasesResponse> {
|
||||||
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -548,7 +548,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* (account in BIP43) specified. This method should return the next external
|
* (account in BIP43) specified. This method should return the next external
|
||||||
* child within this branch.
|
* child within this branch.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: DeriveNextKey(walletrpc.KeyReq) returns (signrpc.KeyDescriptor);
|
* @generated from protobuf rpc: DeriveNextKey
|
||||||
*/
|
*/
|
||||||
deriveNextKey(input: KeyReq, options?: RpcOptions): UnaryCall<KeyReq, KeyDescriptor> {
|
deriveNextKey(input: KeyReq, options?: RpcOptions): UnaryCall<KeyReq, KeyDescriptor> {
|
||||||
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -559,7 +559,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* DeriveKey attempts to derive an arbitrary key specified by the passed
|
* DeriveKey attempts to derive an arbitrary key specified by the passed
|
||||||
* KeyLocator.
|
* KeyLocator.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: DeriveKey(signrpc.KeyLocator) returns (signrpc.KeyDescriptor);
|
* @generated from protobuf rpc: DeriveKey
|
||||||
*/
|
*/
|
||||||
deriveKey(input: KeyLocator, options?: RpcOptions): UnaryCall<KeyLocator, KeyDescriptor> {
|
deriveKey(input: KeyLocator, options?: RpcOptions): UnaryCall<KeyLocator, KeyDescriptor> {
|
||||||
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -569,7 +569,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
*
|
*
|
||||||
* NextAddr returns the next unused address within the wallet.
|
* NextAddr returns the next unused address within the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: NextAddr(walletrpc.AddrRequest) returns (walletrpc.AddrResponse);
|
* @generated from protobuf rpc: NextAddr
|
||||||
*/
|
*/
|
||||||
nextAddr(input: AddrRequest, options?: RpcOptions): UnaryCall<AddrRequest, AddrResponse> {
|
nextAddr(input: AddrRequest, options?: RpcOptions): UnaryCall<AddrRequest, AddrResponse> {
|
||||||
const method = this.methods[6], opt = this._transport.mergeOptions(options);
|
const method = this.methods[6], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -579,7 +579,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* lncli: `wallet gettx`
|
* lncli: `wallet gettx`
|
||||||
* GetTransaction returns details for a transaction found in the wallet.
|
* GetTransaction returns details for a transaction found in the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: GetTransaction(walletrpc.GetTransactionRequest) returns (lnrpc.Transaction);
|
* @generated from protobuf rpc: GetTransaction
|
||||||
*/
|
*/
|
||||||
getTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, Transaction> {
|
getTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, Transaction> {
|
||||||
const method = this.methods[7], opt = this._transport.mergeOptions(options);
|
const method = this.methods[7], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -591,7 +591,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* name and key scope filter can be provided to filter through all of the
|
* name and key scope filter can be provided to filter through all of the
|
||||||
* wallet accounts and return only those matching.
|
* wallet accounts and return only those matching.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListAccounts(walletrpc.ListAccountsRequest) returns (walletrpc.ListAccountsResponse);
|
* @generated from protobuf rpc: ListAccounts
|
||||||
*/
|
*/
|
||||||
listAccounts(input: ListAccountsRequest, options?: RpcOptions): UnaryCall<ListAccountsRequest, ListAccountsResponse> {
|
listAccounts(input: ListAccountsRequest, options?: RpcOptions): UnaryCall<ListAccountsRequest, ListAccountsResponse> {
|
||||||
const method = this.methods[8], opt = this._transport.mergeOptions(options);
|
const method = this.methods[8], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -603,7 +603,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* in the wallet in order to fee bump anchor channels if necessary. The value
|
* in the wallet in order to fee bump anchor channels if necessary. The value
|
||||||
* scales with the number of public anchor channels but is capped at a maximum.
|
* scales with the number of public anchor channels but is capped at a maximum.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RequiredReserve(walletrpc.RequiredReserveRequest) returns (walletrpc.RequiredReserveResponse);
|
* @generated from protobuf rpc: RequiredReserve
|
||||||
*/
|
*/
|
||||||
requiredReserve(input: RequiredReserveRequest, options?: RpcOptions): UnaryCall<RequiredReserveRequest, RequiredReserveResponse> {
|
requiredReserve(input: RequiredReserveRequest, options?: RpcOptions): UnaryCall<RequiredReserveRequest, RequiredReserveResponse> {
|
||||||
const method = this.methods[9], opt = this._transport.mergeOptions(options);
|
const method = this.methods[9], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -615,7 +615,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* account name filter can be provided to filter through all of the
|
* account name filter can be provided to filter through all of the
|
||||||
* wallet accounts and return the addresses of only those matching.
|
* wallet accounts and return the addresses of only those matching.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListAddresses(walletrpc.ListAddressesRequest) returns (walletrpc.ListAddressesResponse);
|
* @generated from protobuf rpc: ListAddresses
|
||||||
*/
|
*/
|
||||||
listAddresses(input: ListAddressesRequest, options?: RpcOptions): UnaryCall<ListAddressesRequest, ListAddressesResponse> {
|
listAddresses(input: ListAddressesRequest, options?: RpcOptions): UnaryCall<ListAddressesRequest, ListAddressesResponse> {
|
||||||
const method = this.methods[10], opt = this._transport.mergeOptions(options);
|
const method = this.methods[10], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -636,7 +636,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* For P2TR addresses this represents a special case. ECDSA is used to create
|
* For P2TR addresses this represents a special case. ECDSA is used to create
|
||||||
* a compact signature which makes the public key of the signature recoverable.
|
* a compact signature which makes the public key of the signature recoverable.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignMessageWithAddr(walletrpc.SignMessageWithAddrRequest) returns (walletrpc.SignMessageWithAddrResponse);
|
* @generated from protobuf rpc: SignMessageWithAddr
|
||||||
*/
|
*/
|
||||||
signMessageWithAddr(input: SignMessageWithAddrRequest, options?: RpcOptions): UnaryCall<SignMessageWithAddrRequest, SignMessageWithAddrResponse> {
|
signMessageWithAddr(input: SignMessageWithAddrRequest, options?: RpcOptions): UnaryCall<SignMessageWithAddrRequest, SignMessageWithAddrResponse> {
|
||||||
const method = this.methods[11], opt = this._transport.mergeOptions(options);
|
const method = this.methods[11], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -664,7 +664,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* taproot key. The compact ECDSA signature format was used because there
|
* taproot key. The compact ECDSA signature format was used because there
|
||||||
* are still no known compact signature schemes for schnorr signatures.
|
* are still no known compact signature schemes for schnorr signatures.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: VerifyMessageWithAddr(walletrpc.VerifyMessageWithAddrRequest) returns (walletrpc.VerifyMessageWithAddrResponse);
|
* @generated from protobuf rpc: VerifyMessageWithAddr
|
||||||
*/
|
*/
|
||||||
verifyMessageWithAddr(input: VerifyMessageWithAddrRequest, options?: RpcOptions): UnaryCall<VerifyMessageWithAddrRequest, VerifyMessageWithAddrResponse> {
|
verifyMessageWithAddr(input: VerifyMessageWithAddrRequest, options?: RpcOptions): UnaryCall<VerifyMessageWithAddrRequest, VerifyMessageWithAddrResponse> {
|
||||||
const method = this.methods[12], opt = this._transport.mergeOptions(options);
|
const method = this.methods[12], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -696,7 +696,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* detected by lnd if they happen after the import. Rescans to detect past
|
* detected by lnd if they happen after the import. Rescans to detect past
|
||||||
* events will be supported later on.
|
* events will be supported later on.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ImportAccount(walletrpc.ImportAccountRequest) returns (walletrpc.ImportAccountResponse);
|
* @generated from protobuf rpc: ImportAccount
|
||||||
*/
|
*/
|
||||||
importAccount(input: ImportAccountRequest, options?: RpcOptions): UnaryCall<ImportAccountRequest, ImportAccountResponse> {
|
importAccount(input: ImportAccountRequest, options?: RpcOptions): UnaryCall<ImportAccountRequest, ImportAccountResponse> {
|
||||||
const method = this.methods[13], opt = this._transport.mergeOptions(options);
|
const method = this.methods[13], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -714,7 +714,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* they happen after the import. Rescans to detect past events will be
|
* they happen after the import. Rescans to detect past events will be
|
||||||
* supported later on.
|
* supported later on.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ImportPublicKey(walletrpc.ImportPublicKeyRequest) returns (walletrpc.ImportPublicKeyResponse);
|
* @generated from protobuf rpc: ImportPublicKey
|
||||||
*/
|
*/
|
||||||
importPublicKey(input: ImportPublicKeyRequest, options?: RpcOptions): UnaryCall<ImportPublicKeyRequest, ImportPublicKeyResponse> {
|
importPublicKey(input: ImportPublicKeyRequest, options?: RpcOptions): UnaryCall<ImportPublicKeyRequest, ImportPublicKeyResponse> {
|
||||||
const method = this.methods[14], opt = this._transport.mergeOptions(options);
|
const method = this.methods[14], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -734,7 +734,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* NOTE: Taproot keys imported through this RPC currently _cannot_ be used for
|
* NOTE: Taproot keys imported through this RPC currently _cannot_ be used for
|
||||||
* funding PSBTs. Only tracking the balance and UTXOs is currently supported.
|
* funding PSBTs. Only tracking the balance and UTXOs is currently supported.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ImportTapscript(walletrpc.ImportTapscriptRequest) returns (walletrpc.ImportTapscriptResponse);
|
* @generated from protobuf rpc: ImportTapscript
|
||||||
*/
|
*/
|
||||||
importTapscript(input: ImportTapscriptRequest, options?: RpcOptions): UnaryCall<ImportTapscriptRequest, ImportTapscriptResponse> {
|
importTapscript(input: ImportTapscriptRequest, options?: RpcOptions): UnaryCall<ImportTapscriptRequest, ImportTapscriptResponse> {
|
||||||
const method = this.methods[15], opt = this._transport.mergeOptions(options);
|
const method = this.methods[15], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -747,7 +747,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* attempt to re-broadcast the transaction on start up, until it enters the
|
* attempt to re-broadcast the transaction on start up, until it enters the
|
||||||
* chain.
|
* chain.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: PublishTransaction(walletrpc.Transaction) returns (walletrpc.PublishResponse);
|
* @generated from protobuf rpc: PublishTransaction
|
||||||
*/
|
*/
|
||||||
publishTransaction(input: Transaction$, options?: RpcOptions): UnaryCall<Transaction$, PublishResponse> {
|
publishTransaction(input: Transaction$, options?: RpcOptions): UnaryCall<Transaction$, PublishResponse> {
|
||||||
const method = this.methods[16], opt = this._transport.mergeOptions(options);
|
const method = this.methods[16], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -758,7 +758,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* RemoveTransaction attempts to remove the provided transaction from the
|
* RemoveTransaction attempts to remove the provided transaction from the
|
||||||
* internal transaction store of the wallet.
|
* internal transaction store of the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: RemoveTransaction(walletrpc.GetTransactionRequest) returns (walletrpc.RemoveTransactionResponse);
|
* @generated from protobuf rpc: RemoveTransaction
|
||||||
*/
|
*/
|
||||||
removeTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, RemoveTransactionResponse> {
|
removeTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall<GetTransactionRequest, RemoveTransactionResponse> {
|
||||||
const method = this.methods[17], opt = this._transport.mergeOptions(options);
|
const method = this.methods[17], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -770,7 +770,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* allows the caller to create a transaction that sends to several outputs at
|
* allows the caller to create a transaction that sends to several outputs at
|
||||||
* once. This is ideal when wanting to batch create a set of transactions.
|
* once. This is ideal when wanting to batch create a set of transactions.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SendOutputs(walletrpc.SendOutputsRequest) returns (walletrpc.SendOutputsResponse);
|
* @generated from protobuf rpc: SendOutputs
|
||||||
*/
|
*/
|
||||||
sendOutputs(input: SendOutputsRequest, options?: RpcOptions): UnaryCall<SendOutputsRequest, SendOutputsResponse> {
|
sendOutputs(input: SendOutputsRequest, options?: RpcOptions): UnaryCall<SendOutputsRequest, SendOutputsResponse> {
|
||||||
const method = this.methods[18], opt = this._transport.mergeOptions(options);
|
const method = this.methods[18], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -782,7 +782,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* determine the fee (in sat/kw) to attach to a transaction in order to
|
* determine the fee (in sat/kw) to attach to a transaction in order to
|
||||||
* achieve the confirmation target.
|
* achieve the confirmation target.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: EstimateFee(walletrpc.EstimateFeeRequest) returns (walletrpc.EstimateFeeResponse);
|
* @generated from protobuf rpc: EstimateFee
|
||||||
*/
|
*/
|
||||||
estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall<EstimateFeeRequest, EstimateFeeResponse> {
|
estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall<EstimateFeeRequest, EstimateFeeResponse> {
|
||||||
const method = this.methods[19], opt = this._transport.mergeOptions(options);
|
const method = this.methods[19], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -799,7 +799,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* remain supported. This is an advanced API that depends on the internals of
|
* remain supported. This is an advanced API that depends on the internals of
|
||||||
* the UtxoSweeper, so things may change.
|
* the UtxoSweeper, so things may change.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: PendingSweeps(walletrpc.PendingSweepsRequest) returns (walletrpc.PendingSweepsResponse);
|
* @generated from protobuf rpc: PendingSweeps
|
||||||
*/
|
*/
|
||||||
pendingSweeps(input: PendingSweepsRequest, options?: RpcOptions): UnaryCall<PendingSweepsRequest, PendingSweepsResponse> {
|
pendingSweeps(input: PendingSweepsRequest, options?: RpcOptions): UnaryCall<PendingSweepsRequest, PendingSweepsResponse> {
|
||||||
const method = this.methods[20], opt = this._transport.mergeOptions(options);
|
const method = this.methods[20], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -836,7 +836,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* done by specifying an outpoint within the low fee transaction that is under
|
* done by specifying an outpoint within the low fee transaction that is under
|
||||||
* the control of the wallet.
|
* the control of the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: BumpFee(walletrpc.BumpFeeRequest) returns (walletrpc.BumpFeeResponse);
|
* @generated from protobuf rpc: BumpFee
|
||||||
*/
|
*/
|
||||||
bumpFee(input: BumpFeeRequest, options?: RpcOptions): UnaryCall<BumpFeeRequest, BumpFeeResponse> {
|
bumpFee(input: BumpFeeRequest, options?: RpcOptions): UnaryCall<BumpFeeRequest, BumpFeeResponse> {
|
||||||
const method = this.methods[21], opt = this._transport.mergeOptions(options);
|
const method = this.methods[21], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -847,7 +847,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* BumpForceCloseFee is an endpoint that allows users to bump the fee of a
|
* BumpForceCloseFee is an endpoint that allows users to bump the fee of a
|
||||||
* channel force close. This only works for channels with option_anchors.
|
* channel force close. This only works for channels with option_anchors.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: BumpForceCloseFee(walletrpc.BumpForceCloseFeeRequest) returns (walletrpc.BumpForceCloseFeeResponse);
|
* @generated from protobuf rpc: BumpForceCloseFee
|
||||||
*/
|
*/
|
||||||
bumpForceCloseFee(input: BumpForceCloseFeeRequest, options?: RpcOptions): UnaryCall<BumpForceCloseFeeRequest, BumpForceCloseFeeResponse> {
|
bumpForceCloseFee(input: BumpForceCloseFeeRequest, options?: RpcOptions): UnaryCall<BumpForceCloseFeeRequest, BumpForceCloseFeeResponse> {
|
||||||
const method = this.methods[22], opt = this._transport.mergeOptions(options);
|
const method = this.methods[22], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -859,7 +859,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* Note that these sweeps may not be confirmed yet, as we record sweeps on
|
* Note that these sweeps may not be confirmed yet, as we record sweeps on
|
||||||
* broadcast, not confirmation.
|
* broadcast, not confirmation.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ListSweeps(walletrpc.ListSweepsRequest) returns (walletrpc.ListSweepsResponse);
|
* @generated from protobuf rpc: ListSweeps
|
||||||
*/
|
*/
|
||||||
listSweeps(input: ListSweepsRequest, options?: RpcOptions): UnaryCall<ListSweepsRequest, ListSweepsResponse> {
|
listSweeps(input: ListSweepsRequest, options?: RpcOptions): UnaryCall<ListSweepsRequest, ListSweepsResponse> {
|
||||||
const method = this.methods[23], opt = this._transport.mergeOptions(options);
|
const method = this.methods[23], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -872,7 +872,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* overwrite the existing transaction label. Labels must not be empty, and
|
* overwrite the existing transaction label. Labels must not be empty, and
|
||||||
* cannot exceed 500 characters.
|
* cannot exceed 500 characters.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: LabelTransaction(walletrpc.LabelTransactionRequest) returns (walletrpc.LabelTransactionResponse);
|
* @generated from protobuf rpc: LabelTransaction
|
||||||
*/
|
*/
|
||||||
labelTransaction(input: LabelTransactionRequest, options?: RpcOptions): UnaryCall<LabelTransactionRequest, LabelTransactionResponse> {
|
labelTransaction(input: LabelTransactionRequest, options?: RpcOptions): UnaryCall<LabelTransactionRequest, LabelTransactionResponse> {
|
||||||
const method = this.methods[24], opt = this._transport.mergeOptions(options);
|
const method = this.methods[24], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -909,7 +909,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* publishing the transaction) or to unlock/release the locked UTXOs in case of
|
* publishing the transaction) or to unlock/release the locked UTXOs in case of
|
||||||
* an error on the caller's side.
|
* an error on the caller's side.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: FundPsbt(walletrpc.FundPsbtRequest) returns (walletrpc.FundPsbtResponse);
|
* @generated from protobuf rpc: FundPsbt
|
||||||
*/
|
*/
|
||||||
fundPsbt(input: FundPsbtRequest, options?: RpcOptions): UnaryCall<FundPsbtRequest, FundPsbtResponse> {
|
fundPsbt(input: FundPsbtRequest, options?: RpcOptions): UnaryCall<FundPsbtRequest, FundPsbtResponse> {
|
||||||
const method = this.methods[25], opt = this._transport.mergeOptions(options);
|
const method = this.methods[25], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -929,7 +929,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* input/output/fee value validation, PSBT finalization). Any input that is
|
* input/output/fee value validation, PSBT finalization). Any input that is
|
||||||
* incomplete will be skipped.
|
* incomplete will be skipped.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: SignPsbt(walletrpc.SignPsbtRequest) returns (walletrpc.SignPsbtResponse);
|
* @generated from protobuf rpc: SignPsbt
|
||||||
*/
|
*/
|
||||||
signPsbt(input: SignPsbtRequest, options?: RpcOptions): UnaryCall<SignPsbtRequest, SignPsbtResponse> {
|
signPsbt(input: SignPsbtRequest, options?: RpcOptions): UnaryCall<SignPsbtRequest, SignPsbtResponse> {
|
||||||
const method = this.methods[26], opt = this._transport.mergeOptions(options);
|
const method = this.methods[26], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -949,7 +949,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo {
|
||||||
* caller's responsibility to either publish the transaction on success or
|
* caller's responsibility to either publish the transaction on success or
|
||||||
* unlock/release any locked UTXOs in case of an error in this method.
|
* unlock/release any locked UTXOs in case of an error in this method.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: FinalizePsbt(walletrpc.FinalizePsbtRequest) returns (walletrpc.FinalizePsbtResponse);
|
* @generated from protobuf rpc: FinalizePsbt
|
||||||
*/
|
*/
|
||||||
finalizePsbt(input: FinalizePsbtRequest, options?: RpcOptions): UnaryCall<FinalizePsbtRequest, FinalizePsbtResponse> {
|
finalizePsbt(input: FinalizePsbtRequest, options?: RpcOptions): UnaryCall<FinalizePsbtRequest, FinalizePsbtResponse> {
|
||||||
const method = this.methods[27], opt = this._transport.mergeOptions(options);
|
const method = this.methods[27], opt = this._transport.mergeOptions(options);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3)
|
// @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||||
|
|
@ -50,7 +50,7 @@ export interface IWalletUnlockerClient {
|
||||||
* method should be used to commit the newly generated seed, and create the
|
* method should be used to commit the newly generated seed, and create the
|
||||||
* wallet.
|
* wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: GenSeed(lnrpc.GenSeedRequest) returns (lnrpc.GenSeedResponse);
|
* @generated from protobuf rpc: GenSeed
|
||||||
*/
|
*/
|
||||||
genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall<GenSeedRequest, GenSeedResponse>;
|
genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall<GenSeedRequest, GenSeedResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -68,7 +68,7 @@ export interface IWalletUnlockerClient {
|
||||||
* seed, then present it to the user. Once it has been verified by the user,
|
* seed, then present it to the user. Once it has been verified by the user,
|
||||||
* the seed can be fed into this RPC in order to commit the new wallet.
|
* the seed can be fed into this RPC in order to commit the new wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: InitWallet(lnrpc.InitWalletRequest) returns (lnrpc.InitWalletResponse);
|
* @generated from protobuf rpc: InitWallet
|
||||||
*/
|
*/
|
||||||
initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall<InitWalletRequest, InitWalletResponse>;
|
initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall<InitWalletRequest, InitWalletResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,7 +76,7 @@ export interface IWalletUnlockerClient {
|
||||||
* UnlockWallet is used at startup of lnd to provide a password to unlock
|
* UnlockWallet is used at startup of lnd to provide a password to unlock
|
||||||
* the wallet database.
|
* the wallet database.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: UnlockWallet(lnrpc.UnlockWalletRequest) returns (lnrpc.UnlockWalletResponse);
|
* @generated from protobuf rpc: UnlockWallet
|
||||||
*/
|
*/
|
||||||
unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall<UnlockWalletRequest, UnlockWalletResponse>;
|
unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall<UnlockWalletRequest, UnlockWalletResponse>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -84,7 +84,7 @@ export interface IWalletUnlockerClient {
|
||||||
* ChangePassword changes the password of the encrypted wallet. This will
|
* ChangePassword changes the password of the encrypted wallet. This will
|
||||||
* automatically unlock the wallet database if successful.
|
* automatically unlock the wallet database if successful.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ChangePassword(lnrpc.ChangePasswordRequest) returns (lnrpc.ChangePasswordResponse);
|
* @generated from protobuf rpc: ChangePassword
|
||||||
*/
|
*/
|
||||||
changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall<ChangePasswordRequest, ChangePasswordResponse>;
|
changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall<ChangePasswordRequest, ChangePasswordResponse>;
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +128,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo
|
||||||
* method should be used to commit the newly generated seed, and create the
|
* method should be used to commit the newly generated seed, and create the
|
||||||
* wallet.
|
* wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: GenSeed(lnrpc.GenSeedRequest) returns (lnrpc.GenSeedResponse);
|
* @generated from protobuf rpc: GenSeed
|
||||||
*/
|
*/
|
||||||
genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall<GenSeedRequest, GenSeedResponse> {
|
genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall<GenSeedRequest, GenSeedResponse> {
|
||||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -149,7 +149,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo
|
||||||
* seed, then present it to the user. Once it has been verified by the user,
|
* seed, then present it to the user. Once it has been verified by the user,
|
||||||
* the seed can be fed into this RPC in order to commit the new wallet.
|
* the seed can be fed into this RPC in order to commit the new wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: InitWallet(lnrpc.InitWalletRequest) returns (lnrpc.InitWalletResponse);
|
* @generated from protobuf rpc: InitWallet
|
||||||
*/
|
*/
|
||||||
initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall<InitWalletRequest, InitWalletResponse> {
|
initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall<InitWalletRequest, InitWalletResponse> {
|
||||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -160,7 +160,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo
|
||||||
* UnlockWallet is used at startup of lnd to provide a password to unlock
|
* UnlockWallet is used at startup of lnd to provide a password to unlock
|
||||||
* the wallet database.
|
* the wallet database.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: UnlockWallet(lnrpc.UnlockWalletRequest) returns (lnrpc.UnlockWalletResponse);
|
* @generated from protobuf rpc: UnlockWallet
|
||||||
*/
|
*/
|
||||||
unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall<UnlockWalletRequest, UnlockWalletResponse> {
|
unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall<UnlockWalletRequest, UnlockWalletResponse> {
|
||||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||||
|
|
@ -171,7 +171,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo
|
||||||
* ChangePassword changes the password of the encrypted wallet. This will
|
* ChangePassword changes the password of the encrypted wallet. This will
|
||||||
* automatically unlock the wallet database if successful.
|
* automatically unlock the wallet database if successful.
|
||||||
*
|
*
|
||||||
* @generated from protobuf rpc: ChangePassword(lnrpc.ChangePasswordRequest) returns (lnrpc.ChangePasswordResponse);
|
* @generated from protobuf rpc: ChangePassword
|
||||||
*/
|
*/
|
||||||
changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall<ChangePasswordRequest, ChangePasswordResponse> {
|
changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall<ChangePasswordRequest, ChangePasswordResponse> {
|
||||||
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// @generated by protobuf-ts 2.8.1
|
// @generated by protobuf-ts 2.11.1
|
||||||
// @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3)
|
// @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3)
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
||||||
|
|
@ -10,7 +10,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime";
|
||||||
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
||||||
import type { PartialMessage } from "@protobuf-ts/runtime";
|
import type { PartialMessage } from "@protobuf-ts/runtime";
|
||||||
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
||||||
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
|
|
||||||
import { MessageType } from "@protobuf-ts/runtime";
|
import { MessageType } from "@protobuf-ts/runtime";
|
||||||
import { ChanBackupSnapshot } from "./lightning.js";
|
import { ChanBackupSnapshot } from "./lightning.js";
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,7 +22,7 @@ export interface GenSeedRequest {
|
||||||
* to encrypt the generated aezeed cipher seed. When using REST, this field
|
* to encrypt the generated aezeed cipher seed. When using REST, this field
|
||||||
* must be encoded as base64.
|
* must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes aezeed_passphrase = 1;
|
* @generated from protobuf field: bytes aezeed_passphrase = 1
|
||||||
*/
|
*/
|
||||||
aezeedPassphrase: Uint8Array;
|
aezeedPassphrase: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,7 +31,7 @@ export interface GenSeedRequest {
|
||||||
* specified, then a fresh set of randomness will be used to create the seed.
|
* specified, then a fresh set of randomness will be used to create the seed.
|
||||||
* When using REST, this field must be encoded as base64.
|
* When using REST, this field must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes seed_entropy = 2;
|
* @generated from protobuf field: bytes seed_entropy = 2
|
||||||
*/
|
*/
|
||||||
seedEntropy: Uint8Array;
|
seedEntropy: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +47,7 @@ export interface GenSeedResponse {
|
||||||
* Otherwise, then the daemon will attempt to recover the wallet state linked
|
* Otherwise, then the daemon will attempt to recover the wallet state linked
|
||||||
* to this cipher seed.
|
* to this cipher seed.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: repeated string cipher_seed_mnemonic = 1;
|
* @generated from protobuf field: repeated string cipher_seed_mnemonic = 1
|
||||||
*/
|
*/
|
||||||
cipherSeedMnemonic: string[];
|
cipherSeedMnemonic: string[];
|
||||||
/**
|
/**
|
||||||
|
|
@ -56,7 +55,7 @@ export interface GenSeedResponse {
|
||||||
* enciphered_seed are the raw aezeed cipher seed bytes. This is the raw
|
* enciphered_seed are the raw aezeed cipher seed bytes. This is the raw
|
||||||
* cipher text before run through our mnemonic encoding scheme.
|
* cipher text before run through our mnemonic encoding scheme.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes enciphered_seed = 2;
|
* @generated from protobuf field: bytes enciphered_seed = 2
|
||||||
*/
|
*/
|
||||||
encipheredSeed: Uint8Array;
|
encipheredSeed: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +70,7 @@ export interface InitWalletRequest {
|
||||||
* password is required to unlock the daemon. When using REST, this field
|
* password is required to unlock the daemon. When using REST, this field
|
||||||
* must be encoded as base64.
|
* must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes wallet_password = 1;
|
* @generated from protobuf field: bytes wallet_password = 1
|
||||||
*/
|
*/
|
||||||
walletPassword: Uint8Array;
|
walletPassword: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -80,7 +79,7 @@ export interface InitWalletRequest {
|
||||||
* cipher seed obtained by the user. This may have been generated by the
|
* cipher seed obtained by the user. This may have been generated by the
|
||||||
* GenSeed method, or be an existing seed.
|
* GenSeed method, or be an existing seed.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: repeated string cipher_seed_mnemonic = 2;
|
* @generated from protobuf field: repeated string cipher_seed_mnemonic = 2
|
||||||
*/
|
*/
|
||||||
cipherSeedMnemonic: string[];
|
cipherSeedMnemonic: string[];
|
||||||
/**
|
/**
|
||||||
|
|
@ -89,7 +88,7 @@ export interface InitWalletRequest {
|
||||||
* to encrypt the generated aezeed cipher seed. When using REST, this field
|
* to encrypt the generated aezeed cipher seed. When using REST, this field
|
||||||
* must be encoded as base64.
|
* must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes aezeed_passphrase = 3;
|
* @generated from protobuf field: bytes aezeed_passphrase = 3
|
||||||
*/
|
*/
|
||||||
aezeedPassphrase: Uint8Array;
|
aezeedPassphrase: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -100,7 +99,7 @@ export interface InitWalletRequest {
|
||||||
* window of zero indicates that no addresses should be recovered, such after
|
* window of zero indicates that no addresses should be recovered, such after
|
||||||
* the first initialization of the wallet.
|
* the first initialization of the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: int32 recovery_window = 4;
|
* @generated from protobuf field: int32 recovery_window = 4
|
||||||
*/
|
*/
|
||||||
recoveryWindow: number;
|
recoveryWindow: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -112,7 +111,7 @@ export interface InitWalletRequest {
|
||||||
* funds, lnd begin to carry out the data loss recovery protocol in order to
|
* funds, lnd begin to carry out the data loss recovery protocol in order to
|
||||||
* recover the funds in each channel from a remote force closed transaction.
|
* recover the funds in each channel from a remote force closed transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 5;
|
* @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 5
|
||||||
*/
|
*/
|
||||||
channelBackups?: ChanBackupSnapshot;
|
channelBackups?: ChanBackupSnapshot;
|
||||||
/**
|
/**
|
||||||
|
|
@ -122,7 +121,7 @@ export interface InitWalletRequest {
|
||||||
* admin macaroon returned in the response MUST be stored by the caller of the
|
* admin macaroon returned in the response MUST be stored by the caller of the
|
||||||
* RPC as otherwise all access to the daemon will be lost!
|
* RPC as otherwise all access to the daemon will be lost!
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bool stateless_init = 6;
|
* @generated from protobuf field: bool stateless_init = 6
|
||||||
*/
|
*/
|
||||||
statelessInit: boolean;
|
statelessInit: boolean;
|
||||||
/**
|
/**
|
||||||
|
|
@ -140,7 +139,7 @@ export interface InitWalletRequest {
|
||||||
* extended_master_key_birthday_timestamp or a "safe" default value will be
|
* extended_master_key_birthday_timestamp or a "safe" default value will be
|
||||||
* used.
|
* used.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: string extended_master_key = 7;
|
* @generated from protobuf field: string extended_master_key = 7
|
||||||
*/
|
*/
|
||||||
extendedMasterKey: string;
|
extendedMasterKey: string;
|
||||||
/**
|
/**
|
||||||
|
|
@ -153,7 +152,7 @@ export interface InitWalletRequest {
|
||||||
* which case lnd will start scanning from the first SegWit block (481824 on
|
* which case lnd will start scanning from the first SegWit block (481824 on
|
||||||
* mainnet).
|
* mainnet).
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint64 extended_master_key_birthday_timestamp = 8;
|
* @generated from protobuf field: uint64 extended_master_key_birthday_timestamp = 8
|
||||||
*/
|
*/
|
||||||
extendedMasterKeyBirthdayTimestamp: bigint;
|
extendedMasterKeyBirthdayTimestamp: bigint;
|
||||||
/**
|
/**
|
||||||
|
|
@ -164,7 +163,7 @@ export interface InitWalletRequest {
|
||||||
* any of the keys and _needs_ to be run with a remote signer that has the
|
* any of the keys and _needs_ to be run with a remote signer that has the
|
||||||
* corresponding private keys and can serve signing RPC requests.
|
* corresponding private keys and can serve signing RPC requests.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: lnrpc.WatchOnly watch_only = 9;
|
* @generated from protobuf field: lnrpc.WatchOnly watch_only = 9
|
||||||
*/
|
*/
|
||||||
watchOnly?: WatchOnly;
|
watchOnly?: WatchOnly;
|
||||||
/**
|
/**
|
||||||
|
|
@ -173,7 +172,7 @@ export interface InitWalletRequest {
|
||||||
* provided when initializing the wallet rather than letting lnd generate one
|
* provided when initializing the wallet rather than letting lnd generate one
|
||||||
* on its own.
|
* on its own.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes macaroon_root_key = 10;
|
* @generated from protobuf field: bytes macaroon_root_key = 10
|
||||||
*/
|
*/
|
||||||
macaroonRootKey: Uint8Array;
|
macaroonRootKey: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +188,7 @@ export interface InitWalletResponse {
|
||||||
* caller. Otherwise a copy of this macaroon is also persisted on disk by the
|
* caller. Otherwise a copy of this macaroon is also persisted on disk by the
|
||||||
* daemon, together with other macaroon files.
|
* daemon, together with other macaroon files.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes admin_macaroon = 1;
|
* @generated from protobuf field: bytes admin_macaroon = 1
|
||||||
*/
|
*/
|
||||||
adminMacaroon: Uint8Array;
|
adminMacaroon: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +204,7 @@ export interface WatchOnly {
|
||||||
* should be left at its default value of 0 in which case lnd will start
|
* should be left at its default value of 0 in which case lnd will start
|
||||||
* scanning from the first SegWit block (481824 on mainnet).
|
* scanning from the first SegWit block (481824 on mainnet).
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint64 master_key_birthday_timestamp = 1;
|
* @generated from protobuf field: uint64 master_key_birthday_timestamp = 1
|
||||||
*/
|
*/
|
||||||
masterKeyBirthdayTimestamp: bigint;
|
masterKeyBirthdayTimestamp: bigint;
|
||||||
/**
|
/**
|
||||||
|
|
@ -215,7 +214,7 @@ export interface WatchOnly {
|
||||||
* required by some hardware wallets for proper identification and signing. The
|
* required by some hardware wallets for proper identification and signing. The
|
||||||
* bytes must be in big-endian order.
|
* bytes must be in big-endian order.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes master_key_fingerprint = 2;
|
* @generated from protobuf field: bytes master_key_fingerprint = 2
|
||||||
*/
|
*/
|
||||||
masterKeyFingerprint: Uint8Array;
|
masterKeyFingerprint: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -226,7 +225,7 @@ export interface WatchOnly {
|
||||||
* scope (m/1017'/<coin_type>'/<account>'), where account is the key family as
|
* scope (m/1017'/<coin_type>'/<account>'), where account is the key family as
|
||||||
* defined in `keychain/derivation.go` (currently indices 0 to 9).
|
* defined in `keychain/derivation.go` (currently indices 0 to 9).
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: repeated lnrpc.WatchOnlyAccount accounts = 3;
|
* @generated from protobuf field: repeated lnrpc.WatchOnlyAccount accounts = 3
|
||||||
*/
|
*/
|
||||||
accounts: WatchOnlyAccount[];
|
accounts: WatchOnlyAccount[];
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +238,7 @@ export interface WatchOnlyAccount {
|
||||||
* Purpose is the first number in the derivation path, must be either 49, 84
|
* Purpose is the first number in the derivation path, must be either 49, 84
|
||||||
* or 1017.
|
* or 1017.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 purpose = 1;
|
* @generated from protobuf field: uint32 purpose = 1
|
||||||
*/
|
*/
|
||||||
purpose: number;
|
purpose: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -248,7 +247,7 @@ export interface WatchOnlyAccount {
|
||||||
* for purposes 49 and 84. It only needs to be set to 1 for purpose 1017 on
|
* for purposes 49 and 84. It only needs to be set to 1 for purpose 1017 on
|
||||||
* testnet or regtest.
|
* testnet or regtest.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 coin_type = 2;
|
* @generated from protobuf field: uint32 coin_type = 2
|
||||||
*/
|
*/
|
||||||
coinType: number;
|
coinType: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -259,14 +258,14 @@ export interface WatchOnlyAccount {
|
||||||
* one account for each of the key families defined in `keychain/derivation.go`
|
* one account for each of the key families defined in `keychain/derivation.go`
|
||||||
* (currently indices 0 to 9)
|
* (currently indices 0 to 9)
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: uint32 account = 3;
|
* @generated from protobuf field: uint32 account = 3
|
||||||
*/
|
*/
|
||||||
account: number;
|
account: number;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The extended public key at depth 3 for the given account.
|
* The extended public key at depth 3 for the given account.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: string xpub = 4;
|
* @generated from protobuf field: string xpub = 4
|
||||||
*/
|
*/
|
||||||
xpub: string;
|
xpub: string;
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +279,7 @@ export interface UnlockWalletRequest {
|
||||||
* will be required to decrypt on-disk material that the daemon requires to
|
* will be required to decrypt on-disk material that the daemon requires to
|
||||||
* function properly. When using REST, this field must be encoded as base64.
|
* function properly. When using REST, this field must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes wallet_password = 1;
|
* @generated from protobuf field: bytes wallet_password = 1
|
||||||
*/
|
*/
|
||||||
walletPassword: Uint8Array;
|
walletPassword: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -291,7 +290,7 @@ export interface UnlockWalletRequest {
|
||||||
* window of zero indicates that no addresses should be recovered, such after
|
* window of zero indicates that no addresses should be recovered, such after
|
||||||
* the first initialization of the wallet.
|
* the first initialization of the wallet.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: int32 recovery_window = 2;
|
* @generated from protobuf field: int32 recovery_window = 2
|
||||||
*/
|
*/
|
||||||
recoveryWindow: number;
|
recoveryWindow: number;
|
||||||
/**
|
/**
|
||||||
|
|
@ -303,7 +302,7 @@ export interface UnlockWalletRequest {
|
||||||
* funds, lnd begin to carry out the data loss recovery protocol in order to
|
* funds, lnd begin to carry out the data loss recovery protocol in order to
|
||||||
* recover the funds in each channel from a remote force closed transaction.
|
* recover the funds in each channel from a remote force closed transaction.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 3;
|
* @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 3
|
||||||
*/
|
*/
|
||||||
channelBackups?: ChanBackupSnapshot;
|
channelBackups?: ChanBackupSnapshot;
|
||||||
/**
|
/**
|
||||||
|
|
@ -311,7 +310,7 @@ export interface UnlockWalletRequest {
|
||||||
* stateless_init is an optional argument instructing the daemon NOT to create
|
* stateless_init is an optional argument instructing the daemon NOT to create
|
||||||
* any *.macaroon files in its file system.
|
* any *.macaroon files in its file system.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bool stateless_init = 4;
|
* @generated from protobuf field: bool stateless_init = 4
|
||||||
*/
|
*/
|
||||||
statelessInit: boolean;
|
statelessInit: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -329,7 +328,7 @@ export interface ChangePasswordRequest {
|
||||||
* current_password should be the current valid passphrase used to unlock the
|
* current_password should be the current valid passphrase used to unlock the
|
||||||
* daemon. When using REST, this field must be encoded as base64.
|
* daemon. When using REST, this field must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes current_password = 1;
|
* @generated from protobuf field: bytes current_password = 1
|
||||||
*/
|
*/
|
||||||
currentPassword: Uint8Array;
|
currentPassword: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -337,7 +336,7 @@ export interface ChangePasswordRequest {
|
||||||
* new_password should be the new passphrase that will be needed to unlock the
|
* new_password should be the new passphrase that will be needed to unlock the
|
||||||
* daemon. When using REST, this field must be encoded as base64.
|
* daemon. When using REST, this field must be encoded as base64.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes new_password = 2;
|
* @generated from protobuf field: bytes new_password = 2
|
||||||
*/
|
*/
|
||||||
newPassword: Uint8Array;
|
newPassword: Uint8Array;
|
||||||
/**
|
/**
|
||||||
|
|
@ -347,7 +346,7 @@ export interface ChangePasswordRequest {
|
||||||
* admin macaroon returned in the response MUST be stored by the caller of the
|
* admin macaroon returned in the response MUST be stored by the caller of the
|
||||||
* RPC as otherwise all access to the daemon will be lost!
|
* RPC as otherwise all access to the daemon will be lost!
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bool stateless_init = 3;
|
* @generated from protobuf field: bool stateless_init = 3
|
||||||
*/
|
*/
|
||||||
statelessInit: boolean;
|
statelessInit: boolean;
|
||||||
/**
|
/**
|
||||||
|
|
@ -356,7 +355,7 @@ export interface ChangePasswordRequest {
|
||||||
* rotate the macaroon root key when set to true. This will invalidate all
|
* rotate the macaroon root key when set to true. This will invalidate all
|
||||||
* previously generated macaroons.
|
* previously generated macaroons.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bool new_macaroon_root_key = 4;
|
* @generated from protobuf field: bool new_macaroon_root_key = 4
|
||||||
*/
|
*/
|
||||||
newMacaroonRootKey: boolean;
|
newMacaroonRootKey: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -373,7 +372,7 @@ export interface ChangePasswordResponse {
|
||||||
* safely by the caller. Otherwise a copy of this macaroon is also persisted on
|
* safely by the caller. Otherwise a copy of this macaroon is also persisted on
|
||||||
* disk by the daemon, together with other macaroon files.
|
* disk by the daemon, together with other macaroon files.
|
||||||
*
|
*
|
||||||
* @generated from protobuf field: bytes admin_macaroon = 1;
|
* @generated from protobuf field: bytes admin_macaroon = 1
|
||||||
*/
|
*/
|
||||||
adminMacaroon: Uint8Array;
|
adminMacaroon: Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
@ -386,8 +385,9 @@ class GenSeedRequest$Type extends MessageType<GenSeedRequest> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<GenSeedRequest>): GenSeedRequest {
|
create(value?: PartialMessage<GenSeedRequest>): GenSeedRequest {
|
||||||
const message = { aezeedPassphrase: new Uint8Array(0), seedEntropy: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.aezeedPassphrase = new Uint8Array(0);
|
||||||
|
message.seedEntropy = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<GenSeedRequest>(this, message, value);
|
reflectionMergePartial<GenSeedRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -440,8 +440,9 @@ class GenSeedResponse$Type extends MessageType<GenSeedResponse> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<GenSeedResponse>): GenSeedResponse {
|
create(value?: PartialMessage<GenSeedResponse>): GenSeedResponse {
|
||||||
const message = { cipherSeedMnemonic: [], encipheredSeed: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.cipherSeedMnemonic = [];
|
||||||
|
message.encipheredSeed = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<GenSeedResponse>(this, message, value);
|
reflectionMergePartial<GenSeedResponse>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -502,8 +503,15 @@ class InitWalletRequest$Type extends MessageType<InitWalletRequest> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<InitWalletRequest>): InitWalletRequest {
|
create(value?: PartialMessage<InitWalletRequest>): InitWalletRequest {
|
||||||
const message = { walletPassword: new Uint8Array(0), cipherSeedMnemonic: [], aezeedPassphrase: new Uint8Array(0), recoveryWindow: 0, statelessInit: false, extendedMasterKey: "", extendedMasterKeyBirthdayTimestamp: 0n, macaroonRootKey: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.walletPassword = new Uint8Array(0);
|
||||||
|
message.cipherSeedMnemonic = [];
|
||||||
|
message.aezeedPassphrase = new Uint8Array(0);
|
||||||
|
message.recoveryWindow = 0;
|
||||||
|
message.statelessInit = false;
|
||||||
|
message.extendedMasterKey = "";
|
||||||
|
message.extendedMasterKeyBirthdayTimestamp = 0n;
|
||||||
|
message.macaroonRootKey = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<InitWalletRequest>(this, message, value);
|
reflectionMergePartial<InitWalletRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -603,8 +611,8 @@ class InitWalletResponse$Type extends MessageType<InitWalletResponse> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<InitWalletResponse>): InitWalletResponse {
|
create(value?: PartialMessage<InitWalletResponse>): InitWalletResponse {
|
||||||
const message = { adminMacaroon: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.adminMacaroon = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<InitWalletResponse>(this, message, value);
|
reflectionMergePartial<InitWalletResponse>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -648,12 +656,14 @@ class WatchOnly$Type extends MessageType<WatchOnly> {
|
||||||
super("lnrpc.WatchOnly", [
|
super("lnrpc.WatchOnly", [
|
||||||
{ no: 1, name: "master_key_birthday_timestamp", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
{ no: 1, name: "master_key_birthday_timestamp", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||||
{ no: 2, name: "master_key_fingerprint", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
{ no: 2, name: "master_key_fingerprint", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||||
{ no: 3, name: "accounts", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => WatchOnlyAccount }
|
{ no: 3, name: "accounts", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => WatchOnlyAccount }
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<WatchOnly>): WatchOnly {
|
create(value?: PartialMessage<WatchOnly>): WatchOnly {
|
||||||
const message = { masterKeyBirthdayTimestamp: 0n, masterKeyFingerprint: new Uint8Array(0), accounts: [] };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.masterKeyBirthdayTimestamp = 0n;
|
||||||
|
message.masterKeyFingerprint = new Uint8Array(0);
|
||||||
|
message.accounts = [];
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<WatchOnly>(this, message, value);
|
reflectionMergePartial<WatchOnly>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -714,8 +724,11 @@ class WatchOnlyAccount$Type extends MessageType<WatchOnlyAccount> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<WatchOnlyAccount>): WatchOnlyAccount {
|
create(value?: PartialMessage<WatchOnlyAccount>): WatchOnlyAccount {
|
||||||
const message = { purpose: 0, coinType: 0, account: 0, xpub: "" };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.purpose = 0;
|
||||||
|
message.coinType = 0;
|
||||||
|
message.account = 0;
|
||||||
|
message.xpub = "";
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<WatchOnlyAccount>(this, message, value);
|
reflectionMergePartial<WatchOnlyAccount>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -782,8 +795,10 @@ class UnlockWalletRequest$Type extends MessageType<UnlockWalletRequest> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<UnlockWalletRequest>): UnlockWalletRequest {
|
create(value?: PartialMessage<UnlockWalletRequest>): UnlockWalletRequest {
|
||||||
const message = { walletPassword: new Uint8Array(0), recoveryWindow: 0, statelessInit: false };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.walletPassword = new Uint8Array(0);
|
||||||
|
message.recoveryWindow = 0;
|
||||||
|
message.statelessInit = false;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<UnlockWalletRequest>(this, message, value);
|
reflectionMergePartial<UnlockWalletRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -845,14 +860,26 @@ class UnlockWalletResponse$Type extends MessageType<UnlockWalletResponse> {
|
||||||
super("lnrpc.UnlockWalletResponse", []);
|
super("lnrpc.UnlockWalletResponse", []);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<UnlockWalletResponse>): UnlockWalletResponse {
|
create(value?: PartialMessage<UnlockWalletResponse>): UnlockWalletResponse {
|
||||||
const message = {};
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<UnlockWalletResponse>(this, message, value);
|
reflectionMergePartial<UnlockWalletResponse>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UnlockWalletResponse): UnlockWalletResponse {
|
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UnlockWalletResponse): UnlockWalletResponse {
|
||||||
return target ?? this.create();
|
let message = target ?? this.create(), end = reader.pos + length;
|
||||||
|
while (reader.pos < end) {
|
||||||
|
let [fieldNo, wireType] = reader.tag();
|
||||||
|
switch (fieldNo) {
|
||||||
|
default:
|
||||||
|
let u = options.readUnknownField;
|
||||||
|
if (u === "throw")
|
||||||
|
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||||
|
let d = reader.skip(wireType);
|
||||||
|
if (u !== false)
|
||||||
|
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
internalBinaryWrite(message: UnlockWalletResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
internalBinaryWrite(message: UnlockWalletResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||||
let u = options.writeUnknownFields;
|
let u = options.writeUnknownFields;
|
||||||
|
|
@ -876,8 +903,11 @@ class ChangePasswordRequest$Type extends MessageType<ChangePasswordRequest> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<ChangePasswordRequest>): ChangePasswordRequest {
|
create(value?: PartialMessage<ChangePasswordRequest>): ChangePasswordRequest {
|
||||||
const message = { currentPassword: new Uint8Array(0), newPassword: new Uint8Array(0), statelessInit: false, newMacaroonRootKey: false };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.currentPassword = new Uint8Array(0);
|
||||||
|
message.newPassword = new Uint8Array(0);
|
||||||
|
message.statelessInit = false;
|
||||||
|
message.newMacaroonRootKey = false;
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<ChangePasswordRequest>(this, message, value);
|
reflectionMergePartial<ChangePasswordRequest>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
@ -941,8 +971,8 @@ class ChangePasswordResponse$Type extends MessageType<ChangePasswordResponse> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
create(value?: PartialMessage<ChangePasswordResponse>): ChangePasswordResponse {
|
create(value?: PartialMessage<ChangePasswordResponse>): ChangePasswordResponse {
|
||||||
const message = { adminMacaroon: new Uint8Array(0) };
|
const message = globalThis.Object.create((this.messagePrototype!));
|
||||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
message.adminMacaroon = new Uint8Array(0);
|
||||||
if (value !== undefined)
|
if (value !== undefined)
|
||||||
reflectionMergePartial<ChangePasswordResponse>(this, message, value);
|
reflectionMergePartial<ChangePasswordResponse>(this, message, value);
|
||||||
return message;
|
return message;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,29 @@
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "lightning.proto";
|
|
||||||
|
|
||||||
package invoicesrpc;
|
package invoicesrpc;
|
||||||
|
|
||||||
|
import "lightning.proto";
|
||||||
|
|
||||||
option go_package = "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc";
|
option go_package = "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Comments in this file will be directly parsed into the API
|
||||||
|
* Documentation as descriptions of the associated method, message, or field.
|
||||||
|
* These descriptions should go right above the definition of the object, and
|
||||||
|
* can be in either block or // comment format.
|
||||||
|
*
|
||||||
|
* An RPC method can be matched to an lncli command by placing a line in the
|
||||||
|
* beginning of the description in exactly the following format:
|
||||||
|
* lncli: `methodname`
|
||||||
|
*
|
||||||
|
* Failure to specify the exact name of the command will cause documentation
|
||||||
|
* generation to fail.
|
||||||
|
*
|
||||||
|
* More information on how exactly the gRPC documentation is generated from
|
||||||
|
* this proto file can be found here:
|
||||||
|
* https://github.com/lightninglabs/lightning-api
|
||||||
|
*/
|
||||||
|
|
||||||
// Invoices is a service that can be used to create, accept, settle and cancel
|
// Invoices is a service that can be used to create, accept, settle and cancel
|
||||||
// invoices.
|
// invoices.
|
||||||
service Invoices {
|
service Invoices {
|
||||||
|
|
@ -17,30 +35,39 @@ service Invoices {
|
||||||
rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest)
|
rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest)
|
||||||
returns (stream lnrpc.Invoice);
|
returns (stream lnrpc.Invoice);
|
||||||
|
|
||||||
/*
|
/* lncli: `cancelinvoice`
|
||||||
CancelInvoice cancels a currently open invoice. If the invoice is already
|
CancelInvoice cancels a currently open invoice. If the invoice is already
|
||||||
canceled, this call will succeed. If the invoice is already settled, it will
|
canceled, this call will succeed. If the invoice is already settled, it will
|
||||||
fail.
|
fail.
|
||||||
*/
|
*/
|
||||||
rpc CancelInvoice (CancelInvoiceMsg) returns (CancelInvoiceResp);
|
rpc CancelInvoice (CancelInvoiceMsg) returns (CancelInvoiceResp);
|
||||||
|
|
||||||
/*
|
/* lncli: `addholdinvoice`
|
||||||
AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
||||||
supplied in the request.
|
supplied in the request.
|
||||||
*/
|
*/
|
||||||
rpc AddHoldInvoice (AddHoldInvoiceRequest) returns (AddHoldInvoiceResp);
|
rpc AddHoldInvoice (AddHoldInvoiceRequest) returns (AddHoldInvoiceResp);
|
||||||
|
|
||||||
/*
|
/* lncli: `settleinvoice`
|
||||||
SettleInvoice settles an accepted invoice. If the invoice is already
|
SettleInvoice settles an accepted invoice. If the invoice is already
|
||||||
settled, this call will succeed.
|
settled, this call will succeed.
|
||||||
*/
|
*/
|
||||||
rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp);
|
rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced
|
LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced
|
||||||
using either its payment hash, payment address, or set ID.
|
using either its payment hash, payment address, or set ID.
|
||||||
*/
|
*/
|
||||||
rpc LookupInvoiceV2 (LookupInvoiceMsg) returns (lnrpc.Invoice);
|
rpc LookupInvoiceV2 (LookupInvoiceMsg) returns (lnrpc.Invoice);
|
||||||
|
|
||||||
|
/*
|
||||||
|
HtlcModifier is a bidirectional streaming RPC that allows a client to
|
||||||
|
intercept and modify the HTLCs that attempt to settle the given invoice. The
|
||||||
|
server will send HTLCs of invoices to the client and the client can modify
|
||||||
|
some aspects of the HTLC in order to pass the invoice acceptance tests.
|
||||||
|
*/
|
||||||
|
rpc HtlcModifier (stream HtlcModifyResponse)
|
||||||
|
returns (stream HtlcModifyRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
message CancelInvoiceMsg {
|
message CancelInvoiceMsg {
|
||||||
|
|
@ -84,7 +111,7 @@ message AddHoldInvoiceRequest {
|
||||||
*/
|
*/
|
||||||
bytes description_hash = 4;
|
bytes description_hash = 4;
|
||||||
|
|
||||||
// Payment request expiry time in seconds. Default is 3600 (1 hour).
|
// Payment request expiry time in seconds. Default is 86400 (24 hours).
|
||||||
int64 expiry = 5;
|
int64 expiry = 5;
|
||||||
|
|
||||||
// Fallback on-chain address.
|
// Fallback on-chain address.
|
||||||
|
|
@ -120,8 +147,9 @@ message AddHoldInvoiceResp {
|
||||||
uint64 add_index = 2;
|
uint64 add_index = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The payment address of the generated invoice. This value should be used
|
The payment address of the generated invoice. This is also called
|
||||||
in all payments for this invoice as we require it for end to end
|
the payment secret in specifications (e.g. BOLT 11). This value should
|
||||||
|
be used in all payments for this invoice as we require it for end to end
|
||||||
security.
|
security.
|
||||||
*/
|
*/
|
||||||
bytes payment_addr = 3;
|
bytes payment_addr = 3;
|
||||||
|
|
@ -173,3 +201,51 @@ message LookupInvoiceMsg {
|
||||||
|
|
||||||
LookupModifier lookup_modifier = 4;
|
LookupModifier lookup_modifier = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CircuitKey is a unique identifier for an HTLC.
|
||||||
|
message CircuitKey {
|
||||||
|
// The id of the channel that the is part of this circuit.
|
||||||
|
uint64 chan_id = 1;
|
||||||
|
|
||||||
|
// The index of the incoming htlc in the incoming channel.
|
||||||
|
uint64 htlc_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HtlcModifyRequest {
|
||||||
|
// The invoice the intercepted HTLC is attempting to settle. The HTLCs in
|
||||||
|
// the invoice are only HTLCs that have already been accepted or settled,
|
||||||
|
// not including the current intercepted HTLC.
|
||||||
|
lnrpc.Invoice invoice = 1;
|
||||||
|
|
||||||
|
// The unique identifier of the HTLC of this intercepted HTLC.
|
||||||
|
CircuitKey exit_htlc_circuit_key = 2;
|
||||||
|
|
||||||
|
// The amount in milli-satoshi that the exit HTLC is attempting to pay.
|
||||||
|
uint64 exit_htlc_amt = 3;
|
||||||
|
|
||||||
|
// The absolute expiry height of the exit HTLC.
|
||||||
|
uint32 exit_htlc_expiry = 4;
|
||||||
|
|
||||||
|
// The current block height.
|
||||||
|
uint32 current_height = 5;
|
||||||
|
|
||||||
|
// The wire message custom records of the exit HTLC.
|
||||||
|
map<uint64, bytes> exit_htlc_wire_custom_records = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HtlcModifyResponse {
|
||||||
|
// The circuit key of the HTLC that the client wants to modify.
|
||||||
|
CircuitKey circuit_key = 1;
|
||||||
|
|
||||||
|
// The modified amount in milli-satoshi that the exit HTLC is paying. This
|
||||||
|
// value can be different from the actual on-chain HTLC amount, in case the
|
||||||
|
// HTLC carries other valuable items, as can be the case with custom channel
|
||||||
|
// types.
|
||||||
|
optional uint64 amt_paid = 2;
|
||||||
|
|
||||||
|
// This flag indicates whether the HTLCs associated with the invoices should
|
||||||
|
// be cancelled. The interceptor client may set this field if some
|
||||||
|
// unexpected behavior is encountered. Setting this will ignore the amt_paid
|
||||||
|
// field.
|
||||||
|
bool cancel_set = 3;
|
||||||
|
}
|
||||||
|
|
@ -274,12 +274,14 @@ service Lightning {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SendPaymentSync is the synchronous non-streaming version of SendPayment.
|
Deprecated, use routerrpc.SendPaymentV2. SendPaymentSync is the synchronous
|
||||||
This RPC is intended to be consumed by clients of the REST proxy.
|
non-streaming version of SendPayment. This RPC is intended to be consumed by
|
||||||
Additionally, this RPC expects the destination's public key and the payment
|
clients of the REST proxy. Additionally, this RPC expects the destination's
|
||||||
hash (if any) to be encoded as hex strings.
|
public key and the payment hash (if any) to be encoded as hex strings.
|
||||||
*/
|
*/
|
||||||
rpc SendPaymentSync (SendRequest) returns (SendResponse);
|
rpc SendPaymentSync (SendRequest) returns (SendResponse) {
|
||||||
|
option deprecated = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* lncli: `sendtoroute`
|
/* lncli: `sendtoroute`
|
||||||
Deprecated, use routerrpc.SendToRouteV2. SendToRoute is a bi-directional
|
Deprecated, use routerrpc.SendToRouteV2. SendToRoute is a bi-directional
|
||||||
|
|
@ -293,10 +295,13 @@ service Lightning {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SendToRouteSync is a synchronous version of SendToRoute. It Will block
|
Deprecated, use routerrpc.SendToRouteV2. SendToRouteSync is a synchronous
|
||||||
until the payment either fails or succeeds.
|
version of SendToRoute. It Will block until the payment either fails or
|
||||||
|
succeeds.
|
||||||
*/
|
*/
|
||||||
rpc SendToRouteSync (SendToRouteRequest) returns (SendResponse);
|
rpc SendToRouteSync (SendToRouteRequest) returns (SendResponse) {
|
||||||
|
option deprecated = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* lncli: `addinvoice`
|
/* lncli: `addinvoice`
|
||||||
AddInvoice attempts to add a new invoice to the invoice database. Any
|
AddInvoice attempts to add a new invoice to the invoice database. Any
|
||||||
|
|
@ -643,6 +648,8 @@ message SendCustomMessageRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message SendCustomMessageResponse {
|
message SendCustomMessageResponse {
|
||||||
|
// The status of the send operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Utxo {
|
message Utxo {
|
||||||
|
|
@ -755,11 +762,35 @@ message GetTransactionsRequest {
|
||||||
|
|
||||||
// An optional filter to only include transactions relevant to an account.
|
// An optional filter to only include transactions relevant to an account.
|
||||||
string account = 3;
|
string account = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The index of a transaction that will be used in a query to determine which
|
||||||
|
transaction should be returned in the response.
|
||||||
|
*/
|
||||||
|
uint32 index_offset = 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The maximal number of transactions returned in the response to this query.
|
||||||
|
This value should be set to 0 to return all transactions.
|
||||||
|
*/
|
||||||
|
uint32 max_transactions = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TransactionDetails {
|
message TransactionDetails {
|
||||||
// The list of transactions relevant to the wallet.
|
// The list of transactions relevant to the wallet.
|
||||||
repeated Transaction transactions = 1;
|
repeated Transaction transactions = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The index of the last item in the set of returned transactions. This can be
|
||||||
|
used to seek further, pagination style.
|
||||||
|
*/
|
||||||
|
uint64 last_index = 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The index of the last item in the set of returned transactions. This can be
|
||||||
|
used to seek backwards, pagination style.
|
||||||
|
*/
|
||||||
|
uint64 first_index = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FeeLimit {
|
message FeeLimit {
|
||||||
|
|
@ -1317,6 +1348,8 @@ message ConnectPeerRequest {
|
||||||
uint64 timeout = 3;
|
uint64 timeout = 3;
|
||||||
}
|
}
|
||||||
message ConnectPeerResponse {
|
message ConnectPeerResponse {
|
||||||
|
// The status of the connect operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DisconnectPeerRequest {
|
message DisconnectPeerRequest {
|
||||||
|
|
@ -1324,6 +1357,8 @@ message DisconnectPeerRequest {
|
||||||
string pub_key = 1;
|
string pub_key = 1;
|
||||||
}
|
}
|
||||||
message DisconnectPeerResponse {
|
message DisconnectPeerResponse {
|
||||||
|
// The status of the disconnect operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message HTLC {
|
message HTLC {
|
||||||
|
|
@ -1346,6 +1381,13 @@ message HTLC {
|
||||||
|
|
||||||
// Index identifying the htlc on the forwarding channel.
|
// Index identifying the htlc on the forwarding channel.
|
||||||
uint64 forwarding_htlc_index = 7;
|
uint64 forwarding_htlc_index = 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Whether the HTLC is locked in. An HTLC is considered locked in when the
|
||||||
|
remote party has sent us the `revoke_and_ack` to irrevocably commit this
|
||||||
|
HTLC.
|
||||||
|
*/
|
||||||
|
bool locked_in = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CommitmentType {
|
enum CommitmentType {
|
||||||
|
|
@ -1388,8 +1430,14 @@ enum CommitmentType {
|
||||||
A channel that uses musig2 for the funding output, and the new tapscript
|
A channel that uses musig2 for the funding output, and the new tapscript
|
||||||
features where relevant.
|
features where relevant.
|
||||||
*/
|
*/
|
||||||
// TODO(roasbeef): need script enforce mirror type for the above as well?
|
|
||||||
SIMPLE_TAPROOT = 5;
|
SIMPLE_TAPROOT = 5;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Identical to the SIMPLE_TAPROOT channel type, but with extra functionality.
|
||||||
|
This channel type also commits to additional meta data in the tapscript
|
||||||
|
leaves for the scripts in a channel.
|
||||||
|
*/
|
||||||
|
SIMPLE_TAPROOT_OVERLAY = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ChannelConstraints {
|
message ChannelConstraints {
|
||||||
|
|
@ -1592,6 +1640,11 @@ message Channel {
|
||||||
the channel's operation.
|
the channel's operation.
|
||||||
*/
|
*/
|
||||||
string memo = 36;
|
string memo = 36;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Custom channel data that might be populated in custom channels.
|
||||||
|
*/
|
||||||
|
bytes custom_channel_data = 37;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListChannelsRequest {
|
message ListChannelsRequest {
|
||||||
|
|
@ -1705,6 +1758,10 @@ message ChannelCloseSummary {
|
||||||
|
|
||||||
// The confirmed SCID for a zero-conf channel.
|
// The confirmed SCID for a zero-conf channel.
|
||||||
uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING];
|
uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING];
|
||||||
|
|
||||||
|
// The TLV encoded custom channel data records for this output, which might
|
||||||
|
// be set for custom channels.
|
||||||
|
bytes custom_channel_data = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ResolutionType {
|
enum ResolutionType {
|
||||||
|
|
@ -1955,8 +2012,8 @@ message GetInfoResponse {
|
||||||
bool synced_to_graph = 18;
|
bool synced_to_graph = 18;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Whether the current node is connected to testnet. This field is
|
Whether the current node is connected to testnet or testnet4. This field is
|
||||||
deprecated and the network field should be used instead
|
deprecated and the network field should be used instead.
|
||||||
*/
|
*/
|
||||||
bool testnet = 10 [deprecated = true];
|
bool testnet = 10 [deprecated = true];
|
||||||
|
|
||||||
|
|
@ -2028,10 +2085,38 @@ message ChannelOpenUpdate {
|
||||||
ChannelPoint channel_point = 1;
|
ChannelPoint channel_point = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message CloseOutput {
|
||||||
|
// The amount in satoshi of this close output. This amount is the final
|
||||||
|
// commitment balance of the channel and the actual amount paid out on chain
|
||||||
|
// might be smaller due to subtracted fees.
|
||||||
|
int64 amount_sat = 1;
|
||||||
|
|
||||||
|
// The pkScript of the close output.
|
||||||
|
bytes pk_script = 2;
|
||||||
|
|
||||||
|
// Whether this output is for the local or remote node.
|
||||||
|
bool is_local = 3;
|
||||||
|
|
||||||
|
// The TLV encoded custom channel data records for this output, which might
|
||||||
|
// be set for custom channels.
|
||||||
|
bytes custom_channel_data = 4;
|
||||||
|
}
|
||||||
|
|
||||||
message ChannelCloseUpdate {
|
message ChannelCloseUpdate {
|
||||||
bytes closing_txid = 1;
|
bytes closing_txid = 1;
|
||||||
|
|
||||||
bool success = 2;
|
bool success = 2;
|
||||||
|
|
||||||
|
// The local channel close output. If the local channel balance was dust to
|
||||||
|
// begin with, this output will not be set.
|
||||||
|
CloseOutput local_close_output = 3;
|
||||||
|
|
||||||
|
// The remote channel close output. If the remote channel balance was dust
|
||||||
|
// to begin with, this output will not be set.
|
||||||
|
CloseOutput remote_close_output = 4;
|
||||||
|
|
||||||
|
// Any additional outputs that might be added for custom channel types.
|
||||||
|
repeated CloseOutput additional_outputs = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CloseChannelRequest {
|
message CloseChannelRequest {
|
||||||
|
|
@ -2072,9 +2157,13 @@ message CloseChannelRequest {
|
||||||
// NOTE: This field is only respected if we're the initiator of the channel.
|
// NOTE: This field is only respected if we're the initiator of the channel.
|
||||||
uint64 max_fee_per_vbyte = 7;
|
uint64 max_fee_per_vbyte = 7;
|
||||||
|
|
||||||
// If true, then the rpc call will not block while it awaits a closing txid.
|
// If true, then the rpc call will not block while it awaits a closing txid
|
||||||
// Consequently this RPC call will not return a closing txid if this value
|
// to be broadcasted to the mempool. To obtain the closing tx one has to
|
||||||
// is set.
|
// listen to the stream for the particular updates. Moreover if a coop close
|
||||||
|
// is specified and this flag is set to true the coop closing flow will be
|
||||||
|
// initiated even if HTLCs are active on the channel. The channel will wait
|
||||||
|
// until all HTLCs are resolved and then start the coop closing process. The
|
||||||
|
// channel will be disabled in the meantime and will disallow any new HTLCs.
|
||||||
bool no_wait = 8;
|
bool no_wait = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2089,9 +2178,15 @@ message CloseStatusUpdate {
|
||||||
message PendingUpdate {
|
message PendingUpdate {
|
||||||
bytes txid = 1;
|
bytes txid = 1;
|
||||||
uint32 output_index = 2;
|
uint32 output_index = 2;
|
||||||
|
int64 fee_per_vbyte = 3;
|
||||||
|
bool local_close_tx = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message InstantUpdate {
|
message InstantUpdate {
|
||||||
|
// The number of pending HTLCs that are currently active on the channel.
|
||||||
|
// These HTLCs need to be resolved before the channel can be closed
|
||||||
|
// cooperatively.
|
||||||
|
int32 num_pending_htlcs = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ReadyForPsbtFunding {
|
message ReadyForPsbtFunding {
|
||||||
|
|
@ -2709,6 +2804,11 @@ message PendingChannelsResponse {
|
||||||
impacts the channel's operation.
|
impacts the channel's operation.
|
||||||
*/
|
*/
|
||||||
string memo = 13;
|
string memo = 13;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Custom channel data that might be populated in custom channels.
|
||||||
|
*/
|
||||||
|
bytes custom_channel_data = 34;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PendingOpenChannel {
|
message PendingOpenChannel {
|
||||||
|
|
@ -2880,6 +2980,7 @@ message ChannelEventUpdate {
|
||||||
ChannelPoint inactive_channel = 4;
|
ChannelPoint inactive_channel = 4;
|
||||||
PendingUpdate pending_open_channel = 6;
|
PendingUpdate pending_open_channel = 6;
|
||||||
ChannelPoint fully_resolved_channel = 7;
|
ChannelPoint fully_resolved_channel = 7;
|
||||||
|
ChannelPoint channel_funding_timeout = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpdateType {
|
enum UpdateType {
|
||||||
|
|
@ -2889,6 +2990,7 @@ message ChannelEventUpdate {
|
||||||
INACTIVE_CHANNEL = 3;
|
INACTIVE_CHANNEL = 3;
|
||||||
PENDING_OPEN_CHANNEL = 4;
|
PENDING_OPEN_CHANNEL = 4;
|
||||||
FULLY_RESOLVED_CHANNEL = 5;
|
FULLY_RESOLVED_CHANNEL = 5;
|
||||||
|
CHANNEL_FUNDING_TIMEOUT = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateType type = 5;
|
UpdateType type = 5;
|
||||||
|
|
@ -2968,6 +3070,12 @@ message ChannelBalanceResponse {
|
||||||
|
|
||||||
// Sum of channels pending remote balances.
|
// Sum of channels pending remote balances.
|
||||||
Amount pending_open_remote_balance = 8;
|
Amount pending_open_remote_balance = 8;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Custom channel data that might be populated if there are custom channels
|
||||||
|
present.
|
||||||
|
*/
|
||||||
|
bytes custom_channel_data = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
message QueryRoutesRequest {
|
message QueryRoutesRequest {
|
||||||
|
|
@ -3293,6 +3401,20 @@ message Route {
|
||||||
The total amount in millisatoshis.
|
The total amount in millisatoshis.
|
||||||
*/
|
*/
|
||||||
int64 total_amt_msat = 6;
|
int64 total_amt_msat = 6;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The actual on-chain amount that was sent out to the first hop. This value is
|
||||||
|
only different from the total_amt_msat field if this is a custom channel
|
||||||
|
payment and the value transported in the HTLC is different from the BTC
|
||||||
|
amount in the HTLC. If this value is zero, then this is an old payment that
|
||||||
|
didn't have this value yet and can be ignored.
|
||||||
|
*/
|
||||||
|
int64 first_hop_amount_msat = 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Custom channel data that might be populated in custom channels.
|
||||||
|
*/
|
||||||
|
bytes custom_channel_data = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NodeInfoRequest {
|
message NodeInfoRequest {
|
||||||
|
|
@ -3478,6 +3600,8 @@ message NetworkInfo {
|
||||||
message StopRequest {
|
message StopRequest {
|
||||||
}
|
}
|
||||||
message StopResponse {
|
message StopResponse {
|
||||||
|
// The status of the stop operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GraphTopologySubscription {
|
message GraphTopologySubscription {
|
||||||
|
|
@ -3922,6 +4046,11 @@ message InvoiceHTLC {
|
||||||
|
|
||||||
// Details relevant to AMP HTLCs, only populated if this is an AMP HTLC.
|
// Details relevant to AMP HTLCs, only populated if this is an AMP HTLC.
|
||||||
AMP amp = 11;
|
AMP amp = 11;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Custom channel data that might be populated in custom channels.
|
||||||
|
*/
|
||||||
|
bytes custom_channel_data = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Details specific to AMP HTLCs.
|
// Details specific to AMP HTLCs.
|
||||||
|
|
@ -4162,6 +4291,12 @@ message Payment {
|
||||||
uint64 payment_index = 15;
|
uint64 payment_index = 15;
|
||||||
|
|
||||||
PaymentFailureReason failure_reason = 16;
|
PaymentFailureReason failure_reason = 16;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The custom TLV records that were sent to the first hop as part of the HTLC
|
||||||
|
wire message for this payment.
|
||||||
|
*/
|
||||||
|
map<uint64, bytes> first_hop_custom_records = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
message HTLCAttempt {
|
message HTLCAttempt {
|
||||||
|
|
@ -4291,9 +4426,13 @@ message DeleteAllPaymentsRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeletePaymentResponse {
|
message DeletePaymentResponse {
|
||||||
|
// The status of the delete operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeleteAllPaymentsResponse {
|
message DeleteAllPaymentsResponse {
|
||||||
|
// The status of the delete operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AbandonChannelRequest {
|
message AbandonChannelRequest {
|
||||||
|
|
@ -4310,6 +4449,8 @@ message AbandonChannelRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message AbandonChannelResponse {
|
message AbandonChannelResponse {
|
||||||
|
// The status of the abandon operation.
|
||||||
|
string status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DebugLevelRequest {
|
message DebugLevelRequest {
|
||||||
|
|
@ -4469,6 +4610,15 @@ message PolicyUpdateRequest {
|
||||||
// Optional inbound fee. If unset, the previously set value will be
|
// Optional inbound fee. If unset, the previously set value will be
|
||||||
// retained [EXPERIMENTAL].
|
// retained [EXPERIMENTAL].
|
||||||
InboundFee inbound_fee = 10;
|
InboundFee inbound_fee = 10;
|
||||||
|
|
||||||
|
// Under unknown circumstances a channel can exist with a missing edge in
|
||||||
|
// the graph database. This can cause an 'edge not found' error when calling
|
||||||
|
// `getchaninfo` and/or cause the default channel policy to be used during
|
||||||
|
// forwards. Setting this flag will recreate the edge if not found, allowing
|
||||||
|
// updating this channel policy and fixing the missing edge problem for this
|
||||||
|
// channel permanently. For fields not set in this command, the default
|
||||||
|
// policy will be created.
|
||||||
|
bool create_missing_edge = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpdateFailure {
|
enum UpdateFailure {
|
||||||
|
|
@ -4562,6 +4712,14 @@ message ForwardingEvent {
|
||||||
// The peer alias of the outgoing channel.
|
// The peer alias of the outgoing channel.
|
||||||
string peer_alias_out = 13;
|
string peer_alias_out = 13;
|
||||||
|
|
||||||
|
// The ID of the incoming HTLC in the payment circuit. This field is
|
||||||
|
// optional and is unset for forwarding events happened before v0.20.
|
||||||
|
optional uint64 incoming_htlc_id = 14;
|
||||||
|
|
||||||
|
// The ID of the outgoing HTLC in the payment circuit. This field is
|
||||||
|
// optional and may be unset for legacy forwarding events.
|
||||||
|
optional uint64 outgoing_htlc_id = 15;
|
||||||
|
|
||||||
// TODO(roasbeef): add settlement latency?
|
// TODO(roasbeef): add settlement latency?
|
||||||
// * use FPE on the chan id?
|
// * use FPE on the chan id?
|
||||||
// * also list failures?
|
// * also list failures?
|
||||||
|
|
@ -4649,12 +4807,15 @@ message RestoreChanBackupRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message RestoreBackupResponse {
|
message RestoreBackupResponse {
|
||||||
|
// The number of channels successfully restored.
|
||||||
|
uint32 num_restored = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ChannelBackupSubscription {
|
message ChannelBackupSubscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
message VerifyChanBackupResponse {
|
message VerifyChanBackupResponse {
|
||||||
|
repeated string chan_points = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MacaroonPermission {
|
message MacaroonPermission {
|
||||||
|
|
@ -4977,6 +5138,22 @@ message RPCMiddlewareRequest {
|
||||||
intercept message.
|
intercept message.
|
||||||
*/
|
*/
|
||||||
uint64 msg_id = 7;
|
uint64 msg_id = 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The metadata pairs that were sent along with the original gRPC request via
|
||||||
|
the golang context.Context using explicit [gRPC
|
||||||
|
metadata](https://grpc.io/docs/guides/metadata/). Context values are not
|
||||||
|
propagated via gRPC and so we send any pairs along explicitly here so that
|
||||||
|
the interceptor can access them.
|
||||||
|
*/
|
||||||
|
map<string, MetadataValues> metadata_pairs = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MetadataValues {
|
||||||
|
/*
|
||||||
|
The set of metadata values that correspond to the metadata key.
|
||||||
|
*/
|
||||||
|
repeated string values = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StreamAuth {
|
message StreamAuth {
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,43 @@
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "lightning.proto";
|
|
||||||
|
|
||||||
package routerrpc;
|
package routerrpc;
|
||||||
|
|
||||||
|
import "lightning.proto";
|
||||||
|
|
||||||
option go_package = "github.com/lightningnetwork/lnd/lnrpc/routerrpc";
|
option go_package = "github.com/lightningnetwork/lnd/lnrpc/routerrpc";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Comments in this file will be directly parsed into the API
|
||||||
|
* Documentation as descriptions of the associated method, message, or field.
|
||||||
|
* These descriptions should go right above the definition of the object, and
|
||||||
|
* can be in either block or // comment format.
|
||||||
|
*
|
||||||
|
* An RPC method can be matched to an lncli command by placing a line in the
|
||||||
|
* beginning of the description in exactly the following format:
|
||||||
|
* lncli: `methodname`
|
||||||
|
*
|
||||||
|
* Failure to specify the exact name of the command will cause documentation
|
||||||
|
* generation to fail.
|
||||||
|
*
|
||||||
|
* More information on how exactly the gRPC documentation is generated from
|
||||||
|
* this proto file can be found here:
|
||||||
|
* https://github.com/lightninglabs/lightning-api
|
||||||
|
*/
|
||||||
|
|
||||||
// Router is a service that offers advanced interaction with the router
|
// Router is a service that offers advanced interaction with the router
|
||||||
// subsystem of the daemon.
|
// subsystem of the daemon.
|
||||||
service Router {
|
service Router {
|
||||||
/*
|
/*
|
||||||
SendPaymentV2 attempts to route a payment described by the passed
|
SendPaymentV2 attempts to route a payment described by the passed
|
||||||
PaymentRequest to the final destination. The call returns a stream of
|
PaymentRequest to the final destination. The call returns a stream of
|
||||||
payment updates.
|
payment updates. When using this RPC, make sure to set a fee limit, as the
|
||||||
|
default routing fee limit is 0 sats. Without a non-zero fee limit only
|
||||||
|
routes without fees will be attempted which often fails with
|
||||||
|
FAILURE_REASON_NO_ROUTE.
|
||||||
*/
|
*/
|
||||||
rpc SendPaymentV2 (SendPaymentRequest) returns (stream lnrpc.Payment);
|
rpc SendPaymentV2 (SendPaymentRequest) returns (stream lnrpc.Payment);
|
||||||
|
|
||||||
/*
|
/* lncli: `trackpayment`
|
||||||
TrackPaymentV2 returns an update stream for the payment identified by the
|
TrackPaymentV2 returns an update stream for the payment identified by the
|
||||||
payment hash.
|
payment hash.
|
||||||
*/
|
*/
|
||||||
|
|
@ -57,21 +78,21 @@ service Router {
|
||||||
*/
|
*/
|
||||||
rpc SendToRouteV2 (SendToRouteRequest) returns (lnrpc.HTLCAttempt);
|
rpc SendToRouteV2 (SendToRouteRequest) returns (lnrpc.HTLCAttempt);
|
||||||
|
|
||||||
/*
|
/* lncli: `resetmc`
|
||||||
ResetMissionControl clears all mission control state and starts with a clean
|
ResetMissionControl clears all mission control state and starts with a clean
|
||||||
slate.
|
slate.
|
||||||
*/
|
*/
|
||||||
rpc ResetMissionControl (ResetMissionControlRequest)
|
rpc ResetMissionControl (ResetMissionControlRequest)
|
||||||
returns (ResetMissionControlResponse);
|
returns (ResetMissionControlResponse);
|
||||||
|
|
||||||
/*
|
/* lncli: `querymc`
|
||||||
QueryMissionControl exposes the internal mission control state to callers.
|
QueryMissionControl exposes the internal mission control state to callers.
|
||||||
It is a development feature.
|
It is a development feature.
|
||||||
*/
|
*/
|
||||||
rpc QueryMissionControl (QueryMissionControlRequest)
|
rpc QueryMissionControl (QueryMissionControlRequest)
|
||||||
returns (QueryMissionControlResponse);
|
returns (QueryMissionControlResponse);
|
||||||
|
|
||||||
/*
|
/* lncli: `importmc`
|
||||||
XImportMissionControl is an experimental API that imports the state provided
|
XImportMissionControl is an experimental API that imports the state provided
|
||||||
to the internal mission control's state, using all results which are more
|
to the internal mission control's state, using all results which are more
|
||||||
recent than our existing values. These values will only be imported
|
recent than our existing values. These values will only be imported
|
||||||
|
|
@ -80,30 +101,36 @@ service Router {
|
||||||
rpc XImportMissionControl (XImportMissionControlRequest)
|
rpc XImportMissionControl (XImportMissionControlRequest)
|
||||||
returns (XImportMissionControlResponse);
|
returns (XImportMissionControlResponse);
|
||||||
|
|
||||||
/*
|
/* lncli: `getmccfg`
|
||||||
GetMissionControlConfig returns mission control's current config.
|
GetMissionControlConfig returns mission control's current config.
|
||||||
*/
|
*/
|
||||||
rpc GetMissionControlConfig (GetMissionControlConfigRequest)
|
rpc GetMissionControlConfig (GetMissionControlConfigRequest)
|
||||||
returns (GetMissionControlConfigResponse);
|
returns (GetMissionControlConfigResponse);
|
||||||
|
|
||||||
/*
|
/* lncli: `setmccfg`
|
||||||
SetMissionControlConfig will set mission control's config, if the config
|
SetMissionControlConfig will set mission control's config, if the config
|
||||||
provided is valid.
|
provided is valid.
|
||||||
*/
|
*/
|
||||||
rpc SetMissionControlConfig (SetMissionControlConfigRequest)
|
rpc SetMissionControlConfig (SetMissionControlConfigRequest)
|
||||||
returns (SetMissionControlConfigResponse);
|
returns (SetMissionControlConfigResponse);
|
||||||
|
|
||||||
/*
|
/* lncli: `queryprob`
|
||||||
QueryProbability returns the current success probability estimate for a
|
Deprecated. QueryProbability returns the current success probability
|
||||||
given node pair and amount.
|
estimate for a given node pair and amount. The call returns a zero success
|
||||||
|
probability if no channel is available or if the amount violates min/max
|
||||||
|
HTLC constraints.
|
||||||
*/
|
*/
|
||||||
rpc QueryProbability (QueryProbabilityRequest)
|
rpc QueryProbability (QueryProbabilityRequest)
|
||||||
returns (QueryProbabilityResponse);
|
returns (QueryProbabilityResponse);
|
||||||
|
|
||||||
/*
|
/* lncli: `buildroute`
|
||||||
BuildRoute builds a fully specified route based on a list of hop public
|
BuildRoute builds a fully specified route based on a list of hop public
|
||||||
keys. It retrieves the relevant channel policies from the graph in order to
|
keys. It retrieves the relevant channel policies from the graph in order to
|
||||||
calculate the correct fees and time locks.
|
calculate the correct fees and time locks.
|
||||||
|
Note that LND will use its default final_cltv_delta if no value is supplied.
|
||||||
|
Make sure to add the correct final_cltv_delta depending on the invoice
|
||||||
|
restriction. Moreover the caller has to make sure to provide the
|
||||||
|
payment_addr if the route is paying an invoice which signaled it.
|
||||||
*/
|
*/
|
||||||
rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse);
|
rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse);
|
||||||
|
|
||||||
|
|
@ -141,7 +168,7 @@ service Router {
|
||||||
rpc HtlcInterceptor (stream ForwardHtlcInterceptResponse)
|
rpc HtlcInterceptor (stream ForwardHtlcInterceptResponse)
|
||||||
returns (stream ForwardHtlcInterceptRequest);
|
returns (stream ForwardHtlcInterceptRequest);
|
||||||
|
|
||||||
/*
|
/* lncli: `updatechanstatus`
|
||||||
UpdateChanStatus attempts to manually set the state of a channel
|
UpdateChanStatus attempts to manually set the state of a channel
|
||||||
(enabled, disabled, or auto). A manual "disable" request will cause the
|
(enabled, disabled, or auto). A manual "disable" request will cause the
|
||||||
channel to stay disabled until a subsequent manual request of either
|
channel to stay disabled until a subsequent manual request of either
|
||||||
|
|
@ -149,6 +176,25 @@ service Router {
|
||||||
*/
|
*/
|
||||||
rpc UpdateChanStatus (UpdateChanStatusRequest)
|
rpc UpdateChanStatus (UpdateChanStatusRequest)
|
||||||
returns (UpdateChanStatusResponse);
|
returns (UpdateChanStatusResponse);
|
||||||
|
|
||||||
|
/*
|
||||||
|
XAddLocalChanAliases is an experimental API that creates a set of new
|
||||||
|
channel SCID alias mappings. The final total set of aliases in the manager
|
||||||
|
after the add operation is returned. This is only a locally stored alias,
|
||||||
|
and will not be communicated to the channel peer via any message. Therefore,
|
||||||
|
routing over such an alias will only work if the peer also calls this same
|
||||||
|
RPC on their end. If an alias already exists, an error is returned
|
||||||
|
*/
|
||||||
|
rpc XAddLocalChanAliases (AddAliasesRequest) returns (AddAliasesResponse);
|
||||||
|
|
||||||
|
/*
|
||||||
|
XDeleteLocalChanAliases is an experimental API that deletes a set of alias
|
||||||
|
mappings. The final total set of aliases in the manager after the delete
|
||||||
|
operation is returned. The deletion will not be communicated to the channel
|
||||||
|
peer via any message.
|
||||||
|
*/
|
||||||
|
rpc XDeleteLocalChanAliases (DeleteAliasesRequest)
|
||||||
|
returns (DeleteAliasesResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
message SendPaymentRequest {
|
message SendPaymentRequest {
|
||||||
|
|
@ -162,13 +208,6 @@ message SendPaymentRequest {
|
||||||
*/
|
*/
|
||||||
int64 amt = 2;
|
int64 amt = 2;
|
||||||
|
|
||||||
/*
|
|
||||||
Number of millisatoshis to send.
|
|
||||||
|
|
||||||
The fields amt and amt_msat are mutually exclusive.
|
|
||||||
*/
|
|
||||||
int64 amt_msat = 12;
|
|
||||||
|
|
||||||
// The hash to use within the payment's HTLC
|
// The hash to use within the payment's HTLC
|
||||||
bytes payment_hash = 3;
|
bytes payment_hash = 3;
|
||||||
|
|
||||||
|
|
@ -178,9 +217,6 @@ message SendPaymentRequest {
|
||||||
*/
|
*/
|
||||||
int32 final_cltv_delta = 4;
|
int32 final_cltv_delta = 4;
|
||||||
|
|
||||||
// An optional payment addr to be included within the last hop of the route.
|
|
||||||
bytes payment_addr = 20;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A bare-bones invoice for a payment within the Lightning Network. With the
|
A bare-bones invoice for a payment within the Lightning Network. With the
|
||||||
details of the invoice, the sender has all the data necessary to send a
|
details of the invoice, the sender has all the data necessary to send a
|
||||||
|
|
@ -191,10 +227,11 @@ message SendPaymentRequest {
|
||||||
string payment_request = 5;
|
string payment_request = 5;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An upper limit on the amount of time we should spend when attempting to
|
An optional limit, expressed in seconds, on the time to wait before
|
||||||
fulfill the payment. This is expressed in seconds. If we cannot make a
|
attempting the first HTLC. Once HTLCs are in flight, the payment will
|
||||||
successful payment within this time frame, an error will be returned.
|
not be aborted until the HTLCs are either settled or failed. If the field
|
||||||
This field must be non-zero.
|
is not set or is explicitly set to zero, the default value of 60 seconds
|
||||||
|
will be applied.
|
||||||
*/
|
*/
|
||||||
int32 timeout_seconds = 6;
|
int32 timeout_seconds = 6;
|
||||||
|
|
||||||
|
|
@ -208,17 +245,6 @@ message SendPaymentRequest {
|
||||||
*/
|
*/
|
||||||
int64 fee_limit_sat = 7;
|
int64 fee_limit_sat = 7;
|
||||||
|
|
||||||
/*
|
|
||||||
The maximum number of millisatoshis that will be paid as a fee of the
|
|
||||||
payment. If this field is left to the default value of 0, only zero-fee
|
|
||||||
routes will be considered. This usually means single hop routes connecting
|
|
||||||
directly to the destination. To send the payment without a fee limit, use
|
|
||||||
max int here.
|
|
||||||
|
|
||||||
The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
|
|
||||||
*/
|
|
||||||
int64 fee_limit_msat = 13;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Deprecated, use outgoing_chan_ids. The channel id of the channel that must
|
Deprecated, use outgoing_chan_ids. The channel id of the channel that must
|
||||||
be taken to the first hop. If zero, any channel may be used (unless
|
be taken to the first hop. If zero, any channel may be used (unless
|
||||||
|
|
@ -227,19 +253,8 @@ message SendPaymentRequest {
|
||||||
uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true];
|
uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The channel ids of the channels are allowed for the first hop. If empty,
|
An optional maximum total time lock for the route. This should not
|
||||||
any channel may be used.
|
exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of
|
||||||
*/
|
|
||||||
repeated uint64 outgoing_chan_ids = 19;
|
|
||||||
|
|
||||||
/*
|
|
||||||
The pubkey of the last hop of the route. If empty, any hop may be used.
|
|
||||||
*/
|
|
||||||
bytes last_hop_pubkey = 14;
|
|
||||||
|
|
||||||
/*
|
|
||||||
An optional maximum total time lock for the route. This should not exceed
|
|
||||||
lnd's `--max-cltv-expiry` setting. If zero, then the value of
|
|
||||||
`--max-cltv-expiry` is enforced.
|
`--max-cltv-expiry` is enforced.
|
||||||
*/
|
*/
|
||||||
int32 cltv_limit = 9;
|
int32 cltv_limit = 9;
|
||||||
|
|
@ -258,6 +273,29 @@ message SendPaymentRequest {
|
||||||
*/
|
*/
|
||||||
map<uint64, bytes> dest_custom_records = 11;
|
map<uint64, bytes> dest_custom_records = 11;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Number of millisatoshis to send.
|
||||||
|
|
||||||
|
The fields amt and amt_msat are mutually exclusive.
|
||||||
|
*/
|
||||||
|
int64 amt_msat = 12;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The maximum number of millisatoshis that will be paid as a fee of the
|
||||||
|
payment. If this field is left to the default value of 0, only zero-fee
|
||||||
|
routes will be considered. This usually means single hop routes connecting
|
||||||
|
directly to the destination. To send the payment without a fee limit, use
|
||||||
|
max int here.
|
||||||
|
|
||||||
|
The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
|
||||||
|
*/
|
||||||
|
int64 fee_limit_msat = 13;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The pubkey of the last hop of the route. If empty, any hop may be used.
|
||||||
|
*/
|
||||||
|
bytes last_hop_pubkey = 14;
|
||||||
|
|
||||||
// If set, circular payments to self are permitted.
|
// If set, circular payments to self are permitted.
|
||||||
bool allow_self_payment = 15;
|
bool allow_self_payment = 15;
|
||||||
|
|
||||||
|
|
@ -282,6 +320,18 @@ message SendPaymentRequest {
|
||||||
*/
|
*/
|
||||||
bool no_inflight_updates = 18;
|
bool no_inflight_updates = 18;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The channel ids of the channels are allowed for the first hop. If empty,
|
||||||
|
any channel may be used.
|
||||||
|
*/
|
||||||
|
repeated uint64 outgoing_chan_ids = 19;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An optional payment addr to be included within the last hop of the route.
|
||||||
|
This is also called payment secret in specifications (e.g. BOLT 11).
|
||||||
|
*/
|
||||||
|
bytes payment_addr = 20;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The largest payment split that should be attempted when making a payment if
|
The largest payment split that should be attempted when making a payment if
|
||||||
splitting is necessary. Setting this value will effectively cause lnd to
|
splitting is necessary. Setting this value will effectively cause lnd to
|
||||||
|
|
@ -300,6 +350,24 @@ message SendPaymentRequest {
|
||||||
only, to 1 to optimize for reliability only or a value inbetween for a mix.
|
only, to 1 to optimize for reliability only or a value inbetween for a mix.
|
||||||
*/
|
*/
|
||||||
double time_pref = 23;
|
double time_pref = 23;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If set, the payment loop can be interrupted by manually canceling the
|
||||||
|
payment context, even before the payment timeout is reached. Note that the
|
||||||
|
payment may still succeed after cancellation, as in-flight attempts can
|
||||||
|
still settle afterwards. Canceling will only prevent further attempts from
|
||||||
|
being sent.
|
||||||
|
*/
|
||||||
|
bool cancelable = 24;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An optional field that can be used to pass an arbitrary set of TLV records
|
||||||
|
to the first hop peer of this payment. This can be used to pass application
|
||||||
|
specific data during the payment attempt. Record types are required to be in
|
||||||
|
the custom range >= 65536. When using REST, the values must be encoded as
|
||||||
|
base64.
|
||||||
|
*/
|
||||||
|
map<uint64, bytes> first_hop_custom_records = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TrackPaymentRequest {
|
message TrackPaymentRequest {
|
||||||
|
|
@ -323,14 +391,39 @@ message TrackPaymentsRequest {
|
||||||
|
|
||||||
message RouteFeeRequest {
|
message RouteFeeRequest {
|
||||||
/*
|
/*
|
||||||
The destination once wishes to obtain a routing fee quote to.
|
The destination one wishes to obtain a routing fee quote to. If set, this
|
||||||
|
parameter requires the amt_sat parameter also to be set. This parameter
|
||||||
|
combination triggers a graph based routing fee estimation as opposed to a
|
||||||
|
payment probe based estimate in case a payment request is provided. The
|
||||||
|
graph based estimation is an algorithm that is executed on the in memory
|
||||||
|
graph. Hence its runtime is significantly shorter than a payment probe
|
||||||
|
estimation that sends out actual payments to the network.
|
||||||
*/
|
*/
|
||||||
bytes dest = 1;
|
bytes dest = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The amount one wishes to send to the target destination.
|
The amount one wishes to send to the target destination. It is only to be
|
||||||
|
used in combination with the dest parameter.
|
||||||
*/
|
*/
|
||||||
int64 amt_sat = 2;
|
int64 amt_sat = 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
A payment request of the target node that the route fee request is intended
|
||||||
|
for. Its parameters are input to probe payments that estimate routing fees.
|
||||||
|
The timeout parameter can be specified to set a maximum time on the probing
|
||||||
|
attempt. Cannot be used in combination with dest and amt_sat.
|
||||||
|
*/
|
||||||
|
string payment_request = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
A user preference of how long a probe payment should maximally be allowed to
|
||||||
|
take, denoted in seconds. The probing payment loop is aborted if this
|
||||||
|
timeout is reached. Note that the probing process itself can take longer
|
||||||
|
than the timeout if the HTLC becomes delayed or stuck. Canceling the context
|
||||||
|
of this call will not cancel the payment loop, the duration is only
|
||||||
|
controlled by the timeout parameter.
|
||||||
|
*/
|
||||||
|
uint32 timeout = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RouteFeeResponse {
|
message RouteFeeResponse {
|
||||||
|
|
@ -346,6 +439,12 @@ message RouteFeeResponse {
|
||||||
value.
|
value.
|
||||||
*/
|
*/
|
||||||
int64 time_lock_delay = 2;
|
int64 time_lock_delay = 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An indication whether a probing payment succeeded or whether and why it
|
||||||
|
failed. FAILURE_REASON_NONE indicates success.
|
||||||
|
*/
|
||||||
|
lnrpc.PaymentFailureReason failure_reason = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SendToRouteRequest {
|
message SendToRouteRequest {
|
||||||
|
|
@ -362,6 +461,15 @@ message SendToRouteRequest {
|
||||||
routes, incorrect payment details, or insufficient funds.
|
routes, incorrect payment details, or insufficient funds.
|
||||||
*/
|
*/
|
||||||
bool skip_temp_err = 3;
|
bool skip_temp_err = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An optional field that can be used to pass an arbitrary set of TLV records
|
||||||
|
to the first hop peer of this payment. This can be used to pass application
|
||||||
|
specific data during the payment attempt. Record types are required to be in
|
||||||
|
the custom range >= 65536. When using REST, the values must be encoded as
|
||||||
|
base64.
|
||||||
|
*/
|
||||||
|
map<uint64, bytes> first_hop_custom_records = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SendToRouteResponse {
|
message SendToRouteResponse {
|
||||||
|
|
@ -465,6 +573,93 @@ message SetMissionControlConfigResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
message MissionControlConfig {
|
message MissionControlConfig {
|
||||||
|
/*
|
||||||
|
Deprecated, use AprioriParameters. The amount of time mission control will
|
||||||
|
take to restore a penalized node or channel back to 50% success probability,
|
||||||
|
expressed in seconds. Setting this value to a higher value will penalize
|
||||||
|
failures for longer, making mission control less likely to route through
|
||||||
|
nodes and channels that we have previously recorded failures for.
|
||||||
|
*/
|
||||||
|
uint64 half_life_seconds = 1 [deprecated = true];
|
||||||
|
|
||||||
|
/*
|
||||||
|
Deprecated, use AprioriParameters. The probability of success mission
|
||||||
|
control should assign to hop in a route where it has no other information
|
||||||
|
available. Higher values will make mission control more willing to try hops
|
||||||
|
that we have no information about, lower values will discourage trying these
|
||||||
|
hops.
|
||||||
|
*/
|
||||||
|
float hop_probability = 2 [deprecated = true];
|
||||||
|
|
||||||
|
/*
|
||||||
|
Deprecated, use AprioriParameters. The importance that mission control
|
||||||
|
should place on historical results, expressed as a value in [0;1]. Setting
|
||||||
|
this value to 1 will ignore all historical payments and just use the hop
|
||||||
|
probability to assess the probability of success for each hop. A zero value
|
||||||
|
ignores hop probability completely and relies entirely on historical
|
||||||
|
results, unless none are available.
|
||||||
|
*/
|
||||||
|
float weight = 3 [deprecated = true];
|
||||||
|
|
||||||
|
/*
|
||||||
|
The maximum number of payment results that mission control will store.
|
||||||
|
*/
|
||||||
|
uint32 maximum_payment_results = 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The minimum time that must have passed since the previously recorded failure
|
||||||
|
before we raise the failure amount.
|
||||||
|
*/
|
||||||
|
uint64 minimum_failure_relax_interval = 5;
|
||||||
|
|
||||||
|
enum ProbabilityModel {
|
||||||
|
APRIORI = 0;
|
||||||
|
BIMODAL = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ProbabilityModel defines which probability estimator should be used in
|
||||||
|
pathfinding. Note that the bimodal estimator is experimental.
|
||||||
|
*/
|
||||||
|
ProbabilityModel model = 6;
|
||||||
|
|
||||||
|
/*
|
||||||
|
EstimatorConfig is populated dependent on the estimator type.
|
||||||
|
*/
|
||||||
|
oneof EstimatorConfig {
|
||||||
|
AprioriParameters apriori = 7;
|
||||||
|
BimodalParameters bimodal = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message BimodalParameters {
|
||||||
|
/*
|
||||||
|
NodeWeight defines how strongly other previous forwardings on channels of a
|
||||||
|
router should be taken into account when computing a channel's probability
|
||||||
|
to route. The allowed values are in the range [0, 1], where a value of 0
|
||||||
|
means that only direct information about a channel is taken into account.
|
||||||
|
*/
|
||||||
|
double node_weight = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
ScaleMsat describes the scale over which channels statistically have some
|
||||||
|
liquidity left. The value determines how quickly the bimodal distribution
|
||||||
|
drops off from the edges of a channel. A larger value (compared to typical
|
||||||
|
channel capacities) means that the drop off is slow and that channel
|
||||||
|
balances are distributed more uniformly. A small value leads to the
|
||||||
|
assumption of very unbalanced channels.
|
||||||
|
*/
|
||||||
|
uint64 scale_msat = 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
DecayTime describes the information decay of knowledge about previous
|
||||||
|
successes and failures in channels. The smaller the decay time, the quicker
|
||||||
|
we forget about past forwardings.
|
||||||
|
*/
|
||||||
|
uint64 decay_time = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AprioriParameters {
|
||||||
/*
|
/*
|
||||||
The amount of time mission control will take to restore a penalized node
|
The amount of time mission control will take to restore a penalized node
|
||||||
or channel back to 50% success probability, expressed in seconds. Setting
|
or channel back to 50% success probability, expressed in seconds. Setting
|
||||||
|
|
@ -480,7 +675,7 @@ message MissionControlConfig {
|
||||||
control more willing to try hops that we have no information about, lower
|
control more willing to try hops that we have no information about, lower
|
||||||
values will discourage trying these hops.
|
values will discourage trying these hops.
|
||||||
*/
|
*/
|
||||||
float hop_probability = 2;
|
double hop_probability = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The importance that mission control should place on historical results,
|
The importance that mission control should place on historical results,
|
||||||
|
|
@ -490,18 +685,15 @@ message MissionControlConfig {
|
||||||
completely and relies entirely on historical results, unless none are
|
completely and relies entirely on historical results, unless none are
|
||||||
available.
|
available.
|
||||||
*/
|
*/
|
||||||
float weight = 3;
|
double weight = 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The maximum number of payment results that mission control will store.
|
The fraction of a channel's capacity that we consider to have liquidity. For
|
||||||
|
amounts that come close to or exceed the fraction, an additional penalty is
|
||||||
|
applied. A value of 1.0 disables the capacity factor. Allowed values are in
|
||||||
|
[0.75, 1.0].
|
||||||
*/
|
*/
|
||||||
uint32 maximum_payment_results = 4;
|
double capacity_fraction = 4;
|
||||||
|
|
||||||
/*
|
|
||||||
The minimum time that must have passed since the previously recorded failure
|
|
||||||
before we raise the failure amount.
|
|
||||||
*/
|
|
||||||
uint64 minimum_failure_relax_interval = 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message QueryProbabilityRequest {
|
message QueryProbabilityRequest {
|
||||||
|
|
@ -548,8 +740,20 @@ message BuildRouteRequest {
|
||||||
*/
|
*/
|
||||||
repeated bytes hop_pubkeys = 4;
|
repeated bytes hop_pubkeys = 4;
|
||||||
|
|
||||||
// An optional payment addr to be included within the last hop of the route.
|
/*
|
||||||
|
An optional payment addr to be included within the last hop of the route.
|
||||||
|
This is also called payment secret in specifications (e.g. BOLT 11).
|
||||||
|
*/
|
||||||
bytes payment_addr = 5;
|
bytes payment_addr = 5;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An optional field that can be used to pass an arbitrary set of TLV records
|
||||||
|
to the first hop peer of this payment. This can be used to pass application
|
||||||
|
specific data during the payment attempt. Record types are required to be in
|
||||||
|
the custom range >= 65536. When using REST, the values must be encoded as
|
||||||
|
base64.
|
||||||
|
*/
|
||||||
|
map<uint64, bytes> first_hop_custom_records = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BuildRouteResponse {
|
message BuildRouteResponse {
|
||||||
|
|
@ -806,12 +1010,17 @@ message ForwardHtlcInterceptRequest {
|
||||||
// The block height at which this htlc will be auto-failed to prevent the
|
// The block height at which this htlc will be auto-failed to prevent the
|
||||||
// channel from force-closing.
|
// channel from force-closing.
|
||||||
int32 auto_fail_height = 10;
|
int32 auto_fail_height = 10;
|
||||||
|
|
||||||
|
// The custom records of the peer's incoming p2p wire message.
|
||||||
|
map<uint64, bytes> in_wire_custom_records = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ForwardHtlcInterceptResponse enables the caller to resolve a previously hold
|
ForwardHtlcInterceptResponse enables the caller to resolve a previously hold
|
||||||
forward. The caller can choose either to:
|
forward. The caller can choose either to:
|
||||||
- `Resume`: Execute the default behavior (usually forward).
|
- `Resume`: Execute the default behavior (usually forward).
|
||||||
|
- `ResumeModified`: Execute the default behavior (usually forward) with HTLC
|
||||||
|
field modifications.
|
||||||
- `Reject`: Fail the htlc backwards.
|
- `Reject`: Fail the htlc backwards.
|
||||||
- `Settle`: Settle this htlc with a given preimage.
|
- `Settle`: Settle this htlc with a given preimage.
|
||||||
*/
|
*/
|
||||||
|
|
@ -842,12 +1051,40 @@ message ForwardHtlcInterceptResponse {
|
||||||
// For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the
|
// For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the
|
||||||
// default value for this field.
|
// default value for this field.
|
||||||
lnrpc.Failure.FailureCode failure_code = 5;
|
lnrpc.Failure.FailureCode failure_code = 5;
|
||||||
|
|
||||||
|
// The amount that was set on the p2p wire message of the incoming HTLC.
|
||||||
|
// This field is ignored if the action is not RESUME_MODIFIED or the amount
|
||||||
|
// is zero.
|
||||||
|
uint64 in_amount_msat = 6;
|
||||||
|
|
||||||
|
// The amount to set on the p2p wire message of the resumed HTLC. This field
|
||||||
|
// is ignored if the action is not RESUME_MODIFIED or the amount is zero.
|
||||||
|
uint64 out_amount_msat = 7;
|
||||||
|
|
||||||
|
// Any custom records that should be set on the p2p wire message message of
|
||||||
|
// the resumed HTLC. This field is ignored if the action is not
|
||||||
|
// RESUME_MODIFIED.
|
||||||
|
//
|
||||||
|
// This map will merge with the existing set of custom records (if any),
|
||||||
|
// replacing any conflicting types. Note that there currently is no support
|
||||||
|
// for deleting existing custom records (they can only be replaced).
|
||||||
|
map<uint64, bytes> out_wire_custom_records = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ResolveHoldForwardAction {
|
enum ResolveHoldForwardAction {
|
||||||
|
// SETTLE is an action that is used to settle an HTLC instead of forwarding
|
||||||
|
// it.
|
||||||
SETTLE = 0;
|
SETTLE = 0;
|
||||||
|
|
||||||
|
// FAIL is an action that is used to fail an HTLC backwards.
|
||||||
FAIL = 1;
|
FAIL = 1;
|
||||||
|
|
||||||
|
// RESUME is an action that is used to resume a forward HTLC.
|
||||||
RESUME = 2;
|
RESUME = 2;
|
||||||
|
|
||||||
|
// RESUME_MODIFIED is an action that is used to resume a hold forward HTLC
|
||||||
|
// with modifications specified during interception.
|
||||||
|
RESUME_MODIFIED = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateChanStatusRequest {
|
message UpdateChanStatusRequest {
|
||||||
|
|
@ -864,3 +1101,19 @@ enum ChanStatusAction {
|
||||||
|
|
||||||
message UpdateChanStatusResponse {
|
message UpdateChanStatusResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddAliasesRequest {
|
||||||
|
repeated lnrpc.AliasMap alias_maps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddAliasesResponse {
|
||||||
|
repeated lnrpc.AliasMap alias_maps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteAliasesRequest {
|
||||||
|
repeated lnrpc.AliasMap alias_maps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteAliasesResponse {
|
||||||
|
repeated lnrpc.AliasMap alias_maps = 1;
|
||||||
|
}
|
||||||
|
|
@ -1172,6 +1172,12 @@ message PendingSweep {
|
||||||
The deadline height used for this output when perform fee bumping.
|
The deadline height used for this output when perform fee bumping.
|
||||||
*/
|
*/
|
||||||
uint32 deadline_height = 14;
|
uint32 deadline_height = 14;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The block height which the input's locktime will expire at. Zero if the
|
||||||
|
input has no locktime.
|
||||||
|
*/
|
||||||
|
uint32 maturity_height = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PendingSweepsRequest {
|
message PendingSweepsRequest {
|
||||||
|
|
@ -1188,9 +1194,8 @@ message BumpFeeRequest {
|
||||||
// The input we're attempting to bump the fee of.
|
// The input we're attempting to bump the fee of.
|
||||||
lnrpc.OutPoint outpoint = 1;
|
lnrpc.OutPoint outpoint = 1;
|
||||||
|
|
||||||
// Optional. The deadline in number of blocks that the input should be spent
|
// Optional. The conf target the underlying fee estimator will use to
|
||||||
// within. When not set, for new inputs, the default value (1008) is used;
|
// estimate the starting fee rate for the fee function.
|
||||||
// for existing inputs, their current values will be retained.
|
|
||||||
uint32 target_conf = 2;
|
uint32 target_conf = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1217,7 +1222,7 @@ message BumpFeeRequest {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Optional. Whether this input will be swept immediately. When set to true,
|
Optional. Whether this input will be swept immediately. When set to true,
|
||||||
the sweeper will sweep this input without waiting for the next batch.
|
the sweeper will sweep this input without waiting for the next block.
|
||||||
*/
|
*/
|
||||||
bool immediate = 6;
|
bool immediate = 6;
|
||||||
|
|
||||||
|
|
@ -1230,6 +1235,12 @@ message BumpFeeRequest {
|
||||||
retained.
|
retained.
|
||||||
*/
|
*/
|
||||||
uint64 budget = 7;
|
uint64 budget = 7;
|
||||||
|
|
||||||
|
// Optional. The deadline delta in number of blocks that the output
|
||||||
|
// should be spent within. This translates internally to the width of the
|
||||||
|
// fee function that the sweeper will use to bump the fee rate. When the
|
||||||
|
// deadline is reached, ALL the budget will be spent as fees.
|
||||||
|
uint32 deadline_delta = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BumpFeeResponse {
|
message BumpFeeResponse {
|
||||||
|
|
@ -1243,7 +1254,8 @@ message BumpForceCloseFeeRequest {
|
||||||
lnrpc.ChannelPoint chan_point = 1;
|
lnrpc.ChannelPoint chan_point = 1;
|
||||||
|
|
||||||
// Optional. The deadline delta in number of blocks that the anchor output
|
// Optional. The deadline delta in number of blocks that the anchor output
|
||||||
// should be spent within to bump the closing transaction.
|
// should be spent within to bump the closing transaction. When the
|
||||||
|
// deadline is reached, ALL the budget will be spent as fees
|
||||||
uint32 deadline_delta = 2;
|
uint32 deadline_delta = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1270,6 +1282,10 @@ message BumpForceCloseFeeRequest {
|
||||||
transaction of the force closed channel otherwise the fee bumping will fail.
|
transaction of the force closed channel otherwise the fee bumping will fail.
|
||||||
*/
|
*/
|
||||||
uint64 budget = 5;
|
uint64 budget = 5;
|
||||||
|
|
||||||
|
// Optional. The conf target the underlying fee estimator will use to
|
||||||
|
// estimate the starting fee rate for the fee function.
|
||||||
|
uint32 target_conf = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BumpForceCloseFeeResponse {
|
message BumpForceCloseFeeResponse {
|
||||||
|
|
@ -1426,6 +1442,16 @@ message FundPsbtRequest {
|
||||||
|
|
||||||
// The max fee to total output amount ratio that this psbt should adhere to.
|
// The max fee to total output amount ratio that this psbt should adhere to.
|
||||||
double max_fee_ratio = 12;
|
double max_fee_ratio = 12;
|
||||||
|
|
||||||
|
// The custom lock ID to use for the inputs in the funded PSBT. The value
|
||||||
|
// if set must be exactly 32 bytes long. If empty, the default lock ID will
|
||||||
|
// be used.
|
||||||
|
bytes custom_lock_id = 13;
|
||||||
|
|
||||||
|
// If set, then the inputs in the funded PSBT will be locked for the
|
||||||
|
// specified duration. The lock duration is specified in seconds. If not
|
||||||
|
// set, the default lock duration will be used.
|
||||||
|
uint64 lock_expiration_seconds = 14;
|
||||||
}
|
}
|
||||||
message FundPsbtResponse {
|
message FundPsbtResponse {
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,20 @@ service LightningPub {
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rpc GetAssetsAndLiabilities(structs.AssetsAndLiabilitiesReq) returns (structs.AssetsAndLiabilities) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/assets/liabilities";
|
||||||
|
option (nostr) = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc BumpTx(structs.BumpTx) returns (structs.Empty) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/tx/bump";
|
||||||
|
option (nostr) = true;
|
||||||
|
};
|
||||||
|
|
||||||
rpc AddApp(structs.AddAppRequest) returns (structs.AuthApp) {
|
rpc AddApp(structs.AddAppRequest) returns (structs.AuthApp) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
|
|
@ -175,6 +189,34 @@ service LightningPub {
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc GetAdminInvoiceSwapQuotes(structs.InvoiceSwapRequest) returns (structs.InvoiceSwapQuoteList) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/swap/invoice/quote";
|
||||||
|
option (nostr) = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc ListAdminInvoiceSwaps(structs.Empty) returns (structs.InvoiceSwapsList) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/swap/invoice/list";
|
||||||
|
option (nostr) = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc PayAdminInvoiceSwap(structs.PayAdminInvoiceSwapRequest) returns (structs.AdminInvoiceSwapResponse) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/swap/invoice/pay";
|
||||||
|
option (nostr) = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc RefundAdminInvoiceSwap(structs.RefundAdminInvoiceSwapRequest) returns (structs.AdminInvoiceSwapResponse) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/swap/invoice/refund";
|
||||||
|
option (nostr) = true;
|
||||||
|
}
|
||||||
|
|
||||||
rpc GetAdminTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList) {
|
rpc GetAdminTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
|
|
@ -182,17 +224,17 @@ service LightningPub {
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc PayAdminTransactionSwap(structs.PayAdminTransactionSwapRequest) returns (structs.AdminSwapResponse) {
|
rpc PayAdminTransactionSwap(structs.PayAdminTransactionSwapRequest) returns (structs.AdminTxSwapResponse) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/swap/transaction/pay";
|
option (http_route) = "/api/admin/swap/transaction/pay";
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc ListAdminSwaps(structs.Empty) returns (structs.SwapsList) {
|
rpc ListAdminTxSwaps(structs.Empty) returns (structs.TxSwapsList) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/swap/list";
|
option (http_route) = "/api/admin/swap/transaction/list";
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,14 +562,14 @@ service LightningPub {
|
||||||
rpc GetTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList){
|
rpc GetTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList){
|
||||||
option (auth_type) = "User";
|
option (auth_type) = "User";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/user/swap/quote";
|
option (http_route) = "/api/user/swap/transaction/quote";
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc ListSwaps(structs.Empty) returns (structs.SwapsList){
|
rpc ListTxSwaps(structs.Empty) returns (structs.TxSwapsList){
|
||||||
option (auth_type) = "User";
|
option (auth_type) = "User";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/user/swap/list";
|
option (http_route) = "/api/user/swap/transaction/list";
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,68 @@ message EncryptionExchangeRequest {
|
||||||
string deviceId = 2;
|
string deviceId = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AssetsAndLiabilitiesReq {
|
||||||
|
optional int64 limit_invoices = 1;
|
||||||
|
optional int64 limit_payments = 2;
|
||||||
|
optional int64 limit_providers = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BumpTx {
|
||||||
|
string txid = 1;
|
||||||
|
int64 output_index = 2;
|
||||||
|
int64 sat_per_vbyte = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum TrackedOperationType {
|
||||||
|
USER = 0;
|
||||||
|
ROOT = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrackedOperation {
|
||||||
|
int64 ts = 1;
|
||||||
|
int64 amount = 2;
|
||||||
|
TrackedOperationType type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AssetOperation {
|
||||||
|
int64 ts = 1;
|
||||||
|
int64 amount = 2;
|
||||||
|
optional TrackedOperation tracked = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrackedLndProvider {
|
||||||
|
int64 confirmed_balance = 1;
|
||||||
|
int64 unconfirmed_balance = 2;
|
||||||
|
int64 channels_balance = 3;
|
||||||
|
repeated AssetOperation payments = 4;
|
||||||
|
repeated AssetOperation invoices = 5;
|
||||||
|
repeated AssetOperation incoming_tx = 6;
|
||||||
|
repeated AssetOperation outgoing_tx = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrackedLiquidityProvider {
|
||||||
|
int64 balance = 1;
|
||||||
|
repeated AssetOperation payments = 2;
|
||||||
|
repeated AssetOperation invoices = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LndAssetProvider {
|
||||||
|
string pubkey = 1;
|
||||||
|
optional TrackedLndProvider tracked = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LiquidityAssetProvider {
|
||||||
|
string pubkey = 1;
|
||||||
|
optional TrackedLiquidityProvider tracked = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AssetsAndLiabilities {
|
||||||
|
int64 users_balance = 1;
|
||||||
|
repeated LndAssetProvider lnds = 2;
|
||||||
|
repeated LiquidityAssetProvider liquidity_providers = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message UserHealthState {
|
message UserHealthState {
|
||||||
string downtime_reason = 1;
|
string downtime_reason = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +99,8 @@ message ErrorStats {
|
||||||
ErrorStat past1m = 5;
|
ErrorStat past1m = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
message MetricsFile {
|
message MetricsFile {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -541,6 +605,7 @@ message UserInfo{
|
||||||
string callback_url = 10;
|
string callback_url = 10;
|
||||||
string bridge_url = 11;
|
string bridge_url = 11;
|
||||||
string nmanage = 12;
|
string nmanage = 12;
|
||||||
|
string topic_id = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -833,6 +898,60 @@ message MessagingToken {
|
||||||
string firebase_messaging_token = 2;
|
string firebase_messaging_token = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message InvoiceSwapRequest {
|
||||||
|
int64 amount_sats = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InvoiceSwapQuote {
|
||||||
|
string swap_operation_id = 1;
|
||||||
|
string invoice = 2;
|
||||||
|
int64 invoice_amount_sats = 3;
|
||||||
|
string address = 4;
|
||||||
|
int64 transaction_amount_sats = 5;
|
||||||
|
int64 chain_fee_sats = 6;
|
||||||
|
int64 service_fee_sats = 7;
|
||||||
|
string service_url = 8;
|
||||||
|
int64 swap_fee_sats = 9;
|
||||||
|
string tx_id = 10;
|
||||||
|
int64 paid_at_unix = 11;
|
||||||
|
int64 expires_at_block_height = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InvoiceSwapQuoteList {
|
||||||
|
repeated InvoiceSwapQuote quotes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InvoiceSwapOperation {
|
||||||
|
InvoiceSwapQuote quote = 1;
|
||||||
|
optional UserOperation operation_payment = 2;
|
||||||
|
optional string failure_reason = 3;
|
||||||
|
optional int64 completed_at_unix = 6;
|
||||||
|
|
||||||
|
optional string refund_address = 7;
|
||||||
|
optional int64 refund_at_unix = 8;
|
||||||
|
optional string refund_tx_id = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InvoiceSwapsList {
|
||||||
|
repeated InvoiceSwapOperation swaps = 1;
|
||||||
|
int64 current_block_height = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RefundAdminInvoiceSwapRequest {
|
||||||
|
string swap_operation_id = 1;
|
||||||
|
int64 sat_per_v_byte = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PayAdminInvoiceSwapRequest {
|
||||||
|
string swap_operation_id = 1;
|
||||||
|
int64 sat_per_v_byte = 2;
|
||||||
|
optional bool no_claim = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AdminInvoiceSwapResponse {
|
||||||
|
string tx_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message TransactionSwapRequest {
|
message TransactionSwapRequest {
|
||||||
int64 transaction_amount_sats = 2;
|
int64 transaction_amount_sats = 2;
|
||||||
}
|
}
|
||||||
|
|
@ -851,27 +970,31 @@ message TransactionSwapQuote {
|
||||||
int64 chain_fee_sats = 5;
|
int64 chain_fee_sats = 5;
|
||||||
int64 service_fee_sats = 7;
|
int64 service_fee_sats = 7;
|
||||||
string service_url = 8;
|
string service_url = 8;
|
||||||
|
|
||||||
|
int64 expires_at_block_height = 9;
|
||||||
|
int64 paid_at_unix = 10;
|
||||||
|
int64 completed_at_unix = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TransactionSwapQuoteList {
|
message TransactionSwapQuoteList {
|
||||||
repeated TransactionSwapQuote quotes = 1;
|
repeated TransactionSwapQuote quotes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdminSwapResponse {
|
message AdminTxSwapResponse {
|
||||||
string tx_id = 1;
|
string tx_id = 1;
|
||||||
int64 network_fee = 2;
|
int64 network_fee = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SwapOperation {
|
message TxSwapOperation {
|
||||||
string swap_operation_id = 1;
|
TransactionSwapQuote quote = 1;
|
||||||
optional UserOperation operation_payment = 2;
|
optional UserOperation operation_payment = 2;
|
||||||
optional string failure_reason = 3;
|
optional string failure_reason = 3;
|
||||||
string address_paid = 4;
|
optional string address_paid = 4;
|
||||||
|
optional string tx_id = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SwapsList {
|
message TxSwapsList {
|
||||||
repeated SwapOperation swaps = 1;
|
repeated TxSwapOperation swaps = 1;
|
||||||
repeated TransactionSwapQuote quotes = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message CumulativeFees {
|
message CumulativeFees {
|
||||||
|
|
@ -886,3 +1009,18 @@ message BeaconData {
|
||||||
optional string nextRelay = 4;
|
optional string nextRelay = 4;
|
||||||
optional CumulativeFees fees = 5;
|
optional CumulativeFees fees = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message PushNotificationEnvelope {
|
||||||
|
string topic_id = 1;
|
||||||
|
string app_npub_hex = 2;
|
||||||
|
string encrypted_payload = 3; // encrypted PushNotificationPayload
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message PushNotificationPayload {
|
||||||
|
oneof data {
|
||||||
|
UserOperation received_operation = 1;
|
||||||
|
UserOperation sent_operation = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
731
src/extensions/README.md
Normal file
731
src/extensions/README.md
Normal file
|
|
@ -0,0 +1,731 @@
|
||||||
|
# Lightning.Pub Extension System
|
||||||
|
|
||||||
|
A modular extension system that allows third-party functionality to be added to Lightning.Pub without modifying core code.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Architecture](#architecture)
|
||||||
|
- [Creating an Extension](#creating-an-extension)
|
||||||
|
- [Extension Lifecycle](#extension-lifecycle)
|
||||||
|
- [ExtensionContext API](#extensioncontext-api)
|
||||||
|
- [Database Isolation](#database-isolation)
|
||||||
|
- [RPC Methods](#rpc-methods)
|
||||||
|
- [HTTP Routes](#http-routes)
|
||||||
|
- [Event Handling](#event-handling)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
- [Examples](#examples)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The extension system provides:
|
||||||
|
|
||||||
|
- **Modularity**: Extensions are self-contained modules with their own code and data
|
||||||
|
- **Isolation**: Each extension gets its own SQLite database
|
||||||
|
- **Integration**: Extensions can register RPC methods, handle events, and interact with Lightning.Pub's payment and Nostr systems
|
||||||
|
- **Lifecycle Management**: Automatic discovery, loading, and graceful shutdown
|
||||||
|
|
||||||
|
### Built-in Extensions
|
||||||
|
|
||||||
|
| Extension | Description |
|
||||||
|
|-----------|-------------|
|
||||||
|
| `marketplace` | NIP-15 Nostr marketplace for selling products via Lightning |
|
||||||
|
| `withdraw` | LNURL-withdraw (LUD-03) for vouchers, faucets, and gifts |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Lightning.Pub │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ Extension Loader │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ Extension A │ │ Extension B │ │ Extension C │ ... │
|
||||||
|
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
|
||||||
|
│ │ │Context│ │ │ │Context│ │ │ │Context│ │ │
|
||||||
|
│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │
|
||||||
|
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
|
||||||
|
│ │ │ DB │ │ │ │ DB │ │ │ │ DB │ │ │
|
||||||
|
│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ Payment Manager │ Nostr Transport │ Application Manager │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Components
|
||||||
|
|
||||||
|
| Component | File | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `ExtensionLoader` | `loader.ts` | Discovers, loads, and manages extensions |
|
||||||
|
| `ExtensionContext` | `context.ts` | Bridge between extensions and Lightning.Pub |
|
||||||
|
| `ExtensionDatabase` | `database.ts` | Isolated SQLite database per extension |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Creating an Extension
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/extensions/
|
||||||
|
└── my-extension/
|
||||||
|
├── index.ts # Main entry point (required)
|
||||||
|
├── types.ts # TypeScript interfaces
|
||||||
|
├── migrations.ts # Database migrations
|
||||||
|
└── managers/ # Business logic
|
||||||
|
└── myManager.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Minimal Extension
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/extensions/my-extension/index.ts
|
||||||
|
|
||||||
|
import { Extension, ExtensionInfo, ExtensionContext, ExtensionDatabase } from '../types.js'
|
||||||
|
|
||||||
|
export default class MyExtension implements Extension {
|
||||||
|
readonly info: ExtensionInfo = {
|
||||||
|
id: 'my-extension', // Must match directory name
|
||||||
|
name: 'My Extension',
|
||||||
|
version: '1.0.0',
|
||||||
|
description: 'Does something useful',
|
||||||
|
author: 'Your Name',
|
||||||
|
minPubVersion: '1.0.0' // Minimum Lightning.Pub version
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise<void> {
|
||||||
|
// Run migrations
|
||||||
|
await db.execute(`
|
||||||
|
CREATE TABLE IF NOT EXISTS my_table (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
data TEXT
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Register RPC methods
|
||||||
|
ctx.registerMethod('my-extension.doSomething', async (req, appId) => {
|
||||||
|
return { result: 'done' }
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.log('info', 'Extension initialized')
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown(): Promise<void> {
|
||||||
|
// Cleanup resources
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extension Interface
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Extension {
|
||||||
|
// Required: Extension metadata
|
||||||
|
readonly info: ExtensionInfo
|
||||||
|
|
||||||
|
// Required: Called once when extension is loaded
|
||||||
|
initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise<void>
|
||||||
|
|
||||||
|
// Optional: Called when Lightning.Pub shuts down
|
||||||
|
shutdown?(): Promise<void>
|
||||||
|
|
||||||
|
// Optional: Health check for monitoring
|
||||||
|
healthCheck?(): Promise<boolean>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExtensionInfo {
|
||||||
|
id: string // Unique identifier (lowercase, no spaces)
|
||||||
|
name: string // Display name
|
||||||
|
version: string // Semver version
|
||||||
|
description: string // Short description
|
||||||
|
author: string // Author name
|
||||||
|
minPubVersion?: string // Minimum Lightning.Pub version
|
||||||
|
dependencies?: string[] // Other extension IDs required
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Extension Lifecycle
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────┐
|
||||||
|
│ Discover │ Scan extensions directory for index.ts files
|
||||||
|
└──────┬───────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────┐
|
||||||
|
│ Load │ Import module, instantiate class
|
||||||
|
└──────┬───────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────┐
|
||||||
|
│ Initialize │ Create database, call initialize()
|
||||||
|
└──────┬───────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────┐
|
||||||
|
│ Ready │ Extension is active, handling requests
|
||||||
|
└──────┬───────┘
|
||||||
|
│
|
||||||
|
▼ (on shutdown)
|
||||||
|
┌──────────────┐
|
||||||
|
│ Shutdown │ Call shutdown(), close database
|
||||||
|
└──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### States
|
||||||
|
|
||||||
|
| State | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `loading` | Extension is being loaded |
|
||||||
|
| `ready` | Extension is active and healthy |
|
||||||
|
| `error` | Initialization failed |
|
||||||
|
| `stopped` | Extension has been shut down |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ExtensionContext API
|
||||||
|
|
||||||
|
The `ExtensionContext` is passed to your extension during initialization. It provides access to Lightning.Pub functionality.
|
||||||
|
|
||||||
|
### Application Management
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Get information about an application
|
||||||
|
const app = await ctx.getApplication(applicationId)
|
||||||
|
// Returns: { id, name, nostr_public, balance_sats } | null
|
||||||
|
```
|
||||||
|
|
||||||
|
### Payment Operations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Create a Lightning invoice
|
||||||
|
const invoice = await ctx.createInvoice(amountSats, {
|
||||||
|
memo: 'Payment for service',
|
||||||
|
expiry: 3600, // seconds
|
||||||
|
metadata: { order_id: '123' } // Returned in payment callback
|
||||||
|
})
|
||||||
|
// Returns: { id, paymentRequest, paymentHash, expiry }
|
||||||
|
|
||||||
|
// Pay a Lightning invoice
|
||||||
|
const result = await ctx.payInvoice(applicationId, bolt11Invoice, maxFeeSats)
|
||||||
|
// Returns: { paymentHash, feeSats }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nostr Operations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Send encrypted DM (NIP-44)
|
||||||
|
const eventId = await ctx.sendEncryptedDM(applicationId, recipientPubkey, content)
|
||||||
|
|
||||||
|
// Publish a Nostr event (signed by application's key)
|
||||||
|
const eventId = await ctx.publishNostrEvent({
|
||||||
|
kind: 30017,
|
||||||
|
pubkey: appPubkey,
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
tags: [['d', 'identifier']],
|
||||||
|
content: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### RPC Method Registration
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Register a method that can be called via RPC
|
||||||
|
ctx.registerMethod('my-extension.methodName', async (request, applicationId, userPubkey?) => {
|
||||||
|
// request: The RPC request payload
|
||||||
|
// applicationId: The calling application's ID
|
||||||
|
// userPubkey: The user's Nostr pubkey (if authenticated)
|
||||||
|
|
||||||
|
return { result: 'success' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Event Subscriptions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Subscribe to payment received events
|
||||||
|
ctx.onPaymentReceived(async (payment) => {
|
||||||
|
// payment: { invoiceId, paymentHash, amountSats, metadata }
|
||||||
|
|
||||||
|
if (payment.metadata?.extension === 'my-extension') {
|
||||||
|
// Handle payment for this extension
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Subscribe to incoming Nostr events
|
||||||
|
ctx.onNostrEvent(async (event, applicationId) => {
|
||||||
|
// event: { id, pubkey, kind, tags, content, created_at }
|
||||||
|
// applicationId: The application this event is for
|
||||||
|
|
||||||
|
if (event.kind === 4) { // DM
|
||||||
|
// Handle incoming message
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
ctx.log('debug', 'Detailed debugging info')
|
||||||
|
ctx.log('info', 'Normal operation info')
|
||||||
|
ctx.log('warn', 'Warning message')
|
||||||
|
ctx.log('error', 'Error occurred', errorObject)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Database Isolation
|
||||||
|
|
||||||
|
Each extension gets its own SQLite database file at:
|
||||||
|
```
|
||||||
|
{databaseDir}/{extension-id}.db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Interface
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ExtensionDatabase {
|
||||||
|
// Execute write queries (INSERT, UPDATE, DELETE, CREATE)
|
||||||
|
execute(sql: string, params?: any[]): Promise<{ changes?: number; lastId?: number }>
|
||||||
|
|
||||||
|
// Execute read queries (SELECT)
|
||||||
|
query<T>(sql: string, params?: any[]): Promise<T[]>
|
||||||
|
|
||||||
|
// Run multiple statements in a transaction
|
||||||
|
transaction<T>(fn: () => Promise<T>): Promise<T>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Migration Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// migrations.ts
|
||||||
|
|
||||||
|
export interface Migration {
|
||||||
|
version: number
|
||||||
|
name: string
|
||||||
|
up: (db: ExtensionDatabase) => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const migrations: Migration[] = [
|
||||||
|
{
|
||||||
|
version: 1,
|
||||||
|
name: 'create_initial_tables',
|
||||||
|
up: async (db) => {
|
||||||
|
await db.execute(`
|
||||||
|
CREATE TABLE items (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
created_at INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: 2,
|
||||||
|
name: 'add_status_column',
|
||||||
|
up: async (db) => {
|
||||||
|
await db.execute(`ALTER TABLE items ADD COLUMN status TEXT DEFAULT 'active'`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// Run migrations in initialize()
|
||||||
|
export async function runMigrations(db: ExtensionDatabase): Promise<void> {
|
||||||
|
const result = await db.query<{ value: string }>(
|
||||||
|
`SELECT value FROM _extension_meta WHERE key = 'migration_version'`
|
||||||
|
).catch(() => [])
|
||||||
|
|
||||||
|
const currentVersion = result.length > 0 ? parseInt(result[0].value, 10) : 0
|
||||||
|
|
||||||
|
for (const migration of migrations) {
|
||||||
|
if (migration.version > currentVersion) {
|
||||||
|
console.log(`Running migration ${migration.version}: ${migration.name}`)
|
||||||
|
await migration.up(db)
|
||||||
|
await db.execute(
|
||||||
|
`INSERT INTO _extension_meta (key, value) VALUES ('migration_version', ?)
|
||||||
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
|
||||||
|
[String(migration.version)]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RPC Methods
|
||||||
|
|
||||||
|
Extensions register RPC methods that can be called by clients.
|
||||||
|
|
||||||
|
### Naming Convention
|
||||||
|
|
||||||
|
Methods should be namespaced with the extension ID:
|
||||||
|
```
|
||||||
|
{extension-id}.{methodName}
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- `marketplace.createStall`
|
||||||
|
- `withdraw.createLink`
|
||||||
|
|
||||||
|
### Method Handler Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type RpcMethodHandler = (
|
||||||
|
request: any, // The request payload
|
||||||
|
applicationId: string, // The calling application
|
||||||
|
userPubkey?: string // The authenticated user (if any)
|
||||||
|
) => Promise<any>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
ctx.registerMethod('my-extension.createItem', async (req, appId, userPubkey) => {
|
||||||
|
// Validate request
|
||||||
|
if (!req.name) {
|
||||||
|
throw new Error('Name is required')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create item
|
||||||
|
const item = await this.manager.create(appId, req)
|
||||||
|
|
||||||
|
// Return response
|
||||||
|
return { item }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## HTTP Routes
|
||||||
|
|
||||||
|
Some extensions need HTTP endpoints (e.g., LNURL protocol). Extensions can define routes that the main application mounts.
|
||||||
|
|
||||||
|
### Defining Routes
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface HttpRoute {
|
||||||
|
method: 'GET' | 'POST'
|
||||||
|
path: string
|
||||||
|
handler: (req: HttpRequest) => Promise<HttpResponse>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HttpRequest {
|
||||||
|
params: Record<string, string> // URL path params
|
||||||
|
query: Record<string, string> // Query string params
|
||||||
|
body?: any // POST body
|
||||||
|
headers: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HttpResponse {
|
||||||
|
status: number
|
||||||
|
body: any
|
||||||
|
headers?: Record<string, string>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class MyExtension implements Extension {
|
||||||
|
getHttpRoutes(): HttpRoute[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/api/v1/my-extension/:id',
|
||||||
|
handler: async (req) => {
|
||||||
|
const item = await this.getItem(req.params.id)
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: item,
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Event Handling
|
||||||
|
|
||||||
|
### Payment Callbacks
|
||||||
|
|
||||||
|
When you create an invoice with metadata, you'll receive that metadata back in the payment callback:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Creating invoice with metadata
|
||||||
|
const invoice = await ctx.createInvoice(1000, {
|
||||||
|
metadata: {
|
||||||
|
extension: 'my-extension',
|
||||||
|
order_id: 'order-123'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Handling payment
|
||||||
|
ctx.onPaymentReceived(async (payment) => {
|
||||||
|
if (payment.metadata?.extension === 'my-extension') {
|
||||||
|
const orderId = payment.metadata.order_id
|
||||||
|
await this.handlePayment(orderId, payment)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nostr Events
|
||||||
|
|
||||||
|
Subscribe to Nostr events for your application:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
ctx.onNostrEvent(async (event, applicationId) => {
|
||||||
|
// Filter by event kind
|
||||||
|
if (event.kind === 4) { // Encrypted DM
|
||||||
|
await this.handleDirectMessage(event, applicationId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Loader Configuration
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ExtensionLoaderConfig {
|
||||||
|
extensionsDir: string // Directory containing extensions
|
||||||
|
databaseDir: string // Directory for extension databases
|
||||||
|
enabledExtensions?: string[] // Whitelist (if set, only these load)
|
||||||
|
disabledExtensions?: string[] // Blacklist
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createExtensionLoader } from './extensions'
|
||||||
|
|
||||||
|
const loader = createExtensionLoader({
|
||||||
|
extensionsDir: './src/extensions',
|
||||||
|
databaseDir: './data/extensions',
|
||||||
|
disabledExtensions: ['experimental-ext']
|
||||||
|
}, mainHandler)
|
||||||
|
|
||||||
|
await loader.loadAll()
|
||||||
|
|
||||||
|
// Call extension methods
|
||||||
|
const result = await loader.callMethod(
|
||||||
|
'marketplace.createStall',
|
||||||
|
{ name: 'My Shop', currency: 'sat', shipping_zones: [] },
|
||||||
|
applicationId,
|
||||||
|
userPubkey
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dispatch events
|
||||||
|
loader.dispatchPaymentReceived(paymentData)
|
||||||
|
loader.dispatchNostrEvent(event, applicationId)
|
||||||
|
|
||||||
|
// Shutdown
|
||||||
|
await loader.shutdown()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example: Simple Counter Extension
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/extensions/counter/index.ts
|
||||||
|
|
||||||
|
import { Extension, ExtensionInfo, ExtensionContext, ExtensionDatabase } from '../types.js'
|
||||||
|
|
||||||
|
export default class CounterExtension implements Extension {
|
||||||
|
readonly info: ExtensionInfo = {
|
||||||
|
id: 'counter',
|
||||||
|
name: 'Simple Counter',
|
||||||
|
version: '1.0.0',
|
||||||
|
description: 'A simple counter for each application',
|
||||||
|
author: 'Example'
|
||||||
|
}
|
||||||
|
|
||||||
|
private db!: ExtensionDatabase
|
||||||
|
|
||||||
|
async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise<void> {
|
||||||
|
this.db = db
|
||||||
|
|
||||||
|
await db.execute(`
|
||||||
|
CREATE TABLE IF NOT EXISTS counters (
|
||||||
|
application_id TEXT PRIMARY KEY,
|
||||||
|
count INTEGER NOT NULL DEFAULT 0
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
|
||||||
|
ctx.registerMethod('counter.increment', async (req, appId) => {
|
||||||
|
await db.execute(
|
||||||
|
`INSERT INTO counters (application_id, count) VALUES (?, 1)
|
||||||
|
ON CONFLICT(application_id) DO UPDATE SET count = count + 1`,
|
||||||
|
[appId]
|
||||||
|
)
|
||||||
|
const result = await db.query<{ count: number }>(
|
||||||
|
'SELECT count FROM counters WHERE application_id = ?',
|
||||||
|
[appId]
|
||||||
|
)
|
||||||
|
return { count: result[0]?.count || 0 }
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.registerMethod('counter.get', async (req, appId) => {
|
||||||
|
const result = await db.query<{ count: number }>(
|
||||||
|
'SELECT count FROM counters WHERE application_id = ?',
|
||||||
|
[appId]
|
||||||
|
)
|
||||||
|
return { count: result[0]?.count || 0 }
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.registerMethod('counter.reset', async (req, appId) => {
|
||||||
|
await db.execute(
|
||||||
|
'UPDATE counters SET count = 0 WHERE application_id = ?',
|
||||||
|
[appId]
|
||||||
|
)
|
||||||
|
return { count: 0 }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Payment-Triggered Extension
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/extensions/donations/index.ts
|
||||||
|
|
||||||
|
import { Extension, ExtensionContext, ExtensionDatabase } from '../types.js'
|
||||||
|
|
||||||
|
export default class DonationsExtension implements Extension {
|
||||||
|
readonly info = {
|
||||||
|
id: 'donations',
|
||||||
|
name: 'Donations',
|
||||||
|
version: '1.0.0',
|
||||||
|
description: 'Accept donations with thank-you messages',
|
||||||
|
author: 'Example'
|
||||||
|
}
|
||||||
|
|
||||||
|
private db!: ExtensionDatabase
|
||||||
|
private ctx!: ExtensionContext
|
||||||
|
|
||||||
|
async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise<void> {
|
||||||
|
this.db = db
|
||||||
|
this.ctx = ctx
|
||||||
|
|
||||||
|
await db.execute(`
|
||||||
|
CREATE TABLE IF NOT EXISTS donations (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
application_id TEXT NOT NULL,
|
||||||
|
amount_sats INTEGER NOT NULL,
|
||||||
|
donor_pubkey TEXT,
|
||||||
|
message TEXT,
|
||||||
|
created_at INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Create donation invoice
|
||||||
|
ctx.registerMethod('donations.createInvoice', async (req, appId) => {
|
||||||
|
const invoice = await ctx.createInvoice(req.amount_sats, {
|
||||||
|
memo: req.message || 'Donation',
|
||||||
|
metadata: {
|
||||||
|
extension: 'donations',
|
||||||
|
donor_pubkey: req.donor_pubkey,
|
||||||
|
message: req.message
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return { invoice: invoice.paymentRequest }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Handle successful payments
|
||||||
|
ctx.onPaymentReceived(async (payment) => {
|
||||||
|
if (payment.metadata?.extension !== 'donations') return
|
||||||
|
|
||||||
|
// Record donation
|
||||||
|
await db.execute(
|
||||||
|
`INSERT INTO donations (id, application_id, amount_sats, donor_pubkey, message, created_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||||
|
[
|
||||||
|
payment.paymentHash,
|
||||||
|
payment.metadata.application_id,
|
||||||
|
payment.amountSats,
|
||||||
|
payment.metadata.donor_pubkey,
|
||||||
|
payment.metadata.message,
|
||||||
|
Math.floor(Date.now() / 1000)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
// Send thank-you DM if donor has pubkey
|
||||||
|
if (payment.metadata.donor_pubkey) {
|
||||||
|
await ctx.sendEncryptedDM(
|
||||||
|
payment.metadata.application_id,
|
||||||
|
payment.metadata.donor_pubkey,
|
||||||
|
`Thank you for your donation of ${payment.amountSats} sats!`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// List donations
|
||||||
|
ctx.registerMethod('donations.list', async (req, appId) => {
|
||||||
|
const donations = await db.query(
|
||||||
|
`SELECT * FROM donations WHERE application_id = ? ORDER BY created_at DESC LIMIT ?`,
|
||||||
|
[appId, req.limit || 50]
|
||||||
|
)
|
||||||
|
return { donations }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Namespace your methods**: Always prefix RPC methods with your extension ID
|
||||||
|
2. **Use migrations**: Never modify existing migration files; create new ones
|
||||||
|
3. **Handle errors gracefully**: Throw descriptive errors, don't return error objects
|
||||||
|
4. **Clean up in shutdown**: Close connections, cancel timers, etc.
|
||||||
|
5. **Log appropriately**: Use debug for verbose info, error for failures
|
||||||
|
6. **Validate inputs**: Check request parameters before processing
|
||||||
|
7. **Use transactions**: For multi-step database operations
|
||||||
|
8. **Document your API**: Include types and descriptions for RPC methods
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Extension not loading
|
||||||
|
|
||||||
|
1. Check that directory name matches `info.id`
|
||||||
|
2. Verify `index.ts` has a default export
|
||||||
|
3. Check for TypeScript/import errors in logs
|
||||||
|
|
||||||
|
### Database errors
|
||||||
|
|
||||||
|
1. Check migration syntax
|
||||||
|
2. Verify column types match queries
|
||||||
|
3. Look for migration version conflicts
|
||||||
|
|
||||||
|
### RPC method not found
|
||||||
|
|
||||||
|
1. Verify method is registered in `initialize()`
|
||||||
|
2. Check method name includes extension prefix
|
||||||
|
3. Ensure extension status is `ready`
|
||||||
|
|
||||||
|
### Payment callbacks not firing
|
||||||
|
|
||||||
|
1. Verify `metadata.extension` matches your extension ID
|
||||||
|
2. Check that `onPaymentReceived` is registered in `initialize()`
|
||||||
|
3. Confirm invoice was created through the extension
|
||||||
309
src/extensions/context.ts
Normal file
309
src/extensions/context.ts
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
import {
|
||||||
|
ExtensionContext,
|
||||||
|
ExtensionDatabase,
|
||||||
|
ExtensionInfo,
|
||||||
|
ApplicationInfo,
|
||||||
|
CreateInvoiceOptions,
|
||||||
|
CreatedInvoice,
|
||||||
|
PaymentReceivedData,
|
||||||
|
NostrEvent,
|
||||||
|
UnsignedNostrEvent,
|
||||||
|
RpcMethodHandler,
|
||||||
|
LnurlPayInfo
|
||||||
|
} from './types.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Handler interface (from Lightning.Pub)
|
||||||
|
* This is a minimal interface - the actual MainHandler has more methods
|
||||||
|
*/
|
||||||
|
export interface MainHandlerInterface {
|
||||||
|
// Application management
|
||||||
|
applicationManager: {
|
||||||
|
getById(id: string): Promise<any>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payment operations
|
||||||
|
paymentManager: {
|
||||||
|
createInvoice(params: {
|
||||||
|
applicationId: string
|
||||||
|
amountSats: number
|
||||||
|
memo?: string
|
||||||
|
expiry?: number
|
||||||
|
metadata?: Record<string, any>
|
||||||
|
}): Promise<{
|
||||||
|
id: string
|
||||||
|
paymentRequest: string
|
||||||
|
paymentHash: string
|
||||||
|
expiry: number
|
||||||
|
}>
|
||||||
|
|
||||||
|
payInvoice(params: {
|
||||||
|
applicationId: string
|
||||||
|
paymentRequest: string
|
||||||
|
maxFeeSats?: number
|
||||||
|
}): Promise<{
|
||||||
|
paymentHash: string
|
||||||
|
feeSats: number
|
||||||
|
}>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LNURL-pay info for a user by their Nostr pubkey
|
||||||
|
* This enables Lightning Address (LUD-16) and zap (NIP-57) support
|
||||||
|
*/
|
||||||
|
getLnurlPayInfoByPubkey(pubkeyHex: string, options?: {
|
||||||
|
metadata?: string
|
||||||
|
description?: string
|
||||||
|
}): Promise<LnurlPayInfo>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nostr operations
|
||||||
|
sendNostrEvent(event: any): Promise<string | null>
|
||||||
|
sendEncryptedDM(applicationId: string, recipientPubkey: string, content: string): Promise<string>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback registries for extension events
|
||||||
|
*/
|
||||||
|
interface CallbackRegistries {
|
||||||
|
paymentReceived: Array<(payment: PaymentReceivedData) => Promise<void>>
|
||||||
|
nostrEvent: Array<(event: NostrEvent, applicationId: string) => Promise<void>>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registered RPC method
|
||||||
|
*/
|
||||||
|
interface RegisteredMethod {
|
||||||
|
extensionId: string
|
||||||
|
handler: RpcMethodHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension Context Implementation
|
||||||
|
*
|
||||||
|
* Provides the interface for extensions to interact with Lightning.Pub.
|
||||||
|
* Each extension gets its own context instance.
|
||||||
|
*/
|
||||||
|
export class ExtensionContextImpl implements ExtensionContext {
|
||||||
|
private callbacks: CallbackRegistries = {
|
||||||
|
paymentReceived: [],
|
||||||
|
nostrEvent: []
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private extensionInfo: ExtensionInfo,
|
||||||
|
private database: ExtensionDatabase,
|
||||||
|
private mainHandler: MainHandlerInterface,
|
||||||
|
private methodRegistry: Map<string, RegisteredMethod>
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about an application
|
||||||
|
*/
|
||||||
|
async getApplication(applicationId: string): Promise<ApplicationInfo | null> {
|
||||||
|
try {
|
||||||
|
const app = await this.mainHandler.applicationManager.getById(applicationId)
|
||||||
|
if (!app) return null
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: app.id,
|
||||||
|
name: app.name,
|
||||||
|
nostr_public: app.nostr_public,
|
||||||
|
balance_sats: app.balance || 0
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.log('error', `Failed to get application ${applicationId}:`, e)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Lightning invoice
|
||||||
|
*/
|
||||||
|
async createInvoice(amountSats: number, options: CreateInvoiceOptions = {}): Promise<CreatedInvoice> {
|
||||||
|
// Note: In practice, this needs an applicationId. Extensions typically
|
||||||
|
// get this from the RPC request context. For now, we'll need to handle
|
||||||
|
// this in the actual implementation.
|
||||||
|
throw new Error('createInvoice requires applicationId from request context')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create invoice with explicit application ID
|
||||||
|
* This is the internal method used by extensions
|
||||||
|
*/
|
||||||
|
async createInvoiceForApp(
|
||||||
|
applicationId: string,
|
||||||
|
amountSats: number,
|
||||||
|
options: CreateInvoiceOptions = {}
|
||||||
|
): Promise<CreatedInvoice> {
|
||||||
|
const result = await this.mainHandler.paymentManager.createInvoice({
|
||||||
|
applicationId,
|
||||||
|
amountSats,
|
||||||
|
memo: options.memo,
|
||||||
|
expiry: options.expiry,
|
||||||
|
metadata: {
|
||||||
|
...options.metadata,
|
||||||
|
extension: this.extensionInfo.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: result.id,
|
||||||
|
paymentRequest: result.paymentRequest,
|
||||||
|
paymentHash: result.paymentHash,
|
||||||
|
expiry: result.expiry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pay a Lightning invoice
|
||||||
|
*/
|
||||||
|
async payInvoice(
|
||||||
|
applicationId: string,
|
||||||
|
paymentRequest: string,
|
||||||
|
maxFeeSats?: number
|
||||||
|
): Promise<{ paymentHash: string; feeSats: number }> {
|
||||||
|
return this.mainHandler.paymentManager.payInvoice({
|
||||||
|
applicationId,
|
||||||
|
paymentRequest,
|
||||||
|
maxFeeSats
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an encrypted DM via Nostr
|
||||||
|
*/
|
||||||
|
async sendEncryptedDM(
|
||||||
|
applicationId: string,
|
||||||
|
recipientPubkey: string,
|
||||||
|
content: string
|
||||||
|
): Promise<string> {
|
||||||
|
return this.mainHandler.sendEncryptedDM(applicationId, recipientPubkey, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish a Nostr event
|
||||||
|
*/
|
||||||
|
async publishNostrEvent(event: UnsignedNostrEvent): Promise<string | null> {
|
||||||
|
return this.mainHandler.sendNostrEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LNURL-pay info for a user by pubkey
|
||||||
|
* Enables Lightning Address and zap support
|
||||||
|
*/
|
||||||
|
async getLnurlPayInfo(pubkeyHex: string, options?: {
|
||||||
|
metadata?: string
|
||||||
|
description?: string
|
||||||
|
}): Promise<LnurlPayInfo> {
|
||||||
|
return this.mainHandler.paymentManager.getLnurlPayInfoByPubkey(pubkeyHex, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to payment received callbacks
|
||||||
|
*/
|
||||||
|
onPaymentReceived(callback: (payment: PaymentReceivedData) => Promise<void>): void {
|
||||||
|
this.callbacks.paymentReceived.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to incoming Nostr events
|
||||||
|
*/
|
||||||
|
onNostrEvent(callback: (event: NostrEvent, applicationId: string) => Promise<void>): void {
|
||||||
|
this.callbacks.nostrEvent.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an RPC method
|
||||||
|
*/
|
||||||
|
registerMethod(name: string, handler: RpcMethodHandler): void {
|
||||||
|
const fullName = name.startsWith(`${this.extensionInfo.id}.`)
|
||||||
|
? name
|
||||||
|
: `${this.extensionInfo.id}.${name}`
|
||||||
|
|
||||||
|
if (this.methodRegistry.has(fullName)) {
|
||||||
|
throw new Error(`RPC method ${fullName} already registered`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.methodRegistry.set(fullName, {
|
||||||
|
extensionId: this.extensionInfo.id,
|
||||||
|
handler
|
||||||
|
})
|
||||||
|
|
||||||
|
this.log('debug', `Registered RPC method: ${fullName}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extension's database
|
||||||
|
*/
|
||||||
|
getDatabase(): ExtensionDatabase {
|
||||||
|
return this.database
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a message
|
||||||
|
*/
|
||||||
|
log(level: 'debug' | 'info' | 'warn' | 'error', message: string, ...args: any[]): void {
|
||||||
|
const prefix = `[Extension:${this.extensionInfo.id}]`
|
||||||
|
switch (level) {
|
||||||
|
case 'debug':
|
||||||
|
console.debug(prefix, message, ...args)
|
||||||
|
break
|
||||||
|
case 'info':
|
||||||
|
console.info(prefix, message, ...args)
|
||||||
|
break
|
||||||
|
case 'warn':
|
||||||
|
console.warn(prefix, message, ...args)
|
||||||
|
break
|
||||||
|
case 'error':
|
||||||
|
console.error(prefix, message, ...args)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Internal Methods (called by ExtensionLoader) =====
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch payment received event to extension callbacks
|
||||||
|
*/
|
||||||
|
async dispatchPaymentReceived(payment: PaymentReceivedData): Promise<void> {
|
||||||
|
for (const callback of this.callbacks.paymentReceived) {
|
||||||
|
try {
|
||||||
|
await callback(payment)
|
||||||
|
} catch (e) {
|
||||||
|
this.log('error', 'Error in payment callback:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch Nostr event to extension callbacks
|
||||||
|
*/
|
||||||
|
async dispatchNostrEvent(event: NostrEvent, applicationId: string): Promise<void> {
|
||||||
|
for (const callback of this.callbacks.nostrEvent) {
|
||||||
|
try {
|
||||||
|
await callback(event, applicationId)
|
||||||
|
} catch (e) {
|
||||||
|
this.log('error', 'Error in Nostr event callback:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get registered callbacks for external access
|
||||||
|
*/
|
||||||
|
getCallbacks(): CallbackRegistries {
|
||||||
|
return this.callbacks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an extension context
|
||||||
|
*/
|
||||||
|
export function createExtensionContext(
|
||||||
|
extensionInfo: ExtensionInfo,
|
||||||
|
database: ExtensionDatabase,
|
||||||
|
mainHandler: MainHandlerInterface,
|
||||||
|
methodRegistry: Map<string, RegisteredMethod>
|
||||||
|
): ExtensionContextImpl {
|
||||||
|
return new ExtensionContextImpl(extensionInfo, database, mainHandler, methodRegistry)
|
||||||
|
}
|
||||||
148
src/extensions/database.ts
Normal file
148
src/extensions/database.ts
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
import Database from 'better-sqlite3'
|
||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs'
|
||||||
|
import { ExtensionDatabase } from './types.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension Database Implementation
|
||||||
|
*
|
||||||
|
* Provides isolated SQLite database access for each extension.
|
||||||
|
* Uses better-sqlite3 for synchronous, high-performance access.
|
||||||
|
*/
|
||||||
|
export class ExtensionDatabaseImpl implements ExtensionDatabase {
|
||||||
|
private db: Database.Database
|
||||||
|
private extensionId: string
|
||||||
|
|
||||||
|
constructor(extensionId: string, databaseDir: string) {
|
||||||
|
this.extensionId = extensionId
|
||||||
|
|
||||||
|
// Ensure database directory exists
|
||||||
|
if (!fs.existsSync(databaseDir)) {
|
||||||
|
fs.mkdirSync(databaseDir, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create database file for this extension
|
||||||
|
const dbPath = path.join(databaseDir, `${extensionId}.db`)
|
||||||
|
this.db = new Database(dbPath)
|
||||||
|
|
||||||
|
// Enable WAL mode for better concurrency
|
||||||
|
this.db.pragma('journal_mode = WAL')
|
||||||
|
|
||||||
|
// Enable foreign keys
|
||||||
|
this.db.pragma('foreign_keys = ON')
|
||||||
|
|
||||||
|
// Create metadata table for tracking migrations
|
||||||
|
this.db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS _extension_meta (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a write query (INSERT, UPDATE, DELETE, CREATE, etc.)
|
||||||
|
*/
|
||||||
|
async execute(sql: string, params: any[] = []): Promise<{ changes?: number; lastId?: number }> {
|
||||||
|
try {
|
||||||
|
const stmt = this.db.prepare(sql)
|
||||||
|
const result = stmt.run(...params)
|
||||||
|
|
||||||
|
return {
|
||||||
|
changes: result.changes,
|
||||||
|
lastId: result.lastInsertRowid as number
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[Extension:${this.extensionId}] Database execute error:`, e)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a read query (SELECT)
|
||||||
|
*/
|
||||||
|
async query<T = any>(sql: string, params: any[] = []): Promise<T[]> {
|
||||||
|
try {
|
||||||
|
const stmt = this.db.prepare(sql)
|
||||||
|
return stmt.all(...params) as T[]
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[Extension:${this.extensionId}] Database query error:`, e)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute multiple statements in a transaction
|
||||||
|
*/
|
||||||
|
async transaction<T>(fn: () => Promise<T>): Promise<T> {
|
||||||
|
const runTransaction = this.db.transaction(() => {
|
||||||
|
// Note: better-sqlite3 transactions are synchronous
|
||||||
|
// We wrap the async function but it executes synchronously
|
||||||
|
return fn()
|
||||||
|
})
|
||||||
|
|
||||||
|
return runTransaction() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a metadata value
|
||||||
|
*/
|
||||||
|
async getMeta(key: string): Promise<string | null> {
|
||||||
|
const rows = await this.query<{ value: string }>(
|
||||||
|
'SELECT value FROM _extension_meta WHERE key = ?',
|
||||||
|
[key]
|
||||||
|
)
|
||||||
|
return rows.length > 0 ? rows[0].value : null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a metadata value
|
||||||
|
*/
|
||||||
|
async setMeta(key: string, value: string): Promise<void> {
|
||||||
|
await this.execute(
|
||||||
|
`INSERT INTO _extension_meta (key, value) VALUES (?, ?)
|
||||||
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
|
||||||
|
[key, value]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current migration version
|
||||||
|
*/
|
||||||
|
async getMigrationVersion(): Promise<number> {
|
||||||
|
const version = await this.getMeta('migration_version')
|
||||||
|
return version ? parseInt(version, 10) : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set migration version
|
||||||
|
*/
|
||||||
|
async setMigrationVersion(version: number): Promise<void> {
|
||||||
|
await this.setMeta('migration_version', String(version))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the database connection
|
||||||
|
*/
|
||||||
|
close(): void {
|
||||||
|
this.db.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the underlying database for advanced operations
|
||||||
|
* (Use with caution - bypasses isolation)
|
||||||
|
*/
|
||||||
|
getUnderlyingDb(): Database.Database {
|
||||||
|
return this.db
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an extension database instance
|
||||||
|
*/
|
||||||
|
export function createExtensionDatabase(
|
||||||
|
extensionId: string,
|
||||||
|
databaseDir: string
|
||||||
|
): ExtensionDatabaseImpl {
|
||||||
|
return new ExtensionDatabaseImpl(extensionId, databaseDir)
|
||||||
|
}
|
||||||
56
src/extensions/index.ts
Normal file
56
src/extensions/index.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
* Lightning.Pub Extension System
|
||||||
|
*
|
||||||
|
* This module provides the extension infrastructure for Lightning.Pub.
|
||||||
|
* Extensions can add functionality like marketplaces, subscriptions,
|
||||||
|
* tipping, and more.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* import { createExtensionLoader, ExtensionLoaderConfig } from './extensions'
|
||||||
|
*
|
||||||
|
* const config: ExtensionLoaderConfig = {
|
||||||
|
* extensionsDir: './extensions',
|
||||||
|
* databaseDir: './data/extensions'
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const loader = createExtensionLoader(config, mainHandler)
|
||||||
|
* await loader.loadAll()
|
||||||
|
*
|
||||||
|
* // Call extension methods
|
||||||
|
* const result = await loader.callMethod(
|
||||||
|
* 'marketplace.createStall',
|
||||||
|
* { name: 'My Shop', currency: 'sat', shipping_zones: [...] },
|
||||||
|
* applicationId
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Export types
|
||||||
|
export {
|
||||||
|
Extension,
|
||||||
|
ExtensionInfo,
|
||||||
|
ExtensionContext,
|
||||||
|
ExtensionDatabase,
|
||||||
|
ExtensionModule,
|
||||||
|
ExtensionConstructor,
|
||||||
|
LoadedExtension,
|
||||||
|
ExtensionLoaderConfig,
|
||||||
|
ApplicationInfo,
|
||||||
|
CreateInvoiceOptions,
|
||||||
|
CreatedInvoice,
|
||||||
|
PaymentReceivedData,
|
||||||
|
NostrEvent,
|
||||||
|
UnsignedNostrEvent,
|
||||||
|
RpcMethodHandler
|
||||||
|
} from './types.js'
|
||||||
|
|
||||||
|
// Export loader
|
||||||
|
export { ExtensionLoader, createExtensionLoader } from './loader.js'
|
||||||
|
|
||||||
|
// Export database utilities
|
||||||
|
export { ExtensionDatabaseImpl, createExtensionDatabase } from './database.js'
|
||||||
|
|
||||||
|
// Export context utilities
|
||||||
|
export { ExtensionContextImpl, createExtensionContext, MainHandlerInterface } from './context.js'
|
||||||
406
src/extensions/loader.ts
Normal file
406
src/extensions/loader.ts
Normal file
|
|
@ -0,0 +1,406 @@
|
||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs'
|
||||||
|
import {
|
||||||
|
Extension,
|
||||||
|
ExtensionInfo,
|
||||||
|
ExtensionModule,
|
||||||
|
LoadedExtension,
|
||||||
|
ExtensionLoaderConfig,
|
||||||
|
RpcMethodHandler,
|
||||||
|
PaymentReceivedData,
|
||||||
|
NostrEvent
|
||||||
|
} from './types.js'
|
||||||
|
import { ExtensionDatabaseImpl, createExtensionDatabase } from './database.js'
|
||||||
|
import { ExtensionContextImpl, createExtensionContext, MainHandlerInterface } from './context.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registered RPC method entry
|
||||||
|
*/
|
||||||
|
interface RegisteredMethod {
|
||||||
|
extensionId: string
|
||||||
|
handler: RpcMethodHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension Loader
|
||||||
|
*
|
||||||
|
* Discovers, loads, and manages Lightning.Pub extensions.
|
||||||
|
* Provides lifecycle management and event dispatching.
|
||||||
|
*/
|
||||||
|
export class ExtensionLoader {
|
||||||
|
private config: ExtensionLoaderConfig
|
||||||
|
private mainHandler: MainHandlerInterface
|
||||||
|
private extensions: Map<string, LoadedExtension> = new Map()
|
||||||
|
private contexts: Map<string, ExtensionContextImpl> = new Map()
|
||||||
|
private methodRegistry: Map<string, RegisteredMethod> = new Map()
|
||||||
|
private initialized = false
|
||||||
|
|
||||||
|
constructor(config: ExtensionLoaderConfig, mainHandler: MainHandlerInterface) {
|
||||||
|
this.config = config
|
||||||
|
this.mainHandler = mainHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover and load all extensions
|
||||||
|
*/
|
||||||
|
async loadAll(): Promise<void> {
|
||||||
|
if (this.initialized) {
|
||||||
|
throw new Error('Extension loader already initialized')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[Extensions] Loading extensions from:', this.config.extensionsDir)
|
||||||
|
|
||||||
|
// Ensure directories exist
|
||||||
|
if (!fs.existsSync(this.config.extensionsDir)) {
|
||||||
|
console.log('[Extensions] Extensions directory does not exist, creating...')
|
||||||
|
fs.mkdirSync(this.config.extensionsDir, { recursive: true })
|
||||||
|
this.initialized = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(this.config.databaseDir)) {
|
||||||
|
fs.mkdirSync(this.config.databaseDir, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discover extensions
|
||||||
|
const extensionDirs = await this.discoverExtensions()
|
||||||
|
console.log(`[Extensions] Found ${extensionDirs.length} extension(s)`)
|
||||||
|
|
||||||
|
// Load extensions in dependency order
|
||||||
|
const loadOrder = await this.resolveDependencies(extensionDirs)
|
||||||
|
|
||||||
|
for (const extDir of loadOrder) {
|
||||||
|
try {
|
||||||
|
await this.loadExtension(extDir)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[Extensions] Failed to load extension from ${extDir}:`, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialized = true
|
||||||
|
console.log(`[Extensions] Loaded ${this.extensions.size} extension(s)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover extension directories
|
||||||
|
*/
|
||||||
|
private async discoverExtensions(): Promise<string[]> {
|
||||||
|
const entries = fs.readdirSync(this.config.extensionsDir, { withFileTypes: true })
|
||||||
|
const extensionDirs: string[] = []
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (!entry.isDirectory()) continue
|
||||||
|
|
||||||
|
const extDir = path.join(this.config.extensionsDir, entry.name)
|
||||||
|
const indexPath = path.join(extDir, 'index.ts')
|
||||||
|
const indexJsPath = path.join(extDir, 'index.js')
|
||||||
|
|
||||||
|
// Check for index file
|
||||||
|
if (fs.existsSync(indexPath) || fs.existsSync(indexJsPath)) {
|
||||||
|
// Check enabled/disabled lists
|
||||||
|
if (this.config.disabledExtensions?.includes(entry.name)) {
|
||||||
|
console.log(`[Extensions] Skipping disabled extension: ${entry.name}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.config.enabledExtensions &&
|
||||||
|
!this.config.enabledExtensions.includes(entry.name)) {
|
||||||
|
console.log(`[Extensions] Skipping non-enabled extension: ${entry.name}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
extensionDirs.push(extDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extensionDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve extension dependencies and return load order
|
||||||
|
*/
|
||||||
|
private async resolveDependencies(extensionDirs: string[]): Promise<string[]> {
|
||||||
|
// For now, simple alphabetical order
|
||||||
|
// TODO: Implement proper dependency resolution with topological sort
|
||||||
|
return extensionDirs.sort()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a single extension
|
||||||
|
*/
|
||||||
|
private async loadExtension(extensionDir: string): Promise<void> {
|
||||||
|
const dirName = path.basename(extensionDir)
|
||||||
|
console.log(`[Extensions] Loading extension: ${dirName}`)
|
||||||
|
|
||||||
|
// Determine index file path
|
||||||
|
let indexPath = path.join(extensionDir, 'index.js')
|
||||||
|
if (!fs.existsSync(indexPath)) {
|
||||||
|
indexPath = path.join(extensionDir, 'index.ts')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic import
|
||||||
|
const moduleUrl = `file://${indexPath}`
|
||||||
|
const module = await import(moduleUrl) as ExtensionModule
|
||||||
|
|
||||||
|
if (!module.default) {
|
||||||
|
throw new Error(`Extension ${dirName} has no default export`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate extension
|
||||||
|
const ExtensionClass = module.default
|
||||||
|
const instance = new ExtensionClass() as Extension
|
||||||
|
|
||||||
|
if (!instance.info) {
|
||||||
|
throw new Error(`Extension ${dirName} has no info property`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = instance.info
|
||||||
|
|
||||||
|
// Validate extension ID matches directory name
|
||||||
|
if (info.id !== dirName) {
|
||||||
|
console.warn(
|
||||||
|
`[Extensions] Extension ID '${info.id}' doesn't match directory '${dirName}'`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate
|
||||||
|
if (this.extensions.has(info.id)) {
|
||||||
|
throw new Error(`Extension ${info.id} already loaded`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create isolated database
|
||||||
|
const database = createExtensionDatabase(info.id, this.config.databaseDir)
|
||||||
|
|
||||||
|
// Create context
|
||||||
|
const context = createExtensionContext(
|
||||||
|
info,
|
||||||
|
database,
|
||||||
|
this.mainHandler,
|
||||||
|
this.methodRegistry
|
||||||
|
)
|
||||||
|
|
||||||
|
// Track as loading
|
||||||
|
const loaded: LoadedExtension = {
|
||||||
|
info,
|
||||||
|
instance,
|
||||||
|
database,
|
||||||
|
status: 'loading',
|
||||||
|
loadedAt: Date.now()
|
||||||
|
}
|
||||||
|
this.extensions.set(info.id, loaded)
|
||||||
|
this.contexts.set(info.id, context)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize extension
|
||||||
|
await instance.initialize(context, database)
|
||||||
|
|
||||||
|
loaded.status = 'ready'
|
||||||
|
console.log(`[Extensions] Extension ${info.id} v${info.version} loaded successfully`)
|
||||||
|
} catch (e) {
|
||||||
|
loaded.status = 'error'
|
||||||
|
loaded.error = e as Error
|
||||||
|
console.error(`[Extensions] Extension ${info.id} initialization failed:`, e)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unload a specific extension
|
||||||
|
*/
|
||||||
|
async unloadExtension(extensionId: string): Promise<void> {
|
||||||
|
const loaded = this.extensions.get(extensionId)
|
||||||
|
if (!loaded) {
|
||||||
|
throw new Error(`Extension ${extensionId} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[Extensions] Unloading extension: ${extensionId}`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Call shutdown if available
|
||||||
|
if (loaded.instance.shutdown) {
|
||||||
|
await loaded.instance.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded.status = 'stopped'
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[Extensions] Error during ${extensionId} shutdown:`, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close database
|
||||||
|
if (loaded.database instanceof ExtensionDatabaseImpl) {
|
||||||
|
loaded.database.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove registered methods
|
||||||
|
for (const [name, method] of this.methodRegistry.entries()) {
|
||||||
|
if (method.extensionId === extensionId) {
|
||||||
|
this.methodRegistry.delete(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from maps
|
||||||
|
this.extensions.delete(extensionId)
|
||||||
|
this.contexts.delete(extensionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown all extensions
|
||||||
|
*/
|
||||||
|
async shutdown(): Promise<void> {
|
||||||
|
console.log('[Extensions] Shutting down all extensions...')
|
||||||
|
|
||||||
|
for (const extensionId of this.extensions.keys()) {
|
||||||
|
try {
|
||||||
|
await this.unloadExtension(extensionId)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[Extensions] Error unloading ${extensionId}:`, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[Extensions] All extensions shut down')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a loaded extension
|
||||||
|
*/
|
||||||
|
getExtension(extensionId: string): LoadedExtension | undefined {
|
||||||
|
return this.extensions.get(extensionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all loaded extensions
|
||||||
|
*/
|
||||||
|
getAllExtensions(): LoadedExtension[] {
|
||||||
|
return Array.from(this.extensions.values())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an extension is loaded and ready
|
||||||
|
*/
|
||||||
|
isReady(extensionId: string): boolean {
|
||||||
|
const ext = this.extensions.get(extensionId)
|
||||||
|
return ext?.status === 'ready'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all registered RPC methods
|
||||||
|
*/
|
||||||
|
getRegisteredMethods(): Map<string, RegisteredMethod> {
|
||||||
|
return this.methodRegistry
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call an extension RPC method
|
||||||
|
*/
|
||||||
|
async callMethod(
|
||||||
|
methodName: string,
|
||||||
|
request: any,
|
||||||
|
applicationId: string,
|
||||||
|
userPubkey?: string
|
||||||
|
): Promise<any> {
|
||||||
|
const method = this.methodRegistry.get(methodName)
|
||||||
|
if (!method) {
|
||||||
|
throw new Error(`Unknown method: ${methodName}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ext = this.extensions.get(method.extensionId)
|
||||||
|
if (!ext || ext.status !== 'ready') {
|
||||||
|
throw new Error(`Extension ${method.extensionId} not ready`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return method.handler(request, applicationId, userPubkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a method exists
|
||||||
|
*/
|
||||||
|
hasMethod(methodName: string): boolean {
|
||||||
|
return this.methodRegistry.has(methodName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch payment received event to all extensions
|
||||||
|
*/
|
||||||
|
async dispatchPaymentReceived(payment: PaymentReceivedData): Promise<void> {
|
||||||
|
for (const context of this.contexts.values()) {
|
||||||
|
try {
|
||||||
|
await context.dispatchPaymentReceived(payment)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[Extensions] Error dispatching payment:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch Nostr event to all extensions
|
||||||
|
*/
|
||||||
|
async dispatchNostrEvent(event: NostrEvent, applicationId: string): Promise<void> {
|
||||||
|
for (const context of this.contexts.values()) {
|
||||||
|
try {
|
||||||
|
await context.dispatchNostrEvent(event, applicationId)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[Extensions] Error dispatching Nostr event:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run health checks on all extensions
|
||||||
|
*/
|
||||||
|
async healthCheck(): Promise<Map<string, boolean>> {
|
||||||
|
const results = new Map<string, boolean>()
|
||||||
|
|
||||||
|
for (const [id, ext] of this.extensions.entries()) {
|
||||||
|
if (ext.status !== 'ready') {
|
||||||
|
results.set(id, false)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (ext.instance.healthCheck) {
|
||||||
|
results.set(id, await ext.instance.healthCheck())
|
||||||
|
} else {
|
||||||
|
results.set(id, true)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
results.set(id, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get extension status summary
|
||||||
|
*/
|
||||||
|
getStatus(): {
|
||||||
|
total: number
|
||||||
|
ready: number
|
||||||
|
error: number
|
||||||
|
extensions: Array<{ id: string; name: string; version: string; status: string }>
|
||||||
|
} {
|
||||||
|
const extensions = this.getAllExtensions().map(ext => ({
|
||||||
|
id: ext.info.id,
|
||||||
|
name: ext.info.name,
|
||||||
|
version: ext.info.version,
|
||||||
|
status: ext.status
|
||||||
|
}))
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: extensions.length,
|
||||||
|
ready: extensions.filter(e => e.status === 'ready').length,
|
||||||
|
error: extensions.filter(e => e.status === 'error').length,
|
||||||
|
extensions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an extension loader instance
|
||||||
|
*/
|
||||||
|
export function createExtensionLoader(
|
||||||
|
config: ExtensionLoaderConfig,
|
||||||
|
mainHandler: MainHandlerInterface
|
||||||
|
): ExtensionLoader {
|
||||||
|
return new ExtensionLoader(config, mainHandler)
|
||||||
|
}
|
||||||
285
src/extensions/types.ts
Normal file
285
src/extensions/types.ts
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
/**
|
||||||
|
* Extension System Core Types
|
||||||
|
*
|
||||||
|
* These types define the contract between Lightning.Pub and extensions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension metadata
|
||||||
|
*/
|
||||||
|
export interface ExtensionInfo {
|
||||||
|
id: string // Unique identifier (lowercase, no spaces)
|
||||||
|
name: string // Display name
|
||||||
|
version: string // Semver version
|
||||||
|
description: string // Short description
|
||||||
|
author: string // Author name or organization
|
||||||
|
minPubVersion?: string // Minimum Lightning.Pub version required
|
||||||
|
dependencies?: string[] // Other extension IDs this depends on
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension database interface
|
||||||
|
* Provides isolated database access for each extension
|
||||||
|
*/
|
||||||
|
export interface ExtensionDatabase {
|
||||||
|
/**
|
||||||
|
* Execute a write query (INSERT, UPDATE, DELETE, CREATE, etc.)
|
||||||
|
*/
|
||||||
|
execute(sql: string, params?: any[]): Promise<{ changes?: number; lastId?: number }>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a read query (SELECT)
|
||||||
|
*/
|
||||||
|
query<T = any>(sql: string, params?: any[]): Promise<T[]>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute multiple statements in a transaction
|
||||||
|
*/
|
||||||
|
transaction<T>(fn: () => Promise<T>): Promise<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application info provided to extensions
|
||||||
|
*/
|
||||||
|
export interface ApplicationInfo {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
nostr_public: string // Application's Nostr pubkey (hex)
|
||||||
|
balance_sats: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice creation options
|
||||||
|
*/
|
||||||
|
export interface CreateInvoiceOptions {
|
||||||
|
memo?: string
|
||||||
|
expiry?: number // Seconds until expiry
|
||||||
|
metadata?: Record<string, any> // Custom metadata for callbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created invoice result
|
||||||
|
*/
|
||||||
|
export interface CreatedInvoice {
|
||||||
|
id: string // Internal invoice ID
|
||||||
|
paymentRequest: string // BOLT11 invoice string
|
||||||
|
paymentHash: string // Payment hash (hex)
|
||||||
|
expiry: number // Expiry timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment received callback data
|
||||||
|
*/
|
||||||
|
export interface PaymentReceivedData {
|
||||||
|
invoiceId: string
|
||||||
|
paymentHash: string
|
||||||
|
amountSats: number
|
||||||
|
metadata?: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LNURL-pay info response (LUD-06/LUD-16)
|
||||||
|
* Used for Lightning Address and zap support
|
||||||
|
*/
|
||||||
|
export interface LnurlPayInfo {
|
||||||
|
tag: 'payRequest'
|
||||||
|
callback: string // URL to call with amount
|
||||||
|
minSendable: number // Minimum msats
|
||||||
|
maxSendable: number // Maximum msats
|
||||||
|
metadata: string // JSON-encoded metadata array
|
||||||
|
allowsNostr?: boolean // Whether zaps are supported
|
||||||
|
nostrPubkey?: string // Pubkey for zap receipts (hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nostr event structure (minimal)
|
||||||
|
*/
|
||||||
|
export interface NostrEvent {
|
||||||
|
id: string
|
||||||
|
pubkey: string
|
||||||
|
created_at: number
|
||||||
|
kind: number
|
||||||
|
tags: string[][]
|
||||||
|
content: string
|
||||||
|
sig?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsigned Nostr event for publishing
|
||||||
|
*/
|
||||||
|
export interface UnsignedNostrEvent {
|
||||||
|
kind: number
|
||||||
|
pubkey: string
|
||||||
|
created_at: number
|
||||||
|
tags: string[][]
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RPC method handler function
|
||||||
|
*/
|
||||||
|
export type RpcMethodHandler = (
|
||||||
|
request: any,
|
||||||
|
applicationId: string,
|
||||||
|
userPubkey?: string
|
||||||
|
) => Promise<any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension context - interface provided to extensions for interacting with Lightning.Pub
|
||||||
|
*/
|
||||||
|
export interface ExtensionContext {
|
||||||
|
/**
|
||||||
|
* Get information about an application
|
||||||
|
*/
|
||||||
|
getApplication(applicationId: string): Promise<ApplicationInfo | null>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Lightning invoice
|
||||||
|
*/
|
||||||
|
createInvoice(amountSats: number, options?: CreateInvoiceOptions): Promise<CreatedInvoice>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pay a Lightning invoice (requires sufficient balance)
|
||||||
|
*/
|
||||||
|
payInvoice(applicationId: string, paymentRequest: string, maxFeeSats?: number): Promise<{
|
||||||
|
paymentHash: string
|
||||||
|
feeSats: number
|
||||||
|
}>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an encrypted DM via Nostr (NIP-44)
|
||||||
|
*/
|
||||||
|
sendEncryptedDM(applicationId: string, recipientPubkey: string, content: string): Promise<string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish a Nostr event (signed by application's key)
|
||||||
|
*/
|
||||||
|
publishNostrEvent(event: UnsignedNostrEvent): Promise<string | null>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LNURL-pay info for a user (by pubkey)
|
||||||
|
* Used to enable Lightning Address support (LUD-16) and zaps (NIP-57)
|
||||||
|
*/
|
||||||
|
getLnurlPayInfo(pubkeyHex: string, options?: {
|
||||||
|
metadata?: string // Custom metadata JSON
|
||||||
|
description?: string // Human-readable description
|
||||||
|
}): Promise<LnurlPayInfo>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to payment received callbacks
|
||||||
|
*/
|
||||||
|
onPaymentReceived(callback: (payment: PaymentReceivedData) => Promise<void>): void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to incoming Nostr events for the application
|
||||||
|
*/
|
||||||
|
onNostrEvent(callback: (event: NostrEvent, applicationId: string) => Promise<void>): void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an RPC method
|
||||||
|
*/
|
||||||
|
registerMethod(name: string, handler: RpcMethodHandler): void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extension's isolated database
|
||||||
|
*/
|
||||||
|
getDatabase(): ExtensionDatabase
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a message (prefixed with extension ID)
|
||||||
|
*/
|
||||||
|
log(level: 'debug' | 'info' | 'warn' | 'error', message: string, ...args: any[]): void
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP route handler types
|
||||||
|
* Used by extensions that expose HTTP endpoints (e.g. LNURL, .well-known)
|
||||||
|
*/
|
||||||
|
export interface HttpRequest {
|
||||||
|
method: string
|
||||||
|
path: string
|
||||||
|
params: Record<string, string>
|
||||||
|
query: Record<string, string>
|
||||||
|
headers: Record<string, string>
|
||||||
|
body?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HttpResponse {
|
||||||
|
status: number
|
||||||
|
body: any
|
||||||
|
headers?: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HttpRoute {
|
||||||
|
method: 'GET' | 'POST'
|
||||||
|
path: string
|
||||||
|
handler: (req: HttpRequest) => Promise<HttpResponse>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension interface - what extensions must implement
|
||||||
|
*/
|
||||||
|
export interface Extension {
|
||||||
|
/**
|
||||||
|
* Extension metadata
|
||||||
|
*/
|
||||||
|
readonly info: ExtensionInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the extension
|
||||||
|
* Called once when the extension is loaded
|
||||||
|
*/
|
||||||
|
initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the extension
|
||||||
|
* Called when Lightning.Pub is shutting down
|
||||||
|
*/
|
||||||
|
shutdown?(): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health check
|
||||||
|
* Return true if extension is healthy
|
||||||
|
*/
|
||||||
|
healthCheck?(): Promise<boolean>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get HTTP routes exposed by this extension
|
||||||
|
* The main HTTP server will mount these routes
|
||||||
|
*/
|
||||||
|
getHttpRoutes?(): HttpRoute[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension constructor type
|
||||||
|
*/
|
||||||
|
export type ExtensionConstructor = new () => Extension
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension module default export
|
||||||
|
*/
|
||||||
|
export interface ExtensionModule {
|
||||||
|
default: ExtensionConstructor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loaded extension state
|
||||||
|
*/
|
||||||
|
export interface LoadedExtension {
|
||||||
|
info: ExtensionInfo
|
||||||
|
instance: Extension
|
||||||
|
database: ExtensionDatabase
|
||||||
|
status: 'loading' | 'ready' | 'error' | 'stopped'
|
||||||
|
error?: Error
|
||||||
|
loadedAt: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension loader configuration
|
||||||
|
*/
|
||||||
|
export interface ExtensionLoaderConfig {
|
||||||
|
extensionsDir: string // Directory containing extensions
|
||||||
|
databaseDir: string // Directory for extension databases
|
||||||
|
enabledExtensions?: string[] // If set, only load these extensions
|
||||||
|
disabledExtensions?: string[] // Extensions to skip
|
||||||
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Stop: () => { mainHandler.adminManager.setNostrConnected(false); return nostr.Stop },
|
Stop: () => { mainHandler.adminManager.setNostrConnected(false); return nostr.Stop },
|
||||||
Send: (...args) => nostr.Send(...args),
|
Send: async (...args) => nostr.Send(...args),
|
||||||
Ping: () => nostr.Ping(),
|
Ping: () => nostr.Ping(),
|
||||||
Reset: (settings: NostrSettings) => nostr.Reset(settings)
|
Reset: (settings: NostrSettings) => nostr.Reset(settings)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
export const DEBUG = Symbol("DEBUG")
|
export const DEBUG = Symbol("DEBUG")
|
||||||
export const ERROR = Symbol("ERROR")
|
export const ERROR = Symbol("ERROR")
|
||||||
export const WARN = Symbol("WARN")
|
export const INFO = Symbol("INFO")
|
||||||
type LoggerParams = { appName?: string, userId?: string, component?: string }
|
type LoggerParams = { appName?: string, userId?: string, component?: string }
|
||||||
export type PubLogger = (...message: (string | number | object | symbol)[]) => void
|
export type PubLogger = (...message: (string | number | object | symbol)[]) => void
|
||||||
type Writer = (message: string) => void
|
type Writer = (message: string) => void
|
||||||
const logsDir = process.env.LOGS_DIR || "logs"
|
const logsDir = process.env.LOGS_DIR || "logs"
|
||||||
const logLevel = process.env.LOG_LEVEL || "DEBUG"
|
const logLevel = process.env.LOG_LEVEL || "INFO"
|
||||||
try {
|
try {
|
||||||
fs.mkdirSync(logsDir)
|
fs.mkdirSync(logsDir)
|
||||||
} catch { }
|
} catch { }
|
||||||
if (logLevel !== "DEBUG" && logLevel !== "WARN" && logLevel !== "ERROR") {
|
if (logLevel !== "DEBUG" && logLevel !== "INFO" && logLevel !== "ERROR") {
|
||||||
throw new Error("Invalid log level " + logLevel + " must be one of (DEBUG, WARN, ERROR)")
|
throw new Error("Invalid log level " + logLevel + " must be one of (DEBUG, INFO, ERROR)")
|
||||||
}
|
}
|
||||||
const z = (n: number) => n < 10 ? `0${n}` : `${n}`
|
const z = (n: number) => n < 10 ? `0${n}` : `${n}`
|
||||||
// Sanitize filename to remove invalid characters for filesystem
|
// Sanitize filename to remove invalid characters for filesystem
|
||||||
|
|
@ -67,19 +67,17 @@ export const getLogger = (params: LoggerParams): PubLogger => {
|
||||||
}
|
}
|
||||||
message[0] = "DEBUG"
|
message[0] = "DEBUG"
|
||||||
break;
|
break;
|
||||||
case WARN:
|
case INFO:
|
||||||
if (logLevel === "ERROR") {
|
if (logLevel === "ERROR") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message[0] = "WARN"
|
message[0] = "INFO"
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
message[0] = "ERROR"
|
message[0] = "ERROR"
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (logLevel !== "DEBUG") {
|
// treats logs without a level as ERROR level, without prefix so it can be found and fixed if needed
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const timestamp = `${now.getFullYear()}-${z(now.getMonth() + 1)}-${z(now.getDate())} ${z(now.getHours())}:${z(now.getMinutes())}:${z(now.getSeconds())}`
|
const timestamp = `${now.getFullYear()}-${z(now.getMonth() + 1)}-${z(now.getDate())} ${z(now.getHours())}:${z(now.getMinutes())}:${z(now.getSeconds())}`
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import { AddInvoiceReq } from './addInvoiceReq.js';
|
||||||
import { PayInvoiceReq } from './payInvoiceReq.js';
|
import { PayInvoiceReq } from './payInvoiceReq.js';
|
||||||
import { SendCoinsReq } from './sendCoinsReq.js';
|
import { SendCoinsReq } from './sendCoinsReq.js';
|
||||||
import { AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice, NewBlockCb, HtlcCb, BalanceInfo, ChannelEventCb } from './settings.js';
|
import { AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice, NewBlockCb, HtlcCb, BalanceInfo, ChannelEventCb } from './settings.js';
|
||||||
import { ERROR, getLogger } from '../helpers/logger.js';
|
import { ERROR, getLogger, DEBUG, INFO } from '../helpers/logger.js';
|
||||||
import { HtlcEvent_EventType } from '../../../proto/lnd/router.js';
|
import { HtlcEvent_EventType } from '../../../proto/lnd/router.js';
|
||||||
import { LiquidityProvider } from '../main/liquidityProvider.js';
|
import { LiquidityProvider } from '../main/liquidityProvider.js';
|
||||||
import { Utils } from '../helpers/utilsWrapper.js';
|
import { Utils } from '../helpers/utilsWrapper.js';
|
||||||
|
|
@ -23,7 +23,7 @@ import { TxPointSettings } from '../storage/tlv/stateBundler.js';
|
||||||
import { WalletKitClient } from '../../../proto/lnd/walletkit.client.js';
|
import { WalletKitClient } from '../../../proto/lnd/walletkit.client.js';
|
||||||
import SettingsManager from '../main/settingsManager.js';
|
import SettingsManager from '../main/settingsManager.js';
|
||||||
import { LndNodeSettings, LndSettings } from '../main/settings.js';
|
import { LndNodeSettings, LndSettings } from '../main/settings.js';
|
||||||
import { ListAddressesResponse } from '../../../proto/lnd/walletkit.js';
|
import { ListAddressesResponse, PublishResponse } from '../../../proto/lnd/walletkit.js';
|
||||||
|
|
||||||
const DeadLineMetadata = (deadline = 10 * 1000) => ({ deadline: Date.now() + deadline })
|
const DeadLineMetadata = (deadline = 10 * 1000) => ({ deadline: Date.now() + deadline })
|
||||||
const deadLndRetrySeconds = 20
|
const deadLndRetrySeconds = 20
|
||||||
|
|
@ -69,7 +69,7 @@ export default class {
|
||||||
|
|
||||||
// Skip LND client initialization if using only liquidity provider
|
// Skip LND client initialization if using only liquidity provider
|
||||||
if (liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
this.log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND client initialization")
|
this.log(INFO, "USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND client initialization")
|
||||||
// Create minimal dummy clients - they won't be used but prevent null reference errors
|
// Create minimal dummy clients - they won't be used but prevent null reference errors
|
||||||
// Use insecure credentials directly (can't combine them)
|
// Use insecure credentials directly (can't combine them)
|
||||||
const { lndAddr } = this.getSettings().lndNodeSettings
|
const { lndAddr } = this.getSettings().lndNodeSettings
|
||||||
|
|
@ -126,13 +126,13 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async Warmup() {
|
async Warmup() {
|
||||||
|
this.log(INFO, "Warming up LND")
|
||||||
// Skip LND warmup if using only liquidity provider
|
// Skip LND warmup if using only liquidity provider
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
this.log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND warmup")
|
this.log(INFO, "USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND warmup")
|
||||||
this.ready = true
|
this.ready = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// console.log("Warming up LND")
|
|
||||||
this.SubscribeAddressPaid()
|
this.SubscribeAddressPaid()
|
||||||
this.SubscribeInvoicePaid()
|
this.SubscribeInvoicePaid()
|
||||||
await this.SubscribeNewBlock()
|
await this.SubscribeNewBlock()
|
||||||
|
|
@ -142,20 +142,32 @@ export default class {
|
||||||
return new Promise<void>((res, rej) => {
|
return new Promise<void>((res, rej) => {
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
await this.GetInfo()
|
const info = await this.GetInfo()
|
||||||
|
if (!info.syncedToChain || !info.syncedToGraph) {
|
||||||
|
this.log("LND responding but not synced yet, waiting...")
|
||||||
|
return
|
||||||
|
}
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
this.ready = true
|
this.ready = true
|
||||||
res()
|
res()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log("LND is not ready yet, will try again in 1 second")
|
this.log(INFO, "LND is not ready yet, will try again in 1 second")
|
||||||
if (Date.now() - now > 1000 * 60) {
|
}
|
||||||
rej(new Error("LND not ready after 1 minute"))
|
if (Date.now() - now > 1000 * 60 * 10) {
|
||||||
}
|
clearInterval(interval)
|
||||||
|
rej(new Error("LND not synced after 10 minutes"))
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async PublishTransaction(txHex: string): Promise<PublishResponse> {
|
||||||
|
const res = await this.walletKit.publishTransaction({
|
||||||
|
txHex: Buffer.from(txHex, 'hex'), label: ""
|
||||||
|
}, DeadLineMetadata())
|
||||||
|
return res.response
|
||||||
|
}
|
||||||
|
|
||||||
async GetInfo(): Promise<NodeInfo> {
|
async GetInfo(): Promise<NodeInfo> {
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
// Return dummy info when bypass is enabled
|
// Return dummy info when bypass is enabled
|
||||||
|
|
@ -169,34 +181,33 @@ export default class {
|
||||||
uris: []
|
uris: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log("Getting info")
|
|
||||||
const res = await this.lightning.getInfo({}, DeadLineMetadata())
|
const res = await this.lightning.getInfo({}, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
async ListPendingChannels(): Promise<PendingChannelsResponse> {
|
async ListPendingChannels(): Promise<PendingChannelsResponse> {
|
||||||
|
this.log(DEBUG, "Listing pending channels")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return { pendingOpenChannels: [], pendingClosingChannels: [], pendingForceClosingChannels: [], waitingCloseChannels: [], totalLimboBalance: 0n }
|
return { pendingOpenChannels: [], pendingClosingChannels: [], pendingForceClosingChannels: [], waitingCloseChannels: [], totalLimboBalance: 0n }
|
||||||
}
|
}
|
||||||
// console.log("Listing pending channels")
|
|
||||||
const res = await this.lightning.pendingChannels({ includeRawTx: false }, DeadLineMetadata())
|
const res = await this.lightning.pendingChannels({ includeRawTx: false }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
async ListChannels(peerLookup = false): Promise<ListChannelsResponse> {
|
async ListChannels(peerLookup = false): Promise<ListChannelsResponse> {
|
||||||
// console.log("Listing channels")
|
this.log(DEBUG, "Listing channels")
|
||||||
const res = await this.lightning.listChannels({
|
const res = await this.lightning.listChannels({
|
||||||
activeOnly: false, inactiveOnly: false, privateOnly: false, publicOnly: false, peer: Buffer.alloc(0), peerAliasLookup: peerLookup
|
activeOnly: false, inactiveOnly: false, privateOnly: false, publicOnly: false, peer: Buffer.alloc(0), peerAliasLookup: peerLookup
|
||||||
}, DeadLineMetadata())
|
}, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
async ListClosedChannels(): Promise<ClosedChannelsResponse> {
|
async ListClosedChannels(): Promise<ClosedChannelsResponse> {
|
||||||
// console.log("Listing closed channels")
|
this.log(DEBUG, "Listing closed channels")
|
||||||
const res = await this.lightning.closedChannels({
|
const res = await this.lightning.closedChannels({
|
||||||
abandoned: true,
|
abandoned: true,
|
||||||
breach: true,
|
breach: true,
|
||||||
cooperative: true,
|
cooperative: true,
|
||||||
fundingCanceled: true,
|
fundingCanceled: true,
|
||||||
localForce: true,
|
localForce: true,
|
||||||
remoteForce: true
|
remoteForce: true,
|
||||||
}, DeadLineMetadata())
|
}, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +217,6 @@ export default class {
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// console.log("Checking health")
|
|
||||||
if (!this.ready) {
|
if (!this.ready) {
|
||||||
throw new Error("not ready")
|
throw new Error("not ready")
|
||||||
}
|
}
|
||||||
|
|
@ -217,73 +227,75 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
RestartStreams() {
|
RestartStreams() {
|
||||||
// console.log("Restarting streams")
|
this.log(INFO, "Restarting streams")
|
||||||
if (!this.ready || this.abortController.signal.aborted) {
|
if (!this.ready || this.abortController.signal.aborted) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.log("LND is dead, will try to reconnect in", deadLndRetrySeconds, "seconds")
|
this.log(INFO, "LND is dead, will try to reconnect in", deadLndRetrySeconds, "seconds")
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
await this.unlockLnd()
|
await this.unlockLnd()
|
||||||
this.log("LND is back online")
|
this.log(INFO, "LND is back online")
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
await this.Warmup()
|
await this.Warmup()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log("LND still dead, will try again in", deadLndRetrySeconds, "seconds")
|
this.log(INFO, "LND still dead, will try again in", deadLndRetrySeconds, "seconds")
|
||||||
}
|
}
|
||||||
}, deadLndRetrySeconds * 1000)
|
}, deadLndRetrySeconds * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
async SubscribeChannelEvents() {
|
async SubscribeChannelEvents() {
|
||||||
// console.log("Subscribing to channel events")
|
this.log(DEBUG, "Subscribing to channel events")
|
||||||
const stream = this.lightning.subscribeChannelEvents({}, { abort: this.abortController.signal })
|
const stream = this.lightning.subscribeChannelEvents({}, { abort: this.abortController.signal })
|
||||||
stream.responses.onMessage(async channel => {
|
stream.responses.onMessage(async channel => {
|
||||||
const channels = await this.ListChannels()
|
const channels = await this.ListChannels()
|
||||||
this.channelEventCb(channel, channels.channels)
|
this.channelEventCb(channel, channels.channels)
|
||||||
})
|
})
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
this.log("Error with subscribeChannelEvents stream")
|
this.log(ERROR, "Error with subscribeChannelEvents stream")
|
||||||
})
|
})
|
||||||
stream.responses.onComplete(() => {
|
stream.responses.onComplete(() => {
|
||||||
this.log("subscribeChannelEvents stream closed")
|
this.log(INFO, "subscribeChannelEvents stream closed")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async SubscribeHtlcEvents() {
|
async SubscribeHtlcEvents() {
|
||||||
// console.log("Subscribing to htlc events")
|
this.log(DEBUG, "Subscribing to htlc events")
|
||||||
const stream = this.router.subscribeHtlcEvents({}, { abort: this.abortController.signal })
|
const stream = this.router.subscribeHtlcEvents({}, { abort: this.abortController.signal })
|
||||||
stream.responses.onMessage(htlc => {
|
stream.responses.onMessage(htlc => {
|
||||||
this.htlcCb(htlc)
|
this.htlcCb(htlc)
|
||||||
})
|
})
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
this.log("Error with subscribeHtlcEvents stream")
|
this.log(ERROR, "Error with subscribeHtlcEvents stream")
|
||||||
})
|
})
|
||||||
stream.responses.onComplete(() => {
|
stream.responses.onComplete(() => {
|
||||||
this.log("subscribeHtlcEvents stream closed")
|
this.log(INFO, "subscribeHtlcEvents stream closed")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async SubscribeNewBlock() {
|
async SubscribeNewBlock() {
|
||||||
// console.log("Subscribing to new block")
|
this.log(DEBUG, "Subscribing to new block")
|
||||||
const { blockHeight } = await this.GetInfo()
|
const { blockHeight } = await this.GetInfo()
|
||||||
const stream = this.chainNotifier.registerBlockEpochNtfn({ height: blockHeight, hash: Buffer.alloc(0) }, { abort: this.abortController.signal })
|
const stream = this.chainNotifier.registerBlockEpochNtfn({ height: blockHeight, hash: Buffer.alloc(0) }, { abort: this.abortController.signal })
|
||||||
stream.responses.onMessage(block => {
|
stream.responses.onMessage(block => {
|
||||||
this.newBlockCb(block.height)
|
this.newBlockCb(block.height)
|
||||||
})
|
})
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
this.log("Error with new block stream")
|
this.log(ERROR, "Error with new block stream")
|
||||||
})
|
})
|
||||||
stream.responses.onComplete(() => {
|
stream.responses.onComplete(() => {
|
||||||
this.log("new block stream closed")
|
this.log(INFO, "new block stream closed")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
SubscribeAddressPaid(): void {
|
SubscribeAddressPaid(): void {
|
||||||
// console.log("Subscribing to address paid")
|
this.log(DEBUG, "Subscribing to address paid")
|
||||||
const stream = this.lightning.subscribeTransactions({
|
const stream = this.lightning.subscribeTransactions({
|
||||||
account: "",
|
account: "",
|
||||||
endHeight: 0,
|
endHeight: 0,
|
||||||
startHeight: this.latestKnownBlockHeigh,
|
startHeight: this.latestKnownBlockHeigh,
|
||||||
|
indexOffset: 0,
|
||||||
|
maxTransactions: 0
|
||||||
}, { abort: this.abortController.signal })
|
}, { abort: this.abortController.signal })
|
||||||
stream.responses.onMessage(tx => {
|
stream.responses.onMessage(tx => {
|
||||||
if (tx.blockHeight > this.latestKnownBlockHeigh) {
|
if (tx.blockHeight > this.latestKnownBlockHeigh) {
|
||||||
|
|
@ -298,15 +310,15 @@ export default class {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
this.log("Error with onchain tx stream")
|
this.log(ERROR, "Error with onchain tx stream")
|
||||||
})
|
})
|
||||||
stream.responses.onComplete(() => {
|
stream.responses.onComplete(() => {
|
||||||
this.log("onchain tx stream closed")
|
this.log(INFO, "onchain tx stream closed")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
SubscribeInvoicePaid(): void {
|
SubscribeInvoicePaid(): void {
|
||||||
// console.log("Subscribing to invoice paid")
|
this.log(DEBUG, "Subscribing to invoice paid")
|
||||||
const stream = this.lightning.subscribeInvoices({
|
const stream = this.lightning.subscribeInvoices({
|
||||||
settleIndex: BigInt(this.latestKnownSettleIndex),
|
settleIndex: BigInt(this.latestKnownSettleIndex),
|
||||||
addIndex: 0n,
|
addIndex: 0n,
|
||||||
|
|
@ -319,14 +331,14 @@ export default class {
|
||||||
})
|
})
|
||||||
let restarted = false
|
let restarted = false
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
this.log("Error with invoice stream")
|
this.log(ERROR, "Error with invoice stream")
|
||||||
if (!restarted) {
|
if (!restarted) {
|
||||||
restarted = true
|
restarted = true
|
||||||
this.RestartStreams()
|
this.RestartStreams()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
stream.responses.onComplete(() => {
|
stream.responses.onComplete(() => {
|
||||||
this.log("invoice stream closed")
|
this.log(INFO, "invoice stream closed")
|
||||||
if (!restarted) {
|
if (!restarted) {
|
||||||
restarted = true
|
restarted = true
|
||||||
this.RestartStreams()
|
this.RestartStreams()
|
||||||
|
|
@ -348,6 +360,7 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListAddresses(): Promise<LndAddress[]> {
|
async ListAddresses(): Promise<LndAddress[]> {
|
||||||
|
this.log(DEBUG, "Listing addresses")
|
||||||
const res = await this.walletKit.listAddresses({ accountName: "", showCustomAccounts: false }, DeadLineMetadata())
|
const res = await this.walletKit.listAddresses({ accountName: "", showCustomAccounts: false }, DeadLineMetadata())
|
||||||
const addresses = res.response.accountWithAddresses.map(a => a.addresses.map(a => ({ address: a.address, change: a.isInternal }))).flat()
|
const addresses = res.response.accountWithAddresses.map(a => a.addresses.map(a => ({ address: a.address, change: a.isInternal }))).flat()
|
||||||
addresses.forEach(a => this.addressesCache[a.address] = { isChange: a.change })
|
addresses.forEach(a => this.addressesCache[a.address] = { isChange: a.change })
|
||||||
|
|
@ -355,11 +368,11 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise<NewAddressResponse> {
|
async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise<NewAddressResponse> {
|
||||||
|
this.log(DEBUG, "Creating new address")
|
||||||
// Force use of provider when bypass is enabled (addresses not supported by provider, but we should fail gracefully)
|
// Force use of provider when bypass is enabled (addresses not supported by provider, but we should fail gracefully)
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
throw new Error("Address generation not supported when USE_ONLY_LIQUIDITY_PROVIDER is enabled")
|
throw new Error("Address generation not supported when USE_ONLY_LIQUIDITY_PROVIDER is enabled")
|
||||||
}
|
}
|
||||||
// console.log("Creating new address")
|
|
||||||
let lndAddressType: AddressType
|
let lndAddressType: AddressType
|
||||||
switch (addressType) {
|
switch (addressType) {
|
||||||
case Types.AddressType.NESTED_PUBKEY_HASH:
|
case Types.AddressType.NESTED_PUBKEY_HASH:
|
||||||
|
|
@ -389,11 +402,11 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions, blind = false): Promise<Invoice> {
|
async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions, blind = false): Promise<Invoice> {
|
||||||
// console.log("Creating new invoice")
|
this.log(DEBUG, "Creating new invoice")
|
||||||
// Force use of provider when bypass is enabled
|
// Force use of provider when bypass is enabled
|
||||||
const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider
|
const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider
|
||||||
if (mustUseProvider) {
|
if (mustUseProvider) {
|
||||||
console.log("using provider")
|
this.log(INFO, "using provider")
|
||||||
const invoice = await this.liquidProvider.AddInvoice(value, memo, from, expiry)
|
const invoice = await this.liquidProvider.AddInvoice(value, memo, from, expiry)
|
||||||
const providerPubkey = this.liquidProvider.GetProviderPubkey()
|
const providerPubkey = this.liquidProvider.GetProviderPubkey()
|
||||||
return { payRequest: invoice, providerPubkey }
|
return { payRequest: invoice, providerPubkey }
|
||||||
|
|
@ -409,6 +422,7 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async DecodeInvoice(paymentRequest: string): Promise<DecodedInvoice> {
|
async DecodeInvoice(paymentRequest: string): Promise<DecodedInvoice> {
|
||||||
|
this.log(DEBUG, "Decoding invoice")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
// Use light-bolt11-decoder when LND is bypassed
|
// Use light-bolt11-decoder when LND is bypassed
|
||||||
try {
|
try {
|
||||||
|
|
@ -434,24 +448,23 @@ export default class {
|
||||||
throw new Error(`Failed to decode invoice: ${err.message}`)
|
throw new Error(`Failed to decode invoice: ${err.message}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log("Decoding invoice")
|
|
||||||
const res = await this.lightning.decodePayReq({ payReq: paymentRequest }, DeadLineMetadata())
|
const res = await this.lightning.decodePayReq({ payReq: paymentRequest }, DeadLineMetadata())
|
||||||
return { numSatoshis: Number(res.response.numSatoshis), paymentHash: res.response.paymentHash }
|
return { numSatoshis: Number(res.response.numSatoshis), paymentHash: res.response.paymentHash }
|
||||||
}
|
}
|
||||||
|
|
||||||
async ChannelBalance(): Promise<{ local: number, remote: number }> {
|
async ChannelBalance(): Promise<{ local: number, remote: number }> {
|
||||||
|
this.log(DEBUG, "Getting channel balance")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return { local: 0, remote: 0 }
|
return { local: 0, remote: 0 }
|
||||||
}
|
}
|
||||||
// console.log("Getting channel balance")
|
|
||||||
const res = await this.lightning.channelBalance({})
|
const res = await this.lightning.channelBalance({})
|
||||||
const r = res.response
|
const r = res.response
|
||||||
return { local: r.localBalance ? Number(r.localBalance.sat) : 0, remote: r.remoteBalance ? Number(r.remoteBalance.sat) : 0 }
|
return { local: r.localBalance ? Number(r.localBalance.sat) : 0, remote: r.remoteBalance ? Number(r.remoteBalance.sat) : 0 }
|
||||||
}
|
}
|
||||||
async PayInvoice(invoice: string, amount: number, { routingFeeLimit, serviceFee }: { routingFeeLimit: number, serviceFee: number }, decodedAmount: number, { useProvider, from }: TxActionOptions, paymentIndexCb?: (index: number) => void): Promise<PaidInvoice> {
|
async PayInvoice(invoice: string, amount: number, { routingFeeLimit, serviceFee }: { routingFeeLimit: number, serviceFee: number }, decodedAmount: number, { useProvider, from }: TxActionOptions, paymentIndexCb?: (index: number) => void): Promise<PaidInvoice> {
|
||||||
// console.log("Paying invoice")
|
this.log(DEBUG, "Paying invoice")
|
||||||
if (this.outgoingOpsLocked) {
|
if (this.outgoingOpsLocked) {
|
||||||
this.log("outgoing ops locked, rejecting payment request")
|
this.log(ERROR, "outgoing ops locked, rejecting payment request")
|
||||||
throw new Error("lnd node is currently out of sync")
|
throw new Error("lnd node is currently out of sync")
|
||||||
}
|
}
|
||||||
// Force use of provider when bypass is enabled
|
// Force use of provider when bypass is enabled
|
||||||
|
|
@ -468,7 +481,7 @@ export default class {
|
||||||
const stream = this.router.sendPaymentV2(req, { abort: abortController.signal })
|
const stream = this.router.sendPaymentV2(req, { abort: abortController.signal })
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
this.log("invoice payment failed", error)
|
this.log(ERROR, "invoice payment failed", error)
|
||||||
rej(error)
|
rej(error)
|
||||||
})
|
})
|
||||||
let indexSent = false
|
let indexSent = false
|
||||||
|
|
@ -480,7 +493,7 @@ export default class {
|
||||||
}
|
}
|
||||||
switch (payment.status) {
|
switch (payment.status) {
|
||||||
case Payment_PaymentStatus.FAILED:
|
case Payment_PaymentStatus.FAILED:
|
||||||
this.log("invoice payment failed", payment.failureReason)
|
this.log(ERROR, "invoice payment failed", payment.failureReason)
|
||||||
rej(PaymentFailureReason[payment.failureReason])
|
rej(PaymentFailureReason[payment.failureReason])
|
||||||
return
|
return
|
||||||
case Payment_PaymentStatus.SUCCEEDED:
|
case Payment_PaymentStatus.SUCCEEDED:
|
||||||
|
|
@ -498,7 +511,7 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async EstimateChainFees(address: string, amount: number, targetConf: number): Promise<EstimateFeeResponse> {
|
async EstimateChainFees(address: string, amount: number, targetConf: number): Promise<EstimateFeeResponse> {
|
||||||
// console.log("Estimating chain fees")
|
this.log(DEBUG, "Estimating chain fees")
|
||||||
await this.Health()
|
await this.Health()
|
||||||
const res = await this.lightning.estimateFee({
|
const res = await this.lightning.estimateFee({
|
||||||
addrToAmount: { [address]: BigInt(amount) },
|
addrToAmount: { [address]: BigInt(amount) },
|
||||||
|
|
@ -511,13 +524,13 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async PayAddress(address: string, amount: number, satPerVByte: number, label = "", { useProvider, from }: TxActionOptions): Promise<SendCoinsResponse> {
|
async PayAddress(address: string, amount: number, satPerVByte: number, label = "", { useProvider, from }: TxActionOptions): Promise<SendCoinsResponse> {
|
||||||
|
this.log(DEBUG, "Paying address")
|
||||||
// Address payments not supported when bypass is enabled
|
// Address payments not supported when bypass is enabled
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
throw new Error("Address payments not supported when USE_ONLY_LIQUIDITY_PROVIDER is enabled")
|
throw new Error("Address payments not supported when USE_ONLY_LIQUIDITY_PROVIDER is enabled")
|
||||||
}
|
}
|
||||||
// console.log("Paying address")
|
|
||||||
if (this.outgoingOpsLocked) {
|
if (this.outgoingOpsLocked) {
|
||||||
this.log("outgoing ops locked, rejecting payment request")
|
this.log(ERROR, "outgoing ops locked, rejecting payment request")
|
||||||
throw new Error("lnd node is currently out of sync")
|
throw new Error("lnd node is currently out of sync")
|
||||||
}
|
}
|
||||||
if (useProvider) {
|
if (useProvider) {
|
||||||
|
|
@ -535,19 +548,19 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetTransactions(startHeight: number): Promise<TransactionDetails> {
|
async GetTransactions(startHeight: number): Promise<TransactionDetails> {
|
||||||
// console.log("Getting transactions")
|
this.log(DEBUG, "Getting transactions")
|
||||||
const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "" }, DeadLineMetadata())
|
const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "", indexOffset: 0, maxTransactions: 0 }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetChannelInfo(chanId: string) {
|
async GetChannelInfo(chanId: string) {
|
||||||
// console.log("Getting channel info")
|
this.log(DEBUG, "Getting channel info")
|
||||||
const res = await this.lightning.getChanInfo({ chanId, chanPoint: "" }, DeadLineMetadata())
|
const res = await this.lightning.getChanInfo({ chanId, chanPoint: "" }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async UpdateChannelPolicy(chanPoint: string, policy: Types.ChannelPolicy) {
|
async UpdateChannelPolicy(chanPoint: string, policy: Types.ChannelPolicy) {
|
||||||
// console.log("Updating channel policy")
|
this.log(DEBUG, "Updating channel policy")
|
||||||
const split = chanPoint.split(':')
|
const split = chanPoint.split(':')
|
||||||
|
|
||||||
const res = await this.lightning.updateChannelPolicy({
|
const res = await this.lightning.updateChannelPolicy({
|
||||||
|
|
@ -560,24 +573,25 @@ export default class {
|
||||||
inboundFee: undefined,
|
inboundFee: undefined,
|
||||||
feeRatePpm: policy.fee_rate_ppm,
|
feeRatePpm: policy.fee_rate_ppm,
|
||||||
minHtlcMsatSpecified: policy.min_htlc_msat > 0,
|
minHtlcMsatSpecified: policy.min_htlc_msat > 0,
|
||||||
|
createMissingEdge: false,
|
||||||
}, DeadLineMetadata())
|
}, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetChannelBalance() {
|
async GetChannelBalance() {
|
||||||
// console.log("Getting channel balance")
|
this.log(DEBUG, "Getting channel balance")
|
||||||
const res = await this.lightning.channelBalance({}, DeadLineMetadata())
|
const res = await this.lightning.channelBalance({}, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetWalletBalance() {
|
async GetWalletBalance() {
|
||||||
// console.log("Getting wallet balance")
|
this.log(DEBUG, "Getting wallet balance")
|
||||||
const res = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata())
|
const res = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetTotalBalace() {
|
async GetTotalBalace() {
|
||||||
// console.log("Getting total balance")
|
this.log(DEBUG, "Getting total balance")
|
||||||
const walletBalance = await this.GetWalletBalance()
|
const walletBalance = await this.GetWalletBalance()
|
||||||
const confirmedWalletBalance = Number(walletBalance.confirmedBalance)
|
const confirmedWalletBalance = Number(walletBalance.confirmedBalance)
|
||||||
this.utils.stateBundler.AddBalancePoint('walletBalance', confirmedWalletBalance)
|
this.utils.stateBundler.AddBalancePoint('walletBalance', confirmedWalletBalance)
|
||||||
|
|
@ -592,10 +606,10 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetBalance(): Promise<BalanceInfo> { // TODO: remove this
|
async GetBalance(): Promise<BalanceInfo> { // TODO: remove this
|
||||||
|
this.log(DEBUG, "Getting balance")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return { confirmedBalance: 0, unconfirmedBalance: 0, totalBalance: 0, channelsBalance: [] }
|
return { confirmedBalance: 0, unconfirmedBalance: 0, totalBalance: 0, channelsBalance: [] }
|
||||||
}
|
}
|
||||||
// console.log("Getting balance")
|
|
||||||
const wRes = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata())
|
const wRes = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata())
|
||||||
const { confirmedBalance, unconfirmedBalance, totalBalance } = wRes.response
|
const { confirmedBalance, unconfirmedBalance, totalBalance } = wRes.response
|
||||||
const { response } = await this.lightning.listChannels({
|
const { response } = await this.lightning.listChannels({
|
||||||
|
|
@ -611,33 +625,48 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetForwardingHistory(indexOffset: number, startTime = 0, endTime = 0): Promise<ForwardingHistoryResponse> {
|
async GetForwardingHistory(indexOffset: number, startTime = 0, endTime = 0): Promise<ForwardingHistoryResponse> {
|
||||||
|
this.log(DEBUG, "Getting forwarding history")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return { forwardingEvents: [], lastOffsetIndex: indexOffset }
|
return { forwardingEvents: [], lastOffsetIndex: indexOffset }
|
||||||
}
|
}
|
||||||
// console.log("Getting forwarding history")
|
|
||||||
const { response } = await this.lightning.forwardingHistory({ indexOffset, numMaxEvents: 0, startTime: BigInt(startTime), endTime: BigInt(endTime), peerAliasLookup: false }, DeadLineMetadata())
|
const { response } = await this.lightning.forwardingHistory({ indexOffset, numMaxEvents: 0, startTime: BigInt(startTime), endTime: BigInt(endTime), peerAliasLookup: false }, DeadLineMetadata())
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetAllPaidInvoices(max: number) {
|
async GetAllInvoices(max: number) {
|
||||||
|
this.log(DEBUG, "Getting all paid invoices")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return { invoices: [] }
|
return { invoices: [] }
|
||||||
}
|
}
|
||||||
// console.log("Getting all paid invoices")
|
|
||||||
const res = await this.lightning.listInvoices({ indexOffset: 0n, numMaxInvoices: BigInt(max), pendingOnly: false, reversed: true, creationDateEnd: 0n, creationDateStart: 0n }, DeadLineMetadata())
|
const res = await this.lightning.listInvoices({ indexOffset: 0n, numMaxInvoices: BigInt(max), pendingOnly: false, reversed: true, creationDateEnd: 0n, creationDateStart: 0n }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
async GetAllPayments(max: number) {
|
async GetAllPayments(max: number) {
|
||||||
|
this.log(DEBUG, "Getting all payments")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return { payments: [] }
|
return { payments: [] }
|
||||||
}
|
}
|
||||||
// console.log("Getting all payments")
|
|
||||||
const res = await this.lightning.listPayments({ countTotalPayments: false, includeIncomplete: false, indexOffset: 0n, maxPayments: BigInt(max), reversed: true, creationDateEnd: 0n, creationDateStart: 0n })
|
const res = await this.lightning.listPayments({ countTotalPayments: false, includeIncomplete: false, indexOffset: 0n, maxPayments: BigInt(max), reversed: true, creationDateEnd: 0n, creationDateStart: 0n })
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async BumpFee(txId: string, outputIndex: number, satPerVbyte: number) {
|
||||||
|
this.log(DEBUG, "Bumping fee")
|
||||||
|
const res = await this.walletKit.bumpFee({
|
||||||
|
budget: 0n, immediate: false, targetConf: 0, satPerVbyte: BigInt(satPerVbyte), outpoint: {
|
||||||
|
txidStr: txId,
|
||||||
|
outputIndex: outputIndex,
|
||||||
|
txidBytes: Buffer.alloc(0)
|
||||||
|
},
|
||||||
|
force: false,
|
||||||
|
satPerByte: 0,
|
||||||
|
deadlineDelta: 0
|
||||||
|
}, DeadLineMetadata())
|
||||||
|
return res.response
|
||||||
|
}
|
||||||
|
|
||||||
async GetPayment(paymentIndex: number) {
|
async GetPayment(paymentIndex: number) {
|
||||||
// console.log("Getting payment")
|
this.log(DEBUG, "Getting payment")
|
||||||
if (paymentIndex === 0) {
|
if (paymentIndex === 0) {
|
||||||
throw new Error("payment index starts from 1")
|
throw new Error("payment index starts from 1")
|
||||||
}
|
}
|
||||||
|
|
@ -649,10 +678,10 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetLatestPaymentIndex(from = 0) {
|
async GetLatestPaymentIndex(from = 0) {
|
||||||
|
this.log(DEBUG, "Getting latest payment index")
|
||||||
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
return from
|
return from
|
||||||
}
|
}
|
||||||
// console.log("Getting latest payment index")
|
|
||||||
let indexOffset = BigInt(from)
|
let indexOffset = BigInt(from)
|
||||||
while (true) {
|
while (true) {
|
||||||
const res = await this.lightning.listPayments({ countTotalPayments: false, includeIncomplete: false, indexOffset, maxPayments: 0n, reversed: false, creationDateEnd: 0n, creationDateStart: 0n }, DeadLineMetadata())
|
const res = await this.lightning.listPayments({ countTotalPayments: false, includeIncomplete: false, indexOffset, maxPayments: 0n, reversed: false, creationDateEnd: 0n, creationDateStart: 0n }, DeadLineMetadata())
|
||||||
|
|
@ -664,7 +693,7 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ConnectPeer(addr: { pubkey: string, host: string }) {
|
async ConnectPeer(addr: { pubkey: string, host: string }) {
|
||||||
// console.log("Connecting to peer")
|
this.log(DEBUG, "Connecting to peer")
|
||||||
const res = await this.lightning.connectPeer({
|
const res = await this.lightning.connectPeer({
|
||||||
addr,
|
addr,
|
||||||
perm: true,
|
perm: true,
|
||||||
|
|
@ -674,7 +703,7 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetPaymentFromHash(paymentHash: string): Promise<Payment | null> {
|
async GetPaymentFromHash(paymentHash: string): Promise<Payment | null> {
|
||||||
// console.log("Getting payment from hash")
|
this.log(DEBUG, "Getting payment from hash")
|
||||||
const abortController = new AbortController()
|
const abortController = new AbortController()
|
||||||
const stream = this.router.trackPaymentV2({
|
const stream = this.router.trackPaymentV2({
|
||||||
paymentHash: Buffer.from(paymentHash, 'hex'),
|
paymentHash: Buffer.from(paymentHash, 'hex'),
|
||||||
|
|
@ -696,13 +725,12 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetTx(txid: string) {
|
async GetTx(txid: string) {
|
||||||
// console.log("Getting transaction")
|
|
||||||
const res = await this.walletKit.getTransaction({ txid }, DeadLineMetadata())
|
const res = await this.walletKit.getTransaction({ txid }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddPeer(pub: string, host: string, port: number) {
|
async AddPeer(pub: string, host: string, port: number) {
|
||||||
// console.log("Adding peer")
|
this.log(DEBUG, "Adding peer")
|
||||||
const res = await this.lightning.connectPeer({
|
const res = await this.lightning.connectPeer({
|
||||||
addr: {
|
addr: {
|
||||||
pubkey: pub,
|
pubkey: pub,
|
||||||
|
|
@ -715,19 +743,19 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListPeers() {
|
async ListPeers() {
|
||||||
// console.log("Listing peers")
|
this.log(DEBUG, "Listing peers")
|
||||||
const res = await this.lightning.listPeers({ latestError: true }, DeadLineMetadata())
|
const res = await this.lightning.listPeers({ latestError: true }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
|
|
||||||
async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number, satsPerVByte: number): Promise<OpenStatusUpdate> {
|
async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number, satsPerVByte: number): Promise<OpenStatusUpdate> {
|
||||||
// console.log("Opening channel")
|
this.log(DEBUG, "Opening channel")
|
||||||
const abortController = new AbortController()
|
const abortController = new AbortController()
|
||||||
const req = OpenChannelReq(destination, closeAddress, fundingAmount, pushSats, satsPerVByte)
|
const req = OpenChannelReq(destination, closeAddress, fundingAmount, pushSats, satsPerVByte)
|
||||||
const stream = this.lightning.openChannel(req, { abort: abortController.signal })
|
const stream = this.lightning.openChannel(req, { abort: abortController.signal })
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
stream.responses.onMessage(message => {
|
stream.responses.onMessage(message => {
|
||||||
console.log("message", message)
|
this.log(DEBUG, "open channel message", message)
|
||||||
switch (message.update.oneofKind) {
|
switch (message.update.oneofKind) {
|
||||||
case 'chanPending':
|
case 'chanPending':
|
||||||
res(message)
|
res(message)
|
||||||
|
|
@ -735,14 +763,14 @@ export default class {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
console.log("error", error)
|
this.log(ERROR, "open channel error", error)
|
||||||
rej(error)
|
rej(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async CloseChannel(fundingTx: string, outputIndex: number, force: boolean, satPerVByte: number): Promise<PendingUpdate> {
|
async CloseChannel(fundingTx: string, outputIndex: number, force: boolean, satPerVByte: number): Promise<PendingUpdate> {
|
||||||
// console.log("Closing channel")
|
this.log(DEBUG, "Closing channel")
|
||||||
const stream = this.lightning.closeChannel({
|
const stream = this.lightning.closeChannel({
|
||||||
deliveryAddress: "",
|
deliveryAddress: "",
|
||||||
force: force,
|
force: force,
|
||||||
|
|
@ -761,7 +789,7 @@ export default class {
|
||||||
}, DeadLineMetadata())
|
}, DeadLineMetadata())
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
stream.responses.onMessage(message => {
|
stream.responses.onMessage(message => {
|
||||||
console.log("message", message)
|
this.log(DEBUG, "close channel message", message)
|
||||||
switch (message.update.oneofKind) {
|
switch (message.update.oneofKind) {
|
||||||
case 'closePending':
|
case 'closePending':
|
||||||
res(message.update.closePending)
|
res(message.update.closePending)
|
||||||
|
|
@ -769,7 +797,7 @@ export default class {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
stream.responses.onError(error => {
|
stream.responses.onError(error => {
|
||||||
console.log("error", error)
|
this.log(ERROR, "close channel error", error)
|
||||||
rej(error)
|
rej(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,7 @@ export const PayInvoiceReq = (invoice: string, amount: number, feeLimit: number)
|
||||||
paymentHash: Buffer.alloc(0),
|
paymentHash: Buffer.alloc(0),
|
||||||
routeHints: [],
|
routeHints: [],
|
||||||
timePref: 0,
|
timePref: 0,
|
||||||
outgoingChanId: '0'
|
outgoingChanId: '0',
|
||||||
|
cancelable: false,
|
||||||
|
firstHopCustomRecords: {}
|
||||||
})
|
})
|
||||||
|
|
@ -1,657 +0,0 @@
|
||||||
import zkpInit from '@vulpemventures/secp256k1-zkp';
|
|
||||||
import axios from 'axios';
|
|
||||||
import { crypto, initEccLib, Transaction, address, Network } from 'bitcoinjs-lib';
|
|
||||||
// import bolt11 from 'bolt11';
|
|
||||||
import {
|
|
||||||
Musig, SwapTreeSerializer, TaprootUtils, detectSwap,
|
|
||||||
constructClaimTransaction, targetFee, OutputType,
|
|
||||||
Networks,
|
|
||||||
} from 'boltz-core';
|
|
||||||
import { randomBytes, createHash } from 'crypto';
|
|
||||||
import { ECPairFactory, ECPairInterface } from 'ecpair';
|
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import ws from 'ws';
|
|
||||||
import { getLogger, PubLogger, ERROR } from '../helpers/logger.js';
|
|
||||||
import SettingsManager from '../main/settingsManager.js';
|
|
||||||
import * as Types from '../../../proto/autogenerated/ts/types.js';
|
|
||||||
import { BTCNetwork } from '../main/settings.js';
|
|
||||||
import Storage from '../storage/index.js';
|
|
||||||
import LND from './lnd.js';
|
|
||||||
import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js';
|
|
||||||
type InvoiceSwapResponse = { id: string, claimPublicKey: string, swapTree: string }
|
|
||||||
type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface }
|
|
||||||
type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo }
|
|
||||||
|
|
||||||
type TransactionSwapFees = {
|
|
||||||
percentage: number,
|
|
||||||
minerFees: {
|
|
||||||
claim: number,
|
|
||||||
lockup: number,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TransactionSwapFeesRes = {
|
|
||||||
BTC?: {
|
|
||||||
BTC?: {
|
|
||||||
fees: TransactionSwapFees
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type TransactionSwapResponse = {
|
|
||||||
id: string, refundPublicKey: string, swapTree: string,
|
|
||||||
timeoutBlockHeight: number, lockupAddress: string, invoice: string,
|
|
||||||
onchainAmount?: number
|
|
||||||
}
|
|
||||||
type TransactionSwapInfo = { destinationAddress: string, preimage: Buffer, keys: ECPairInterface, chainFee: number }
|
|
||||||
export type TransactionSwapData = { createdResponse: TransactionSwapResponse, info: TransactionSwapInfo }
|
|
||||||
export class Swaps {
|
|
||||||
settings: SettingsManager
|
|
||||||
revSwappers: Record<string, ReverseSwaps>
|
|
||||||
// submarineSwaps: SubmarineSwaps
|
|
||||||
storage: Storage
|
|
||||||
lnd: LND
|
|
||||||
log = getLogger({ component: 'swaps' })
|
|
||||||
constructor(settings: SettingsManager, storage: Storage) {
|
|
||||||
this.settings = settings
|
|
||||||
this.revSwappers = {}
|
|
||||||
const network = settings.getSettings().lndSettings.network
|
|
||||||
const { boltzHttpUrl, boltzWebSocketUrl, boltsHttpUrlAlt, boltsWebSocketUrlAlt } = settings.getSettings().swapsSettings
|
|
||||||
if (boltzHttpUrl && boltzWebSocketUrl) {
|
|
||||||
this.revSwappers[boltzHttpUrl] = new ReverseSwaps({ httpUrl: boltzHttpUrl, wsUrl: boltzWebSocketUrl, network })
|
|
||||||
}
|
|
||||||
if (boltsHttpUrlAlt && boltsWebSocketUrlAlt) {
|
|
||||||
this.revSwappers[boltsHttpUrlAlt] = new ReverseSwaps({ httpUrl: boltsHttpUrlAlt, wsUrl: boltsWebSocketUrlAlt, network })
|
|
||||||
}
|
|
||||||
this.storage = storage
|
|
||||||
}
|
|
||||||
|
|
||||||
SetLnd = (lnd: LND) => {
|
|
||||||
this.lnd = lnd
|
|
||||||
}
|
|
||||||
|
|
||||||
Stop = () => { }
|
|
||||||
|
|
||||||
GetKeys = (privateKey: string) => {
|
|
||||||
const keys = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKey, 'hex'))
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
ListSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise<Types.SwapsList> => {
|
|
||||||
const completedSwaps = await this.storage.paymentStorage.ListCompletedSwaps(appUserId, payments)
|
|
||||||
const pendingSwaps = await this.storage.paymentStorage.ListPendingTransactionSwaps(appUserId)
|
|
||||||
return {
|
|
||||||
swaps: completedSwaps.map(s => {
|
|
||||||
const p = s.payment
|
|
||||||
const op = p ? newOp(p) : undefined
|
|
||||||
return {
|
|
||||||
operation_payment: op,
|
|
||||||
swap_operation_id: s.swap.swap_operation_id,
|
|
||||||
address_paid: s.swap.address_paid,
|
|
||||||
failure_reason: s.swap.failure_reason,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
quotes: pendingSwaps.map(s => {
|
|
||||||
const serviceFee = getServiceFee(s.invoice_amount)
|
|
||||||
return {
|
|
||||||
swap_operation_id: s.swap_operation_id,
|
|
||||||
invoice_amount_sats: s.invoice_amount,
|
|
||||||
transaction_amount_sats: s.transaction_amount,
|
|
||||||
chain_fee_sats: s.chain_fee_sats,
|
|
||||||
service_fee_sats: serviceFee,
|
|
||||||
swap_fee_sats: s.swap_fee_sats,
|
|
||||||
service_url: s.service_url,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GetTxSwapQuotes = async (appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise<Types.TransactionSwapQuote[]> => {
|
|
||||||
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
|
||||||
throw new Error("Swaps are not enabled")
|
|
||||||
}
|
|
||||||
const swappers = Object.values(this.revSwappers)
|
|
||||||
if (swappers.length === 0) {
|
|
||||||
throw new Error("No swap services available")
|
|
||||||
}
|
|
||||||
const res = await Promise.allSettled(swappers.map(sw => this.getTxSwapQuote(sw, appUserId, amt, getServiceFee)))
|
|
||||||
const failures: string[] = []
|
|
||||||
const success: Types.TransactionSwapQuote[] = []
|
|
||||||
for (const r of res) {
|
|
||||||
if (r.status === 'fulfilled') {
|
|
||||||
success.push(r.value)
|
|
||||||
} else {
|
|
||||||
failures.push(r.reason.message ? r.reason.message : r.reason.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (success.length === 0) {
|
|
||||||
throw new Error(failures.join("\n"))
|
|
||||||
}
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getTxSwapQuote(swapper: ReverseSwaps, appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise<Types.TransactionSwapQuote> {
|
|
||||||
this.log("getting transaction swap quote")
|
|
||||||
const feesRes = await swapper.GetFees()
|
|
||||||
if (!feesRes.ok) {
|
|
||||||
throw new Error(feesRes.error)
|
|
||||||
}
|
|
||||||
const { claim, lockup } = feesRes.fees.minerFees
|
|
||||||
const minerFee = claim + lockup
|
|
||||||
const chainTotal = amt + minerFee
|
|
||||||
const res = await swapper.SwapTransaction(chainTotal)
|
|
||||||
if (!res.ok) {
|
|
||||||
throw new Error(res.error)
|
|
||||||
}
|
|
||||||
const decoded = await this.lnd.DecodeInvoice(res.createdResponse.invoice)
|
|
||||||
const swapFee = decoded.numSatoshis - chainTotal
|
|
||||||
const serviceFee = getServiceFee(decoded.numSatoshis)
|
|
||||||
const newSwap = await this.storage.paymentStorage.AddTransactionSwap({
|
|
||||||
app_user_id: appUserId,
|
|
||||||
swap_quote_id: res.createdResponse.id,
|
|
||||||
swap_tree: JSON.stringify(res.createdResponse.swapTree),
|
|
||||||
lockup_address: res.createdResponse.lockupAddress,
|
|
||||||
refund_public_key: res.createdResponse.refundPublicKey,
|
|
||||||
timeout_block_height: res.createdResponse.timeoutBlockHeight,
|
|
||||||
invoice: res.createdResponse.invoice,
|
|
||||||
invoice_amount: decoded.numSatoshis,
|
|
||||||
transaction_amount: chainTotal,
|
|
||||||
swap_fee_sats: swapFee,
|
|
||||||
chain_fee_sats: minerFee,
|
|
||||||
preimage: res.preimage,
|
|
||||||
ephemeral_private_key: res.privKey,
|
|
||||||
ephemeral_public_key: res.pubkey,
|
|
||||||
service_url: swapper.getHttpUrl(),
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
swap_operation_id: newSwap.swap_operation_id,
|
|
||||||
swap_fee_sats: swapFee,
|
|
||||||
invoice_amount_sats: decoded.numSatoshis,
|
|
||||||
transaction_amount_sats: amt,
|
|
||||||
chain_fee_sats: minerFee,
|
|
||||||
service_fee_sats: serviceFee,
|
|
||||||
service_url: swapper.getHttpUrl(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async PayAddrWithSwap(appUserId: string, swapOpId: string, address: string, payInvoice: (invoice: string, amt: number) => Promise<void>) {
|
|
||||||
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
|
||||||
throw new Error("Swaps are not enabled")
|
|
||||||
}
|
|
||||||
this.log("paying address with swap", { appUserId, swapOpId, address })
|
|
||||||
if (!swapOpId) {
|
|
||||||
throw new Error("request a swap quote before paying an external address")
|
|
||||||
}
|
|
||||||
const txSwap = await this.storage.paymentStorage.GetTransactionSwap(swapOpId, appUserId)
|
|
||||||
if (!txSwap) {
|
|
||||||
throw new Error("swap quote not found")
|
|
||||||
}
|
|
||||||
const info = await this.lnd.GetInfo()
|
|
||||||
if (info.blockHeight >= txSwap.timeout_block_height) {
|
|
||||||
throw new Error("swap timeout")
|
|
||||||
}
|
|
||||||
const swapper = this.revSwappers[txSwap.service_url]
|
|
||||||
if (!swapper) {
|
|
||||||
throw new Error("swapper service not found")
|
|
||||||
}
|
|
||||||
const keys = this.GetKeys(txSwap.ephemeral_private_key)
|
|
||||||
const data: TransactionSwapData = {
|
|
||||||
createdResponse: {
|
|
||||||
id: txSwap.swap_quote_id,
|
|
||||||
invoice: txSwap.invoice,
|
|
||||||
lockupAddress: txSwap.lockup_address,
|
|
||||||
refundPublicKey: txSwap.refund_public_key,
|
|
||||||
swapTree: txSwap.swap_tree,
|
|
||||||
timeoutBlockHeight: txSwap.timeout_block_height,
|
|
||||||
onchainAmount: txSwap.transaction_amount,
|
|
||||||
},
|
|
||||||
info: {
|
|
||||||
destinationAddress: address,
|
|
||||||
keys,
|
|
||||||
chainFee: txSwap.chain_fee_sats,
|
|
||||||
preimage: Buffer.from(txSwap.preimage, 'hex'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// the swap and the invoice payment are linked, swap will not start until the invoice payment is started, and will not complete once the invoice payment is completed
|
|
||||||
let swapResult = { ok: false, error: "swap never completed" } as { ok: true, txId: string } | { ok: false, error: string }
|
|
||||||
swapper.SubscribeToTransactionSwap(data, result => {
|
|
||||||
swapResult = result
|
|
||||||
})
|
|
||||||
try {
|
|
||||||
await payInvoice(txSwap.invoice, txSwap.invoice_amount)
|
|
||||||
if (!swapResult.ok) {
|
|
||||||
this.log("invoice payment successful, but swap failed")
|
|
||||||
await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error)
|
|
||||||
throw new Error(swapResult.error)
|
|
||||||
}
|
|
||||||
this.log("swap completed successfully")
|
|
||||||
await this.storage.paymentStorage.FinalizeTransactionSwap(swapOpId, address, swapResult.txId)
|
|
||||||
} catch (err: any) {
|
|
||||||
if (swapResult.ok) {
|
|
||||||
this.log("failed to pay swap invoice, but swap completed successfully", swapResult.txId)
|
|
||||||
await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, err.message)
|
|
||||||
} else {
|
|
||||||
this.log("failed to pay swap invoice and swap failed", swapResult.error)
|
|
||||||
await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error)
|
|
||||||
}
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
const networkFeesTotal = txSwap.chain_fee_sats + txSwap.swap_fee_sats
|
|
||||||
return {
|
|
||||||
txId: swapResult.txId,
|
|
||||||
network_fee: networkFeesTotal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class ReverseSwaps {
|
|
||||||
// settings: SettingsManager
|
|
||||||
private httpUrl: string
|
|
||||||
private wsUrl: string
|
|
||||||
log: PubLogger
|
|
||||||
private network: BTCNetwork
|
|
||||||
constructor({ httpUrl, wsUrl, network }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) {
|
|
||||||
this.httpUrl = httpUrl
|
|
||||||
this.wsUrl = wsUrl
|
|
||||||
this.network = network
|
|
||||||
this.log = getLogger({ component: 'ReverseSwaps' })
|
|
||||||
initEccLib(ecc)
|
|
||||||
}
|
|
||||||
|
|
||||||
getHttpUrl = () => {
|
|
||||||
return this.httpUrl
|
|
||||||
}
|
|
||||||
getWsUrl = () => {
|
|
||||||
return this.wsUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateFees = (fees: TransactionSwapFees, receiveAmount: number) => {
|
|
||||||
const pct = fees.percentage / 100
|
|
||||||
const minerFee = fees.minerFees.claim + fees.minerFees.lockup
|
|
||||||
|
|
||||||
const preFee = receiveAmount + minerFee
|
|
||||||
const fee = Math.ceil(preFee * pct)
|
|
||||||
const total = preFee + fee
|
|
||||||
return { total, fee, minerFee }
|
|
||||||
}
|
|
||||||
|
|
||||||
GetFees = async (): Promise<{ ok: true, fees: TransactionSwapFees, } | { ok: false, error: string }> => {
|
|
||||||
const url = `${this.httpUrl}/v2/swap/reverse`
|
|
||||||
const feesRes = await loggedGet<TransactionSwapFeesRes>(this.log, url)
|
|
||||||
if (!feesRes.ok) {
|
|
||||||
return { ok: false, error: feesRes.error }
|
|
||||||
}
|
|
||||||
if (!feesRes.data.BTC?.BTC?.fees) {
|
|
||||||
return { ok: false, error: 'No fees found for BTC to BTC swap' }
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ok: true, fees: feesRes.data.BTC.BTC.fees }
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapTransaction = async (txAmount: number): Promise<{ ok: true, createdResponse: TransactionSwapResponse, preimage: string, pubkey: string, privKey: string } | { ok: false, error: string }> => {
|
|
||||||
const preimage = randomBytes(32);
|
|
||||||
const keys = ECPairFactory(ecc).makeRandom()
|
|
||||||
if (!keys.privateKey) {
|
|
||||||
return { ok: false, error: 'Failed to generate keys' }
|
|
||||||
}
|
|
||||||
const url = `${this.httpUrl}/v2/swap/reverse`
|
|
||||||
const req: any = {
|
|
||||||
onchainAmount: txAmount,
|
|
||||||
to: 'BTC',
|
|
||||||
from: 'BTC',
|
|
||||||
claimPublicKey: Buffer.from(keys.publicKey).toString('hex'),
|
|
||||||
preimageHash: createHash('sha256').update(preimage).digest('hex'),
|
|
||||||
}
|
|
||||||
const createdResponseRes = await loggedPost<TransactionSwapResponse>(this.log, url, req)
|
|
||||||
if (!createdResponseRes.ok) {
|
|
||||||
return createdResponseRes
|
|
||||||
}
|
|
||||||
const createdResponse = createdResponseRes.data
|
|
||||||
this.log('Created transaction swap');
|
|
||||||
this.log(createdResponse);
|
|
||||||
return {
|
|
||||||
ok: true, createdResponse,
|
|
||||||
preimage: Buffer.from(preimage).toString('hex'),
|
|
||||||
pubkey: Buffer.from(keys.publicKey).toString('hex'),
|
|
||||||
privKey: Buffer.from(keys.privateKey).toString('hex')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscribeToTransactionSwap = async (data: TransactionSwapData, swapDone: (result: { ok: true, txId: string } | { ok: false, error: string }) => void) => {
|
|
||||||
const webSocket = new ws(`${this.wsUrl}/v2/ws`)
|
|
||||||
const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] }
|
|
||||||
webSocket.on('open', () => {
|
|
||||||
webSocket.send(JSON.stringify(subReq))
|
|
||||||
})
|
|
||||||
let txId = "", isDone = false
|
|
||||||
const done = () => {
|
|
||||||
isDone = true
|
|
||||||
webSocket.close()
|
|
||||||
swapDone({ ok: true, txId })
|
|
||||||
}
|
|
||||||
webSocket.on('error', (err) => {
|
|
||||||
this.log(ERROR, 'Error in WebSocket', err.message)
|
|
||||||
})
|
|
||||||
webSocket.on('close', () => {
|
|
||||||
if (!isDone) {
|
|
||||||
this.log(ERROR, 'WebSocket closed before swap was done');
|
|
||||||
swapDone({ ok: false, error: 'WebSocket closed before swap was done' })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
webSocket.on('message', async (rawMsg) => {
|
|
||||||
try {
|
|
||||||
const result = await this.handleSwapTransactionMessage(rawMsg, data, done)
|
|
||||||
if (result) {
|
|
||||||
txId = result
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
this.log(ERROR, 'Error handling transaction WebSocket message', err.message)
|
|
||||||
isDone = true
|
|
||||||
webSocket.close()
|
|
||||||
swapDone({ ok: false, error: err.message })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, done: () => void) => {
|
|
||||||
const msg = JSON.parse(rawMsg.toString('utf-8'));
|
|
||||||
if (msg.event !== 'update') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('Got WebSocket update');
|
|
||||||
this.log(msg);
|
|
||||||
switch (msg.args[0].status) {
|
|
||||||
// "swap.created" means Boltz is waiting for the invoice to be paid
|
|
||||||
case 'swap.created':
|
|
||||||
this.log('Waiting invoice to be paid');
|
|
||||||
return;
|
|
||||||
|
|
||||||
// "transaction.mempool" means that Boltz sent an onchain transaction
|
|
||||||
case 'transaction.mempool':
|
|
||||||
const txIdRes = await this.handleTransactionMempool(data, msg.args[0].transaction.hex)
|
|
||||||
if (!txIdRes.ok) {
|
|
||||||
throw new Error(txIdRes.error)
|
|
||||||
}
|
|
||||||
return txIdRes.txId
|
|
||||||
case 'invoice.settled':
|
|
||||||
this.log('Transaction swap successful');
|
|
||||||
done()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTransactionMempool = async (data: TransactionSwapData, txHex: string): Promise<{ ok: true, txId: string } | { ok: false, error: string }> => {
|
|
||||||
this.log('Creating claim transaction');
|
|
||||||
const { createdResponse, info } = data
|
|
||||||
const { destinationAddress, keys, preimage, chainFee } = info
|
|
||||||
const boltzPublicKey = Buffer.from(
|
|
||||||
createdResponse.refundPublicKey,
|
|
||||||
'hex',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create a musig signing session and tweak it with the Taptree of the swap scripts
|
|
||||||
const musig = new Musig(await zkpInit(), keys, randomBytes(32), [
|
|
||||||
boltzPublicKey,
|
|
||||||
Buffer.from(keys.publicKey),
|
|
||||||
]);
|
|
||||||
const tweakedKey = TaprootUtils.tweakMusig(
|
|
||||||
musig,
|
|
||||||
// swap tree can either be a string or an object
|
|
||||||
SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Parse the lockup transaction and find the output relevant for the swap
|
|
||||||
const lockupTx = Transaction.fromHex(txHex);
|
|
||||||
const swapOutput = detectSwap(tweakedKey, lockupTx);
|
|
||||||
if (swapOutput === undefined) {
|
|
||||||
this.log(ERROR, 'No swap output found in lockup transaction');
|
|
||||||
return { ok: false, error: 'No swap output found in lockup transaction' }
|
|
||||||
}
|
|
||||||
const network = getNetwork(this.network)
|
|
||||||
// Create a claim transaction to be signed cooperatively via a key path spend
|
|
||||||
const claimTx = constructClaimTransaction(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
...swapOutput,
|
|
||||||
keys,
|
|
||||||
preimage,
|
|
||||||
cooperative: true,
|
|
||||||
type: OutputType.Taproot,
|
|
||||||
txHash: lockupTx.getHash(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
address.toOutputScript(destinationAddress, network),
|
|
||||||
chainFee,
|
|
||||||
)
|
|
||||||
// Get the partial signature from Boltz
|
|
||||||
const claimUrl = `${this.httpUrl}/v2/swap/reverse/${createdResponse.id}/claim`
|
|
||||||
const claimReq = {
|
|
||||||
index: 0,
|
|
||||||
transaction: claimTx.toHex(),
|
|
||||||
preimage: preimage.toString('hex'),
|
|
||||||
pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'),
|
|
||||||
}
|
|
||||||
const boltzSigRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq)
|
|
||||||
if (!boltzSigRes.ok) {
|
|
||||||
return boltzSigRes
|
|
||||||
}
|
|
||||||
const boltzSig = boltzSigRes.data
|
|
||||||
|
|
||||||
// Aggregate the nonces
|
|
||||||
musig.aggregateNonces([
|
|
||||||
[boltzPublicKey, Buffer.from(boltzSig.pubNonce, 'hex')],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Initialize the session to sign the claim transaction
|
|
||||||
musig.initializeSession(
|
|
||||||
claimTx.hashForWitnessV1(
|
|
||||||
0,
|
|
||||||
[swapOutput.script],
|
|
||||||
[swapOutput.value],
|
|
||||||
Transaction.SIGHASH_DEFAULT,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the partial signature from Boltz
|
|
||||||
musig.addPartial(
|
|
||||||
boltzPublicKey,
|
|
||||||
Buffer.from(boltzSig.partialSignature, 'hex'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create our partial signature
|
|
||||||
musig.signPartial();
|
|
||||||
|
|
||||||
// Witness of the input to the aggregated signature
|
|
||||||
claimTx.ins[0].witness = [musig.aggregatePartials()];
|
|
||||||
|
|
||||||
// Broadcast the finalized transaction
|
|
||||||
const broadcastUrl = `${this.httpUrl}/v2/chain/BTC/transaction`
|
|
||||||
const broadcastReq = {
|
|
||||||
hex: claimTx.toHex(),
|
|
||||||
}
|
|
||||||
|
|
||||||
const broadcastResponse = await loggedPost<any>(this.log, broadcastUrl, broadcastReq)
|
|
||||||
if (!broadcastResponse.ok) {
|
|
||||||
return broadcastResponse
|
|
||||||
}
|
|
||||||
this.log('Transaction broadcasted', broadcastResponse.data)
|
|
||||||
const txId = claimTx.getId()
|
|
||||||
return { ok: true, txId }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const loggedPost = async <T>(log: PubLogger, url: string, req: any): Promise<{ ok: true, data: T } | { ok: false, error: string }> => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.post(url, req)
|
|
||||||
return { ok: true, data: data as T }
|
|
||||||
} catch (err: any) {
|
|
||||||
if (err.response?.data) {
|
|
||||||
log(ERROR, 'Error sending request', err.response.data)
|
|
||||||
return { ok: false, error: JSON.stringify(err.response.data) }
|
|
||||||
}
|
|
||||||
log(ERROR, 'Error sending request', err.message)
|
|
||||||
return { ok: false, error: err.message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const loggedGet = async <T>(log: PubLogger, url: string): Promise<{ ok: true, data: T } | { ok: false, error: string }> => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get(url)
|
|
||||||
return { ok: true, data: data as T }
|
|
||||||
} catch (err: any) {
|
|
||||||
if (err.response?.data) {
|
|
||||||
log(ERROR, 'Error getting request', err.response.data)
|
|
||||||
return { ok: false, error: err.response.data }
|
|
||||||
}
|
|
||||||
log(ERROR, 'Error getting request', err.message)
|
|
||||||
return { ok: false, error: err.message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getNetwork = (network: BTCNetwork): Network => {
|
|
||||||
switch (network) {
|
|
||||||
case 'mainnet':
|
|
||||||
return Networks.bitcoinMainnet
|
|
||||||
case 'testnet':
|
|
||||||
return Networks.bitcoinTestnet
|
|
||||||
case 'regtest':
|
|
||||||
return Networks.bitcoinRegtest
|
|
||||||
default:
|
|
||||||
throw new Error(`Invalid network: ${network}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submarine swaps currently not supported, keeping the code for future reference
|
|
||||||
/*
|
|
||||||
export class SubmarineSwaps {
|
|
||||||
settings: SettingsManager
|
|
||||||
log: PubLogger
|
|
||||||
constructor(settings: SettingsManager) {
|
|
||||||
this.settings = settings
|
|
||||||
this.log = getLogger({ component: 'SubmarineSwaps' })
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapInvoice = async (invoice: string, paymentHash: string) => {
|
|
||||||
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
|
||||||
this.log(ERROR, 'Swaps are not enabled');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const keys = ECPairFactory(ecc).makeRandom()
|
|
||||||
const refundPublicKey = Buffer.from(keys.publicKey).toString('hex')
|
|
||||||
const req = { invoice, to: 'BTC', from: 'BTC', refundPublicKey }
|
|
||||||
const url = `${this.settings.getSettings().swapsSettings.boltzHttpUrl}/v2/swap/submarine`
|
|
||||||
this.log('Sending invoice swap request to', url);
|
|
||||||
const createdResponseRes = await loggedPost<InvoiceSwapResponse>(this.log, url, req)
|
|
||||||
if (!createdResponseRes.ok) {
|
|
||||||
return createdResponseRes
|
|
||||||
}
|
|
||||||
const createdResponse = createdResponseRes.data
|
|
||||||
this.log('Created invoice swap');
|
|
||||||
this.log(createdResponse);
|
|
||||||
|
|
||||||
const webSocket = new ws(`${this.settings.getSettings().swapsSettings.boltzWebSocketUrl}/v2/ws`)
|
|
||||||
const subReq = { op: 'subscribe', channel: 'swap.update', args: [createdResponse.id] }
|
|
||||||
webSocket.on('open', () => {
|
|
||||||
webSocket.send(JSON.stringify(subReq))
|
|
||||||
})
|
|
||||||
|
|
||||||
webSocket.on('message', async (rawMsg) => {
|
|
||||||
try {
|
|
||||||
await this.handleSwapInvoiceMessage(rawMsg, { createdResponse, info: { paymentHash, keys } }, () => webSocket.close())
|
|
||||||
} catch (err: any) {
|
|
||||||
this.log(ERROR, 'Error handling invoice WebSocket message', err.message)
|
|
||||||
webSocket.close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void) => {
|
|
||||||
const msg = JSON.parse(rawMsg.toString('utf-8'));
|
|
||||||
if (msg.event !== 'update') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('Got invoice WebSocket update');
|
|
||||||
this.log(msg);
|
|
||||||
switch (msg.args[0].status) {
|
|
||||||
// "invoice.set" means Boltz is waiting for an onchain transaction to be sent
|
|
||||||
case 'invoice.set':
|
|
||||||
this.log('Waiting for onchain transaction');
|
|
||||||
return;
|
|
||||||
// Create a partial signature to allow Boltz to do a key path spend to claim the mainchain coins
|
|
||||||
case 'transaction.claim.pending':
|
|
||||||
await this.handleInvoiceClaimPending(data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 'transaction.claimed':
|
|
||||||
this.log('Invoice swap successful');
|
|
||||||
closeWebSocket()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInvoiceClaimPending = async (data: InvoiceSwapData) => {
|
|
||||||
this.log('Creating cooperative claim transaction');
|
|
||||||
const { createdResponse, info } = data
|
|
||||||
const { paymentHash, keys } = info
|
|
||||||
const { boltzHttpUrl } = this.settings.getSettings().swapsSettings
|
|
||||||
// Get the information request to create a partial signature
|
|
||||||
const url = `${boltzHttpUrl}/v2/swap/submarine/${createdResponse.id}/claim`
|
|
||||||
const claimTxDetailsRes = await loggedGet<{ preimage: string, transactionHash: string, pubNonce: string }>(this.log, url)
|
|
||||||
if (!claimTxDetailsRes.ok) {
|
|
||||||
return claimTxDetailsRes
|
|
||||||
}
|
|
||||||
const claimTxDetails = claimTxDetailsRes.data
|
|
||||||
// Verify that Boltz actually paid the invoice by comparing the preimage hash
|
|
||||||
// of the invoice to the SHA256 hash of the preimage from the response
|
|
||||||
const claimTxPreimageHash = createHash('sha256').update(Buffer.from(claimTxDetails.preimage, 'hex')).digest()
|
|
||||||
const invoicePreimageHash = Buffer.from(paymentHash, 'hex')
|
|
||||||
|
|
||||||
if (!claimTxPreimageHash.equals(invoicePreimageHash)) {
|
|
||||||
this.log(ERROR, 'Boltz provided invalid preimage');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boltzPublicKey = Buffer.from(createdResponse.claimPublicKey, 'hex')
|
|
||||||
|
|
||||||
// Create a musig signing instance
|
|
||||||
const musig = new Musig(await zkpInit(), keys, randomBytes(32), [
|
|
||||||
boltzPublicKey,
|
|
||||||
Buffer.from(keys.publicKey),
|
|
||||||
]);
|
|
||||||
// Tweak that musig with the Taptree of the swap scripts
|
|
||||||
TaprootUtils.tweakMusig(
|
|
||||||
musig,
|
|
||||||
SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Aggregate the nonces
|
|
||||||
musig.aggregateNonces([
|
|
||||||
[boltzPublicKey, Buffer.from(claimTxDetails.pubNonce, 'hex')],
|
|
||||||
]);
|
|
||||||
// Initialize the session to sign the transaction hash from the response
|
|
||||||
musig.initializeSession(
|
|
||||||
Buffer.from(claimTxDetails.transactionHash, 'hex'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Give our public nonce and the partial signature to Boltz
|
|
||||||
const claimUrl = `${boltzHttpUrl}/v2/swap/submarine/${createdResponse.id}/claim`
|
|
||||||
const claimReq = {
|
|
||||||
pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'),
|
|
||||||
partialSignature: Buffer.from(musig.signPartial()).toString('hex'),
|
|
||||||
}
|
|
||||||
const claimResponseRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq)
|
|
||||||
if (!claimResponseRes.ok) {
|
|
||||||
return claimResponseRes
|
|
||||||
}
|
|
||||||
const claimResponse = claimResponseRes.data
|
|
||||||
this.log('Claim response', claimResponse)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
299
src/services/lnd/swaps/reverseSwaps.ts
Normal file
299
src/services/lnd/swaps/reverseSwaps.ts
Normal file
|
|
@ -0,0 +1,299 @@
|
||||||
|
import secp256k1ZkpModule from '@vulpemventures/secp256k1-zkp';
|
||||||
|
const zkpInit = (secp256k1ZkpModule as any).default || secp256k1ZkpModule;
|
||||||
|
import { initEccLib, Transaction, address } from 'bitcoinjs-lib';
|
||||||
|
// import bolt11 from 'bolt11';
|
||||||
|
import {
|
||||||
|
Musig, SwapTreeSerializer, TaprootUtils, detectSwap,
|
||||||
|
constructClaimTransaction, OutputType, constructRefundTransaction
|
||||||
|
} from 'boltz-core';
|
||||||
|
import { randomBytes, createHash } from 'crypto';
|
||||||
|
import { ECPairFactory, ECPairInterface } from 'ecpair';
|
||||||
|
import * as ecc from 'tiny-secp256k1';
|
||||||
|
import ws from 'ws';
|
||||||
|
import { getLogger, PubLogger, ERROR } from '../../helpers/logger.js';
|
||||||
|
import { BTCNetwork } from '../../main/settings.js';
|
||||||
|
import { loggedGet, loggedPost, getNetwork } from './swapHelpers.js';
|
||||||
|
|
||||||
|
|
||||||
|
type TransactionSwapFees = {
|
||||||
|
percentage: number,
|
||||||
|
minerFees: {
|
||||||
|
claim: number,
|
||||||
|
lockup: number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransactionSwapFeesRes = {
|
||||||
|
BTC?: {
|
||||||
|
BTC?: {
|
||||||
|
fees: TransactionSwapFees
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type TransactionSwapResponse = {
|
||||||
|
id: string, refundPublicKey: string, swapTree: string,
|
||||||
|
timeoutBlockHeight: number, lockupAddress: string, invoice: string,
|
||||||
|
onchainAmount?: number
|
||||||
|
}
|
||||||
|
type TransactionSwapInfo = { destinationAddress: string, preimage: Buffer, keys: ECPairInterface, chainFee: number }
|
||||||
|
export type TransactionSwapData = { createdResponse: TransactionSwapResponse, info: TransactionSwapInfo }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class ReverseSwaps {
|
||||||
|
// settings: SettingsManager
|
||||||
|
private httpUrl: string
|
||||||
|
private wsUrl: string
|
||||||
|
log: PubLogger
|
||||||
|
private network: BTCNetwork
|
||||||
|
constructor({ httpUrl, wsUrl, network }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) {
|
||||||
|
this.httpUrl = httpUrl
|
||||||
|
this.wsUrl = wsUrl
|
||||||
|
this.network = network
|
||||||
|
this.log = getLogger({ component: 'ReverseSwaps' })
|
||||||
|
initEccLib(ecc)
|
||||||
|
}
|
||||||
|
|
||||||
|
getHttpUrl = () => {
|
||||||
|
return this.httpUrl
|
||||||
|
}
|
||||||
|
getWsUrl = () => {
|
||||||
|
return this.wsUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateFees = (fees: TransactionSwapFees, receiveAmount: number) => {
|
||||||
|
const pct = fees.percentage / 100
|
||||||
|
const minerFee = fees.minerFees.claim + fees.minerFees.lockup
|
||||||
|
|
||||||
|
const preFee = receiveAmount + minerFee
|
||||||
|
const fee = Math.ceil(preFee * pct)
|
||||||
|
const total = preFee + fee
|
||||||
|
return { total, fee, minerFee }
|
||||||
|
}
|
||||||
|
|
||||||
|
GetFees = async (): Promise<{ ok: true, fees: TransactionSwapFees, } | { ok: false, error: string }> => {
|
||||||
|
const url = `${this.httpUrl}/v2/swap/reverse`
|
||||||
|
const feesRes = await loggedGet<TransactionSwapFeesRes>(this.log, url)
|
||||||
|
if (!feesRes.ok) {
|
||||||
|
return { ok: false, error: feesRes.error }
|
||||||
|
}
|
||||||
|
if (!feesRes.data.BTC?.BTC?.fees) {
|
||||||
|
return { ok: false, error: 'No fees found for BTC to BTC swap' }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ok: true, fees: feesRes.data.BTC.BTC.fees }
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapTransaction = async (txAmount: number): Promise<{ ok: true, createdResponse: TransactionSwapResponse, preimage: string, pubkey: string, privKey: string } | { ok: false, error: string }> => {
|
||||||
|
const preimage = randomBytes(32);
|
||||||
|
const keys = ECPairFactory(ecc).makeRandom()
|
||||||
|
if (!keys.privateKey) {
|
||||||
|
return { ok: false, error: 'Failed to generate keys' }
|
||||||
|
}
|
||||||
|
const url = `${this.httpUrl}/v2/swap/reverse`
|
||||||
|
const req: any = {
|
||||||
|
onchainAmount: txAmount,
|
||||||
|
to: 'BTC',
|
||||||
|
from: 'BTC',
|
||||||
|
claimPublicKey: Buffer.from(keys.publicKey).toString('hex'),
|
||||||
|
preimageHash: createHash('sha256').update(preimage).digest('hex'),
|
||||||
|
}
|
||||||
|
const createdResponseRes = await loggedPost<TransactionSwapResponse>(this.log, url, req)
|
||||||
|
if (!createdResponseRes.ok) {
|
||||||
|
return createdResponseRes
|
||||||
|
}
|
||||||
|
const createdResponse = createdResponseRes.data
|
||||||
|
this.log('Created transaction swap');
|
||||||
|
this.log(createdResponse);
|
||||||
|
return {
|
||||||
|
ok: true, createdResponse,
|
||||||
|
preimage: Buffer.from(preimage).toString('hex'),
|
||||||
|
pubkey: Buffer.from(keys.publicKey).toString('hex'),
|
||||||
|
privKey: Buffer.from(keys.privateKey).toString('hex')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscribeToTransactionSwap = async (data: TransactionSwapData, swapDone: (result: { ok: true, txId: string } | { ok: false, error: string }) => void) => {
|
||||||
|
const webSocket = new ws(`${this.wsUrl}/v2/ws`)
|
||||||
|
const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] }
|
||||||
|
webSocket.on('open', () => {
|
||||||
|
webSocket.send(JSON.stringify(subReq))
|
||||||
|
})
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
webSocket.ping()
|
||||||
|
}, 30 * 1000)
|
||||||
|
let txId = "", isDone = false
|
||||||
|
const done = (failureReason?: string) => {
|
||||||
|
isDone = true
|
||||||
|
clearInterval(interval)
|
||||||
|
webSocket.close()
|
||||||
|
if (failureReason) {
|
||||||
|
swapDone({ ok: false, error: failureReason })
|
||||||
|
} else {
|
||||||
|
swapDone({ ok: true, txId })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
webSocket.on('pong', () => {
|
||||||
|
this.log('WebSocket transaction swap pong received')
|
||||||
|
})
|
||||||
|
webSocket.on('error', (err) => {
|
||||||
|
this.log(ERROR, 'Error in WebSocket', err.message)
|
||||||
|
})
|
||||||
|
webSocket.on('close', () => {
|
||||||
|
if (!isDone) {
|
||||||
|
this.log(ERROR, 'WebSocket closed before swap was done');
|
||||||
|
done('WebSocket closed before swap was done')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
webSocket.on('message', async (rawMsg) => {
|
||||||
|
try {
|
||||||
|
const result = await this.handleSwapTransactionMessage(rawMsg, data, done)
|
||||||
|
if (result) {
|
||||||
|
txId = result
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
this.log(ERROR, 'Error handling transaction WebSocket message', err.message)
|
||||||
|
done(err.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, done: (failureReason?: string) => void) => {
|
||||||
|
const msg = JSON.parse(rawMsg.toString('utf-8'));
|
||||||
|
if (msg.event !== 'update') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log('Got WebSocket update');
|
||||||
|
this.log(msg);
|
||||||
|
switch (msg.args[0].status) {
|
||||||
|
// "swap.created" means Boltz is waiting for the invoice to be paid
|
||||||
|
case 'swap.created':
|
||||||
|
this.log('Waiting invoice to be paid');
|
||||||
|
return;
|
||||||
|
|
||||||
|
// "transaction.mempool" means that Boltz sent an onchain transaction
|
||||||
|
case 'transaction.mempool':
|
||||||
|
const txIdRes = await this.handleTransactionMempool(data, msg.args[0].transaction.hex)
|
||||||
|
if (!txIdRes.ok) {
|
||||||
|
throw new Error(txIdRes.error)
|
||||||
|
}
|
||||||
|
return txIdRes.txId
|
||||||
|
case 'invoice.settled':
|
||||||
|
this.log('Transaction swap successful');
|
||||||
|
done()
|
||||||
|
return;
|
||||||
|
case 'invoice.expired':
|
||||||
|
case 'swap.expired':
|
||||||
|
case 'transaction.failed':
|
||||||
|
done(`swap ${data.createdResponse.id} failed with status ${msg.args[0].status}`)
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
this.log('Unknown swap transaction WebSocket message', msg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTransactionMempool = async (data: TransactionSwapData, txHex: string): Promise<{ ok: true, txId: string } | { ok: false, error: string }> => {
|
||||||
|
this.log('Creating claim transaction');
|
||||||
|
const { createdResponse, info } = data
|
||||||
|
const { destinationAddress, keys, preimage, chainFee } = info
|
||||||
|
const boltzPublicKey = Buffer.from(
|
||||||
|
createdResponse.refundPublicKey,
|
||||||
|
'hex',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a musig signing session and tweak it with the Taptree of the swap scripts
|
||||||
|
const musig = new Musig(await zkpInit(), keys, randomBytes(32), [
|
||||||
|
boltzPublicKey,
|
||||||
|
Buffer.from(keys.publicKey),
|
||||||
|
]);
|
||||||
|
const tweakedKey = TaprootUtils.tweakMusig(
|
||||||
|
musig,
|
||||||
|
// swap tree can either be a string or an object
|
||||||
|
SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Parse the lockup transaction and find the output relevant for the swap
|
||||||
|
const lockupTx = Transaction.fromHex(txHex);
|
||||||
|
const swapOutput = detectSwap(tweakedKey, lockupTx);
|
||||||
|
if (swapOutput === undefined) {
|
||||||
|
this.log(ERROR, 'No swap output found in lockup transaction');
|
||||||
|
return { ok: false, error: 'No swap output found in lockup transaction' }
|
||||||
|
}
|
||||||
|
const network = getNetwork(this.network)
|
||||||
|
// Create a claim transaction to be signed cooperatively via a key path spend
|
||||||
|
const claimTx = constructClaimTransaction(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
...swapOutput,
|
||||||
|
keys,
|
||||||
|
preimage,
|
||||||
|
cooperative: true,
|
||||||
|
type: OutputType.Taproot,
|
||||||
|
txHash: lockupTx.getHash(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
address.toOutputScript(destinationAddress, network),
|
||||||
|
chainFee,
|
||||||
|
)
|
||||||
|
// Get the partial signature from Boltz
|
||||||
|
const claimUrl = `${this.httpUrl}/v2/swap/reverse/${createdResponse.id}/claim`
|
||||||
|
const claimReq = {
|
||||||
|
index: 0,
|
||||||
|
transaction: claimTx.toHex(),
|
||||||
|
preimage: preimage.toString('hex'),
|
||||||
|
pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'),
|
||||||
|
}
|
||||||
|
const boltzSigRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq)
|
||||||
|
if (!boltzSigRes.ok) {
|
||||||
|
return boltzSigRes
|
||||||
|
}
|
||||||
|
const boltzSig = boltzSigRes.data
|
||||||
|
|
||||||
|
// Aggregate the nonces
|
||||||
|
musig.aggregateNonces([
|
||||||
|
[boltzPublicKey, Buffer.from(boltzSig.pubNonce, 'hex')],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Initialize the session to sign the claim transaction
|
||||||
|
musig.initializeSession(
|
||||||
|
claimTx.hashForWitnessV1(
|
||||||
|
0,
|
||||||
|
[swapOutput.script],
|
||||||
|
[swapOutput.value],
|
||||||
|
Transaction.SIGHASH_DEFAULT,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the partial signature from Boltz
|
||||||
|
musig.addPartial(
|
||||||
|
boltzPublicKey,
|
||||||
|
Buffer.from(boltzSig.partialSignature, 'hex'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create our partial signature
|
||||||
|
musig.signPartial();
|
||||||
|
|
||||||
|
// Witness of the input to the aggregated signature
|
||||||
|
claimTx.ins[0].witness = [musig.aggregatePartials()];
|
||||||
|
|
||||||
|
// Broadcast the finalized transaction
|
||||||
|
const broadcastUrl = `${this.httpUrl}/v2/chain/BTC/transaction`
|
||||||
|
const broadcastReq = {
|
||||||
|
hex: claimTx.toHex(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const broadcastResponse = await loggedPost<any>(this.log, broadcastUrl, broadcastReq)
|
||||||
|
if (!broadcastResponse.ok) {
|
||||||
|
return broadcastResponse
|
||||||
|
}
|
||||||
|
this.log('Transaction broadcasted', broadcastResponse.data)
|
||||||
|
const txId = claimTx.getId()
|
||||||
|
return { ok: true, txId }
|
||||||
|
}
|
||||||
|
}
|
||||||
539
src/services/lnd/swaps/submarineSwaps.ts
Normal file
539
src/services/lnd/swaps/submarineSwaps.ts
Normal file
|
|
@ -0,0 +1,539 @@
|
||||||
|
import secp256k1ZkpModule from '@vulpemventures/secp256k1-zkp';
|
||||||
|
const zkpInit = (secp256k1ZkpModule as any).default || secp256k1ZkpModule;
|
||||||
|
// import bolt11 from 'bolt11';
|
||||||
|
import {
|
||||||
|
Musig, SwapTreeSerializer, TaprootUtils, constructRefundTransaction,
|
||||||
|
detectSwap, OutputType, targetFee
|
||||||
|
} from 'boltz-core';
|
||||||
|
import { randomBytes, createHash } from 'crypto';
|
||||||
|
import { ECPairFactory, ECPairInterface } from 'ecpair';
|
||||||
|
import * as ecc from 'tiny-secp256k1';
|
||||||
|
import { Transaction, address } from 'bitcoinjs-lib';
|
||||||
|
import ws from 'ws';
|
||||||
|
import { getLogger, PubLogger, ERROR } from '../../helpers/logger.js';
|
||||||
|
import { loggedGet, loggedPost, getNetwork } from './swapHelpers.js';
|
||||||
|
import { BTCNetwork } from '../../main/settings.js';
|
||||||
|
|
||||||
|
/* type InvoiceSwapFees = {
|
||||||
|
hash: string,
|
||||||
|
rate: number,
|
||||||
|
limits: {
|
||||||
|
maximal: number,
|
||||||
|
minimal: number,
|
||||||
|
maximalZeroConf: number
|
||||||
|
},
|
||||||
|
fees: {
|
||||||
|
percentage: number,
|
||||||
|
minerFees: number,
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
type InvoiceSwapFees = {
|
||||||
|
percentage: number,
|
||||||
|
minerFees: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvoiceSwapFeesRes = {
|
||||||
|
BTC?: {
|
||||||
|
BTC?: {
|
||||||
|
fees: InvoiceSwapFees
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type InvoiceSwapResponse = {
|
||||||
|
id: string, claimPublicKey: string, swapTree: string, timeoutBlockHeight: number,
|
||||||
|
expectedAmount: number, address: string
|
||||||
|
}
|
||||||
|
type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface }
|
||||||
|
export type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo }
|
||||||
|
|
||||||
|
export class SubmarineSwaps {
|
||||||
|
private httpUrl: string
|
||||||
|
private wsUrl: string
|
||||||
|
private network: BTCNetwork
|
||||||
|
log: PubLogger
|
||||||
|
constructor({ httpUrl, wsUrl, network }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) {
|
||||||
|
this.httpUrl = httpUrl
|
||||||
|
this.wsUrl = wsUrl
|
||||||
|
this.network = network
|
||||||
|
this.log = getLogger({ component: 'SubmarineSwaps' })
|
||||||
|
}
|
||||||
|
|
||||||
|
getHttpUrl = () => {
|
||||||
|
return this.httpUrl
|
||||||
|
}
|
||||||
|
getWsUrl = () => {
|
||||||
|
return this.wsUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
GetFees = async (): Promise<{ ok: true, fees: InvoiceSwapFees, } | { ok: false, error: string }> => {
|
||||||
|
const url = `${this.httpUrl}/v2/swap/submarine`
|
||||||
|
const feesRes = await loggedGet<InvoiceSwapFeesRes>(this.log, url)
|
||||||
|
if (!feesRes.ok) {
|
||||||
|
return { ok: false, error: feesRes.error }
|
||||||
|
}
|
||||||
|
if (!feesRes.data.BTC?.BTC?.fees) {
|
||||||
|
return { ok: false, error: 'No fees found for BTC to BTC swap' }
|
||||||
|
}
|
||||||
|
return { ok: true, fees: feesRes.data.BTC.BTC.fees }
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapInvoice = async (invoice: string): Promise<{ ok: true, createdResponse: InvoiceSwapResponse, pubkey: string, privKey: string } | { ok: false, error: string }> => {
|
||||||
|
const keys = ECPairFactory(ecc).makeRandom()
|
||||||
|
if (!keys.privateKey) {
|
||||||
|
return { ok: false, error: 'Failed to generate keys' }
|
||||||
|
}
|
||||||
|
const refundPublicKey = Buffer.from(keys.publicKey).toString('hex')
|
||||||
|
const req = { invoice, to: 'BTC', from: 'BTC', refundPublicKey }
|
||||||
|
const url = `${this.httpUrl}/v2/swap/submarine`
|
||||||
|
this.log('Sending invoice swap request to', url);
|
||||||
|
const createdResponseRes = await loggedPost<InvoiceSwapResponse>(this.log, url, req)
|
||||||
|
if (!createdResponseRes.ok) {
|
||||||
|
return createdResponseRes
|
||||||
|
}
|
||||||
|
const createdResponse = createdResponseRes.data
|
||||||
|
this.log('Created invoice swap');
|
||||||
|
this.log(createdResponse);
|
||||||
|
return {
|
||||||
|
ok: true, createdResponse,
|
||||||
|
pubkey: refundPublicKey,
|
||||||
|
privKey: Buffer.from(keys.privateKey).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the lockup transaction for a swap from Boltz
|
||||||
|
*/
|
||||||
|
private getLockupTransaction = async (swapId: string): Promise<{ ok: true, data: { hex: string } } | { ok: false, error: string }> => {
|
||||||
|
const url = `${this.httpUrl}/v2/swap/submarine/${swapId}/transaction`
|
||||||
|
return await loggedGet<{ hex: string }>(this.log, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get partial refund signature from Boltz for cooperative refund
|
||||||
|
*/
|
||||||
|
private getPartialRefundSignature = async (
|
||||||
|
swapId: string,
|
||||||
|
pubNonce: Buffer,
|
||||||
|
transaction: Transaction,
|
||||||
|
index: number
|
||||||
|
): Promise<{ ok: true, data: { pubNonce: string, partialSignature: string } } | { ok: false, error: string }> => {
|
||||||
|
const url = `${this.httpUrl}/v2/swap/submarine/${swapId}/refund`
|
||||||
|
const req = {
|
||||||
|
index,
|
||||||
|
pubNonce: pubNonce.toString('hex'),
|
||||||
|
transaction: transaction.toHex()
|
||||||
|
}
|
||||||
|
return await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, url, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Taproot refund transaction (cooperative or uncooperative)
|
||||||
|
*/
|
||||||
|
private constructTaprootRefund = async (
|
||||||
|
swapId: string,
|
||||||
|
claimPublicKey: string,
|
||||||
|
swapTree: string,
|
||||||
|
timeoutBlockHeight: number,
|
||||||
|
lockupTx: Transaction,
|
||||||
|
privateKey: ECPairInterface,
|
||||||
|
refundAddress: string,
|
||||||
|
feePerVbyte: number,
|
||||||
|
cooperative: boolean = true,
|
||||||
|
allowUncooperativeFallback: boolean = true,
|
||||||
|
cooperativeErrorMessage?: string
|
||||||
|
): Promise<{
|
||||||
|
ok: true,
|
||||||
|
transaction: Transaction,
|
||||||
|
cooperativeError?: string
|
||||||
|
} | {
|
||||||
|
ok: false,
|
||||||
|
error: string
|
||||||
|
}> => {
|
||||||
|
this.log(`Constructing ${cooperative ? 'cooperative' : 'uncooperative'} Taproot refund for swap ${swapId}`)
|
||||||
|
|
||||||
|
const boltzPublicKey = Buffer.from(claimPublicKey, 'hex')
|
||||||
|
const swapTreeDeserialized = SwapTreeSerializer.deserializeSwapTree(swapTree)
|
||||||
|
|
||||||
|
// Create musig and tweak it
|
||||||
|
let musig = new Musig(await zkpInit(), privateKey, randomBytes(32), [
|
||||||
|
boltzPublicKey,
|
||||||
|
Buffer.from(privateKey.publicKey),
|
||||||
|
])
|
||||||
|
const tweakedKey = TaprootUtils.tweakMusig(musig, swapTreeDeserialized.tree)
|
||||||
|
|
||||||
|
// Detect the swap output in the lockup transaction
|
||||||
|
const swapOutput = detectSwap(tweakedKey, lockupTx)
|
||||||
|
if (!swapOutput) {
|
||||||
|
return { ok: false, error: 'Could not detect swap output in lockup transaction' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const network = getNetwork(this.network)
|
||||||
|
// const decodedAddress = address.fromBech32(refundAddress)
|
||||||
|
|
||||||
|
const details = [
|
||||||
|
{
|
||||||
|
...swapOutput,
|
||||||
|
keys: privateKey,
|
||||||
|
cooperative,
|
||||||
|
type: OutputType.Taproot,
|
||||||
|
txHash: lockupTx.getHash(),
|
||||||
|
swapTree: swapTreeDeserialized,
|
||||||
|
internalKey: musig.getAggregatedPublicKey(),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const outputScript = address.toOutputScript(refundAddress, network)
|
||||||
|
// Construct the refund transaction: targetFee converts sat/vbyte rate to flat fee
|
||||||
|
const refundTx = targetFee(
|
||||||
|
feePerVbyte,
|
||||||
|
(fee) => constructRefundTransaction(
|
||||||
|
details,
|
||||||
|
outputScript,
|
||||||
|
cooperative ? 0 : timeoutBlockHeight,
|
||||||
|
fee,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!cooperative) {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
transaction: refundTx,
|
||||||
|
cooperativeError: cooperativeErrorMessage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cooperative refund, get Boltz's partial signature
|
||||||
|
try {
|
||||||
|
musig = new Musig(await zkpInit(), privateKey, randomBytes(32), [
|
||||||
|
boltzPublicKey,
|
||||||
|
Buffer.from(privateKey.publicKey),
|
||||||
|
])
|
||||||
|
// Get the partial signature from Boltz
|
||||||
|
const boltzSigRes = await this.getPartialRefundSignature(
|
||||||
|
swapId,
|
||||||
|
Buffer.from(musig.getPublicNonce()),
|
||||||
|
refundTx,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!boltzSigRes.ok) {
|
||||||
|
this.log(ERROR, 'Failed to get Boltz partial signature')
|
||||||
|
if (!allowUncooperativeFallback) {
|
||||||
|
return { ok: false, error: `Failed to get Boltz partial signature: ${boltzSigRes.error}` }
|
||||||
|
}
|
||||||
|
this.log(ERROR, 'Falling back to uncooperative refund')
|
||||||
|
// Fallback to uncooperative refund
|
||||||
|
return await this.constructTaprootRefund(
|
||||||
|
swapId,
|
||||||
|
claimPublicKey,
|
||||||
|
swapTree,
|
||||||
|
timeoutBlockHeight,
|
||||||
|
lockupTx,
|
||||||
|
privateKey,
|
||||||
|
refundAddress,
|
||||||
|
feePerVbyte,
|
||||||
|
false,
|
||||||
|
allowUncooperativeFallback,
|
||||||
|
boltzSigRes.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const boltzSig = boltzSigRes.data
|
||||||
|
|
||||||
|
// Aggregate nonces
|
||||||
|
musig.aggregateNonces([
|
||||||
|
[boltzPublicKey, Musig.parsePubNonce(boltzSig.pubNonce)],
|
||||||
|
])
|
||||||
|
|
||||||
|
// Tweak musig again after aggregating nonces
|
||||||
|
TaprootUtils.tweakMusig(musig, swapTreeDeserialized.tree)
|
||||||
|
|
||||||
|
// Initialize session and sign
|
||||||
|
musig.initializeSession(
|
||||||
|
TaprootUtils.hashForWitnessV1(
|
||||||
|
details,
|
||||||
|
refundTx,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
musig.signPartial()
|
||||||
|
musig.addPartial(boltzPublicKey, Buffer.from(boltzSig.partialSignature, 'hex'))
|
||||||
|
|
||||||
|
// Set the witness to the aggregated signature
|
||||||
|
refundTx.ins[0].witness = [musig.aggregatePartials()]
|
||||||
|
|
||||||
|
return { ok: true, transaction: refundTx }
|
||||||
|
} catch (error: any) {
|
||||||
|
this.log(ERROR, 'Cooperative refund failed:', error.message)
|
||||||
|
if (!allowUncooperativeFallback) {
|
||||||
|
return { ok: false, error: `Cooperative refund failed: ${error.message}` }
|
||||||
|
}
|
||||||
|
// Fallback to uncooperative refund
|
||||||
|
return await this.constructTaprootRefund(
|
||||||
|
swapId,
|
||||||
|
claimPublicKey,
|
||||||
|
swapTree,
|
||||||
|
timeoutBlockHeight,
|
||||||
|
lockupTx,
|
||||||
|
privateKey,
|
||||||
|
refundAddress,
|
||||||
|
feePerVbyte,
|
||||||
|
false,
|
||||||
|
allowUncooperativeFallback,
|
||||||
|
error.message
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcasts a refund transaction
|
||||||
|
*/
|
||||||
|
private broadcastRefundTransaction = async (transaction: Transaction): Promise<{ ok: true, txId: string } | { ok: false, error: string }> => {
|
||||||
|
const url = `${this.httpUrl}/v2/chain/BTC/transaction`
|
||||||
|
const req = { hex: transaction.toHex() }
|
||||||
|
|
||||||
|
const result = await loggedPost<{ id: string }>(this.log, url, req)
|
||||||
|
if (!result.ok) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ok: true, txId: result.data.id }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refund a submarine swap
|
||||||
|
* @param swapId - The swap ID
|
||||||
|
* @param claimPublicKey - Boltz's claim public key
|
||||||
|
* @param swapTree - The swap tree
|
||||||
|
* @param timeoutBlockHeight - The timeout block height
|
||||||
|
* @param privateKey - The refund private key (hex string)
|
||||||
|
* @param refundAddress - The address to refund to
|
||||||
|
* @param currentHeight - The current block height
|
||||||
|
* @param lockupTxHex - The lockup transaction hex (optional, will fetch from Boltz if not provided)
|
||||||
|
* @param feePerVbyte - Fee rate in sat/vbyte (optional, will use default if not provided)
|
||||||
|
*/
|
||||||
|
RefundSwap = async (params: {
|
||||||
|
swapId: string,
|
||||||
|
claimPublicKey: string,
|
||||||
|
swapTree: string,
|
||||||
|
timeoutBlockHeight: number,
|
||||||
|
privateKeyHex: string,
|
||||||
|
refundAddress: string,
|
||||||
|
currentHeight: number,
|
||||||
|
lockupTxHex?: string,
|
||||||
|
feePerVbyte?: number,
|
||||||
|
allowEarlyRefund?: boolean
|
||||||
|
}): Promise<{ ok: true, publish: { done: false, txHex: string, txId: string } | { done: true, txId: string } } | { ok: false, error: string }> => {
|
||||||
|
const { swapId, claimPublicKey, swapTree, timeoutBlockHeight, privateKeyHex, refundAddress, currentHeight, lockupTxHex, feePerVbyte = 2, allowEarlyRefund = false } = params
|
||||||
|
|
||||||
|
this.log('Starting refund process for swap:', swapId)
|
||||||
|
|
||||||
|
// Get the lockup transaction (from parameter or fetch from Boltz)
|
||||||
|
let lockupTx: Transaction
|
||||||
|
if (lockupTxHex) {
|
||||||
|
this.log('Using provided lockup transaction hex')
|
||||||
|
lockupTx = Transaction.fromHex(lockupTxHex)
|
||||||
|
} else {
|
||||||
|
this.log('Fetching lockup transaction from Boltz')
|
||||||
|
const lockupTxRes = await this.getLockupTransaction(swapId)
|
||||||
|
if (!lockupTxRes.ok) {
|
||||||
|
return { ok: false, error: `Failed to get lockup transaction: ${lockupTxRes.error}` }
|
||||||
|
}
|
||||||
|
lockupTx = Transaction.fromHex(lockupTxRes.data.hex)
|
||||||
|
}
|
||||||
|
this.log('Lockup transaction retrieved:', lockupTx.getId())
|
||||||
|
|
||||||
|
const hasTimedOut = currentHeight >= timeoutBlockHeight
|
||||||
|
|
||||||
|
// For stuck swaps, only allow refund after timeout. For completed (failed) swaps,
|
||||||
|
// we may attempt a cooperative refund before timeout.
|
||||||
|
if (!hasTimedOut && !allowEarlyRefund) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
error: `Swap has not timed out yet. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasTimedOut) {
|
||||||
|
this.log(`Swap has timed out. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}`)
|
||||||
|
} else {
|
||||||
|
this.log(`Swap has not timed out yet, attempting cooperative refund`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the private key
|
||||||
|
const privateKey = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKeyHex, 'hex'))
|
||||||
|
|
||||||
|
// Construct the refund transaction (tries cooperative first, then falls back to uncooperative)
|
||||||
|
const refundTxRes = await this.constructTaprootRefund(
|
||||||
|
swapId,
|
||||||
|
claimPublicKey,
|
||||||
|
swapTree,
|
||||||
|
timeoutBlockHeight,
|
||||||
|
lockupTx,
|
||||||
|
privateKey,
|
||||||
|
refundAddress,
|
||||||
|
feePerVbyte,
|
||||||
|
true, // Try cooperative first
|
||||||
|
hasTimedOut // only allow uncooperative fallback once timeout has passed
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!refundTxRes.ok) {
|
||||||
|
return { ok: false, error: refundTxRes.error }
|
||||||
|
}
|
||||||
|
|
||||||
|
const cooperative = !refundTxRes.cooperativeError
|
||||||
|
this.log(`Refund transaction constructed (${cooperative ? 'cooperative' : 'uncooperative'}):`, refundTxRes.transaction.getId())
|
||||||
|
if (!cooperative) {
|
||||||
|
return { ok: true, publish: { done: false, txHex: refundTxRes.transaction.toHex(), txId: refundTxRes.transaction.getId() } }
|
||||||
|
}
|
||||||
|
// Broadcast the refund transaction
|
||||||
|
const broadcastRes = await this.broadcastRefundTransaction(refundTxRes.transaction)
|
||||||
|
if (!broadcastRes.ok) {
|
||||||
|
return { ok: false, error: `Failed to broadcast refund transaction: ${broadcastRes.error}` }
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log('Refund transaction broadcasted successfully:', broadcastRes.txId)
|
||||||
|
return { ok: true, publish: { done: true, txId: broadcastRes.txId } }
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscribeToInvoiceSwap = (data: InvoiceSwapData, swapDone: (result: { ok: true } | { ok: false, error: string }) => void, waitingTx: () => void) => {
|
||||||
|
this.log("subscribing to invoice swap", { id: data.createdResponse.id })
|
||||||
|
const webSocket = new ws(`${this.wsUrl}/v2/ws`)
|
||||||
|
const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] }
|
||||||
|
webSocket.on('open', () => {
|
||||||
|
webSocket.send(JSON.stringify(subReq))
|
||||||
|
})
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
webSocket.ping()
|
||||||
|
}, 30 * 1000)
|
||||||
|
let isDone = false
|
||||||
|
const done = (failureReason?: string) => {
|
||||||
|
isDone = true
|
||||||
|
clearInterval(interval)
|
||||||
|
webSocket.close()
|
||||||
|
if (failureReason) {
|
||||||
|
swapDone({ ok: false, error: failureReason })
|
||||||
|
} else {
|
||||||
|
swapDone({ ok: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
webSocket.on('pong', () => {
|
||||||
|
this.log('WebSocket invoice swap pong received')
|
||||||
|
})
|
||||||
|
webSocket.on('error', (err) => {
|
||||||
|
this.log(ERROR, 'Error in WebSocket', err.message)
|
||||||
|
})
|
||||||
|
webSocket.on('close', () => {
|
||||||
|
if (!isDone) {
|
||||||
|
this.log(ERROR, 'WebSocket closed before swap was done');
|
||||||
|
done('WebSocket closed before swap was done')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
webSocket.on('message', async (rawMsg) => {
|
||||||
|
try {
|
||||||
|
await this.handleSwapInvoiceMessage(rawMsg, data, done, waitingTx)
|
||||||
|
} catch (err: any) {
|
||||||
|
this.log(ERROR, 'Error handling invoice WebSocket message', err.message)
|
||||||
|
done(err.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
webSocket.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: (failureReason?: string) => void, waitingTx: () => void) => {
|
||||||
|
const msg = JSON.parse(rawMsg.toString('utf-8'));
|
||||||
|
if (msg.event !== 'update') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log('Got invoice WebSocket update');
|
||||||
|
this.log(msg);
|
||||||
|
switch (msg.args[0].status) {
|
||||||
|
// "invoice.set" means Boltz is waiting for an onchain transaction to be sent
|
||||||
|
case 'invoice.set':
|
||||||
|
this.log('Waiting for onchain transaction');
|
||||||
|
waitingTx()
|
||||||
|
return;
|
||||||
|
// Create a partial signature to allow Boltz to do a key path spend to claim the mainchain coins
|
||||||
|
case 'transaction.claim.pending':
|
||||||
|
await this.handleInvoiceClaimPending(data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 'transaction.claimed':
|
||||||
|
this.log('Invoice swap successful');
|
||||||
|
closeWebSocket()
|
||||||
|
return;
|
||||||
|
case 'swap.expired':
|
||||||
|
case 'transaction.lockupFailed':
|
||||||
|
case 'invoice.failedToPay':
|
||||||
|
closeWebSocket(`swap ${data.createdResponse.id} failed with status ${msg.args[0].status}`)
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
this.log('Unknown swap invoice WebSocket message', msg)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInvoiceClaimPending = async (data: InvoiceSwapData) => {
|
||||||
|
this.log('Creating cooperative claim transaction');
|
||||||
|
const { createdResponse, info } = data
|
||||||
|
const { paymentHash, keys } = info
|
||||||
|
// Get the information request to create a partial signature
|
||||||
|
const url = `${this.httpUrl}/v2/swap/submarine/${createdResponse.id}/claim`
|
||||||
|
const claimTxDetailsRes = await loggedGet<{ preimage: string, transactionHash: string, pubNonce: string }>(this.log, url)
|
||||||
|
if (!claimTxDetailsRes.ok) {
|
||||||
|
return claimTxDetailsRes
|
||||||
|
}
|
||||||
|
const claimTxDetails = claimTxDetailsRes.data
|
||||||
|
// Verify that Boltz actually paid the invoice by comparing the preimage hash
|
||||||
|
// of the invoice to the SHA256 hash of the preimage from the response
|
||||||
|
const claimTxPreimageHash = createHash('sha256').update(Buffer.from(claimTxDetails.preimage, 'hex')).digest()
|
||||||
|
const invoicePreimageHash = Buffer.from(paymentHash, 'hex')
|
||||||
|
|
||||||
|
if (!claimTxPreimageHash.equals(invoicePreimageHash)) {
|
||||||
|
this.log(ERROR, 'Boltz provided invalid preimage');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boltzPublicKey = Buffer.from(createdResponse.claimPublicKey, 'hex')
|
||||||
|
|
||||||
|
// Create a musig signing instance
|
||||||
|
const musig = new Musig(await zkpInit(), keys, randomBytes(32), [
|
||||||
|
boltzPublicKey,
|
||||||
|
Buffer.from(keys.publicKey),
|
||||||
|
]);
|
||||||
|
// Tweak that musig with the Taptree of the swap scripts
|
||||||
|
TaprootUtils.tweakMusig(
|
||||||
|
musig,
|
||||||
|
SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Aggregate the nonces
|
||||||
|
musig.aggregateNonces([
|
||||||
|
[boltzPublicKey, Buffer.from(claimTxDetails.pubNonce, 'hex')],
|
||||||
|
]);
|
||||||
|
// Initialize the session to sign the transaction hash from the response
|
||||||
|
musig.initializeSession(
|
||||||
|
Buffer.from(claimTxDetails.transactionHash, 'hex'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Give our public nonce and the partial signature to Boltz
|
||||||
|
const claimUrl = `${this.httpUrl}/v2/swap/submarine/${createdResponse.id}/claim`
|
||||||
|
const claimReq = {
|
||||||
|
pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'),
|
||||||
|
partialSignature: Buffer.from(musig.signPartial()).toString('hex'),
|
||||||
|
}
|
||||||
|
const claimResponseRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq)
|
||||||
|
if (!claimResponseRes.ok) {
|
||||||
|
return claimResponseRes
|
||||||
|
}
|
||||||
|
const claimResponse = claimResponseRes.data
|
||||||
|
this.log('Claim response', claimResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/services/lnd/swaps/swapHelpers.ts
Normal file
50
src/services/lnd/swaps/swapHelpers.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import { Network } from 'bitcoinjs-lib';
|
||||||
|
// import bolt11 from 'bolt11';
|
||||||
|
import {
|
||||||
|
Networks,
|
||||||
|
} from 'boltz-core';
|
||||||
|
import { PubLogger, ERROR } from '../../helpers/logger.js';
|
||||||
|
import { BTCNetwork } from '../../main/settings.js';
|
||||||
|
|
||||||
|
|
||||||
|
export const loggedPost = async <T>(log: PubLogger, url: string, req: any): Promise<{ ok: true, data: T } | { ok: false, error: string }> => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.post(url, req)
|
||||||
|
return { ok: true, data: data as T }
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err.response?.data) {
|
||||||
|
log(ERROR, 'Error sending request', err.response.data)
|
||||||
|
return { ok: false, error: JSON.stringify(err.response.data) }
|
||||||
|
}
|
||||||
|
log(ERROR, 'Error sending request', err.message)
|
||||||
|
return { ok: false, error: err.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loggedGet = async <T>(log: PubLogger, url: string): Promise<{ ok: true, data: T } | { ok: false, error: string }> => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get(url)
|
||||||
|
return { ok: true, data: data as T }
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err.response?.data) {
|
||||||
|
log(ERROR, 'Error getting request', err.response.data)
|
||||||
|
return { ok: false, error: err.response.data }
|
||||||
|
}
|
||||||
|
log(ERROR, 'Error getting request', err.message)
|
||||||
|
return { ok: false, error: err.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getNetwork = (network: BTCNetwork): Network => {
|
||||||
|
switch (network) {
|
||||||
|
case 'mainnet':
|
||||||
|
return Networks.bitcoinMainnet
|
||||||
|
case 'testnet':
|
||||||
|
return Networks.bitcoinTestnet
|
||||||
|
case 'regtest':
|
||||||
|
return Networks.bitcoinRegtest
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid network: ${network}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
452
src/services/lnd/swaps/swaps.ts
Normal file
452
src/services/lnd/swaps/swaps.ts
Normal file
|
|
@ -0,0 +1,452 @@
|
||||||
|
import { ECPairFactory } from 'ecpair';
|
||||||
|
import * as ecc from 'tiny-secp256k1';
|
||||||
|
import { getLogger } from '../../helpers/logger.js';
|
||||||
|
import SettingsManager from '../../main/settingsManager.js';
|
||||||
|
import * as Types from '../../../../proto/autogenerated/ts/types.js';
|
||||||
|
import Storage from '../../storage/index.js';
|
||||||
|
import LND from '../lnd.js';
|
||||||
|
import { UserInvoicePayment } from '../../storage/entity/UserInvoicePayment.js';
|
||||||
|
import { ReverseSwaps, TransactionSwapData } from './reverseSwaps.js';
|
||||||
|
import { SubmarineSwaps, InvoiceSwapData } from './submarineSwaps.js';
|
||||||
|
import { InvoiceSwap } from '../../storage/entity/InvoiceSwap.js';
|
||||||
|
import { TransactionSwap } from '../../storage/entity/TransactionSwap.js';
|
||||||
|
|
||||||
|
|
||||||
|
export class Swaps {
|
||||||
|
settings: SettingsManager
|
||||||
|
revSwappers: Record<string, ReverseSwaps>
|
||||||
|
subSwappers: Record<string, SubmarineSwaps>
|
||||||
|
storage: Storage
|
||||||
|
lnd: LND
|
||||||
|
waitingSwaps: Record<string, boolean> = {}
|
||||||
|
log = getLogger({ component: 'swaps' })
|
||||||
|
constructor(settings: SettingsManager, storage: Storage) {
|
||||||
|
this.settings = settings
|
||||||
|
this.revSwappers = {}
|
||||||
|
this.subSwappers = {}
|
||||||
|
const network = settings.getSettings().lndSettings.network
|
||||||
|
const { boltzHttpUrl, boltzWebSocketUrl, boltsHttpUrlAlt, boltsWebSocketUrlAlt } = settings.getSettings().swapsSettings
|
||||||
|
if (boltzHttpUrl && boltzWebSocketUrl) {
|
||||||
|
this.revSwappers[boltzHttpUrl] = new ReverseSwaps({ httpUrl: boltzHttpUrl, wsUrl: boltzWebSocketUrl, network })
|
||||||
|
this.subSwappers[boltzHttpUrl] = new SubmarineSwaps({ httpUrl: boltzHttpUrl, wsUrl: boltzWebSocketUrl, network })
|
||||||
|
}
|
||||||
|
if (boltsHttpUrlAlt && boltsWebSocketUrlAlt) {
|
||||||
|
this.revSwappers[boltsHttpUrlAlt] = new ReverseSwaps({ httpUrl: boltsHttpUrlAlt, wsUrl: boltsWebSocketUrlAlt, network })
|
||||||
|
this.subSwappers[boltsHttpUrlAlt] = new SubmarineSwaps({ httpUrl: boltsHttpUrlAlt, wsUrl: boltsWebSocketUrlAlt, network })
|
||||||
|
}
|
||||||
|
this.storage = storage
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLnd = (lnd: LND) => {
|
||||||
|
this.lnd = lnd
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop = () => { }
|
||||||
|
|
||||||
|
GetKeys = (privateKey: string) => {
|
||||||
|
const keys = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKey, 'hex'))
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
GetInvoiceSwapQuotes = async (appUserId: string, invoice: string): Promise<Types.InvoiceSwapQuote[]> => {
|
||||||
|
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
||||||
|
throw new Error("Swaps are not enabled")
|
||||||
|
}
|
||||||
|
const swappers = Object.values(this.subSwappers)
|
||||||
|
if (swappers.length === 0) {
|
||||||
|
throw new Error("No swap services available")
|
||||||
|
}
|
||||||
|
const res = await Promise.allSettled(swappers.map(sw => this.getInvoiceSwapQuote(sw, appUserId, invoice)))
|
||||||
|
const failures: string[] = []
|
||||||
|
const success: Types.InvoiceSwapQuote[] = []
|
||||||
|
for (const r of res) {
|
||||||
|
if (r.status === 'fulfilled') {
|
||||||
|
success.push(r.value)
|
||||||
|
} else {
|
||||||
|
failures.push(r.reason.message ? r.reason.message : r.reason.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success.length === 0) {
|
||||||
|
throw new Error(failures.join("\n"))
|
||||||
|
}
|
||||||
|
return success
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapInvoiceSwapQuote = (s: InvoiceSwap): Types.InvoiceSwapQuote => {
|
||||||
|
return {
|
||||||
|
swap_operation_id: s.swap_operation_id,
|
||||||
|
invoice: s.invoice,
|
||||||
|
invoice_amount_sats: s.invoice_amount,
|
||||||
|
address: s.address,
|
||||||
|
transaction_amount_sats: s.transaction_amount,
|
||||||
|
chain_fee_sats: s.chain_fee_sats,
|
||||||
|
service_fee_sats: 0,
|
||||||
|
service_url: s.service_url,
|
||||||
|
swap_fee_sats: s.swap_fee_sats,
|
||||||
|
tx_id: s.tx_id,
|
||||||
|
paid_at_unix: s.paid_at_unix || (s.tx_id ? 1 : 0),
|
||||||
|
expires_at_block_height: s.timeout_block_height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListInvoiceSwaps = async (appUserId: string): Promise<Types.InvoiceSwapsList> => {
|
||||||
|
const info = await this.lnd.GetInfo()
|
||||||
|
const currentBlockHeight = info.blockHeight
|
||||||
|
const completedSwaps = await this.storage.paymentStorage.ListCompletedInvoiceSwaps(appUserId)
|
||||||
|
const pendingSwaps = await this.storage.paymentStorage.ListPendingInvoiceSwaps(appUserId)
|
||||||
|
const quotes: Types.InvoiceSwapOperation[] = pendingSwaps.map(s => ({ quote: this.mapInvoiceSwapQuote(s) }))
|
||||||
|
const operations: Types.InvoiceSwapOperation[] = completedSwaps.map(s => ({
|
||||||
|
quote: this.mapInvoiceSwapQuote(s),
|
||||||
|
failure_reason: s.failure_reason,
|
||||||
|
completed_at_unix: s.completed_at_unix || 1,
|
||||||
|
refund_address: s.refund_address,
|
||||||
|
refund_at_unix: s.refund_at_unix,
|
||||||
|
refund_tx_id: s.refund_tx_id,
|
||||||
|
}))
|
||||||
|
return {
|
||||||
|
current_block_height: currentBlockHeight,
|
||||||
|
swaps: operations.concat(quotes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefundInvoiceSwap = async (swapOperationId: string, satPerVByte: number, refundAddress: string, currentHeight: number): Promise<{ published: false, txHex: string, txId: string } | { published: true, txId: string }> => {
|
||||||
|
this.log("refunding invoice swap", { swapOperationId, satPerVByte, refundAddress, currentHeight })
|
||||||
|
const swap = await this.storage.paymentStorage.GetRefundableInvoiceSwap(swapOperationId)
|
||||||
|
if (!swap) {
|
||||||
|
throw new Error("Swap not found or already used")
|
||||||
|
}
|
||||||
|
const allowEarlyRefund = !!swap.failure_reason
|
||||||
|
const swapper = this.subSwappers[swap.service_url]
|
||||||
|
if (!swapper) {
|
||||||
|
throw new Error("swapper service not found")
|
||||||
|
}
|
||||||
|
const result = await swapper.RefundSwap({
|
||||||
|
swapId: swap.swap_quote_id,
|
||||||
|
claimPublicKey: swap.claim_public_key,
|
||||||
|
currentHeight,
|
||||||
|
privateKeyHex: swap.ephemeral_private_key,
|
||||||
|
refundAddress,
|
||||||
|
swapTree: swap.swap_tree,
|
||||||
|
timeoutBlockHeight: swap.timeout_block_height,
|
||||||
|
allowEarlyRefund,
|
||||||
|
feePerVbyte: satPerVByte,
|
||||||
|
lockupTxHex: swap.lockup_tx_hex,
|
||||||
|
})
|
||||||
|
if (!result.ok) {
|
||||||
|
throw new Error(result.error)
|
||||||
|
}
|
||||||
|
await this.storage.paymentStorage.UpdateRefundInvoiceSwap(swapOperationId, refundAddress, result.publish.txId)
|
||||||
|
if (result.publish.done) {
|
||||||
|
return { published: true, txId: result.publish.txId }
|
||||||
|
}
|
||||||
|
return { published: false, txHex: result.publish.txHex, txId: result.publish.txId }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PayInvoiceSwap = async (appUserId: string, swapOpId: string, satPerVByte: number, payAddress: (address: string, amt: number) => Promise<{ txId: string }>): Promise<void> => {
|
||||||
|
this.log("paying invoice swap", { appUserId, swapOpId, satPerVByte })
|
||||||
|
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
||||||
|
throw new Error("Swaps are not enabled")
|
||||||
|
}
|
||||||
|
if (!swapOpId) {
|
||||||
|
throw new Error("swap operation id is required")
|
||||||
|
}
|
||||||
|
if (!satPerVByte) {
|
||||||
|
throw new Error("sat per v byte is required")
|
||||||
|
}
|
||||||
|
const swap = await this.storage.paymentStorage.GetInvoiceSwap(swapOpId, appUserId)
|
||||||
|
if (!swap) {
|
||||||
|
throw new Error("swap not found")
|
||||||
|
}
|
||||||
|
const swapper = this.subSwappers[swap.service_url]
|
||||||
|
if (!swapper) {
|
||||||
|
throw new Error("swapper service not found")
|
||||||
|
}
|
||||||
|
if (this.waitingSwaps[swapOpId]) {
|
||||||
|
throw new Error("swap already in progress")
|
||||||
|
}
|
||||||
|
this.waitingSwaps[swapOpId] = true
|
||||||
|
const data = this.getInvoiceSwapData(swap)
|
||||||
|
let txId = ""
|
||||||
|
const close = swapper.SubscribeToInvoiceSwap(data, async (result) => {
|
||||||
|
if (result.ok) {
|
||||||
|
await this.storage.paymentStorage.FinalizeInvoiceSwap(swapOpId)
|
||||||
|
this.log("invoice swap completed", { swapOpId, txId })
|
||||||
|
} else {
|
||||||
|
await this.storage.paymentStorage.FailInvoiceSwap(swapOpId, result.error)
|
||||||
|
this.log("invoice swap failed", { swapOpId, error: result.error })
|
||||||
|
}
|
||||||
|
}, () => payAddress(swap.address, swap.transaction_amount)
|
||||||
|
.then(res => { txId = res.txId })
|
||||||
|
.catch(err => { close(); this.log("error paying address", err.message || err) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
ResumeInvoiceSwaps = async () => {
|
||||||
|
this.log("resuming invoice swaps")
|
||||||
|
const swaps = await this.storage.paymentStorage.ListUnfinishedInvoiceSwaps()
|
||||||
|
this.log("resuming", swaps.length, "invoice swaps")
|
||||||
|
for (const swap of swaps) {
|
||||||
|
try {
|
||||||
|
this.resumeInvoiceSwap(swap)
|
||||||
|
} catch (err: any) {
|
||||||
|
this.log("error resuming invoice swap", err.message || err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private resumeInvoiceSwap = (swap: InvoiceSwap) => {
|
||||||
|
// const swap = await this.storage.paymentStorage.GetInvoiceSwap(swapOpId, appUserId)
|
||||||
|
if (!swap || !swap.tx_id || swap.used) {
|
||||||
|
throw new Error("swap to resume not found, or does not have a tx id")
|
||||||
|
}
|
||||||
|
const swapper = this.subSwappers[swap.service_url]
|
||||||
|
if (!swapper) {
|
||||||
|
throw new Error("swapper service not found")
|
||||||
|
}
|
||||||
|
const data = this.getInvoiceSwapData(swap)
|
||||||
|
swapper.SubscribeToInvoiceSwap(data, async (result) => {
|
||||||
|
if (result.ok) {
|
||||||
|
await this.storage.paymentStorage.FinalizeInvoiceSwap(swap.swap_operation_id)
|
||||||
|
this.log("invoice swap completed", { swapOpId: swap.swap_operation_id, txId: swap.tx_id })
|
||||||
|
} else {
|
||||||
|
await this.storage.paymentStorage.FailInvoiceSwap(swap.swap_operation_id, result.error)
|
||||||
|
this.log("invoice swap failed", { swapOpId: swap.swap_operation_id, error: result.error })
|
||||||
|
}
|
||||||
|
}, () => { throw new Error("swap tx already paid") })
|
||||||
|
}
|
||||||
|
|
||||||
|
private getInvoiceSwapData = (swap: InvoiceSwap) => {
|
||||||
|
return {
|
||||||
|
createdResponse: {
|
||||||
|
address: swap.address,
|
||||||
|
claimPublicKey: swap.claim_public_key,
|
||||||
|
id: swap.swap_quote_id,
|
||||||
|
swapTree: swap.swap_tree,
|
||||||
|
timeoutBlockHeight: swap.timeout_block_height,
|
||||||
|
expectedAmount: swap.transaction_amount,
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
keys: this.GetKeys(swap.ephemeral_private_key),
|
||||||
|
paymentHash: swap.payment_hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getInvoiceSwapQuote(swapper: SubmarineSwaps, appUserId: string, invoice: string): Promise<Types.InvoiceSwapQuote> {
|
||||||
|
const feesRes = await swapper.GetFees()
|
||||||
|
if (!feesRes.ok) {
|
||||||
|
throw new Error(feesRes.error)
|
||||||
|
}
|
||||||
|
const decoded = await this.lnd.DecodeInvoice(invoice)
|
||||||
|
const amt = decoded.numSatoshis
|
||||||
|
const fee = Math.ceil((feesRes.fees.percentage / 100) * amt) + feesRes.fees.minerFees
|
||||||
|
const res = await swapper.SwapInvoice(invoice)
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(res.error)
|
||||||
|
}
|
||||||
|
const newSwap = await this.storage.paymentStorage.AddInvoiceSwap({
|
||||||
|
app_user_id: appUserId,
|
||||||
|
swap_quote_id: res.createdResponse.id,
|
||||||
|
swap_tree: JSON.stringify(res.createdResponse.swapTree),
|
||||||
|
timeout_block_height: res.createdResponse.timeoutBlockHeight,
|
||||||
|
ephemeral_public_key: res.pubkey,
|
||||||
|
ephemeral_private_key: res.privKey,
|
||||||
|
invoice: invoice,
|
||||||
|
invoice_amount: amt,
|
||||||
|
transaction_amount: res.createdResponse.expectedAmount,
|
||||||
|
swap_fee_sats: fee,
|
||||||
|
chain_fee_sats: 0,
|
||||||
|
service_url: swapper.getHttpUrl(),
|
||||||
|
address: res.createdResponse.address,
|
||||||
|
claim_public_key: res.createdResponse.claimPublicKey,
|
||||||
|
payment_hash: decoded.paymentHash,
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
swap_operation_id: newSwap.swap_operation_id,
|
||||||
|
invoice: invoice,
|
||||||
|
invoice_amount_sats: amt,
|
||||||
|
address: res.createdResponse.address,
|
||||||
|
transaction_amount_sats: res.createdResponse.expectedAmount,
|
||||||
|
chain_fee_sats: 0,
|
||||||
|
service_fee_sats: 0,
|
||||||
|
service_url: swapper.getHttpUrl(),
|
||||||
|
swap_fee_sats: fee,
|
||||||
|
tx_id: newSwap.tx_id,
|
||||||
|
paid_at_unix: newSwap.paid_at_unix,
|
||||||
|
expires_at_block_height: newSwap.timeout_block_height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapTransactionSwapQuote = (s: TransactionSwap, getServiceFee: (amt: number) => number): Types.TransactionSwapQuote => {
|
||||||
|
const serviceFee = getServiceFee(s.invoice_amount)
|
||||||
|
return {
|
||||||
|
swap_operation_id: s.swap_operation_id,
|
||||||
|
transaction_amount_sats: s.transaction_amount,
|
||||||
|
invoice_amount_sats: s.invoice_amount,
|
||||||
|
chain_fee_sats: s.chain_fee_sats,
|
||||||
|
service_fee_sats: serviceFee,
|
||||||
|
swap_fee_sats: s.swap_fee_sats,
|
||||||
|
expires_at_block_height: s.timeout_block_height,
|
||||||
|
service_url: s.service_url,
|
||||||
|
paid_at_unix: s.paid_at_unix,
|
||||||
|
completed_at_unix: s.completed_at_unix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListTxSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise<Types.TxSwapsList> => {
|
||||||
|
const completedSwaps = await this.storage.paymentStorage.ListCompletedTxSwaps(appUserId, payments)
|
||||||
|
const pendingSwaps = await this.storage.paymentStorage.ListPendingTransactionSwaps(appUserId)
|
||||||
|
const quotes: Types.TxSwapOperation[] = pendingSwaps.map(s => ({ quote: this.mapTransactionSwapQuote(s, getServiceFee) }))
|
||||||
|
const swaps: Types.TxSwapOperation[] = completedSwaps.map(s => ({
|
||||||
|
quote: this.mapTransactionSwapQuote(s.swap, getServiceFee),
|
||||||
|
operation_payment: s.payment ? newOp(s.payment) : undefined,
|
||||||
|
address_paid: s.swap.address_paid,
|
||||||
|
tx_id: s.swap.tx_id,
|
||||||
|
failure_reason: s.swap.failure_reason,
|
||||||
|
}))
|
||||||
|
return {
|
||||||
|
swaps: swaps.concat(quotes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GetTxSwapQuotes = async (appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise<Types.TransactionSwapQuote[]> => {
|
||||||
|
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
||||||
|
throw new Error("Swaps are not enabled")
|
||||||
|
}
|
||||||
|
const swappers = Object.values(this.revSwappers)
|
||||||
|
if (swappers.length === 0) {
|
||||||
|
throw new Error("No swap services available")
|
||||||
|
}
|
||||||
|
const res = await Promise.allSettled(swappers.map(sw => this.getTxSwapQuote(sw, appUserId, amt, getServiceFee)))
|
||||||
|
const failures: string[] = []
|
||||||
|
const success: Types.TransactionSwapQuote[] = []
|
||||||
|
for (const r of res) {
|
||||||
|
if (r.status === 'fulfilled') {
|
||||||
|
success.push(r.value)
|
||||||
|
} else {
|
||||||
|
failures.push(r.reason.message ? r.reason.message : r.reason.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success.length === 0) {
|
||||||
|
throw new Error(failures.join("\n"))
|
||||||
|
}
|
||||||
|
return success
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getTxSwapQuote(swapper: ReverseSwaps, appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise<Types.TransactionSwapQuote> {
|
||||||
|
this.log("getting transaction swap quote")
|
||||||
|
const feesRes = await swapper.GetFees()
|
||||||
|
if (!feesRes.ok) {
|
||||||
|
throw new Error(feesRes.error)
|
||||||
|
}
|
||||||
|
const { claim, lockup } = feesRes.fees.minerFees
|
||||||
|
const minerFee = claim + lockup
|
||||||
|
const chainTotal = amt + minerFee
|
||||||
|
const res = await swapper.SwapTransaction(chainTotal)
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(res.error)
|
||||||
|
}
|
||||||
|
const decoded = await this.lnd.DecodeInvoice(res.createdResponse.invoice)
|
||||||
|
const swapFee = decoded.numSatoshis - chainTotal
|
||||||
|
const serviceFee = getServiceFee(decoded.numSatoshis)
|
||||||
|
const newSwap = await this.storage.paymentStorage.AddTransactionSwap({
|
||||||
|
app_user_id: appUserId,
|
||||||
|
swap_quote_id: res.createdResponse.id,
|
||||||
|
swap_tree: JSON.stringify(res.createdResponse.swapTree),
|
||||||
|
lockup_address: res.createdResponse.lockupAddress,
|
||||||
|
refund_public_key: res.createdResponse.refundPublicKey,
|
||||||
|
timeout_block_height: res.createdResponse.timeoutBlockHeight,
|
||||||
|
invoice: res.createdResponse.invoice,
|
||||||
|
invoice_amount: decoded.numSatoshis,
|
||||||
|
transaction_amount: chainTotal,
|
||||||
|
swap_fee_sats: swapFee,
|
||||||
|
chain_fee_sats: minerFee,
|
||||||
|
preimage: res.preimage,
|
||||||
|
ephemeral_private_key: res.privKey,
|
||||||
|
ephemeral_public_key: res.pubkey,
|
||||||
|
service_url: swapper.getHttpUrl(),
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
swap_operation_id: newSwap.swap_operation_id,
|
||||||
|
swap_fee_sats: swapFee,
|
||||||
|
invoice_amount_sats: decoded.numSatoshis,
|
||||||
|
transaction_amount_sats: amt,
|
||||||
|
chain_fee_sats: minerFee,
|
||||||
|
service_fee_sats: serviceFee,
|
||||||
|
service_url: swapper.getHttpUrl(),
|
||||||
|
expires_at_block_height: res.createdResponse.timeoutBlockHeight,
|
||||||
|
paid_at_unix: newSwap.paid_at_unix,
|
||||||
|
completed_at_unix: newSwap.completed_at_unix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async PayAddrWithSwap(appUserId: string, swapOpId: string, address: string, payInvoice: (invoice: string, amt: number) => Promise<void>) {
|
||||||
|
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
||||||
|
throw new Error("Swaps are not enabled")
|
||||||
|
}
|
||||||
|
this.log("paying address with swap", { appUserId, swapOpId, address })
|
||||||
|
if (!swapOpId) {
|
||||||
|
throw new Error("request a swap quote before paying an external address")
|
||||||
|
}
|
||||||
|
const txSwap = await this.storage.paymentStorage.GetTransactionSwap(swapOpId, appUserId)
|
||||||
|
if (!txSwap) {
|
||||||
|
throw new Error("swap quote not found")
|
||||||
|
}
|
||||||
|
const info = await this.lnd.GetInfo()
|
||||||
|
if (info.blockHeight >= txSwap.timeout_block_height) {
|
||||||
|
throw new Error("swap timeout")
|
||||||
|
}
|
||||||
|
const swapper = this.revSwappers[txSwap.service_url]
|
||||||
|
if (!swapper) {
|
||||||
|
throw new Error("swapper service not found")
|
||||||
|
}
|
||||||
|
const keys = this.GetKeys(txSwap.ephemeral_private_key)
|
||||||
|
const data: TransactionSwapData = {
|
||||||
|
createdResponse: {
|
||||||
|
id: txSwap.swap_quote_id,
|
||||||
|
invoice: txSwap.invoice,
|
||||||
|
lockupAddress: txSwap.lockup_address,
|
||||||
|
refundPublicKey: txSwap.refund_public_key,
|
||||||
|
swapTree: txSwap.swap_tree,
|
||||||
|
timeoutBlockHeight: txSwap.timeout_block_height,
|
||||||
|
onchainAmount: txSwap.transaction_amount,
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
destinationAddress: address,
|
||||||
|
keys,
|
||||||
|
chainFee: txSwap.chain_fee_sats,
|
||||||
|
preimage: Buffer.from(txSwap.preimage, 'hex'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the swap and the invoice payment are linked, swap will not start until the invoice payment is started, and will not complete once the invoice payment is completed
|
||||||
|
let swapResult = { ok: false, error: "swap never completed" } as { ok: true, txId: string } | { ok: false, error: string }
|
||||||
|
swapper.SubscribeToTransactionSwap(data, result => {
|
||||||
|
swapResult = result
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
await this.storage.paymentStorage.SetTransactionSwapPaid(swapOpId)
|
||||||
|
await payInvoice(txSwap.invoice, txSwap.invoice_amount)
|
||||||
|
if (!swapResult.ok) {
|
||||||
|
this.log("invoice payment successful, but swap failed")
|
||||||
|
await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error)
|
||||||
|
throw new Error(swapResult.error)
|
||||||
|
}
|
||||||
|
this.log("swap completed successfully")
|
||||||
|
await this.storage.paymentStorage.FinalizeTransactionSwap(swapOpId, address, swapResult.txId)
|
||||||
|
} catch (err: any) {
|
||||||
|
if (swapResult.ok) {
|
||||||
|
this.log("failed to pay swap invoice, but swap completed successfully", swapResult.txId)
|
||||||
|
await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, err.message)
|
||||||
|
} else {
|
||||||
|
this.log("failed to pay swap invoice and swap failed", swapResult.error)
|
||||||
|
await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error)
|
||||||
|
}
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
const networkFeesTotal = txSwap.chain_fee_sats + txSwap.swap_fee_sats
|
||||||
|
return {
|
||||||
|
txId: swapResult.txId,
|
||||||
|
network_fee: networkFeesTotal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,9 +5,50 @@ import Storage from "../storage/index.js";
|
||||||
import * as Types from '../../../proto/autogenerated/ts/types.js'
|
import * as Types from '../../../proto/autogenerated/ts/types.js'
|
||||||
import LND from "../lnd/lnd.js";
|
import LND from "../lnd/lnd.js";
|
||||||
import SettingsManager from "./settingsManager.js";
|
import SettingsManager from "./settingsManager.js";
|
||||||
import { Swaps } from "../lnd/swaps.js";
|
import { Swaps } from "../lnd/swaps/swaps.js";
|
||||||
|
import { defaultInvoiceExpiry } from "../storage/paymentStorage.js";
|
||||||
|
import { TrackedProvider } from "../storage/entity/TrackedProvider.js";
|
||||||
|
import { NodeInfo } from "../lnd/settings.js";
|
||||||
|
import { Invoice, Payment, OutputDetail, Transaction, Payment_PaymentStatus, Invoice_InvoiceState } from "../../../proto/lnd/lightning.js";
|
||||||
|
import { LiquidityProvider } from "./liquidityProvider.js";
|
||||||
|
/* type TrackedOperation = {
|
||||||
|
ts: number
|
||||||
|
amount: number
|
||||||
|
type: 'user' | 'root'
|
||||||
|
}
|
||||||
|
|
||||||
|
type AssetOperation = {
|
||||||
|
ts: number
|
||||||
|
amount: number
|
||||||
|
tracked?: TrackedOperation
|
||||||
|
}
|
||||||
|
type TrackedLndProvider = {
|
||||||
|
confirmedBalance: number
|
||||||
|
unconfirmedBalance: number
|
||||||
|
channelsBalace: number
|
||||||
|
payments: AssetOperation[]
|
||||||
|
invoices: AssetOperation[]
|
||||||
|
incomingTx: AssetOperation[]
|
||||||
|
outgoingTx: AssetOperation[]
|
||||||
|
}
|
||||||
|
type LndAssetProvider = {
|
||||||
|
pubkey: string
|
||||||
|
tracked?: TrackedLndProvider
|
||||||
|
}
|
||||||
|
type TrackedLiquidityProvider = {
|
||||||
|
balance: number
|
||||||
|
payments: AssetOperation[]
|
||||||
|
invoices: AssetOperation[]
|
||||||
|
}
|
||||||
|
type ProviderAssetProvider = {
|
||||||
|
pubkey: string
|
||||||
|
tracked?: TrackedLiquidityProvider
|
||||||
|
} */
|
||||||
|
const ROOT_OP = Types.TrackedOperationType.ROOT
|
||||||
|
const USER_OP = Types.TrackedOperationType.USER
|
||||||
export class AdminManager {
|
export class AdminManager {
|
||||||
settings: SettingsManager
|
settings: SettingsManager
|
||||||
|
liquidityProvider: LiquidityProvider | null = null
|
||||||
storage: Storage
|
storage: Storage
|
||||||
log = getLogger({ component: "adminManager" })
|
log = getLogger({ component: "adminManager" })
|
||||||
adminNpub = ""
|
adminNpub = ""
|
||||||
|
|
@ -40,6 +81,10 @@ export class AdminManager {
|
||||||
this.start()
|
this.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attachLiquidityProvider(liquidityProvider: LiquidityProvider) {
|
||||||
|
this.liquidityProvider = liquidityProvider
|
||||||
|
}
|
||||||
|
|
||||||
attachNostrReset(f: () => Promise<void>) {
|
attachNostrReset(f: () => Promise<void>) {
|
||||||
this.nostrReset = f
|
this.nostrReset = f
|
||||||
}
|
}
|
||||||
|
|
@ -260,15 +305,64 @@ export class AdminManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListAdminSwaps(): Promise<Types.SwapsList> {
|
async ListAdminInvoiceSwaps(): Promise<Types.InvoiceSwapsList> {
|
||||||
return this.swaps.ListSwaps("admin", [], p => undefined, amt => 0)
|
return this.swaps.ListInvoiceSwaps("admin")
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetAdminInvoiceSwapQuotes(req: Types.InvoiceSwapRequest): Promise<Types.InvoiceSwapQuoteList> {
|
||||||
|
const invoice = await this.lnd.NewInvoice(req.amount_sats, "Admin Swap", defaultInvoiceExpiry, { useProvider: false, from: 'system' })
|
||||||
|
const quotes = await this.swaps.GetInvoiceSwapQuotes("admin", invoice.payRequest)
|
||||||
|
return { quotes }
|
||||||
|
}
|
||||||
|
|
||||||
|
async PayAdminInvoiceSwap(req: Types.PayAdminInvoiceSwapRequest): Promise<Types.AdminInvoiceSwapResponse> {
|
||||||
|
const resolvedTxId = await new Promise<string>(res => {
|
||||||
|
this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => {
|
||||||
|
const tx = await this.lnd.PayAddress(addr, amt, req.sat_per_v_byte, "", { useProvider: false, from: 'system' })
|
||||||
|
this.log("paid admin invoice swap", { swapOpId: req.swap_operation_id, txId: tx.txid })
|
||||||
|
await this.storage.metricsStorage.AddRootOperation("chain_payment", tx.txid, amt, true)
|
||||||
|
|
||||||
|
// Fetch the full transaction hex for potential refunds
|
||||||
|
let lockupTxHex: string | undefined
|
||||||
|
let chainFeeSats = 0
|
||||||
|
try {
|
||||||
|
const txDetails = await this.lnd.GetTx(tx.txid)
|
||||||
|
chainFeeSats = Number(txDetails.totalFees)
|
||||||
|
lockupTxHex = txDetails.rawTxHex
|
||||||
|
} catch (err: any) {
|
||||||
|
this.log("Warning: Could not fetch transaction hex for refund purposes:", err.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, tx.txid, chainFeeSats, lockupTxHex)
|
||||||
|
this.log("saved admin swap txid", { swapOpId: req.swap_operation_id, txId: tx.txid })
|
||||||
|
res(tx.txid)
|
||||||
|
return { txId: tx.txid }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return { tx_id: resolvedTxId }
|
||||||
|
}
|
||||||
|
|
||||||
|
async RefundAdminInvoiceSwap(req: Types.RefundAdminInvoiceSwapRequest): Promise<Types.AdminInvoiceSwapResponse> {
|
||||||
|
const info = await this.lnd.GetInfo()
|
||||||
|
const currentHeight = info.blockHeight
|
||||||
|
const address = await this.lnd.NewAddress(Types.AddressType.WITNESS_PUBKEY_HASH, { useProvider: false, from: 'system' })
|
||||||
|
const result = await this.swaps.RefundInvoiceSwap(req.swap_operation_id, req.sat_per_v_byte, address.address, currentHeight)
|
||||||
|
if (result.published) {
|
||||||
|
return { tx_id: result.txId }
|
||||||
|
}
|
||||||
|
await this.lnd.PublishTransaction(result.txHex)
|
||||||
|
return { tx_id: result.txId }
|
||||||
|
}
|
||||||
|
|
||||||
|
async ListAdminTxSwaps(): Promise<Types.TxSwapsList> {
|
||||||
|
return this.swaps.ListTxSwaps("admin", [], p => undefined, amt => 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetAdminTransactionSwapQuotes(req: Types.TransactionSwapRequest): Promise<Types.TransactionSwapQuoteList> {
|
async GetAdminTransactionSwapQuotes(req: Types.TransactionSwapRequest): Promise<Types.TransactionSwapQuoteList> {
|
||||||
const quotes = await this.swaps.GetTxSwapQuotes("admin", req.transaction_amount_sats, () => 0)
|
const quotes = await this.swaps.GetTxSwapQuotes("admin", req.transaction_amount_sats, () => 0)
|
||||||
return { quotes }
|
return { quotes }
|
||||||
}
|
}
|
||||||
async PayAdminTransactionSwap(req: Types.PayAdminTransactionSwapRequest): Promise<Types.AdminSwapResponse> {
|
async PayAdminTransactionSwap(req: Types.PayAdminTransactionSwapRequest): Promise<Types.AdminTxSwapResponse> {
|
||||||
const routingFloor = this.settings.getSettings().lndSettings.routingFeeFloor
|
const routingFloor = this.settings.getSettings().lndSettings.routingFeeFloor
|
||||||
const routingLimit = this.settings.getSettings().lndSettings.routingFeeLimitBps / 10000
|
const routingLimit = this.settings.getSettings().lndSettings.routingFeeLimitBps / 10000
|
||||||
|
|
||||||
|
|
@ -282,6 +376,222 @@ export class AdminManager {
|
||||||
network_fee: swap.network_fee,
|
network_fee: swap.network_fee,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async GetAssetsAndLiabilities(req: Types.AssetsAndLiabilitiesReq): Promise<Types.AssetsAndLiabilities> {
|
||||||
|
const providers = await this.storage.liquidityStorage.GetTrackedProviders()
|
||||||
|
|
||||||
|
const lnds: Types.LndAssetProvider[] = []
|
||||||
|
const liquidityProviders: Types.LiquidityAssetProvider[] = []
|
||||||
|
for (const provider of providers) {
|
||||||
|
if (provider.provider_type === 'lnd') {
|
||||||
|
const lndEntry = await this.GetLndAssetsAndLiabilities(req, provider)
|
||||||
|
lnds.push(lndEntry)
|
||||||
|
} else if (provider.provider_type === 'lnPub') {
|
||||||
|
const liquidityEntry = await this.GetProviderAssetsAndLiabilities(req, provider)
|
||||||
|
liquidityProviders.push(liquidityEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const usersBalance = await this.storage.paymentStorage.GetTotalUsersBalance(true)
|
||||||
|
return {
|
||||||
|
users_balance: usersBalance,
|
||||||
|
lnds,
|
||||||
|
liquidity_providers: liquidityProviders,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetProviderAssetsAndLiabilities(req: Types.AssetsAndLiabilitiesReq, provider: TrackedProvider): Promise<Types.LiquidityAssetProvider> {
|
||||||
|
if (!this.liquidityProvider) {
|
||||||
|
throw new Error("liquidity provider not attached")
|
||||||
|
}
|
||||||
|
if (this.liquidityProvider.GetProviderPubkey() !== provider.provider_pubkey) {
|
||||||
|
return { pubkey: provider.provider_pubkey, tracked: undefined }
|
||||||
|
}
|
||||||
|
const providerOps = await this.liquidityProvider.GetOperations(req.limit_providers || 100)
|
||||||
|
// we only care about invoices cuz they are the only ops we can generate with a provider
|
||||||
|
const invoices: Types.AssetOperation[] = []
|
||||||
|
const payments: Types.AssetOperation[] = []
|
||||||
|
for (const op of providerOps.latestIncomingInvoiceOperations.operations) {
|
||||||
|
const assetOp = await this.GetProviderInvoiceAssetOperation(op)
|
||||||
|
invoices.push(assetOp)
|
||||||
|
}
|
||||||
|
for (const op of providerOps.latestOutgoingInvoiceOperations.operations) {
|
||||||
|
const assetOp = await this.GetProviderPaymentAssetOperation(op)
|
||||||
|
payments.push(assetOp)
|
||||||
|
}
|
||||||
|
const balance = await this.liquidityProvider.GetUserState()
|
||||||
|
return {
|
||||||
|
pubkey: provider.provider_pubkey,
|
||||||
|
tracked: {
|
||||||
|
balance: balance.status === 'OK' ? balance.balance : 0,
|
||||||
|
payments,
|
||||||
|
invoices,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetProviderInvoiceAssetOperation(op: Types.UserOperation): Promise<Types.AssetOperation> {
|
||||||
|
const ts = Number(op.paidAtUnix)
|
||||||
|
const amount = Number(op.amount)
|
||||||
|
const invoice = op.identifier
|
||||||
|
const userInvoice = await this.storage.paymentStorage.GetInvoiceOwner(invoice)
|
||||||
|
if (userInvoice) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice", invoice)
|
||||||
|
if (rootOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
return { ts, amount, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetProviderPaymentAssetOperation(op: Types.UserOperation): Promise<Types.AssetOperation> {
|
||||||
|
const ts = Number(op.paidAtUnix)
|
||||||
|
const amount = Number(op.amount)
|
||||||
|
const invoice = op.identifier
|
||||||
|
const userInvoice = await this.storage.paymentStorage.GetPaymentOwner(invoice)
|
||||||
|
if (userInvoice) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice_payment", invoice)
|
||||||
|
if (rootOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
return { ts, amount, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetLndAssetsAndLiabilities(req: Types.AssetsAndLiabilitiesReq, provider: TrackedProvider): Promise<Types.LndAssetProvider> {
|
||||||
|
const info = await this.lnd.GetInfo()
|
||||||
|
if (provider.provider_pubkey !== info.identityPubkey) {
|
||||||
|
return { pubkey: provider.provider_pubkey, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
const latestLndPayments = await this.lnd.GetAllPayments(req.limit_payments || 50)
|
||||||
|
const payments: Types.AssetOperation[] = []
|
||||||
|
for (const payment of latestLndPayments.payments) {
|
||||||
|
if (payment.status !== Payment_PaymentStatus.SUCCEEDED) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const assetOp = await this.GetPaymentAssetOperation(payment)
|
||||||
|
payments.push(assetOp)
|
||||||
|
}
|
||||||
|
const invoices: Types.AssetOperation[] = []
|
||||||
|
const paidInvoices = await this.lnd.GetAllInvoices(req.limit_invoices || 100)
|
||||||
|
for (const invoiceEntry of paidInvoices.invoices) {
|
||||||
|
if (invoiceEntry.state !== Invoice_InvoiceState.SETTLED) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const assetOp = await this.GetInvoiceAssetOperation(invoiceEntry)
|
||||||
|
invoices.push(assetOp)
|
||||||
|
}
|
||||||
|
const latestLndTransactions = await this.lnd.GetTransactions(info.blockHeight)
|
||||||
|
const txOuts: Types.AssetOperation[] = []
|
||||||
|
const txIns: Types.AssetOperation[] = []
|
||||||
|
for (const transaction of latestLndTransactions.transactions) {
|
||||||
|
for (const output of transaction.outputDetails) {
|
||||||
|
if (output.isOurAddress) {
|
||||||
|
const assetOp = await this.GetTxOutAssetOperation(transaction, output)
|
||||||
|
txOuts.push(assetOp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we only produce TXs with a single output
|
||||||
|
const input = transaction.previousOutpoints.find(p => p.isOurOutput)
|
||||||
|
if (input) {
|
||||||
|
const assetOp = await this.GetTxInAssetOperation(transaction)
|
||||||
|
txIns.push(assetOp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const balance = await this.lnd.GetBalance()
|
||||||
|
const channelsBalance = balance.channelsBalance.reduce((acc, c) => acc + Number(c.localBalanceSats), 0)
|
||||||
|
return {
|
||||||
|
pubkey: provider.provider_pubkey,
|
||||||
|
tracked: {
|
||||||
|
confirmed_balance: Number(balance.confirmedBalance),
|
||||||
|
unconfirmed_balance: Number(balance.unconfirmedBalance),
|
||||||
|
channels_balance: channelsBalance,
|
||||||
|
payments,
|
||||||
|
invoices,
|
||||||
|
incoming_tx: txOuts, // tx outputs, are incoming sats
|
||||||
|
outgoing_tx: txIns, // tx inputs, are outgoing sats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetPaymentAssetOperation(payment: Payment): Promise<Types.AssetOperation> {
|
||||||
|
const invoice = payment.paymentRequest
|
||||||
|
const userInvoice = await this.storage.paymentStorage.GetPaymentOwner(invoice)
|
||||||
|
const ts = Number(payment.creationTimeNs / (BigInt(1000_000_000)))
|
||||||
|
const amount = Number(payment.valueSat)
|
||||||
|
if (userInvoice) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice_payment", invoice)
|
||||||
|
if (rootOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
return { ts, amount, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetInvoiceAssetOperation(invoiceEntry: Invoice): Promise<Types.AssetOperation> {
|
||||||
|
const invoice = invoiceEntry.paymentRequest
|
||||||
|
const ts = Number(invoiceEntry.settleDate)
|
||||||
|
const amount = Number(invoiceEntry.amtPaidSat)
|
||||||
|
const userInvoice = await this.storage.paymentStorage.GetInvoiceOwner(invoice)
|
||||||
|
if (userInvoice) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice", invoice)
|
||||||
|
if (rootOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
return { ts, amount, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetTxInAssetOperation(tx: Transaction): Promise<Types.AssetOperation> {
|
||||||
|
const ts = Number(tx.timeStamp)
|
||||||
|
const amount = Number(tx.amount)
|
||||||
|
const userOp = await this.storage.paymentStorage.GetTxHashPaymentOwner(tx.txHash)
|
||||||
|
if (userOp) {
|
||||||
|
// user transaction payments are actually deprecated from lnd, but we keep this for consstency
|
||||||
|
const tracked: Types.TrackedOperation = { ts: userOp.paid_at_unix, amount: userOp.paid_amount, type: USER_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
const rootOp = await this.storage.metricsStorage.GetRootOperation("chain_payment", tx.txHash)
|
||||||
|
if (rootOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
return { ts, amount, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetTxOutAssetOperation(tx: Transaction, output: OutputDetail): Promise<Types.AssetOperation> {
|
||||||
|
const ts = Number(tx.timeStamp)
|
||||||
|
const amount = Number(output.amount)
|
||||||
|
const outputIndex = Number(output.outputIndex)
|
||||||
|
const userOp = await this.storage.paymentStorage.GetAddressReceivingTransactionOwner(output.address, tx.txHash)
|
||||||
|
if (userOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: userOp.paid_at_unix, amount: userOp.paid_amount, type: USER_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
const rootOp = await this.storage.metricsStorage.GetRootAddressTransaction(output.address, tx.txHash, outputIndex)
|
||||||
|
if (rootOp) {
|
||||||
|
const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP }
|
||||||
|
return { ts, amount, tracked }
|
||||||
|
}
|
||||||
|
return { ts, amount, tracked: undefined }
|
||||||
|
}
|
||||||
|
|
||||||
|
async BumpTx(req: Types.BumpTx): Promise<void> {
|
||||||
|
await this.lnd.BumpFee(req.txid, req.output_index, req.sat_per_vbyte)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDataPath = (dataDir: string, dataPath: string) => {
|
const getDataPath = (dataDir: string, dataPath: string) => {
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export default class {
|
||||||
const appUser = await this.storage.applicationStorage.GetAppUserFromUser(app, user.user_id)
|
const appUser = await this.storage.applicationStorage.GetAppUserFromUser(app, user.user_id)
|
||||||
|
|
||||||
if (!appUser) {
|
if (!appUser) {
|
||||||
throw new Error(`app user ${ctx.user_id} not found`) // TODO: fix logs doxing
|
throw new Error("app user not found")
|
||||||
}
|
}
|
||||||
const nostrSettings = this.settings.getSettings().nostrRelaySettings
|
const nostrSettings = this.settings.getSettings().nostrRelaySettings
|
||||||
const { max, serviceFeeFloor, serviceFeeBps } = this.applicationManager.paymentManager.GetMaxPayableInvoice(user.balance_sats)
|
const { max, serviceFeeFloor, serviceFeeBps } = this.applicationManager.paymentManager.GetMaxPayableInvoice(user.balance_sats)
|
||||||
|
|
@ -82,7 +82,8 @@ export default class {
|
||||||
ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }),
|
ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }),
|
||||||
nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }),
|
nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }),
|
||||||
callback_url: appUser.callback_url,
|
callback_url: appUser.callback_url,
|
||||||
bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl
|
bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl,
|
||||||
|
topic_id: appUser.topic_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,12 +132,12 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log("Found", toDelete.length, "inactive users to delete")
|
this.log("Found", toDelete.length, "inactive users to delete")
|
||||||
// await this.RemoveUsers(toDelete)
|
await this.LockUsers(toDelete.map(u => u.userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
async CleanupNeverActiveUsers() {
|
async CleanupNeverActiveUsers() {
|
||||||
this.log("Cleaning up never active users")
|
this.log("Cleaning up never active users")
|
||||||
const inactiveUsers = await this.storage.userStorage.GetInactiveUsers(30)
|
const inactiveUsers = await this.storage.userStorage.GetInactiveUsers(90)
|
||||||
const toDelete: { userId: string, appUserIds: string[] }[] = []
|
const toDelete: { userId: string, appUserIds: string[] }[] = []
|
||||||
for (const u of inactiveUsers) {
|
for (const u of inactiveUsers) {
|
||||||
const user = await this.storage.userStorage.GetUser(u.user_id)
|
const user = await this.storage.userStorage.GetUser(u.user_id)
|
||||||
|
|
@ -160,25 +161,52 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log("Found", toDelete.length, "never active users to delete")
|
this.log("Found", toDelete.length, "never active users to delete")
|
||||||
// await this.RemoveUsers(toDelete) TODO: activate deletion
|
await this.RemoveUsers(toDelete)
|
||||||
|
}
|
||||||
|
|
||||||
|
async LockUsers(toLock: string[]) {
|
||||||
|
this.log("Locking", toLock.length, "users")
|
||||||
|
for (const userId of toLock) {
|
||||||
|
await this.storage.userStorage.BanUser(userId)
|
||||||
|
}
|
||||||
|
this.log("Locked users")
|
||||||
}
|
}
|
||||||
|
|
||||||
async RemoveUsers(toDelete: { userId: string, appUserIds: string[] }[]) {
|
async RemoveUsers(toDelete: { userId: string, appUserIds: string[] }[]) {
|
||||||
this.log("Deleting", toDelete.length, "inactive users")
|
this.log("Deleting", toDelete.length, "inactive users")
|
||||||
for (let i = 0; i < toDelete.length; i++) {
|
for (let i = 0; i < toDelete.length; i++) {
|
||||||
const { userId, appUserIds } = toDelete[i]
|
const { userId, appUserIds } = toDelete[i]
|
||||||
|
const user = await this.storage.userStorage.FindUser(userId)
|
||||||
|
if (!user || user.balance_sats > 0) {
|
||||||
|
if (user) this.log("Skipping user", userId, "has balance", user.balance_sats)
|
||||||
|
continue
|
||||||
|
}
|
||||||
this.log("Deleting user", userId, "progress", i + 1, "/", toDelete.length)
|
this.log("Deleting user", userId, "progress", i + 1, "/", toDelete.length)
|
||||||
await this.storage.StartTransaction(async tx => {
|
await this.storage.StartTransaction(async tx => {
|
||||||
for (const appUserId of appUserIds) {
|
for (let j = 0; j < appUserIds.length; j++) {
|
||||||
|
const appUserId = appUserIds[j]
|
||||||
|
this.log("Deleting app user", appUserId, "progress", j + 1, "/", appUserIds.length)
|
||||||
|
this.log("Removing user grants")
|
||||||
await this.storage.managementStorage.removeUserGrants(appUserId, tx)
|
await this.storage.managementStorage.removeUserGrants(appUserId, tx)
|
||||||
|
this.log("Removing user offers")
|
||||||
await this.storage.offerStorage.DeleteUserOffers(appUserId, tx)
|
await this.storage.offerStorage.DeleteUserOffers(appUserId, tx)
|
||||||
|
this.log("Removing user debit access")
|
||||||
await this.storage.debitStorage.RemoveUserDebitAccess(appUserId, tx)
|
await this.storage.debitStorage.RemoveUserDebitAccess(appUserId, tx)
|
||||||
|
this.log("Removing user devices")
|
||||||
await this.storage.applicationStorage.RemoveAppUserDevices(appUserId, tx)
|
await this.storage.applicationStorage.RemoveAppUserDevices(appUserId, tx)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
this.log("Removing user invoices")
|
||||||
await this.storage.paymentStorage.RemoveUserInvoices(userId, tx)
|
await this.storage.paymentStorage.RemoveUserInvoices(userId, tx)
|
||||||
|
this.log("Removing user products")
|
||||||
await this.storage.productStorage.RemoveUserProducts(userId, tx)
|
await this.storage.productStorage.RemoveUserProducts(userId, tx)
|
||||||
|
this.log("Removing user ephemeral keys")
|
||||||
await this.storage.paymentStorage.RemoveUserEphemeralKeys(userId, tx)
|
await this.storage.paymentStorage.RemoveUserEphemeralKeys(userId, tx)
|
||||||
|
await this.storage.paymentStorage.RemoveUserInvoicePayments(userId, tx)
|
||||||
|
await this.storage.paymentStorage.RemoveUserTransactionPayments(userId, tx)
|
||||||
|
await this.storage.paymentStorage.RemoveUserToUserPayments(userId, tx)
|
||||||
|
await this.storage.paymentStorage.RemoveUserReceivingAddresses(userId, tx)
|
||||||
|
await this.storage.userStorage.DeleteUserAccess(userId, tx)
|
||||||
|
await this.storage.applicationStorage.RemoveAppUsersAndBaseUsers(appUserIds, userId, tx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.log("Cleaned up inactive users")
|
this.log("Cleaned up inactive users")
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,8 @@ export default class {
|
||||||
ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }),
|
ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }),
|
||||||
nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }),
|
nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }),
|
||||||
callback_url: u.callback_url,
|
callback_url: u.callback_url,
|
||||||
bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl
|
bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl,
|
||||||
|
topic_id: u.topic_id
|
||||||
|
|
||||||
},
|
},
|
||||||
max_withdrawable: max
|
max_withdrawable: max
|
||||||
|
|
@ -193,7 +194,7 @@ export default class {
|
||||||
const cbUrl = req.http_callback_url || receiver.callback_url || ""
|
const cbUrl = req.http_callback_url || receiver.callback_url || ""
|
||||||
let zapInfo: ZapInfo | undefined = undefined
|
let zapInfo: ZapInfo | undefined = undefined
|
||||||
if (req.invoice_req.zap) {
|
if (req.invoice_req.zap) {
|
||||||
zapInfo = this.paymentManager.validateZapEvent(req.invoice_req.zap, req.invoice_req.amountSats)
|
zapInfo = this.paymentManager.validateZapEvent(req.invoice_req.zap, req.invoice_req.amountSats * 1000)
|
||||||
}
|
}
|
||||||
const expiry = req.invoice_req.expiry ? Math.min(req.invoice_req.expiry, defaultInvoiceExpiry) : defaultInvoiceExpiry
|
const expiry = req.invoice_req.expiry ? Math.min(req.invoice_req.expiry, defaultInvoiceExpiry) : defaultInvoiceExpiry
|
||||||
const opts: InboundOptionals = {
|
const opts: InboundOptionals = {
|
||||||
|
|
@ -227,7 +228,8 @@ export default class {
|
||||||
ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }),
|
ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }),
|
||||||
nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }),
|
nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }),
|
||||||
callback_url: user.callback_url,
|
callback_url: user.callback_url,
|
||||||
bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl
|
bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl,
|
||||||
|
topic_id: user.topic_id
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -239,6 +241,8 @@ export default class {
|
||||||
const paid = await this.paymentManager.PayInvoice(appUser.user.user_id, req, app, {
|
const paid = await this.paymentManager.PayInvoice(appUser.user.user_id, req, app, {
|
||||||
ack: pendingOp => { this.notifyAppUserPayment(appUser, pendingOp) }
|
ack: pendingOp => { this.notifyAppUserPayment(appUser, pendingOp) }
|
||||||
})
|
})
|
||||||
|
// Refresh appUser balance from DB so notification has accurate latest_balance
|
||||||
|
appUser.user.balance_sats = paid.latest_balance
|
||||||
this.notifyAppUserPayment(appUser, paid.operation)
|
this.notifyAppUserPayment(appUser, paid.operation)
|
||||||
getLogger({ appName: app.name })(appUser.identifier, "invoice paid", paid.amount_paid, "sats")
|
getLogger({ appName: app.name })(appUser.identifier, "invoice paid", paid.amount_paid, "sats")
|
||||||
return paid
|
return paid
|
||||||
|
|
|
||||||
|
|
@ -153,13 +153,14 @@ export class DebitManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyPaymentSuccess = (debitRes: NdebitSuccess, event: { pub: string, id: string, appId: string }) => {
|
notifyPaymentSuccess = (debitRes: NdebitSuccess, event: { pub: string, id: string, appId: string }) => {
|
||||||
|
this.logger("✅ [DEBIT REQUEST] Payment successful, sending OK response to", event.pub.slice(0, 16) + "...", "for event", event.id.slice(0, 16) + "...")
|
||||||
this.sendDebitResponse(debitRes, event)
|
this.sendDebitResponse(debitRes, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
sendDebitResponse = (debitRes: NdebitFailure | NdebitSuccess, event: { pub: string, id: string, appId: string }) => {
|
sendDebitResponse = (debitRes: NdebitFailure | NdebitSuccess, event: { pub: string, id: string, appId: string }) => {
|
||||||
|
this.logger("📤 [DEBIT RESPONSE] Sending Kind 21002 response:", JSON.stringify(debitRes), "to", event.pub.slice(0, 16) + "...")
|
||||||
const e = newNdebitResponse(JSON.stringify(debitRes), event)
|
const e = newNdebitResponse(JSON.stringify(debitRes), event)
|
||||||
this.storage.NostrSender().Send({ type: 'app', appId: event.appId }, { type: 'event', event: e, encrypt: { toPub: event.pub } })
|
this.storage.NostrSender().Send({ type: 'app', appId: event.appId }, { type: 'event', event: e, encrypt: { toPub: event.pub } })
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payNdebitInvoice = async (event: NostrEvent, pointerdata: NdebitData): Promise<HandleNdebitRes> => {
|
payNdebitInvoice = async (event: NostrEvent, pointerdata: NdebitData): Promise<HandleNdebitRes> => {
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ export default class {
|
||||||
this.unlocker = unlocker
|
this.unlocker = unlocker
|
||||||
const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.getSettings().liquiditySettings.liquidityProviderPub, b)
|
const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.getSettings().liquiditySettings.liquidityProviderPub, b)
|
||||||
this.liquidityProvider = new LiquidityProvider(() => this.settings.getSettings().liquiditySettings, this.utils, this.invoicePaidCb, updateProviderBalance)
|
this.liquidityProvider = new LiquidityProvider(() => this.settings.getSettings().liquiditySettings, this.utils, this.invoicePaidCb, updateProviderBalance)
|
||||||
|
adminManager.attachLiquidityProvider(this.liquidityProvider)
|
||||||
this.rugPullTracker = new RugPullTracker(this.storage, this.liquidityProvider)
|
this.rugPullTracker = new RugPullTracker(this.storage, this.liquidityProvider)
|
||||||
const lndGetSettings = () => ({
|
const lndGetSettings = () => ({
|
||||||
lndSettings: settings.getSettings().lndSettings,
|
lndSettings: settings.getSettings().lndSettings,
|
||||||
|
|
@ -161,19 +162,25 @@ export default class {
|
||||||
NewBlockHandler = async (height: number, skipMetrics?: boolean) => {
|
NewBlockHandler = async (height: number, skipMetrics?: boolean) => {
|
||||||
let confirmed: (PendingTx & { confs: number; })[]
|
let confirmed: (PendingTx & { confs: number; })[]
|
||||||
let log = getLogger({})
|
let log = getLogger({})
|
||||||
|
// log("NewBlockHandler called", JSON.stringify({ height, skipMetrics }))
|
||||||
this.storage.paymentStorage.DeleteExpiredTransactionSwaps(height)
|
this.storage.paymentStorage.DeleteExpiredTransactionSwaps(height)
|
||||||
.catch(err => log(ERROR, "failed to delete expired transaction swaps", err.message || err))
|
.catch(err => log(ERROR, "failed to delete expired transaction swaps", err.message || err))
|
||||||
|
this.storage.paymentStorage.DeleteExpiredInvoiceSwaps(height)
|
||||||
|
.catch(err => log(ERROR, "failed to delete expired invoice swaps", err.message || err))
|
||||||
try {
|
try {
|
||||||
const balanceEvents = await this.paymentManager.GetLndBalance()
|
const balanceEvents = await this.paymentManager.GetLndBalance()
|
||||||
if (!skipMetrics) {
|
if (!skipMetrics) {
|
||||||
await this.metricsManager.NewBlockCb(height, balanceEvents)
|
await this.metricsManager.NewBlockCb(height, balanceEvents)
|
||||||
}
|
}
|
||||||
confirmed = await this.paymentManager.CheckNewlyConfirmedTxs(height)
|
confirmed = await this.paymentManager.CheckNewlyConfirmedTxs()
|
||||||
await this.liquidityManager.onNewBlock()
|
await this.liquidityManager.onNewBlock()
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
log(ERROR, "failed to check transactions after new block", err.message || err)
|
log(ERROR, "failed to check transactions after new block", err.message || err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (confirmed.length > 0) {
|
||||||
|
log("NewBlockHandler new confirmed transactions", confirmed.length)
|
||||||
|
}
|
||||||
await Promise.all(confirmed.map(async c => {
|
await Promise.all(confirmed.map(async c => {
|
||||||
if (c.type === 'outgoing') {
|
if (c.type === 'outgoing') {
|
||||||
await this.storage.paymentStorage.UpdateUserTransactionPayment(c.tx.serial_id, { confs: c.confs })
|
await this.storage.paymentStorage.UpdateUserTransactionPayment(c.tx.serial_id, { confs: c.confs })
|
||||||
|
|
@ -208,6 +215,7 @@ export default class {
|
||||||
|
|
||||||
addressPaidCb: AddressPaidCb = (txOutput, address, amount, used, broadcastHeight) => {
|
addressPaidCb: AddressPaidCb = (txOutput, address, amount, used, broadcastHeight) => {
|
||||||
return this.storage.StartTransaction(async tx => {
|
return this.storage.StartTransaction(async tx => {
|
||||||
|
getLogger({})("addressPaidCb called", JSON.stringify({ txOutput, address, amount, used, broadcastHeight }))
|
||||||
// On-chain payments not supported when bypass is enabled
|
// On-chain payments not supported when bypass is enabled
|
||||||
if (this.liquidityProvider.getSettings().useOnlyLiquidityProvider) {
|
if (this.liquidityProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
getLogger({})("addressPaidCb called but USE_ONLY_LIQUIDITY_PROVIDER is enabled, ignoring")
|
getLogger({})("addressPaidCb called but USE_ONLY_LIQUIDITY_PROVIDER is enabled, ignoring")
|
||||||
|
|
@ -419,13 +427,36 @@ export default class {
|
||||||
if (devices.length === 0 || !app.nostr_public_key || !app.nostr_private_key || !appUser.nostr_public_key) {
|
if (devices.length === 0 || !app.nostr_public_key || !app.nostr_private_key || !appUser.nostr_public_key) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokens = devices.map(d => d.firebase_messaging_token)
|
const tokens = devices.map(d => d.firebase_messaging_token)
|
||||||
const ck = nip44.getConversationKey(Buffer.from(app.nostr_private_key, 'hex'), appUser.nostr_public_key)
|
const ck = nip44.getConversationKey(Buffer.from(app.nostr_private_key, 'hex'), appUser.nostr_public_key)
|
||||||
const j = JSON.stringify(op)
|
|
||||||
|
let payloadToEncrypt: Types.PushNotificationPayload;
|
||||||
|
if (op.inbound) {
|
||||||
|
payloadToEncrypt = {
|
||||||
|
data: {
|
||||||
|
type: Types.PushNotificationPayload_data_type.RECEIVED_OPERATION,
|
||||||
|
received_operation: op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
payloadToEncrypt = {
|
||||||
|
data: {
|
||||||
|
type: Types.PushNotificationPayload_data_type.SENT_OPERATION,
|
||||||
|
sent_operation: op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const j = JSON.stringify(payloadToEncrypt)
|
||||||
const encrypted = nip44.encrypt(j, ck)
|
const encrypted = nip44.encrypt(j, ck)
|
||||||
const encryptedData: { encrypted: string, app_npub_hex: string } = { encrypted, app_npub_hex: app.nostr_public_key }
|
|
||||||
|
const envelope: Types.PushNotificationEnvelope = {
|
||||||
|
topic_id: appUser.topic_id,
|
||||||
|
app_npub_hex: app.nostr_public_key,
|
||||||
|
encrypted_payload: encrypted
|
||||||
|
}
|
||||||
const notification: ShockPushNotification = {
|
const notification: ShockPushNotification = {
|
||||||
message: JSON.stringify(encryptedData),
|
message: JSON.stringify(envelope),
|
||||||
body,
|
body,
|
||||||
title
|
title
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { AdminManager } from "./adminManager.js"
|
||||||
import SettingsManager from "./settingsManager.js"
|
import SettingsManager from "./settingsManager.js"
|
||||||
import { LoadStorageSettingsFromEnv } from "../storage/index.js"
|
import { LoadStorageSettingsFromEnv } from "../storage/index.js"
|
||||||
import { NostrSender } from "../nostr/sender.js"
|
import { NostrSender } from "../nostr/sender.js"
|
||||||
import { Swaps } from "../lnd/swaps.js"
|
import { Swaps } from "../lnd/swaps/swaps.js"
|
||||||
export type AppData = {
|
export type AppData = {
|
||||||
privateKey: string;
|
privateKey: string;
|
||||||
publicKey: string;
|
publicKey: string;
|
||||||
|
|
@ -79,6 +79,7 @@ export const initMainHandler = async (log: PubLogger, settingsManager: SettingsM
|
||||||
await mainHandler.paymentManager.CleanupOldUnpaidInvoices()
|
await mainHandler.paymentManager.CleanupOldUnpaidInvoices()
|
||||||
await mainHandler.appUserManager.CleanupInactiveUsers()
|
await mainHandler.appUserManager.CleanupInactiveUsers()
|
||||||
await mainHandler.appUserManager.CleanupNeverActiveUsers()
|
await mainHandler.appUserManager.CleanupNeverActiveUsers()
|
||||||
|
await swaps.ResumeInvoiceSwaps()
|
||||||
await mainHandler.paymentManager.watchDog.Start()
|
await mainHandler.paymentManager.watchDog.Start()
|
||||||
return { mainHandler, apps, localProviderClient, wizard, adminManager }
|
return { mainHandler, apps, localProviderClient, wizard, adminManager }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,14 +277,14 @@ export class LiquidityProvider {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
GetOperations = async () => {
|
GetOperations = async (max = 200) => {
|
||||||
if (!this.IsReady()) {
|
if (!this.IsReady()) {
|
||||||
throw new Error("liquidity provider is not ready yet, disabled or unreachable")
|
throw new Error("liquidity provider is not ready yet, disabled or unreachable")
|
||||||
}
|
}
|
||||||
const res = await this.client.GetUserOperations({
|
const res = await this.client.GetUserOperations({
|
||||||
latestIncomingInvoice: { ts: 0, id: 0 }, latestOutgoingInvoice: { ts: 0, id: 0 },
|
latestIncomingInvoice: { ts: 0, id: 0 }, latestOutgoingInvoice: { ts: 0, id: 0 },
|
||||||
latestIncomingTx: { ts: 0, id: 0 }, latestOutgoingTx: { ts: 0, id: 0 }, latestIncomingUserToUserPayment: { ts: 0, id: 0 },
|
latestIncomingTx: { ts: 0, id: 0 }, latestOutgoingTx: { ts: 0, id: 0 }, latestIncomingUserToUserPayment: { ts: 0, id: 0 },
|
||||||
latestOutgoingUserToUserPayment: { ts: 0, id: 0 }, max_size: 200
|
latestOutgoingUserToUserPayment: { ts: 0, id: 0 }, max_size: max
|
||||||
})
|
})
|
||||||
if (res.status === 'ERROR') {
|
if (res.status === 'ERROR') {
|
||||||
this.log("error getting operations", res.reason)
|
this.log("error getting operations", res.reason)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import { LiquidityManager } from './liquidityManager.js'
|
||||||
import { Utils } from '../helpers/utilsWrapper.js'
|
import { Utils } from '../helpers/utilsWrapper.js'
|
||||||
import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js'
|
import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js'
|
||||||
import SettingsManager from './settingsManager.js'
|
import SettingsManager from './settingsManager.js'
|
||||||
import { Swaps, TransactionSwapData } from '../lnd/swaps.js'
|
import { Swaps } from '../lnd/swaps/swaps.js'
|
||||||
import { Transaction, OutputDetail } from '../../../proto/lnd/lightning.js'
|
import { Transaction, OutputDetail } from '../../../proto/lnd/lightning.js'
|
||||||
import { LndAddress } from '../lnd/lnd.js'
|
import { LndAddress } from '../lnd/lnd.js'
|
||||||
import Metrics from '../metrics/index.js'
|
import Metrics from '../metrics/index.js'
|
||||||
|
|
@ -201,24 +201,11 @@ export default class {
|
||||||
} else {
|
} else {
|
||||||
log("no missed chain transactions found")
|
log("no missed chain transactions found")
|
||||||
}
|
}
|
||||||
await this.reprocessStuckPendingTx(log, currentHeight)
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
log(ERROR, "failed to check for missed chain transactions:", err.message || err)
|
log(ERROR, "failed to check for missed chain transactions:", err.message || err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reprocessStuckPendingTx = async (log: PubLogger, currentHeight: number) => {
|
|
||||||
const { incoming } = await this.storage.paymentStorage.GetPendingTransactions()
|
|
||||||
const found = incoming.find(t => t.broadcast_height < currentHeight - 100)
|
|
||||||
if (found) {
|
|
||||||
log("found a possibly stuck pending transaction, reprocessing with full transaction history")
|
|
||||||
// There is a pending transaction more than 100 blocks old, this is likely a transaction
|
|
||||||
// that has a broadcast height higher than it actually is, so its not getting picked up when being processed
|
|
||||||
// by calling new block cb with height of 1, we make sure that even if the transaction has a newer height, it will still be processed
|
|
||||||
await this.newBlockCb(1, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getLatestTransactions(log: PubLogger): Promise<{ txs: Transaction[], currentHeight: number, lndPubkey: string, startHeight: number }> {
|
private async getLatestTransactions(log: PubLogger): Promise<{ txs: Transaction[], currentHeight: number, lndPubkey: string, startHeight: number }> {
|
||||||
const lndInfo = await this.lnd.GetInfo()
|
const lndInfo = await this.lnd.GetInfo()
|
||||||
const lndPubkey = lndInfo.identityPubkey
|
const lndPubkey = lndInfo.identityPubkey
|
||||||
|
|
@ -273,14 +260,14 @@ export default class {
|
||||||
private async processRootAddressOutput(output: OutputDetail, tx: Transaction, addresses: LndAddress[], log: PubLogger): Promise<boolean> {
|
private async processRootAddressOutput(output: OutputDetail, tx: Transaction, addresses: LndAddress[], log: PubLogger): Promise<boolean> {
|
||||||
const addr = addresses.find(a => a.address === output.address)
|
const addr = addresses.find(a => a.address === output.address)
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
throw new Error(`address ${output.address} not found in list of addresses`)
|
throw new Error(`root address ${output.address} not found in list of addresses`)
|
||||||
}
|
}
|
||||||
if (addr.change) {
|
if (addr.change) {
|
||||||
log(`ignoring change address ${output.address}`)
|
log(`ignoring change address ${output.address}`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const outputIndex = Number(output.outputIndex)
|
const outputIndex = Number(output.outputIndex)
|
||||||
const existingRootOp = await this.metrics.GetRootAddressTransaction(output.address, tx.txHash, outputIndex)
|
const existingRootOp = await this.storage.metricsStorage.GetRootAddressTransaction(output.address, tx.txHash, outputIndex)
|
||||||
if (existingRootOp) {
|
if (existingRootOp) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -302,8 +289,11 @@ export default class {
|
||||||
const amount = Number(output.amount)
|
const amount = Number(output.amount)
|
||||||
const outputIndex = Number(output.outputIndex)
|
const outputIndex = Number(output.outputIndex)
|
||||||
log(`processing missed chain tx: address=${output.address}, txHash=${tx.txHash}, amount=${amount}, outputIndex=${outputIndex}`)
|
log(`processing missed chain tx: address=${output.address}, txHash=${tx.txHash}, amount=${amount}, outputIndex=${outputIndex}`)
|
||||||
this.addressPaidCb({ hash: tx.txHash, index: outputIndex }, output.address, amount, 'lnd', startHeight)
|
try {
|
||||||
.catch(err => log(ERROR, "failed to process user address output:", err.message || err))
|
await this.addressPaidCb({ hash: tx.txHash, index: outputIndex }, output.address, amount, 'lnd', startHeight)
|
||||||
|
} catch (err: any) {
|
||||||
|
log(ERROR, "failed to process user address output:", err.message || err)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,9 +595,15 @@ export default class {
|
||||||
|
|
||||||
async PayInternalAddress(ctx: Types.UserContext, req: Types.PayAddressRequest): Promise<Types.PayAddressResponse> {
|
async PayInternalAddress(ctx: Types.UserContext, req: Types.PayAddressRequest): Promise<Types.PayAddressResponse> {
|
||||||
this.log("paying internal address")
|
this.log("paying internal address")
|
||||||
|
let amount = req.amountSats
|
||||||
if (req.swap_operation_id) {
|
if (req.swap_operation_id) {
|
||||||
|
const swap = await this.storage.paymentStorage.GetTransactionSwap(req.swap_operation_id, ctx.app_user_id)
|
||||||
|
amount = amount > 0 ? amount : swap?.invoice_amount || 0
|
||||||
await this.storage.paymentStorage.DeleteTransactionSwap(req.swap_operation_id)
|
await this.storage.paymentStorage.DeleteTransactionSwap(req.swap_operation_id)
|
||||||
}
|
}
|
||||||
|
if (amount <= 0) {
|
||||||
|
throw new Error("invalid tx amount")
|
||||||
|
}
|
||||||
const { blockHeight } = await this.lnd.GetInfo()
|
const { blockHeight } = await this.lnd.GetInfo()
|
||||||
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
||||||
const isManagedUser = ctx.user_id !== app.owner.user_id
|
const isManagedUser = ctx.user_id !== app.owner.user_id
|
||||||
|
|
@ -634,11 +630,13 @@ export default class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListSwaps(ctx: Types.UserContext): Promise<Types.SwapsList> {
|
async ListTxSwaps(ctx: Types.UserContext): Promise<Types.TxSwapsList> {
|
||||||
const payments = await this.storage.paymentStorage.ListSwapPayments(ctx.app_user_id)
|
console.log("listing tx swaps", { appUserId: ctx.app_user_id })
|
||||||
|
const payments = await this.storage.paymentStorage.ListTxSwapPayments(ctx.app_user_id)
|
||||||
|
console.log("payments", payments.length)
|
||||||
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
||||||
const isManagedUser = ctx.user_id !== app.owner.user_id
|
const isManagedUser = ctx.user_id !== app.owner.user_id
|
||||||
return this.swaps.ListSwaps(ctx.app_user_id, payments, p => {
|
return this.swaps.ListTxSwaps(ctx.app_user_id, payments, p => {
|
||||||
const opId = `${Types.UserOperationType.OUTGOING_TX}-${p.serial_id}`
|
const opId = `${Types.UserOperationType.OUTGOING_TX}-${p.serial_id}`
|
||||||
return this.newInvoicePaymentOperation({ amount: p.paid_amount, confirmed: p.paid_at_unix !== 0, invoice: p.invoice, opId, networkFee: p.routing_fees, serviceFee: p.service_fees, paidAtUnix: p.paid_at_unix })
|
return this.newInvoicePaymentOperation({ amount: p.paid_amount, confirmed: p.paid_at_unix !== 0, invoice: p.invoice, opId, networkFee: p.routing_fees, serviceFee: p.service_fees, paidAtUnix: p.paid_at_unix })
|
||||||
}, amt => this.getSendServiceFee(Types.UserOperationType.OUTGOING_INVOICE, amt, isManagedUser))
|
}, amt => this.getSendServiceFee(Types.UserOperationType.OUTGOING_INVOICE, amt, isManagedUser))
|
||||||
|
|
@ -973,29 +971,40 @@ export default class {
|
||||||
return { amount: payment.paid_amount, fees: payment.service_fees }
|
return { amount: payment.paid_amount, fees: payment.service_fees }
|
||||||
}
|
}
|
||||||
|
|
||||||
async CheckNewlyConfirmedTxs(height: number) {
|
private async getTxConfs(txHash: string): Promise<number> {
|
||||||
const pending = await this.storage.paymentStorage.GetPendingTransactions()
|
try {
|
||||||
let lowestHeight = height
|
const info = await this.lnd.GetTx(txHash)
|
||||||
const map: Record<string, PendingTx> = {}
|
const { numConfirmations: confs, amount: amt } = info
|
||||||
|
|
||||||
const checkTx = (t: PendingTx) => {
|
|
||||||
if (t.tx.broadcast_height < lowestHeight) { lowestHeight = t.tx.broadcast_height }
|
|
||||||
map[t.tx.tx_hash] = t
|
|
||||||
}
|
|
||||||
pending.incoming.forEach(t => checkTx({ type: "incoming", tx: t }))
|
|
||||||
pending.outgoing.forEach(t => checkTx({ type: "outgoing", tx: t }))
|
|
||||||
const { transactions } = await this.lnd.GetTransactions(lowestHeight)
|
|
||||||
const newlyConfirmedTxs = transactions.map(tx => {
|
|
||||||
const { txHash, numConfirmations: confs, amount: amt } = tx
|
|
||||||
const t = map[txHash]
|
|
||||||
if (!t || confs === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (confs > 2 || (amt <= confInTwo && confs > 1) || (amt <= confInOne && confs > 0)) {
|
if (confs > 2 || (amt <= confInTwo && confs > 1) || (amt <= confInOne && confs > 0)) {
|
||||||
return { ...t, confs }
|
return confs
|
||||||
}
|
}
|
||||||
})
|
} catch (err: any) {
|
||||||
return newlyConfirmedTxs.filter(t => t !== undefined) as (PendingTx & { confs: number })[]
|
getLogger({})("failed to get tx info", err.message || err)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
async CheckNewlyConfirmedTxs() {
|
||||||
|
const pending = await this.storage.paymentStorage.GetPendingTransactions()
|
||||||
|
let log = getLogger({})
|
||||||
|
if (pending.incoming.length > 0 || pending.outgoing.length > 0) {
|
||||||
|
log("CheckNewlyConfirmedTxs ", pending.incoming.length, "incoming", pending.outgoing.length, "outgoing")
|
||||||
|
}
|
||||||
|
const confirmedIncoming: (PendingTx & { confs: number })[] = []
|
||||||
|
const confirmedOutgoing: (PendingTx & { confs: number })[] = []
|
||||||
|
for (const tx of pending.incoming) {
|
||||||
|
const confs = await this.getTxConfs(tx.tx_hash)
|
||||||
|
if (confs > 0) {
|
||||||
|
confirmedIncoming.push({ type: "incoming", tx: tx, confs })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const tx of pending.outgoing) {
|
||||||
|
const confs = await this.getTxConfs(tx.tx_hash)
|
||||||
|
if (confs > 0) {
|
||||||
|
confirmedOutgoing.push({ type: "outgoing", tx: tx, confs })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return confirmedIncoming.concat(confirmedOutgoing)
|
||||||
}
|
}
|
||||||
|
|
||||||
async CleanupOldUnpaidInvoices() {
|
async CleanupOldUnpaidInvoices() {
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ export default class SanityChecker {
|
||||||
|
|
||||||
async VerifyEventsLog() {
|
async VerifyEventsLog() {
|
||||||
this.events = await this.storage.eventsLog.GetAllLogs()
|
this.events = await this.storage.eventsLog.GetAllLogs()
|
||||||
this.invoices = (await this.lnd.GetAllPaidInvoices(1000)).invoices
|
this.invoices = (await this.lnd.GetAllInvoices(1000)).invoices
|
||||||
this.payments = (await this.lnd.GetAllPayments(1000)).payments
|
this.payments = (await this.lnd.GetAllPayments(1000)).payments
|
||||||
|
|
||||||
this.incrementSources = {}
|
this.incrementSources = {}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ export class Watchdog {
|
||||||
ready = false
|
ready = false
|
||||||
interval: NodeJS.Timer;
|
interval: NodeJS.Timer;
|
||||||
lndPubKey: string;
|
lndPubKey: string;
|
||||||
|
lastHandlerRootOpsAtUnix = 0
|
||||||
constructor(settings: SettingsManager, liquidityManager: LiquidityManager, lnd: LND, storage: Storage, utils: Utils, rugPullTracker: RugPullTracker) {
|
constructor(settings: SettingsManager, liquidityManager: LiquidityManager, lnd: LND, storage: Storage, utils: Utils, rugPullTracker: RugPullTracker) {
|
||||||
this.lnd = lnd;
|
this.lnd = lnd;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
|
@ -67,7 +68,7 @@ export class Watchdog {
|
||||||
await this.getTracker()
|
await this.getTracker()
|
||||||
const totalUsersBalance = await this.storage.paymentStorage.GetTotalUsersBalance()
|
const totalUsersBalance = await this.storage.paymentStorage.GetTotalUsersBalance()
|
||||||
this.utils.stateBundler.AddBalancePoint('usersBalance', totalUsersBalance)
|
this.utils.stateBundler.AddBalancePoint('usersBalance', totalUsersBalance)
|
||||||
const { totalExternal, otherExternal } = await this.getAggregatedExternalBalance()
|
const { totalExternal } = await this.getAggregatedExternalBalance()
|
||||||
this.initialLndBalance = totalExternal
|
this.initialLndBalance = totalExternal
|
||||||
this.initialUsersBalance = totalUsersBalance
|
this.initialUsersBalance = totalUsersBalance
|
||||||
const fwEvents = await this.lnd.GetForwardingHistory(0, this.startedAtUnix)
|
const fwEvents = await this.lnd.GetForwardingHistory(0, this.startedAtUnix)
|
||||||
|
|
@ -76,8 +77,6 @@ export class Watchdog {
|
||||||
const paymentFound = await this.storage.paymentStorage.GetMaxPaymentIndex()
|
const paymentFound = await this.storage.paymentStorage.GetMaxPaymentIndex()
|
||||||
const knownMaxIndex = paymentFound.length > 0 ? Math.max(paymentFound[0].paymentIndex, 0) : 0
|
const knownMaxIndex = paymentFound.length > 0 ? Math.max(paymentFound[0].paymentIndex, 0) : 0
|
||||||
this.latestPaymentIndexOffset = await this.lnd.GetLatestPaymentIndex(knownMaxIndex)
|
this.latestPaymentIndexOffset = await this.lnd.GetLatestPaymentIndex(knownMaxIndex)
|
||||||
const other = { ilnd: this.initialLndBalance, hf: this.accumulatedHtlcFees, iu: this.initialUsersBalance, tu: totalUsersBalance, oext: otherExternal }
|
|
||||||
//getLogger({ component: 'watchdog_debug2' })(JSON.stringify({ deltaLnd: 0, deltaUsers: 0, totalExternal, latestIndex: this.latestPaymentIndexOffset, other }))
|
|
||||||
this.interval = setInterval(() => {
|
this.interval = setInterval(() => {
|
||||||
if (this.latestCheckStart + (1000 * 58) < Date.now()) {
|
if (this.latestCheckStart + (1000 * 58) < Date.now()) {
|
||||||
this.PaymentRequested()
|
this.PaymentRequested()
|
||||||
|
|
@ -93,7 +92,49 @@ export class Watchdog {
|
||||||
fwEvents.forwardingEvents.forEach((event) => {
|
fwEvents.forwardingEvents.forEach((event) => {
|
||||||
this.accumulatedHtlcFees += Number(event.fee)
|
this.accumulatedHtlcFees += Number(event.fee)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRootOperations = async () => {
|
||||||
|
let pendingChange = 0
|
||||||
|
const pendingChainPayments = await this.storage.metricsStorage.GetPendingChainPayments()
|
||||||
|
for (const payment of pendingChainPayments) {
|
||||||
|
try {
|
||||||
|
const tx = await this.lnd.GetTx(payment.operation_identifier)
|
||||||
|
if (tx.numConfirmations > 0) {
|
||||||
|
await this.storage.metricsStorage.SetRootOpConfirmed(payment.serial_id)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tx.outputDetails.forEach(o => pendingChange += o.isOurAddress ? Number(o.amount) : 0)
|
||||||
|
} catch (err: any) {
|
||||||
|
this.log("Error getting tx for root operation", err.message || err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
let newReceived = 0
|
||||||
|
let newSpent = 0
|
||||||
|
if (this.lastHandlerRootOpsAtUnix === 0) {
|
||||||
|
this.lastHandlerRootOpsAtUnix = Math.floor(Date.now() / 1000)
|
||||||
|
return { newReceived, newSpent, pendingChange }
|
||||||
|
}
|
||||||
|
|
||||||
|
const newOps = await this.storage.metricsStorage.GetRootOperations({ from: this.lastHandlerRootOpsAtUnix })
|
||||||
|
newOps.forEach(o => {
|
||||||
|
switch (o.operation_type) {
|
||||||
|
case 'chain_payment':
|
||||||
|
newSpent += Number(o.operation_amount)
|
||||||
|
break
|
||||||
|
case 'invoice_payment':
|
||||||
|
newSpent += Number(o.operation_amount)
|
||||||
|
break
|
||||||
|
case 'chain':
|
||||||
|
newReceived += Number(o.operation_amount)
|
||||||
|
break
|
||||||
|
case 'invoice':
|
||||||
|
newReceived += Number(o.operation_amount)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return { newReceived, newSpent, pendingChange }
|
||||||
}
|
}
|
||||||
|
|
||||||
getAggregatedExternalBalance = async () => {
|
getAggregatedExternalBalance = async () => {
|
||||||
|
|
@ -101,8 +142,9 @@ export class Watchdog {
|
||||||
const feesPaidForLiquidity = this.liquidityManager.GetPaidFees()
|
const feesPaidForLiquidity = this.liquidityManager.GetPaidFees()
|
||||||
const pb = await this.rugPullTracker.CheckProviderBalance()
|
const pb = await this.rugPullTracker.CheckProviderBalance()
|
||||||
const providerBalance = pb.prevBalance || pb.balance
|
const providerBalance = pb.prevBalance || pb.balance
|
||||||
const otherExternal = { pb: providerBalance, f: feesPaidForLiquidity, lnd: totalLndBalance, olnd: othersFromLnd }
|
const { newReceived, newSpent, pendingChange } = await this.handleRootOperations()
|
||||||
return { totalExternal: totalLndBalance + providerBalance + feesPaidForLiquidity, otherExternal }
|
const opsTotal = newReceived + pendingChange - newSpent
|
||||||
|
return { totalExternal: totalLndBalance + providerBalance + feesPaidForLiquidity + opsTotal }
|
||||||
}
|
}
|
||||||
|
|
||||||
checkBalanceUpdate = async (deltaLnd: number, deltaUsers: number) => {
|
checkBalanceUpdate = async (deltaLnd: number, deltaUsers: number) => {
|
||||||
|
|
@ -187,7 +229,7 @@ export class Watchdog {
|
||||||
}
|
}
|
||||||
const totalUsersBalance = await this.storage.paymentStorage.GetTotalUsersBalance()
|
const totalUsersBalance = await this.storage.paymentStorage.GetTotalUsersBalance()
|
||||||
this.utils.stateBundler.AddBalancePoint('usersBalance', totalUsersBalance)
|
this.utils.stateBundler.AddBalancePoint('usersBalance', totalUsersBalance)
|
||||||
const { totalExternal, otherExternal } = await this.getAggregatedExternalBalance()
|
const { totalExternal } = await this.getAggregatedExternalBalance()
|
||||||
this.utils.stateBundler.AddBalancePoint('accumulatedHtlcFees', this.accumulatedHtlcFees)
|
this.utils.stateBundler.AddBalancePoint('accumulatedHtlcFees', this.accumulatedHtlcFees)
|
||||||
const deltaLnd = totalExternal - (this.initialLndBalance + this.accumulatedHtlcFees)
|
const deltaLnd = totalExternal - (this.initialLndBalance + this.accumulatedHtlcFees)
|
||||||
const deltaUsers = totalUsersBalance - this.initialUsersBalance
|
const deltaUsers = totalUsersBalance - this.initialUsersBalance
|
||||||
|
|
@ -196,15 +238,17 @@ export class Watchdog {
|
||||||
const knownMaxIndex = Math.max(maxFromDb, this.latestPaymentIndexOffset)
|
const knownMaxIndex = Math.max(maxFromDb, this.latestPaymentIndexOffset)
|
||||||
const newLatest = await this.lnd.GetLatestPaymentIndex(knownMaxIndex)
|
const newLatest = await this.lnd.GetLatestPaymentIndex(knownMaxIndex)
|
||||||
const historyMismatch = newLatest > knownMaxIndex
|
const historyMismatch = newLatest > knownMaxIndex
|
||||||
const other = { ilnd: this.initialLndBalance, hf: this.accumulatedHtlcFees, iu: this.initialUsersBalance, tu: totalUsersBalance, km: knownMaxIndex, nl: newLatest, oext: otherExternal }
|
|
||||||
//getLogger({ component: 'watchdog_debug2' })(JSON.stringify({ deltaLnd, deltaUsers, totalExternal, other }))
|
|
||||||
const deny = await this.checkBalanceUpdate(deltaLnd, deltaUsers)
|
|
||||||
if (historyMismatch) {
|
if (historyMismatch) {
|
||||||
getLogger({ component: 'bark' })("History mismatch detected in absolute update, locking outgoing operations")
|
this.log("Payment index advanced from", knownMaxIndex, "to", newLatest, "- updating offset (likely LND restart or external payment)")
|
||||||
this.lnd.LockOutgoingOperations()
|
this.latestPaymentIndexOffset = newLatest
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
const deny = await this.checkBalanceUpdate(deltaLnd, deltaUsers)
|
||||||
if (deny) {
|
if (deny) {
|
||||||
|
if (historyMismatch) {
|
||||||
|
getLogger({ component: 'bark' })("Balance mismatch with unexpected payment history, locking outgoing operations")
|
||||||
|
this.lnd.LockOutgoingOperations()
|
||||||
|
return
|
||||||
|
}
|
||||||
this.log("Balance mismatch detected in absolute update, but history is ok")
|
this.log("Balance mismatch detected in absolute update, but history is ok")
|
||||||
}
|
}
|
||||||
this.lnd.UnlockOutgoingOperations()
|
this.lnd.UnlockOutgoingOperations()
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,15 @@ import HtlcTracker from './htlcTracker.js'
|
||||||
import { getLogger } from '../helpers/logger.js'
|
import { getLogger } from '../helpers/logger.js'
|
||||||
import { encodeTLV, usageMetricsToTlv } from '../helpers/tlv.js'
|
import { encodeTLV, usageMetricsToTlv } from '../helpers/tlv.js'
|
||||||
import { ChannelCloseSummary_ClosureType } from '../../../proto/lnd/lightning.js'
|
import { ChannelCloseSummary_ClosureType } from '../../../proto/lnd/lightning.js'
|
||||||
|
const cacheTTL = 1000 * 60 * 5 // 5 minutes
|
||||||
export default class Handler {
|
export default class Handler {
|
||||||
|
|
||||||
storage: Storage
|
storage: Storage
|
||||||
lnd: LND
|
lnd: LND
|
||||||
htlcTracker: HtlcTracker
|
htlcTracker: HtlcTracker
|
||||||
|
appsMetricsCache: CacheController<Types.AppsMetrics> = new CacheController<Types.AppsMetrics>()
|
||||||
|
lndForwardingMetricsCache: CacheController<Types.LndForwardingMetrics> = new CacheController<Types.LndForwardingMetrics>()
|
||||||
|
lndMetricsCache: CacheController<Types.LndMetrics> = new CacheController<Types.LndMetrics>()
|
||||||
logger = getLogger({ component: "metrics" })
|
logger = getLogger({ component: "metrics" })
|
||||||
constructor(storage: Storage, lnd: LND) {
|
constructor(storage: Storage, lnd: LND) {
|
||||||
this.storage = storage
|
this.storage = storage
|
||||||
|
|
@ -183,8 +186,6 @@ export default class Handler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* addTrackedMetric = (appId: string, method: string, metric: Uint8Array) => {
|
/* addTrackedMetric = (appId: string, method: string, metric: Uint8Array) => {
|
||||||
if (!this.metaReady) {
|
if (!this.metaReady) {
|
||||||
throw new Error("meta metrics not ready")
|
throw new Error("meta metrics not ready")
|
||||||
|
|
@ -203,13 +204,21 @@ export default class Handler {
|
||||||
} */
|
} */
|
||||||
|
|
||||||
async GetAppsMetrics(req: Types.AppsMetricsRequest): Promise<Types.AppsMetrics> {
|
async GetAppsMetrics(req: Types.AppsMetricsRequest): Promise<Types.AppsMetrics> {
|
||||||
|
const cached = this.appsMetricsCache.Get(req)
|
||||||
|
const now = Date.now()
|
||||||
|
if (cached && now - cached.createdAt < cacheTTL) {
|
||||||
|
|
||||||
|
return cached.metrics
|
||||||
|
}
|
||||||
const dbApps = await this.storage.applicationStorage.GetApplications()
|
const dbApps = await this.storage.applicationStorage.GetApplications()
|
||||||
const apps = await Promise.all(dbApps.map(app => this.GetAppMetrics(req, app)))
|
const apps = await Promise.all(dbApps.map(app => this.GetAppMetrics(req, app)))
|
||||||
const unlinked = await this.GetAppMetrics(req, null)
|
const unlinked = await this.GetAppMetrics(req, null)
|
||||||
apps.push(unlinked)
|
apps.push(unlinked)
|
||||||
return {
|
const metrics = {
|
||||||
apps
|
apps
|
||||||
}
|
}
|
||||||
|
this.appsMetricsCache.Set(req, { metrics, createdAt: now })
|
||||||
|
return metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetAppMetrics(req: Types.AppsMetricsRequest, app: Application | null): Promise<Types.AppMetrics> {
|
async GetAppMetrics(req: Types.AppsMetricsRequest, app: Application | null): Promise<Types.AppMetrics> {
|
||||||
|
|
@ -332,6 +341,11 @@ export default class Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetLndForwardingMetrics(req: Types.LndMetricsRequest): Promise<Types.LndForwardingMetrics> {
|
async GetLndForwardingMetrics(req: Types.LndMetricsRequest): Promise<Types.LndForwardingMetrics> {
|
||||||
|
const cached = this.lndForwardingMetricsCache.Get(req)
|
||||||
|
const now = Date.now()
|
||||||
|
if (cached && now - cached.createdAt < cacheTTL) {
|
||||||
|
return cached.metrics
|
||||||
|
}
|
||||||
const fwEvents = await this.lnd.GetForwardingHistory(0, req.from_unix, req.to_unix)
|
const fwEvents = await this.lnd.GetForwardingHistory(0, req.from_unix, req.to_unix)
|
||||||
let totalFees = 0
|
let totalFees = 0
|
||||||
const events: Types.LndForwardingEvent[] = fwEvents.forwardingEvents.map(e => {
|
const events: Types.LndForwardingEvent[] = fwEvents.forwardingEvents.map(e => {
|
||||||
|
|
@ -340,14 +354,21 @@ export default class Handler {
|
||||||
chan_id_in: e.chanIdIn, chan_id_out: e.chanIdOut, amt_in: Number(e.amtIn), amt_out: Number(e.amtOut), fee: Number(e.fee), at_unix: Number(e.timestampNs)
|
chan_id_in: e.chanIdIn, chan_id_out: e.chanIdOut, amt_in: Number(e.amtIn), amt_out: Number(e.amtOut), fee: Number(e.fee), at_unix: Number(e.timestampNs)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return {
|
const metrics = {
|
||||||
total_fees: totalFees,
|
total_fees: totalFees,
|
||||||
events: events
|
events: events
|
||||||
}
|
}
|
||||||
|
this.lndForwardingMetricsCache.Set(req, { metrics, createdAt: now })
|
||||||
|
return metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async GetLndMetrics(req: Types.LndMetricsRequest): Promise<Types.LndMetrics> {
|
async GetLndMetrics(req: Types.LndMetricsRequest): Promise<Types.LndMetrics> {
|
||||||
|
const cached = this.lndMetricsCache.Get(req)
|
||||||
|
const now = Date.now()
|
||||||
|
if (cached && now - cached.createdAt < cacheTTL) {
|
||||||
|
return cached.metrics
|
||||||
|
}
|
||||||
const [chansInfo, pendingChansInfo, closedChansInfo, routing, rootOps, channelsActivity] = await Promise.all([
|
const [chansInfo, pendingChansInfo, closedChansInfo, routing, rootOps, channelsActivity] = await Promise.all([
|
||||||
this.GetChannelsInfo(),
|
this.GetChannelsInfo(),
|
||||||
this.GetPendingChannelsInfo(),
|
this.GetPendingChannelsInfo(),
|
||||||
|
|
@ -392,7 +413,7 @@ export default class Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
}))
|
}))
|
||||||
return {
|
const metrics = {
|
||||||
nodes: [{
|
nodes: [{
|
||||||
chain_balance: chainBalance,
|
chain_balance: chainBalance,
|
||||||
channel_balance: chansBalance,
|
channel_balance: chansBalance,
|
||||||
|
|
@ -408,15 +429,15 @@ export default class Handler {
|
||||||
root_ops: rootOps.map(r => ({ amount: r.operation_amount, created_at_unix: r.at_unix || 0, op_id: r.operation_identifier, op_type: mapRootOpType(r.operation_type) })),
|
root_ops: rootOps.map(r => ({ amount: r.operation_amount, created_at_unix: r.at_unix || 0, op_id: r.operation_identifier, op_type: mapRootOpType(r.operation_type) })),
|
||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
|
this.lndMetricsCache.Set(req, { metrics, createdAt: now })
|
||||||
|
return metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddRootAddressPaid(address: string, txOutput: { hash: string; index: number }, amount: number) {
|
async AddRootAddressPaid(address: string, txOutput: { hash: string; index: number }, amount: number) {
|
||||||
await this.storage.metricsStorage.AddRootOperation("chain", `${address}:${txOutput.hash}:${txOutput.index}`, amount)
|
await this.storage.metricsStorage.AddRootOperation("chain", `${address}:${txOutput.hash}:${txOutput.index}`, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetRootAddressTransaction(address: string, txHash: string, index: number) {
|
|
||||||
return this.storage.metricsStorage.GetRootOperation("chain", `${address}:${txHash}:${index}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
async AddRootInvoicePaid(paymentRequest: string, amount: number) {
|
async AddRootInvoicePaid(paymentRequest: string, amount: number) {
|
||||||
await this.storage.metricsStorage.AddRootOperation("invoice", paymentRequest, amount)
|
await this.storage.metricsStorage.AddRootOperation("invoice", paymentRequest, amount)
|
||||||
|
|
@ -425,8 +446,41 @@ export default class Handler {
|
||||||
|
|
||||||
const mapRootOpType = (opType: string): Types.OperationType => {
|
const mapRootOpType = (opType: string): Types.OperationType => {
|
||||||
switch (opType) {
|
switch (opType) {
|
||||||
case "chain": return Types.OperationType.CHAIN_OP
|
case "chain_payment":
|
||||||
case "invoice": return Types.OperationType.INVOICE_OP
|
case "chain":
|
||||||
|
return Types.OperationType.CHAIN_OP
|
||||||
|
case "invoice_payment":
|
||||||
|
case "invoice":
|
||||||
|
return Types.OperationType.INVOICE_OP
|
||||||
|
|
||||||
default: throw new Error("Unknown operation type")
|
default: throw new Error("Unknown operation type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CacheData<T> = {
|
||||||
|
metrics: T
|
||||||
|
createdAt: number
|
||||||
|
}
|
||||||
|
|
||||||
|
class CacheController<T> {
|
||||||
|
private cache: Record<string, CacheData<T>> = {}
|
||||||
|
Get = (req: Types.AppsMetricsRequest): CacheData<T> | undefined => {
|
||||||
|
const key = this.getKey(req)
|
||||||
|
return this.cache[key]
|
||||||
|
}
|
||||||
|
Set = (req: Types.AppsMetricsRequest, metrics: CacheData<T>) => {
|
||||||
|
const key = this.getKey(req)
|
||||||
|
this.cache[key] = metrics
|
||||||
|
}
|
||||||
|
Clear = (req: Types.AppsMetricsRequest) => {
|
||||||
|
const key = this.getKey(req)
|
||||||
|
delete this.cache[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
private getKey = (req: Types.AppsMetricsRequest) => {
|
||||||
|
const start = req.from_unix || 0
|
||||||
|
const end = req.to_unix || 0
|
||||||
|
const includeOperations = req.include_operations ? "1" : "0"
|
||||||
|
return `${start}:${end}:${includeOperations}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -132,12 +132,12 @@ const handleNostrSettings = (settings: NostrSettings) => {
|
||||||
send(event)
|
send(event)
|
||||||
})
|
})
|
||||||
} */
|
} */
|
||||||
const sendToNostr: NostrSend = (initiator, data, relays) => {
|
const sendToNostr: NostrSend = async (initiator, data, relays) => {
|
||||||
if (!subProcessHandler) {
|
if (!subProcessHandler) {
|
||||||
getLogger({ component: "nostrMiddleware" })(ERROR, "nostr was not initialized")
|
getLogger({ component: "nostrMiddleware" })(ERROR, "nostr was not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
subProcessHandler.Send(initiator, data, relays)
|
await subProcessHandler.Send(initiator, data, relays)
|
||||||
}
|
}
|
||||||
|
|
||||||
send({ type: 'ready' })
|
send({ type: 'ready' })
|
||||||
|
|
|
||||||
|
|
@ -11,28 +11,69 @@ export default class NostrSubprocess {
|
||||||
utils: Utils
|
utils: Utils
|
||||||
awaitingPongs: (() => void)[] = []
|
awaitingPongs: (() => void)[] = []
|
||||||
log = getLogger({})
|
log = getLogger({})
|
||||||
|
latestRestart = 0
|
||||||
|
private settings: NostrSettings
|
||||||
|
private eventCallback: EventCallback
|
||||||
|
private beaconCallback: BeaconCallback
|
||||||
|
private isShuttingDown = false
|
||||||
|
|
||||||
constructor(settings: NostrSettings, utils: Utils, eventCallback: EventCallback, beaconCallback: BeaconCallback) {
|
constructor(settings: NostrSettings, utils: Utils, eventCallback: EventCallback, beaconCallback: BeaconCallback) {
|
||||||
this.utils = utils
|
this.utils = utils
|
||||||
|
this.settings = settings
|
||||||
|
this.eventCallback = eventCallback
|
||||||
|
this.beaconCallback = beaconCallback
|
||||||
|
this.startSubProcess()
|
||||||
|
}
|
||||||
|
|
||||||
|
private cleanupProcess() {
|
||||||
|
if (this.childProcess) {
|
||||||
|
this.childProcess.removeAllListeners()
|
||||||
|
if (!this.childProcess.killed) {
|
||||||
|
this.childProcess.kill('SIGTERM')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private startSubProcess() {
|
||||||
|
this.cleanupProcess()
|
||||||
|
|
||||||
this.childProcess = fork("./build/src/services/nostr/handler")
|
this.childProcess = fork("./build/src/services/nostr/handler")
|
||||||
|
|
||||||
this.childProcess.on("error", (error) => {
|
this.childProcess.on("error", (error) => {
|
||||||
this.log(ERROR, "nostr subprocess error", error)
|
this.log(ERROR, "nostr subprocess error", error)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.childProcess.on("exit", (code) => {
|
this.childProcess.on("exit", (code, signal) => {
|
||||||
this.log(ERROR, `nostr subprocess exited with code ${code}`)
|
if (this.isShuttingDown) {
|
||||||
if (!code) {
|
this.log("nostr subprocess stopped")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error(`nostr subprocess exited with code ${code}`)
|
|
||||||
|
if (code === 0) {
|
||||||
|
this.log("nostr subprocess exited cleanly")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`)
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
if (now - this.latestRestart < 5000) {
|
||||||
|
this.log(ERROR, "nostr subprocess exited too quickly, not restarting")
|
||||||
|
throw new Error("nostr subprocess crashed repeatedly")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log("restarting nostr subprocess...")
|
||||||
|
this.latestRestart = now
|
||||||
|
setTimeout(() => this.startSubProcess(), 100)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.childProcess.on("message", (message: ChildProcessResponse) => {
|
this.childProcess.on("message", (message: ChildProcessResponse) => {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'ready':
|
case 'ready':
|
||||||
this.sendToChildProcess({ type: 'settings', settings: settings })
|
this.sendToChildProcess({ type: 'settings', settings: this.settings })
|
||||||
break;
|
break;
|
||||||
case 'event':
|
case 'event':
|
||||||
eventCallback(message.event)
|
this.eventCallback(message.event)
|
||||||
break
|
break
|
||||||
case 'processMetrics':
|
case 'processMetrics':
|
||||||
this.utils.tlvStorageFactory.ProcessMetrics(message.metrics, 'nostr')
|
this.utils.tlvStorageFactory.ProcessMetrics(message.metrics, 'nostr')
|
||||||
|
|
@ -42,7 +83,7 @@ export default class NostrSubprocess {
|
||||||
this.awaitingPongs = []
|
this.awaitingPongs = []
|
||||||
break
|
break
|
||||||
case 'beacon':
|
case 'beacon':
|
||||||
beaconCallback({ content: message.content, pub: message.pub })
|
this.beaconCallback({ content: message.content, pub: message.pub })
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
console.error("unknown nostr event response", message)
|
console.error("unknown nostr event response", message)
|
||||||
|
|
@ -50,11 +91,15 @@ export default class NostrSubprocess {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sendToChildProcess(message: ChildProcessRequest) {
|
sendToChildProcess(message: ChildProcessRequest) {
|
||||||
this.childProcess.send(message)
|
if (this.childProcess && !this.childProcess.killed) {
|
||||||
|
this.childProcess.send(message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reset(settings: NostrSettings) {
|
Reset(settings: NostrSettings) {
|
||||||
|
this.settings = settings
|
||||||
this.sendToChildProcess({ type: 'settings', settings })
|
this.sendToChildProcess({ type: 'settings', settings })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +113,9 @@ export default class NostrSubprocess {
|
||||||
Send(initiator: SendInitiator, data: SendData, relays?: string[]) {
|
Send(initiator: SendInitiator, data: SendData, relays?: string[]) {
|
||||||
this.sendToChildProcess({ type: 'send', data, initiator, relays })
|
this.sendToChildProcess({ type: 'send', data, initiator, relays })
|
||||||
}
|
}
|
||||||
|
|
||||||
Stop() {
|
Stop() {
|
||||||
this.childProcess.kill()
|
this.isShuttingDown = true
|
||||||
|
this.cleanupProcess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { base64 } from "@scure/base";
|
import { base64, hex } from "@scure/base";
|
||||||
import { randomBytes } from "@noble/hashes/utils";
|
import { randomBytes } from "@noble/hashes/utils";
|
||||||
import { streamXOR as xchacha20 } from "@stablelib/xchacha20";
|
import { streamXOR as xchacha20 } from "@stablelib/xchacha20";
|
||||||
import { secp256k1 } from "@noble/curves/secp256k1";
|
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
||||||
import { sha256 } from "@noble/hashes/sha256";
|
import { sha256 } from "@noble/hashes/sha256";
|
||||||
export type EncryptedData = {
|
export type EncryptedData = {
|
||||||
ciphertext: Uint8Array;
|
ciphertext: Uint8Array;
|
||||||
nonce: Uint8Array;
|
nonce: Uint8Array;
|
||||||
}
|
}
|
||||||
export const getSharedSecret = (privateKey: string, publicKey: string) => {
|
export const getSharedSecret = (privateKey: string, publicKey: string) => {
|
||||||
const key = secp256k1.getSharedSecret(privateKey, "02" + publicKey);
|
const key = secp256k1.getSharedSecret(hex.decode(privateKey), hex.decode("02" + publicKey));
|
||||||
return sha256(key.slice(1, 33));
|
return sha256(key.slice(1, 33));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export type SendDataContent = { type: "content", content: string, pub: string }
|
||||||
export type SendDataEvent = { type: "event", event: UnsignedEvent, encrypt?: { toPub: string } }
|
export type SendDataEvent = { type: "event", event: UnsignedEvent, encrypt?: { toPub: string } }
|
||||||
export type SendData = SendDataContent | SendDataEvent
|
export type SendData = SendDataContent | SendDataEvent
|
||||||
export type SendInitiator = { type: 'app', appId: string } | { type: 'client', clientId: string }
|
export type SendInitiator = { type: 'app', appId: string } | { type: 'client', clientId: string }
|
||||||
export type NostrSend = (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => void
|
export type NostrSend = (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => Promise<void>
|
||||||
|
|
||||||
export type LinkedProviderInfo = { pubkey: string, clientId: string, relayUrl: string }
|
export type LinkedProviderInfo = { pubkey: string, clientId: string, relayUrl: string }
|
||||||
export type AppInfo = { appId: string, publicKey: string, privateKey: string, name: string, provider?: LinkedProviderInfo }
|
export type AppInfo = { appId: string, publicKey: string, privateKey: string, name: string, provider?: LinkedProviderInfo }
|
||||||
|
|
@ -203,21 +203,26 @@ export class NostrPool {
|
||||||
const signed = finalizeEvent(event, Buffer.from(keys.privateKey, 'hex'))
|
const signed = finalizeEvent(event, Buffer.from(keys.privateKey, 'hex'))
|
||||||
let sent = false
|
let sent = false
|
||||||
const log = getLogger({ appName: keys.name })
|
const log = getLogger({ appName: keys.name })
|
||||||
// const r = relays ? relays : this.getServiceRelays()
|
this.log(`📤 Publishing Kind ${event.kind} event to ${relays.length} relay(s): ${relays.join(', ')}`)
|
||||||
const pool = new SimplePool()
|
const pool = new SimplePool()
|
||||||
await Promise.all(pool.publish(relays, signed).map(async p => {
|
try {
|
||||||
try {
|
await Promise.all(pool.publish(relays, signed).map(async p => {
|
||||||
await p
|
try {
|
||||||
sent = true
|
await p
|
||||||
} catch (e: any) {
|
sent = true
|
||||||
console.log(e)
|
} catch (e: any) {
|
||||||
log(e)
|
this.log(ERROR, `Failed to publish Kind ${event.kind} event:`, e.message || e)
|
||||||
|
log(e)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
if (!sent) {
|
||||||
|
this.log(ERROR, `Failed to send Kind ${event.kind} event to any relay`)
|
||||||
|
log("failed to send event")
|
||||||
|
} else {
|
||||||
|
this.log(`✅ Kind ${event.kind} event published successfully (id: ${signed.id.slice(0, 16)}...)`)
|
||||||
}
|
}
|
||||||
}))
|
} finally {
|
||||||
if (!sent) {
|
pool.close(relays)
|
||||||
log("failed to send event")
|
|
||||||
} else {
|
|
||||||
//log("sent event")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { NostrSend, SendData, SendInitiator } from "./nostrPool.js"
|
import { NostrSend, SendData, SendInitiator } from "./nostrPool.js"
|
||||||
import { getLogger } from "../helpers/logger.js"
|
import { ERROR, getLogger } from "../helpers/logger.js"
|
||||||
export class NostrSender {
|
export class NostrSender {
|
||||||
private _nostrSend: NostrSend = () => { throw new Error('nostr send not initialized yet') }
|
private _nostrSend: NostrSend = async () => { throw new Error('nostr send not initialized yet') }
|
||||||
private isReady: boolean = false
|
private isReady: boolean = false
|
||||||
private onReadyCallbacks: (() => void)[] = []
|
private onReadyCallbacks: (() => void)[] = []
|
||||||
private pendingSends: { initiator: SendInitiator, data: SendData, relays?: string[] | undefined }[] = []
|
private pendingSends: { initiator: SendInitiator, data: SendData, relays?: string[] | undefined }[] = []
|
||||||
|
|
@ -12,7 +12,12 @@ export class NostrSender {
|
||||||
this.isReady = true
|
this.isReady = true
|
||||||
this.onReadyCallbacks.forEach(cb => cb())
|
this.onReadyCallbacks.forEach(cb => cb())
|
||||||
this.onReadyCallbacks = []
|
this.onReadyCallbacks = []
|
||||||
this.pendingSends.forEach(send => this._nostrSend(send.initiator, send.data, send.relays))
|
// Process pending sends with proper error handling
|
||||||
|
this.pendingSends.forEach(send => {
|
||||||
|
this._nostrSend(send.initiator, send.data, send.relays).catch(e => {
|
||||||
|
this.log(ERROR, "failed to send pending event", e.message || e)
|
||||||
|
})
|
||||||
|
})
|
||||||
this.pendingSends = []
|
this.pendingSends = []
|
||||||
}
|
}
|
||||||
OnReady(callback: () => void) {
|
OnReady(callback: () => void) {
|
||||||
|
|
@ -22,13 +27,16 @@ export class NostrSender {
|
||||||
this.onReadyCallbacks.push(callback)
|
this.onReadyCallbacks.push(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Send(initiator: SendInitiator, data: SendData, relays?: string[] | undefined) {
|
Send(initiator: SendInitiator, data: SendData, relays?: string[] | undefined): void {
|
||||||
if (!this.isReady) {
|
if (!this.isReady) {
|
||||||
this.log("tried to send before nostr was ready, caching request")
|
this.log("tried to send before nostr was ready, caching request")
|
||||||
this.pendingSends.push({ initiator, data, relays })
|
this.pendingSends.push({ initiator, data, relays })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this._nostrSend(initiator, data, relays)
|
// Fire and forget but log errors
|
||||||
|
this._nostrSend(initiator, data, relays).catch(e => {
|
||||||
|
this.log(ERROR, "failed to send event", e.message || e)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
IsReady() {
|
IsReady() {
|
||||||
return this.isReady
|
return this.isReady
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,14 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
if (err != null) throw new Error(err.message)
|
if (err != null) throw new Error(err.message)
|
||||||
return mainHandler.adminManager.CloseChannel(req)
|
return mainHandler.adminManager.CloseChannel(req)
|
||||||
},
|
},
|
||||||
|
BumpTx: async ({ ctx, req }) => {
|
||||||
|
const err = Types.BumpTxValidate(req, {
|
||||||
|
txid_CustomCheck: txid => txid !== '',
|
||||||
|
sat_per_vbyte_CustomCheck: spv => spv > 0
|
||||||
|
})
|
||||||
|
if (err != null) throw new Error(err.message)
|
||||||
|
return mainHandler.adminManager.BumpTx(req)
|
||||||
|
},
|
||||||
GetAdminTransactionSwapQuotes: async ({ ctx, req }) => {
|
GetAdminTransactionSwapQuotes: async ({ ctx, req }) => {
|
||||||
const err = Types.TransactionSwapRequestValidate(req, {
|
const err = Types.TransactionSwapRequestValidate(req, {
|
||||||
transaction_amount_sats_CustomCheck: amt => amt > 0
|
transaction_amount_sats_CustomCheck: amt => amt > 0
|
||||||
|
|
@ -106,6 +114,36 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
if (err != null) throw new Error(err.message)
|
if (err != null) throw new Error(err.message)
|
||||||
return mainHandler.adminManager.PayAdminTransactionSwap(req)
|
return mainHandler.adminManager.PayAdminTransactionSwap(req)
|
||||||
},
|
},
|
||||||
|
ListAdminTxSwaps: async ({ ctx }) => {
|
||||||
|
return mainHandler.adminManager.ListAdminTxSwaps()
|
||||||
|
},
|
||||||
|
GetAdminInvoiceSwapQuotes: async ({ ctx, req }) => {
|
||||||
|
const err = Types.InvoiceSwapRequestValidate(req, {
|
||||||
|
amount_sats_CustomCheck: amt => amt > 0
|
||||||
|
})
|
||||||
|
if (err != null) throw new Error(err.message)
|
||||||
|
return mainHandler.adminManager.GetAdminInvoiceSwapQuotes(req)
|
||||||
|
},
|
||||||
|
RefundAdminInvoiceSwap: async ({ ctx, req }) => {
|
||||||
|
const err = Types.RefundAdminInvoiceSwapRequestValidate(req, {
|
||||||
|
swap_operation_id_CustomCheck: id => id !== '',
|
||||||
|
})
|
||||||
|
if (err != null) throw new Error(err.message)
|
||||||
|
return mainHandler.adminManager.RefundAdminInvoiceSwap(req)
|
||||||
|
},
|
||||||
|
ListAdminInvoiceSwaps: async ({ ctx }) => {
|
||||||
|
return mainHandler.adminManager.ListAdminInvoiceSwaps()
|
||||||
|
},
|
||||||
|
PayAdminInvoiceSwap: async ({ ctx, req }) => {
|
||||||
|
const err = Types.PayAdminInvoiceSwapRequestValidate(req, {
|
||||||
|
swap_operation_id_CustomCheck: id => id !== '',
|
||||||
|
})
|
||||||
|
if (err != null) throw new Error(err.message)
|
||||||
|
return mainHandler.adminManager.PayAdminInvoiceSwap(req)
|
||||||
|
},
|
||||||
|
GetAssetsAndLiabilities: async ({ ctx, req }) => {
|
||||||
|
return mainHandler.adminManager.GetAssetsAndLiabilities(req)
|
||||||
|
},
|
||||||
GetProvidersDisruption: async () => {
|
GetProvidersDisruption: async () => {
|
||||||
return mainHandler.metricsManager.GetProvidersDisruption()
|
return mainHandler.metricsManager.GetProvidersDisruption()
|
||||||
},
|
},
|
||||||
|
|
@ -145,9 +183,7 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
GetUserOperations: async ({ ctx, req }) => {
|
GetUserOperations: async ({ ctx, req }) => {
|
||||||
return mainHandler.paymentManager.GetUserOperations(ctx.user_id, req)
|
return mainHandler.paymentManager.GetUserOperations(ctx.user_id, req)
|
||||||
},
|
},
|
||||||
ListAdminSwaps: async ({ ctx }) => {
|
|
||||||
return mainHandler.adminManager.ListAdminSwaps()
|
|
||||||
},
|
|
||||||
GetPaymentState: async ({ ctx, req }) => {
|
GetPaymentState: async ({ ctx, req }) => {
|
||||||
const err = Types.GetPaymentStateRequestValidate(req, {
|
const err = Types.GetPaymentStateRequestValidate(req, {
|
||||||
invoice_CustomCheck: invoice => invoice !== ""
|
invoice_CustomCheck: invoice => invoice !== ""
|
||||||
|
|
@ -159,14 +195,14 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
PayAddress: async ({ ctx, req }) => {
|
PayAddress: async ({ ctx, req }) => {
|
||||||
const err = Types.PayAddressRequestValidate(req, {
|
const err = Types.PayAddressRequestValidate(req, {
|
||||||
address_CustomCheck: addr => addr !== '',
|
address_CustomCheck: addr => addr !== '',
|
||||||
amountSats_CustomCheck: amt => amt > 0,
|
// amountSats_CustomCheck: amt => amt > 0,
|
||||||
// satsPerVByte_CustomCheck: spb => spb > 0
|
// satsPerVByte_CustomCheck: spb => spb > 0
|
||||||
})
|
})
|
||||||
if (err != null) throw new Error(err.message)
|
if (err != null) throw new Error(err.message)
|
||||||
return mainHandler.paymentManager.PayAddress(ctx, req)
|
return mainHandler.paymentManager.PayAddress(ctx, req)
|
||||||
},
|
},
|
||||||
ListSwaps: async ({ ctx }) => {
|
ListTxSwaps: async ({ ctx }) => {
|
||||||
return mainHandler.paymentManager.ListSwaps(ctx)
|
return mainHandler.paymentManager.ListTxSwaps(ctx)
|
||||||
},
|
},
|
||||||
GetTransactionSwapQuotes: async ({ ctx, req }) => {
|
GetTransactionSwapQuotes: async ({ ctx, req }) => {
|
||||||
return mainHandler.paymentManager.GetTransactionSwapQuotes(ctx, req)
|
return mainHandler.paymentManager.GetTransactionSwapQuotes(ctx, req)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { Between, FindOperator, IsNull, LessThanOrEqual, MoreThanOrEqual, In } from "typeorm"
|
import { Between, FindOperator, IsNull, LessThanOrEqual, MoreThanOrEqual } from "typeorm"
|
||||||
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
||||||
import { Application } from "./entity/Application.js"
|
import { Application } from "./entity/Application.js"
|
||||||
import UserStorage from './userStorage.js';
|
import UserStorage from './userStorage.js';
|
||||||
|
|
@ -72,7 +72,8 @@ export default class {
|
||||||
user: user,
|
user: user,
|
||||||
application,
|
application,
|
||||||
identifier: userIdentifier,
|
identifier: userIdentifier,
|
||||||
nostr_public_key: nostrPub
|
nostr_public_key: nostrPub,
|
||||||
|
topic_id: crypto.randomBytes(32).toString('hex')
|
||||||
}, txId)
|
}, txId)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -160,10 +161,16 @@ export default class {
|
||||||
this.dbs.Remove<User>('User', baseUser, txId)
|
this.dbs.Remove<User>('User', baseUser, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async RemoveAppUsersAndBaseUsers(appUserIds: string[],baseUser:string, txId?: string) {
|
async RemoveAppUsersAndBaseUsers(appUserIds: string[], baseUser: string, txId?: string) {
|
||||||
await this.dbs.Delete<ApplicationUser>('ApplicationUser', { identifier: In(appUserIds) }, txId)
|
for (const appUserId of appUserIds) {
|
||||||
await this.dbs.Delete<User>('User', { user_id: baseUser }, txId)
|
const appUser = await this.dbs.FindOne<ApplicationUser>('ApplicationUser', { where: { identifier: appUserId } }, txId)
|
||||||
|
if (appUser) {
|
||||||
|
await this.dbs.Delete<ApplicationUser>('ApplicationUser', appUser.serial_id, txId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const user = await this.userStorage.FindUser(baseUser, txId)
|
||||||
|
if (!user) return
|
||||||
|
await this.dbs.Delete<User>('User', user.serial_id, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import * as fs from 'fs'
|
||||||
import { UserAccess } from "../entity/UserAccess.js"
|
import { UserAccess } from "../entity/UserAccess.js"
|
||||||
import { AdminSettings } from "../entity/AdminSettings.js"
|
import { AdminSettings } from "../entity/AdminSettings.js"
|
||||||
import { TransactionSwap } from "../entity/TransactionSwap.js"
|
import { TransactionSwap } from "../entity/TransactionSwap.js"
|
||||||
|
import { InvoiceSwap } from "../entity/InvoiceSwap.js"
|
||||||
|
|
||||||
|
|
||||||
export type DbSettings = {
|
export type DbSettings = {
|
||||||
|
|
@ -76,7 +77,8 @@ export const MainDbEntities = {
|
||||||
'AppUserDevice': AppUserDevice,
|
'AppUserDevice': AppUserDevice,
|
||||||
'UserAccess': UserAccess,
|
'UserAccess': UserAccess,
|
||||||
'AdminSettings': AdminSettings,
|
'AdminSettings': AdminSettings,
|
||||||
'TransactionSwap': TransactionSwap
|
'TransactionSwap': TransactionSwap,
|
||||||
|
'InvoiceSwap': InvoiceSwap
|
||||||
}
|
}
|
||||||
export type MainDbNames = keyof typeof MainDbEntities
|
export type MainDbNames = keyof typeof MainDbEntities
|
||||||
export const MainDbEntitiesNames = Object.keys(MainDbEntities)
|
export const MainDbEntitiesNames = Object.keys(MainDbEntities)
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,19 @@ type SerializedFindOperator = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serializeFindOperator(operator: FindOperator<any>): SerializedFindOperator {
|
export function serializeFindOperator(operator: FindOperator<any>): SerializedFindOperator {
|
||||||
|
let value: any;
|
||||||
|
if (Array.isArray(operator['value']) && operator['type'] !== 'between') {
|
||||||
|
value = operator['value'].map(serializeFindOperator);
|
||||||
|
} else if ((operator as any).child !== undefined) {
|
||||||
|
// Not(IsNull()) etc.: TypeORM's .value getter unwraps nested FindOperators, so we'd lose the inner operator. Use .child to serialize the nested operator.
|
||||||
|
value = serializeFindOperator((operator as any).child);
|
||||||
|
} else {
|
||||||
|
value = operator['value'];
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
_type: 'FindOperator',
|
_type: 'FindOperator',
|
||||||
type: operator['type'],
|
type: operator['type'],
|
||||||
value: (Array.isArray(operator['value']) && operator['type'] !== 'between') ? operator["value"].map(serializeFindOperator) : operator["value"],
|
value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +60,8 @@ export function deserializeFindOperator(serialized: SerializedFindOperator): Fin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serializeRequest<T>(r: object): T {
|
export function serializeRequest<T>(r: object, debug = false): T {
|
||||||
|
if (debug) console.log("serializeRequest", r)
|
||||||
if (!r || typeof r !== 'object') {
|
if (!r || typeof r !== 'object') {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
@ -61,23 +71,24 @@ export function serializeRequest<T>(r: object): T {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(r)) {
|
if (Array.isArray(r)) {
|
||||||
return r.map(item => serializeRequest(item)) as any;
|
return r.map(item => serializeRequest(item, debug)) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: any = {};
|
const result: any = {};
|
||||||
for (const [key, value] of Object.entries(r)) {
|
for (const [key, value] of Object.entries(r)) {
|
||||||
result[key] = serializeRequest(value);
|
result[key] = serializeRequest(value, debug);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deserializeRequest<T>(r: object): T {
|
export function deserializeRequest<T>(r: object, debug = false): T {
|
||||||
|
if (debug) console.log("deserializeRequest", r)
|
||||||
if (!r || typeof r !== 'object') {
|
if (!r || typeof r !== 'object') {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(r)) {
|
if (Array.isArray(r)) {
|
||||||
return r.map(item => deserializeRequest(item)) as any;
|
return r.map(item => deserializeRequest(item, debug)) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r && typeof r === 'object' && (r as any)._type === 'FindOperator') {
|
if (r && typeof r === 'object' && (r as any)._type === 'FindOperator') {
|
||||||
|
|
@ -86,7 +97,7 @@ export function deserializeRequest<T>(r: object): T {
|
||||||
|
|
||||||
const result: any = {};
|
const result: any = {};
|
||||||
for (const [key, value] of Object.entries(r)) {
|
for (const [key, value] of Object.entries(r)) {
|
||||||
result[key] = deserializeRequest(value);
|
result[key] = deserializeRequest(value, debug);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export class StorageInterface extends EventEmitter {
|
||||||
private debug: boolean = false;
|
private debug: boolean = false;
|
||||||
private utils: Utils
|
private utils: Utils
|
||||||
private dbType: 'main' | 'metrics'
|
private dbType: 'main' | 'metrics'
|
||||||
private log = getLogger({component: 'StorageInterface'})
|
private log = getLogger({ component: 'StorageInterface' })
|
||||||
constructor(utils: Utils) {
|
constructor(utils: Utils) {
|
||||||
super();
|
super();
|
||||||
this.initializeSubprocess();
|
this.initializeSubprocess();
|
||||||
|
|
@ -61,13 +61,13 @@ export class StorageInterface extends EventEmitter {
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.process.on('exit', (code: number) => {
|
this.process.on('exit', (code: number, signal: string) => {
|
||||||
this.log(ERROR, `Storage processor exited with code ${code}`);
|
this.log(ERROR, `Storage processor exited with code ${code} and signal ${signal}`);
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
if (!code) {
|
if (code === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error(`Storage processor exited with code ${code}`)
|
throw new Error(`Storage processor exited with code ${code} and signal ${signal}`)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.isConnected = true;
|
this.isConnected = true;
|
||||||
|
|
@ -104,9 +104,10 @@ export class StorageInterface extends EventEmitter {
|
||||||
return this.handleOp<T | null>(findOp)
|
return this.handleOp<T | null>(findOp)
|
||||||
}
|
}
|
||||||
|
|
||||||
Find<T>(entity: DBNames, q: QueryOptions<T>, txId?: string): Promise<T[]> {
|
Find<T>(entity: DBNames, q: QueryOptions<T>, txId?: string, debug = false): Promise<T[]> {
|
||||||
|
if (debug) console.log("Find", { entity })
|
||||||
const opId = Math.random().toString()
|
const opId = Math.random().toString()
|
||||||
const findOp: FindOperation<T> = { type: 'find', entity, opId, q, txId }
|
const findOp: FindOperation<T> = { type: 'find', entity, opId, q, txId, debug }
|
||||||
return this.handleOp<T[]>(findOp)
|
return this.handleOp<T[]>(findOp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,32 +167,33 @@ export class StorageInterface extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleOp<T>(op: IStorageOperation): Promise<T> {
|
private handleOp<T>(op: IStorageOperation): Promise<T> {
|
||||||
if (this.debug) console.log('handleOp', op)
|
if (this.debug || op.debug) console.log('handleOp', op)
|
||||||
this.checkConnected()
|
this.checkConnected()
|
||||||
return new Promise<T>((resolve, reject) => {
|
return new Promise<T>((resolve, reject) => {
|
||||||
const responseHandler = (response: OperationResponse<T>) => {
|
const responseHandler = (response: OperationResponse<T>) => {
|
||||||
if (this.debug) console.log('responseHandler', response)
|
if (this.debug || op.debug) console.log('responseHandler', response)
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
reject(new Error(response.error));
|
reject(new Error(response.error));
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (this.debug || op.debug) console.log("response", response, op)
|
||||||
if (response.type !== op.type) {
|
if (response.type !== op.type) {
|
||||||
reject(new Error('Invalid storage response type'));
|
reject(new Error('Invalid storage response type'));
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resolve(deserializeResponseData(response.data));
|
resolve(deserializeResponseData(response.data));
|
||||||
}
|
}
|
||||||
this.once(op.opId, responseHandler)
|
this.once(op.opId, responseHandler)
|
||||||
this.process.send(this.serializeOperation(op))
|
this.process.send(this.serializeOperation(op))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private serializeOperation(operation: IStorageOperation): IStorageOperation {
|
private serializeOperation(operation: IStorageOperation, debug = false): IStorageOperation {
|
||||||
const serialized = { ...operation };
|
const serialized = { ...operation };
|
||||||
if ('q' in serialized) {
|
if ('q' in serialized) {
|
||||||
(serialized as any).q = serializeRequest((serialized as any).q);
|
(serialized as any).q = serializeRequest((serialized as any).q, debug);
|
||||||
}
|
}
|
||||||
if (this.debug) {
|
if (this.debug || debug) {
|
||||||
serialized.debug = true
|
serialized.debug = true
|
||||||
}
|
}
|
||||||
return serialized;
|
return serialized;
|
||||||
|
|
@ -205,7 +207,7 @@ export class StorageInterface extends EventEmitter {
|
||||||
|
|
||||||
public disconnect() {
|
public disconnect() {
|
||||||
if (this.process) {
|
if (this.process) {
|
||||||
this.process.kill();
|
this.process.kill(0);
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
this.debug = false;
|
this.debug = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ export default class {
|
||||||
|
|
||||||
async execNextInQueue() {
|
async execNextInQueue() {
|
||||||
this.pendingTx = false
|
this.pendingTx = false
|
||||||
const next = this.transactionsQueue.pop()
|
const next = this.transactionsQueue.shift()
|
||||||
if (!next) {
|
if (!next) {
|
||||||
this.doneWriting()
|
this.doneWriting()
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ export class ApplicationUser {
|
||||||
@Column({ default: "" })
|
@Column({ default: "" })
|
||||||
callback_url: string
|
callback_url: string
|
||||||
|
|
||||||
|
@Column({ unique: true })
|
||||||
|
topic_id: string;
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|
|
||||||
100
src/services/storage/entity/InvoiceSwap.ts
Normal file
100
src/services/storage/entity/InvoiceSwap.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn, UpdateDateColumn } from "typeorm";
|
||||||
|
import { User } from "./User";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class InvoiceSwap {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
swap_operation_id: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
app_user_id: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
swap_quote_id: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
swap_tree: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
claim_public_key: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
payment_hash: string
|
||||||
|
|
||||||
|
/* @Column()
|
||||||
|
lockup_address: string */
|
||||||
|
|
||||||
|
/* @Column()
|
||||||
|
refund_public_key: string */
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
timeout_block_height: number
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
invoice: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
invoice_amount: number
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
transaction_amount: number
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
swap_fee_sats: number
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
chain_fee_sats: number
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
ephemeral_public_key: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
address: string
|
||||||
|
|
||||||
|
// the private key is used on to perform a swap, it does not hold any funds once the swap is completed
|
||||||
|
// the swap should only last a few seconds, so it is not a security risk to store the private key in the database
|
||||||
|
// the key is stored here mostly for recovery purposes, in case something goes wrong with the swap
|
||||||
|
@Column()
|
||||||
|
ephemeral_private_key: string
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
used: boolean
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
completed_at_unix: number
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
paid_at_unix: number
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
preimage: string
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
failure_reason: string
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
tx_id: string
|
||||||
|
|
||||||
|
@Column({ default: "", type: "text" })
|
||||||
|
lockup_tx_hex: string
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
refund_address: string
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
refund_at_unix: number
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
refund_tx_id: string
|
||||||
|
|
||||||
|
@Column({ default: "" })
|
||||||
|
service_url: string
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
created_at: Date
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updated_at: Date
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,9 @@ export class RootOperation {
|
||||||
@Column({ default: 0 })
|
@Column({ default: 0 })
|
||||||
at_unix: number
|
at_unix: number
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
pending: boolean
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,12 @@ export class TransactionSwap {
|
||||||
@Column({ default: "" })
|
@Column({ default: "" })
|
||||||
tx_id: string
|
tx_id: string
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
completed_at_unix: number
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
paid_at_unix: number
|
||||||
|
|
||||||
@Column({ default: "" })
|
@Column({ default: "" })
|
||||||
address_paid: string
|
address_paid: string
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { StorageInterface } from "./db/storageInterface.js";
|
||||||
import { Utils } from "../helpers/utilsWrapper.js";
|
import { Utils } from "../helpers/utilsWrapper.js";
|
||||||
import { Channel, ChannelEventUpdate } from "../../../proto/lnd/lightning.js";
|
import { Channel, ChannelEventUpdate } from "../../../proto/lnd/lightning.js";
|
||||||
import { ChannelEvent } from "./entity/ChannelEvent.js";
|
import { ChannelEvent } from "./entity/ChannelEvent.js";
|
||||||
|
export type RootOperationType = 'chain' | 'invoice' | 'chain_payment' | 'invoice_payment'
|
||||||
export default class {
|
export default class {
|
||||||
//DB: DataSource | EntityManager
|
//DB: DataSource | EntityManager
|
||||||
settings: StorageSettings
|
settings: StorageSettings
|
||||||
|
|
@ -145,13 +146,27 @@ export default class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddRootOperation(opType: string, id: string, amount: number, txId?: string) {
|
async AddRootOperation(opType: RootOperationType, id: string, amount: number, pending = false, dbTxId?: string) {
|
||||||
return this.dbs.CreateAndSave<RootOperation>('RootOperation', { operation_type: opType, operation_amount: amount, operation_identifier: id, at_unix: Math.floor(Date.now() / 1000) }, txId)
|
return this.dbs.CreateAndSave<RootOperation>('RootOperation', {
|
||||||
|
operation_type: opType, operation_amount: amount,
|
||||||
|
operation_identifier: id, at_unix: Math.floor(Date.now() / 1000), pending
|
||||||
|
}, dbTxId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetRootOperation(opType: string, id: string, txId?: string) {
|
async GetRootOperation(opType: RootOperationType, id: string, txId?: string) {
|
||||||
return this.dbs.FindOne<RootOperation>('RootOperation', { where: { operation_type: opType, operation_identifier: id } }, txId)
|
return this.dbs.FindOne<RootOperation>('RootOperation', { where: { operation_type: opType, operation_identifier: id } }, txId)
|
||||||
}
|
}
|
||||||
|
async GetRootAddressTransaction(address: string, txHash: string, index: number) {
|
||||||
|
return this.GetRootOperation("chain", `${address}:${txHash}:${index}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetPendingChainPayments() {
|
||||||
|
return this.dbs.Find<RootOperation>('RootOperation', { where: { operation_type: 'chain_payment', pending: true } })
|
||||||
|
}
|
||||||
|
|
||||||
|
async SetRootOpConfirmed(serialId: number) {
|
||||||
|
return this.dbs.Update<RootOperation>('RootOperation', serialId, { pending: false })
|
||||||
|
}
|
||||||
|
|
||||||
async GetRootOperations({ from, to }: { from?: number, to?: number }, txId?: string) {
|
async GetRootOperations({ from, to }: { from?: number, to?: number }, txId?: string) {
|
||||||
const q = getTimeQuery({ from, to })
|
const q = getTimeQuery({ from, to })
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class InvoiceSwaps1769529793283 implements MigrationInterface {
|
||||||
|
name = 'InvoiceSwaps1769529793283'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')))`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "invoice_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class InvoiceSwapsFixes1769805357459 implements MigrationInterface {
|
||||||
|
name = 'InvoiceSwapsFixes1769805357459'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at" FROM "invoice_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "invoice_swap"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_invoice_swap" RENAME TO "invoice_swap"`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "invoice_swap" RENAME TO "temporary_invoice_swap"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at" FROM "temporary_invoice_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_invoice_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class ApplicationUserTopicId1770038768784 implements MigrationInterface {
|
||||||
|
name = 'ApplicationUserTopicId1770038768784'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_0a0dbb25a73306b037dec82251"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_application_user" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "identifier" varchar NOT NULL, "nostr_public_key" varchar, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "applicationSerialId" integer, "callback_url" varchar NOT NULL DEFAULT (''), "topic_id" varchar NOT NULL, CONSTRAINT "UQ_3175dc397c8285d1e532554dea5" UNIQUE ("nostr_public_key"), CONSTRAINT "REL_0796a381bcc624f52e9a155712" UNIQUE ("userSerialId"), CONSTRAINT "UQ_bd1a42f39fd7b4218bed5cc63d9" UNIQUE ("topic_id"), CONSTRAINT "FK_0796a381bcc624f52e9a155712b" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1b3bdb6f660cd99533a1e673ef1" FOREIGN KEY ("applicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_application_user"("serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url", "topic_id") SELECT "serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url", lower(hex(randomblob(32))) FROM "application_user"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "application_user"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_application_user" RENAME TO "application_user"`);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0a0dbb25a73306b037dec82251" ON "application_user" ("identifier") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_0a0dbb25a73306b037dec82251"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "application_user" RENAME TO "temporary_application_user"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "application_user" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "identifier" varchar NOT NULL, "nostr_public_key" varchar, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "applicationSerialId" integer, "callback_url" varchar NOT NULL DEFAULT (''), CONSTRAINT "UQ_3175dc397c8285d1e532554dea5" UNIQUE ("nostr_public_key"), CONSTRAINT "REL_0796a381bcc624f52e9a155712" UNIQUE ("userSerialId"), CONSTRAINT "FK_0796a381bcc624f52e9a155712b" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1b3bdb6f660cd99533a1e673ef1" FOREIGN KEY ("applicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "application_user"("serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url") SELECT "serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url" FROM "temporary_application_user"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_application_user"`);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0a0dbb25a73306b037dec82251" ON "application_user" ("identifier") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class SwapTimestamps1771347307798 implements MigrationInterface {
|
||||||
|
name = 'SwapTimestamps1771347307798'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex" FROM "invoice_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "invoice_swap"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_invoice_swap" RENAME TO "invoice_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "invoice_swap" RENAME TO "temporary_invoice_swap"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex" FROM "temporary_invoice_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_invoice_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class RootOpPending1771524665409 implements MigrationInterface {
|
||||||
|
name = 'RootOpPending1771524665409'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_root_operation" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "operation_type" varchar NOT NULL, "operation_amount" integer NOT NULL, "operation_identifier" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "at_unix" integer NOT NULL DEFAULT (0), "pending" boolean NOT NULL DEFAULT (0))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_root_operation"("serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix") SELECT "serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix" FROM "root_operation"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "root_operation"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_root_operation" RENAME TO "root_operation"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "root_operation" RENAME TO "temporary_root_operation"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "root_operation" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "operation_type" varchar NOT NULL, "operation_amount" integer NOT NULL, "operation_identifier" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "at_unix" integer NOT NULL DEFAULT (0))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "root_operation"("serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix") SELECT "serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix" FROM "temporary_root_operation"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_root_operation"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class TxSwapTimestamps1771878683383 implements MigrationInterface {
|
||||||
|
name = 'TxSwapTimestamps1771878683383'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_transaction_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "lockup_address" varchar NOT NULL, "refund_public_key" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "preimage" varchar NOT NULL, "ephemeral_public_key" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "address_paid" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_transaction_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url" FROM "transaction_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "transaction_swap"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_transaction_swap" RENAME TO "transaction_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "transaction_swap" RENAME TO "temporary_transaction_swap"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "transaction_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "lockup_address" varchar NOT NULL, "refund_public_key" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "preimage" varchar NOT NULL, "ephemeral_public_key" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "address_paid" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "transaction_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url" FROM "temporary_transaction_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_transaction_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class RefundSwapInfo1773082318982 implements MigrationInterface {
|
||||||
|
name = 'RefundSwapInfo1773082318982'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0), "refund_address" varchar NOT NULL DEFAULT (''), "refund_at_unix" integer NOT NULL DEFAULT (''), "refund_tx_id" varchar NOT NULL DEFAULT (''))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix" FROM "invoice_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "invoice_swap"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_invoice_swap" RENAME TO "invoice_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "invoice_swap" RENAME TO "temporary_invoice_swap"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0))`);
|
||||||
|
await queryRunner.query(`INSERT INTO "invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix" FROM "temporary_invoice_swap"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_invoice_swap"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,21 @@
|
||||||
import { Initial1703170309875 } from './1703170309875-initial.js'
|
import { Initial1703170309875 } from './1703170309875-initial.js'
|
||||||
import { LndMetrics1703170330183 } from './1703170330183-lnd_metrics.js'
|
|
||||||
import { ChannelRouting1709316653538 } from './1709316653538-channel_routing.js'
|
|
||||||
import { LspOrder1718387847693 } from './1718387847693-lsp_order.js'
|
import { LspOrder1718387847693 } from './1718387847693-lsp_order.js'
|
||||||
import { LiquidityProvider1719335699480 } from './1719335699480-liquidity_provider.js'
|
import { LiquidityProvider1719335699480 } from './1719335699480-liquidity_provider.js'
|
||||||
import { LndNodeInfo1720187506189 } from './1720187506189-lnd_node_info.js'
|
import { LndNodeInfo1720187506189 } from './1720187506189-lnd_node_info.js'
|
||||||
import { TrackedProvider1720814323679 } from './1720814323679-tracked_provider.js'
|
import { TrackedProvider1720814323679 } from './1720814323679-tracked_provider.js'
|
||||||
import { CreateInviteTokenTable1721751414878 } from "./1721751414878-create_invite_token_table.js"
|
import { CreateInviteTokenTable1721751414878 } from "./1721751414878-create_invite_token_table.js"
|
||||||
import { PaymentIndex1721760297610 } from './1721760297610-payment_index.js'
|
import { PaymentIndex1721760297610 } from './1721760297610-payment_index.js'
|
||||||
import { HtlcCount1724266887195 } from './1724266887195-htlc_count.js'
|
|
||||||
import { BalanceEvents1724860966825 } from './1724860966825-balance_events.js'
|
|
||||||
import { DebitAccess1726496225078 } from './1726496225078-debit_access.js'
|
import { DebitAccess1726496225078 } from './1726496225078-debit_access.js'
|
||||||
import { DebitAccessFixes1726685229264 } from './1726685229264-debit_access_fixes.js'
|
import { DebitAccessFixes1726685229264 } from './1726685229264-debit_access_fixes.js'
|
||||||
import { DebitToPub1727105758354 } from './1727105758354-debit_to_pub.js'
|
import { DebitToPub1727105758354 } from './1727105758354-debit_to_pub.js'
|
||||||
import { UserCbUrl1727112281043 } from './1727112281043-user_cb_url.js'
|
import { UserCbUrl1727112281043 } from './1727112281043-user_cb_url.js'
|
||||||
import { RootOps1732566440447 } from './1732566440447-root_ops.js'
|
|
||||||
import { UserOffer1733502626042 } from './1733502626042-user_offer.js'
|
import { UserOffer1733502626042 } from './1733502626042-user_offer.js'
|
||||||
import { RootOpsTime1745428134124 } from './1745428134124-root_ops_time.js'
|
|
||||||
import { ChannelEvents1750777346411 } from './1750777346411-channel_events.js'
|
|
||||||
import { ManagementGrant1751307732346 } from './1751307732346-management_grant.js'
|
import { ManagementGrant1751307732346 } from './1751307732346-management_grant.js'
|
||||||
import { ManagementGrantBanned1751989251513 } from './1751989251513-management_grant_banned.js'
|
import { ManagementGrantBanned1751989251513 } from './1751989251513-management_grant_banned.js'
|
||||||
import { InvoiceCallbackUrls1752425992291 } from './1752425992291-invoice_callback_urls.js'
|
import { InvoiceCallbackUrls1752425992291 } from './1752425992291-invoice_callback_urls.js'
|
||||||
import { AppUserDevice1753285173175 } from './1753285173175-app_user_device.js'
|
|
||||||
import { OldSomethingLeftover1753106599604 } from './1753106599604-old_something_leftover.js'
|
import { OldSomethingLeftover1753106599604 } from './1753106599604-old_something_leftover.js'
|
||||||
import { UserReceivingInvoiceIdx1753109184611 } from './1753109184611-user_receiving_invoice_idx.js'
|
import { UserReceivingInvoiceIdx1753109184611 } from './1753109184611-user_receiving_invoice_idx.js'
|
||||||
|
import { AppUserDevice1753285173175 } from './1753285173175-app_user_device.js'
|
||||||
import { UserAccess1759426050669 } from './1759426050669-user_access.js'
|
import { UserAccess1759426050669 } from './1759426050669-user_access.js'
|
||||||
import { AddBlindToUserOffer1760000000000 } from './1760000000000-add_blind_to_user_offer.js'
|
import { AddBlindToUserOffer1760000000000 } from './1760000000000-add_blind_to_user_offer.js'
|
||||||
import { ApplicationAvatarUrl1761000001000 } from './1761000001000-application_avatar_url.js'
|
import { ApplicationAvatarUrl1761000001000 } from './1761000001000-application_avatar_url.js'
|
||||||
|
|
@ -32,6 +25,24 @@ import { TxSwapAddress1764779178945 } from './1764779178945-tx_swap_address.js'
|
||||||
import { ClinkRequester1765497600000 } from './1765497600000-clink_requester.js'
|
import { ClinkRequester1765497600000 } from './1765497600000-clink_requester.js'
|
||||||
import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_provider_height.js'
|
import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_provider_height.js'
|
||||||
import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js'
|
import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js'
|
||||||
|
import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js'
|
||||||
|
import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fixes.js'
|
||||||
|
import { ApplicationUserTopicId1770038768784 } from './1770038768784-application_user_topic_id.js'
|
||||||
|
import { SwapTimestamps1771347307798 } from './1771347307798-swap_timestamps.js'
|
||||||
|
import { TxSwapTimestamps1771878683383 } from './1771878683383-tx_swap_timestamps.js'
|
||||||
|
import { RefundSwapInfo1773082318982 } from './1773082318982-refund_swap_info.js'
|
||||||
|
|
||||||
|
import { LndMetrics1703170330183 } from './1703170330183-lnd_metrics.js'
|
||||||
|
import { ChannelRouting1709316653538 } from './1709316653538-channel_routing.js'
|
||||||
|
import { HtlcCount1724266887195 } from './1724266887195-htlc_count.js'
|
||||||
|
import { BalanceEvents1724860966825 } from './1724860966825-balance_events.js'
|
||||||
|
import { RootOps1732566440447 } from './1732566440447-root_ops.js'
|
||||||
|
import { RootOpsTime1745428134124 } from './1745428134124-root_ops_time.js'
|
||||||
|
import { ChannelEvents1750777346411 } from './1750777346411-channel_events.js'
|
||||||
|
|
||||||
|
import { RootOpPending1771524665409 } from './1771524665409-root_op_pending.js'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189,
|
export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189,
|
||||||
|
|
@ -39,9 +50,13 @@ export const allMigrations = [Initial1703170309875, LspOrder1718387847693, Liqui
|
||||||
DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513,
|
DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513,
|
||||||
InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175,
|
InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175,
|
||||||
UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098,
|
UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098,
|
||||||
TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036]
|
TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036,
|
||||||
|
InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798,
|
||||||
|
TxSwapTimestamps1771878683383, RefundSwapInfo1773082318982]
|
||||||
|
|
||||||
export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411]
|
|
||||||
|
export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825,
|
||||||
|
RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411, RootOpPending1771524665409]
|
||||||
/* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
|
/* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
|
||||||
await connectAndMigrate(log, storageManager, allMigrations, allMetricsMigrations)
|
await connectAndMigrate(log, storageManager, allMigrations, allMetricsMigrations)
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import TransactionsQueue from "./db/transactionsQueue.js";
|
||||||
import { LoggedEvent } from './eventsLog.js';
|
import { LoggedEvent } from './eventsLog.js';
|
||||||
import { StorageInterface } from './db/storageInterface.js';
|
import { StorageInterface } from './db/storageInterface.js';
|
||||||
import { TransactionSwap } from './entity/TransactionSwap.js';
|
import { TransactionSwap } from './entity/TransactionSwap.js';
|
||||||
|
import { InvoiceSwap } from './entity/InvoiceSwap.js';
|
||||||
export type InboundOptionals = { product?: Product, callbackUrl?: string, expiry: number, expectedPayer?: User, linkedApplication?: Application, zapInfo?: ZapInfo, offerId?: string, payerData?: Record<string, string>, rejectUnauthorized?: boolean, token?: string, blind?: boolean, clinkRequesterPub?: string, clinkRequesterEventId?: string }
|
export type InboundOptionals = { product?: Product, callbackUrl?: string, expiry: number, expectedPayer?: User, linkedApplication?: Application, zapInfo?: ZapInfo, offerId?: string, payerData?: Record<string, string>, rejectUnauthorized?: boolean, token?: string, blind?: boolean, clinkRequesterPub?: string, clinkRequesterEventId?: string }
|
||||||
export const defaultInvoiceExpiry = 60 * 60
|
export const defaultInvoiceExpiry = 60 * 60
|
||||||
export default class {
|
export default class {
|
||||||
|
|
@ -137,7 +138,15 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async RemoveUserInvoices(userId: string, txId?: string) {
|
async RemoveUserInvoices(userId: string, txId?: string) {
|
||||||
return this.dbs.Delete<UserReceivingInvoice>('UserReceivingInvoice', { user: { user_id: userId } }, txId)
|
const invoices = await this.dbs.Find<UserReceivingInvoice>('UserReceivingInvoice', { where: { user: { user_id: userId } } }, txId)
|
||||||
|
if (invoices.length === 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let deleted = 0
|
||||||
|
for (const invoice of invoices) {
|
||||||
|
deleted += await this.dbs.Delete<UserReceivingInvoice>('UserReceivingInvoice', invoice.serial_id, txId)
|
||||||
|
}
|
||||||
|
return deleted
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetAddressOwner(address: string, txId?: string): Promise<UserReceivingAddress | null> {
|
async GetAddressOwner(address: string, txId?: string): Promise<UserReceivingAddress | null> {
|
||||||
|
|
@ -151,6 +160,10 @@ export default class {
|
||||||
return this.dbs.FindOne<UserTransactionPayment>('UserTransactionPayment', { where: { address, tx_hash: txHash } }, txId)
|
return this.dbs.FindOne<UserTransactionPayment>('UserTransactionPayment', { where: { address, tx_hash: txHash } }, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async GetTxHashPaymentOwner(txHash: string, txId?: string): Promise<UserTransactionPayment | null> {
|
||||||
|
return this.dbs.FindOne<UserTransactionPayment>('UserTransactionPayment', { where: { tx_hash: txHash } }, txId)
|
||||||
|
}
|
||||||
|
|
||||||
async GetInvoiceOwner(paymentRequest: string, txId?: string): Promise<UserReceivingInvoice | null> {
|
async GetInvoiceOwner(paymentRequest: string, txId?: string): Promise<UserReceivingInvoice | null> {
|
||||||
return this.dbs.FindOne<UserReceivingInvoice>('UserReceivingInvoice', { where: { invoice: paymentRequest } }, txId)
|
return this.dbs.FindOne<UserReceivingInvoice>('UserReceivingInvoice', { where: { invoice: paymentRequest } }, txId)
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +330,51 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async RemoveUserEphemeralKeys(userId: string, txId?: string) {
|
async RemoveUserEphemeralKeys(userId: string, txId?: string) {
|
||||||
return this.dbs.Delete<UserEphemeralKey>('UserEphemeralKey', { user: { user_id: userId } }, txId)
|
const keys = await this.dbs.Find<UserEphemeralKey>('UserEphemeralKey', { where: { user: { user_id: userId } } }, txId)
|
||||||
|
if (keys.length === 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let deleted = 0
|
||||||
|
for (const key of keys) {
|
||||||
|
deleted += await this.dbs.Delete<UserEphemeralKey>('UserEphemeralKey', key.serial_id, txId)
|
||||||
|
}
|
||||||
|
return deleted
|
||||||
|
}
|
||||||
|
|
||||||
|
async RemoveUserReceivingAddresses(userId: string, txId?: string) {
|
||||||
|
const addresses = await this.dbs.Find<UserReceivingAddress>('UserReceivingAddress', { where: { user: { user_id: userId } } }, txId)
|
||||||
|
for (const addr of addresses) {
|
||||||
|
const txs = await this.dbs.Find<AddressReceivingTransaction>('AddressReceivingTransaction', { where: { user_address: { serial_id: addr.serial_id } } }, txId)
|
||||||
|
for (const tx of txs) {
|
||||||
|
await this.dbs.Delete<AddressReceivingTransaction>('AddressReceivingTransaction', tx.serial_id, txId)
|
||||||
|
}
|
||||||
|
await this.dbs.Delete<UserReceivingAddress>('UserReceivingAddress', addr.serial_id, txId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async RemoveUserInvoicePayments(userId: string, txId?: string) {
|
||||||
|
const payments = await this.dbs.Find<UserInvoicePayment>('UserInvoicePayment', { where: { user: { user_id: userId } } }, txId)
|
||||||
|
for (const p of payments) {
|
||||||
|
await this.dbs.Delete<UserInvoicePayment>('UserInvoicePayment', p.serial_id, txId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async RemoveUserTransactionPayments(userId: string, txId?: string) {
|
||||||
|
const payments = await this.dbs.Find<UserTransactionPayment>('UserTransactionPayment', { where: { user: { user_id: userId } } }, txId)
|
||||||
|
for (const p of payments) {
|
||||||
|
await this.dbs.Delete<UserTransactionPayment>('UserTransactionPayment', p.serial_id, txId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async RemoveUserToUserPayments(userId: string, txId?: string) {
|
||||||
|
const asSender = await this.dbs.Find<UserToUserPayment>('UserToUserPayment', { where: { from_user: { user_id: userId } } }, txId)
|
||||||
|
const asReceiver = await this.dbs.Find<UserToUserPayment>('UserToUserPayment', { where: { to_user: { user_id: userId } } }, txId)
|
||||||
|
const seen = new Set<number>()
|
||||||
|
for (const p of [...asSender, ...asReceiver]) {
|
||||||
|
if (seen.has(p.serial_id)) continue
|
||||||
|
seen.add(p.serial_id)
|
||||||
|
await this.dbs.Delete<UserToUserPayment>('UserToUserPayment', p.serial_id, txId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddPendingUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, linkedApplication: Application, txId: string) {
|
async AddPendingUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, linkedApplication: Application, txId: string) {
|
||||||
|
|
@ -447,8 +504,12 @@ export default class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetTotalUsersBalance(txId?: string) {
|
async GetTotalUsersBalance(excludeLocked?: boolean, txId?: string) {
|
||||||
const total = await this.dbs.Sum<User>('User', "balance_sats", {})
|
const where: { locked?: boolean } = {}
|
||||||
|
if (excludeLocked) {
|
||||||
|
where.locked = false
|
||||||
|
}
|
||||||
|
const total = await this.dbs.Sum<User>('User', "balance_sats", where, txId)
|
||||||
return total || 0
|
return total || 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,20 +533,31 @@ export default class {
|
||||||
return this.dbs.FindOne<TransactionSwap>('TransactionSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId)
|
return this.dbs.FindOne<TransactionSwap>('TransactionSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async FinalizeTransactionSwap(swapOperationId: string, address: string, txId: string) {
|
async SetTransactionSwapPaid(swapOperationId: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
return this.dbs.Update<TransactionSwap>('TransactionSwap', { swap_operation_id: swapOperationId }, {
|
return this.dbs.Update<TransactionSwap>('TransactionSwap', { swap_operation_id: swapOperationId }, {
|
||||||
used: true,
|
paid_at_unix: now,
|
||||||
tx_id: txId,
|
}, txId)
|
||||||
address_paid: address,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async FailTransactionSwap(swapOperationId: string, address: string, failureReason: string) {
|
async FinalizeTransactionSwap(swapOperationId: string, address: string, chainTxId: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
|
return this.dbs.Update<TransactionSwap>('TransactionSwap', { swap_operation_id: swapOperationId }, {
|
||||||
|
used: true,
|
||||||
|
tx_id: chainTxId,
|
||||||
|
address_paid: address,
|
||||||
|
completed_at_unix: now,
|
||||||
|
}, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async FailTransactionSwap(swapOperationId: string, address: string, failureReason: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
return this.dbs.Update<TransactionSwap>('TransactionSwap', { swap_operation_id: swapOperationId }, {
|
return this.dbs.Update<TransactionSwap>('TransactionSwap', { swap_operation_id: swapOperationId }, {
|
||||||
used: true,
|
used: true,
|
||||||
failure_reason: failureReason,
|
failure_reason: failureReason,
|
||||||
address_paid: address,
|
address_paid: address,
|
||||||
})
|
completed_at_unix: now,
|
||||||
|
}, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async DeleteTransactionSwap(swapOperationId: string, txId?: string) {
|
async DeleteTransactionSwap(swapOperationId: string, txId?: string) {
|
||||||
|
|
@ -493,18 +565,18 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async DeleteExpiredTransactionSwaps(currentHeight: number, txId?: string) {
|
async DeleteExpiredTransactionSwaps(currentHeight: number, txId?: string) {
|
||||||
return this.dbs.Delete<TransactionSwap>('TransactionSwap', { timeout_block_height: LessThan(currentHeight) }, txId)
|
return this.dbs.Delete<TransactionSwap>('TransactionSwap', { timeout_block_height: LessThan(currentHeight), used: false }, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListPendingTransactionSwaps(appUserId: string, txId?: string) {
|
async ListPendingTransactionSwaps(appUserId: string, txId?: string) {
|
||||||
return this.dbs.Find<TransactionSwap>('TransactionSwap', { where: { used: false, app_user_id: appUserId } }, txId)
|
return this.dbs.Find<TransactionSwap>('TransactionSwap', { where: { used: false, app_user_id: appUserId } }, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListSwapPayments(userId: string, txId?: string) {
|
async ListTxSwapPayments(userId: string, txId?: string) {
|
||||||
return this.dbs.Find<UserInvoicePayment>('UserInvoicePayment', { where: { swap_operation_id: Not(IsNull()), user: { user_id: userId } } }, txId)
|
return this.dbs.Find<UserInvoicePayment>('UserInvoicePayment', { where: { swap_operation_id: Not(IsNull()), user: { user_id: userId } } }, txId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async ListCompletedSwaps(appUserId: string, payments: UserInvoicePayment[], txId?: string) {
|
async ListCompletedTxSwaps(appUserId: string, payments: UserInvoicePayment[], txId?: string) {
|
||||||
const completed = await this.dbs.Find<TransactionSwap>('TransactionSwap', { where: { used: true, app_user_id: appUserId } }, txId)
|
const completed = await this.dbs.Find<TransactionSwap>('TransactionSwap', { where: { used: true, app_user_id: appUserId } }, txId)
|
||||||
// const payments = await this.dbs.Find<UserInvoicePayment>('UserInvoicePayment', { where: { swap_operation_id: Not(IsNull()), } }, txId)
|
// const payments = await this.dbs.Find<UserInvoicePayment>('UserInvoicePayment', { where: { swap_operation_id: Not(IsNull()), } }, txId)
|
||||||
const paymentsMap = new Map<string, UserInvoicePayment>()
|
const paymentsMap = new Map<string, UserInvoicePayment>()
|
||||||
|
|
@ -515,6 +587,94 @@ export default class {
|
||||||
swap: c, payment: paymentsMap.get(c.swap_operation_id)
|
swap: c, payment: paymentsMap.get(c.swap_operation_id)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async AddInvoiceSwap(swap: Partial<InvoiceSwap>) {
|
||||||
|
return this.dbs.CreateAndSave<InvoiceSwap>('InvoiceSwap', swap)
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetInvoiceSwap(swapOperationId: string, appUserId: string, txId?: string) {
|
||||||
|
const swap = await this.dbs.FindOne<InvoiceSwap>('InvoiceSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId)
|
||||||
|
if (!swap || swap.tx_id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return swap
|
||||||
|
}
|
||||||
|
|
||||||
|
async FinalizeInvoiceSwap(swapOperationId: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
|
return this.dbs.Update<InvoiceSwap>('InvoiceSwap', { swap_operation_id: swapOperationId }, {
|
||||||
|
used: true,
|
||||||
|
completed_at_unix: now,
|
||||||
|
}, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async UpdateInvoiceSwap(swapOperationId: string, update: Partial<InvoiceSwap>, txId?: string) {
|
||||||
|
return this.dbs.Update<InvoiceSwap>('InvoiceSwap', { swap_operation_id: swapOperationId }, update, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, chainFeeSats: number, lockupTxHex?: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
|
const update: Partial<InvoiceSwap> = {
|
||||||
|
tx_id: chainTxId,
|
||||||
|
paid_at_unix: now,
|
||||||
|
chain_fee_sats: chainFeeSats,
|
||||||
|
}
|
||||||
|
if (lockupTxHex) {
|
||||||
|
update.lockup_tx_hex = lockupTxHex
|
||||||
|
}
|
||||||
|
return this.dbs.Update<InvoiceSwap>('InvoiceSwap', { swap_operation_id: swapOperationId }, update, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async FailInvoiceSwap(swapOperationId: string, failureReason: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
|
return this.dbs.Update<InvoiceSwap>('InvoiceSwap', { swap_operation_id: swapOperationId }, {
|
||||||
|
used: true,
|
||||||
|
failure_reason: failureReason,
|
||||||
|
completed_at_unix: now,
|
||||||
|
}, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async DeleteInvoiceSwap(swapOperationId: string, txId?: string) {
|
||||||
|
return this.dbs.Delete<InvoiceSwap>('InvoiceSwap', { swap_operation_id: swapOperationId }, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async DeleteExpiredInvoiceSwaps(currentHeight: number, txId?: string) {
|
||||||
|
return this.dbs.Delete<InvoiceSwap>('InvoiceSwap', { timeout_block_height: LessThan(currentHeight), used: false, tx_id: "" }, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async ListCompletedInvoiceSwaps(appUserId: string, txId?: string) {
|
||||||
|
return this.dbs.Find<InvoiceSwap>('InvoiceSwap', { where: { used: true, app_user_id: appUserId } }, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async ListPendingInvoiceSwaps(appUserId: string, txId?: string) {
|
||||||
|
return this.dbs.Find<InvoiceSwap>('InvoiceSwap', { where: { used: false, app_user_id: appUserId } }, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async ListUnfinishedInvoiceSwaps(txId?: string) {
|
||||||
|
const swaps = await this.dbs.Find<InvoiceSwap>('InvoiceSwap', { where: { used: false } }, txId)
|
||||||
|
return swaps.filter(s => !!s.tx_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
async UpdateRefundInvoiceSwap(swapOperationId: string, refundAddress: string, refundTxId: string, txId?: string) {
|
||||||
|
const now = Math.floor(Date.now() / 1000)
|
||||||
|
return this.dbs.Update<InvoiceSwap>('InvoiceSwap', { swap_operation_id: swapOperationId }, {
|
||||||
|
refund_address: refundAddress,
|
||||||
|
refund_at_unix: now,
|
||||||
|
refund_tx_id: refundTxId,
|
||||||
|
}, txId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetRefundableInvoiceSwap(swapOperationId: string, txId?: string) {
|
||||||
|
const swap = await this.dbs.FindOne<InvoiceSwap>('InvoiceSwap', { where: { swap_operation_id: swapOperationId } }, txId)
|
||||||
|
if (!swap || !swap.tx_id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (swap.used && !swap.failure_reason) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return swap
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const orFail = async <T>(resultPromise: Promise<T | null>) => {
|
const orFail = async <T>(resultPromise: Promise<T | null>) => {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,14 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async RemoveUserProducts(userId: string, txId?: string) {
|
async RemoveUserProducts(userId: string, txId?: string) {
|
||||||
return this.dbs.Delete<Product>('Product', { owner: { user_id: userId } }, txId)
|
const products = await this.dbs.Find<Product>('Product', { where: { owner: { user_id: userId } } }, txId)
|
||||||
|
if (products.length === 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let deleted = 0
|
||||||
|
for (const product of products) {
|
||||||
|
deleted += await this.dbs.Delete<Product>('Product', { product_id: product.product_id }, txId)
|
||||||
|
}
|
||||||
|
return deleted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,13 +53,13 @@ export class TlvStorageFactory extends EventEmitter {
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.process.on('exit', (code: number) => {
|
this.process.on('exit', (code: number, signal: string) => {
|
||||||
this.log(ERROR, `Tlv Storage processor exited with code ${code}`);
|
this.log(ERROR, `Tlv Storage processor exited with code ${code} and signal ${signal}`);
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
if (!code) {
|
if (code === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error(`Tlv Storage processor exited with code ${code}`)
|
throw new Error(`Tlv Storage processor exited with code ${code} and signal ${signal}`)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.isConnected = true;
|
this.isConnected = true;
|
||||||
|
|
@ -173,7 +173,7 @@ export class TlvStorageFactory extends EventEmitter {
|
||||||
|
|
||||||
public disconnect() {
|
public disconnect() {
|
||||||
if (this.process) {
|
if (this.process) {
|
||||||
this.process.kill();
|
this.process.kill(0);
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
this.debug = false;
|
this.debug = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ class TlvFilesStorageProcessor {
|
||||||
throw new Error('Unknown metric type: ' + t)
|
throw new Error('Unknown metric type: ' + t)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.wrtc.attachNostrSend((initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => {
|
this.wrtc.attachNostrSend(async (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => {
|
||||||
this.sendResponse({
|
this.sendResponse({
|
||||||
success: true,
|
success: true,
|
||||||
type: 'nostrSend',
|
type: 'nostrSend',
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export default class {
|
||||||
async GetUser(userId: string, txId?: string): Promise<User> {
|
async GetUser(userId: string, txId?: string): Promise<User> {
|
||||||
const user = await this.FindUser(userId, txId)
|
const user = await this.FindUser(userId, txId)
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error(`user ${userId} not found`) // TODO: fix logs doxing
|
throw new Error(`user not found`)
|
||||||
}
|
}
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ export default class {
|
||||||
async UnbanUser(userId: string, txId?: string) {
|
async UnbanUser(userId: string, txId?: string) {
|
||||||
const affected = await this.dbs.Update<User>('User', { user_id: userId }, { locked: false }, txId)
|
const affected = await this.dbs.Update<User>('User', { user_id: userId }, { locked: false }, txId)
|
||||||
if (!affected) {
|
if (!affected) {
|
||||||
throw new Error("unaffected user unlock for " + userId) // TODO: fix logs doxing
|
throw new Error("unaffected user unlock")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ export default class {
|
||||||
const user = await this.GetUser(userId, txId)
|
const user = await this.GetUser(userId, txId)
|
||||||
const affected = await this.dbs.Update<User>('User', { user_id: userId }, { balance_sats: 0, locked: true }, txId)
|
const affected = await this.dbs.Update<User>('User', { user_id: userId }, { balance_sats: 0, locked: true }, txId)
|
||||||
if (!affected) {
|
if (!affected) {
|
||||||
throw new Error("unaffected ban user for " + userId) // TODO: fix logs doxing
|
throw new Error("unaffected ban user")
|
||||||
}
|
}
|
||||||
if (user.balance_sats > 0) {
|
if (user.balance_sats > 0) {
|
||||||
this.eventsLog.LogEvent({ type: 'balance_decrement', userId, appId: "", appUserId: "", balance: user.balance_sats, data: 'ban', amount: user.balance_sats })
|
this.eventsLog.LogEvent({ type: 'balance_decrement', userId, appId: "", appUserId: "", balance: user.balance_sats, data: 'ban', amount: user.balance_sats })
|
||||||
|
|
@ -80,7 +80,7 @@ export default class {
|
||||||
const affected = await this.dbs.Increment<User>('User', { user_id: userId }, "balance_sats", increment, txId)
|
const affected = await this.dbs.Increment<User>('User', { user_id: userId }, "balance_sats", increment, txId)
|
||||||
if (!affected) {
|
if (!affected) {
|
||||||
getLogger({ userId: userId, component: "balanceUpdates" })("user unaffected by increment")
|
getLogger({ userId: userId, component: "balanceUpdates" })("user unaffected by increment")
|
||||||
throw new Error("unaffected balance increment for " + userId) // TODO: fix logs doxing
|
throw new Error("unaffected balance increment")
|
||||||
}
|
}
|
||||||
getLogger({ userId: userId, component: "balanceUpdates" })("incremented balance from", user.balance_sats, "sats, by", increment, "sats")
|
getLogger({ userId: userId, component: "balanceUpdates" })("incremented balance from", user.balance_sats, "sats, by", increment, "sats")
|
||||||
this.eventsLog.LogEvent({ type: 'balance_increment', userId, appId: "", appUserId: "", balance: user.balance_sats, data: reason, amount: increment })
|
this.eventsLog.LogEvent({ type: 'balance_increment', userId, appId: "", appUserId: "", balance: user.balance_sats, data: reason, amount: increment })
|
||||||
|
|
@ -105,7 +105,7 @@ export default class {
|
||||||
const affected = await this.dbs.Decrement<User>('User', { user_id: userId }, "balance_sats", decrement, txId)
|
const affected = await this.dbs.Decrement<User>('User', { user_id: userId }, "balance_sats", decrement, txId)
|
||||||
if (!affected) {
|
if (!affected) {
|
||||||
getLogger({ userId: userId, component: "balanceUpdates" })("user unaffected by decrement")
|
getLogger({ userId: userId, component: "balanceUpdates" })("user unaffected by decrement")
|
||||||
throw new Error("unaffected balance decrement for " + userId) // TODO: fix logs doxing
|
throw new Error("unaffected balance decrement")
|
||||||
}
|
}
|
||||||
getLogger({ userId: userId, component: "balanceUpdates" })("decremented balance from", user.balance_sats, "sats, by", decrement, "sats")
|
getLogger({ userId: userId, component: "balanceUpdates" })("decremented balance from", user.balance_sats, "sats, by", decrement, "sats")
|
||||||
this.eventsLog.LogEvent({ type: 'balance_decrement', userId, appId: "", appUserId: "", balance: user.balance_sats, data: reason, amount: decrement })
|
this.eventsLog.LogEvent({ type: 'balance_decrement', userId, appId: "", appUserId: "", balance: user.balance_sats, data: reason, amount: decrement })
|
||||||
|
|
@ -126,4 +126,8 @@ export default class {
|
||||||
const lastSeenAtUnix = now - seconds
|
const lastSeenAtUnix = now - seconds
|
||||||
return this.dbs.Find<UserAccess>('UserAccess', { where: { last_seen_at_unix: LessThan(lastSeenAtUnix) } })
|
return this.dbs.Find<UserAccess>('UserAccess', { where: { last_seen_at_unix: LessThan(lastSeenAtUnix) } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async DeleteUserAccess(userId: string, txId?: string) {
|
||||||
|
return this.dbs.Delete<UserAccess>('UserAccess', { user_id: userId }, txId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,11 +27,11 @@ export default class webRTC {
|
||||||
attachNostrSend(f: NostrSend) {
|
attachNostrSend(f: NostrSend) {
|
||||||
this._nostrSend = f
|
this._nostrSend = f
|
||||||
}
|
}
|
||||||
private nostrSend: NostrSend = (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => {
|
private nostrSend: NostrSend = async (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => {
|
||||||
if (!this._nostrSend) {
|
if (!this._nostrSend) {
|
||||||
throw new Error("No nostrSend attached")
|
throw new Error("No nostrSend attached")
|
||||||
}
|
}
|
||||||
this._nostrSend(initiator, data, relays)
|
await this._nostrSend(initiator, data, relays)
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendCandidate = (u: WebRtcUserInfo, candidate: string) => {
|
private sendCandidate = (u: WebRtcUserInfo, candidate: string) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue