pending txs

This commit is contained in:
boufni95 2023-11-24 22:38:37 +01:00
parent dcb68d0069
commit 6c219c6f62
17 changed files with 3445 additions and 2161 deletions

View file

@ -374,51 +374,24 @@ The nostr server will send back a message response, and inside the body there wi
## Messages
### The content of requests and response from the methods
### AddAppUserRequest
- __identifier__: _string_
- __fail_if_exists__: _boolean_
- __balance__: _number_
### NewAddressResponse
- __address__: _string_
### HandleLnurlPayResponse
- __pr__: _string_
- __routes__: ARRAY of: _[Empty](#Empty)_
### Application
- __name__: _string_
- __id__: _string_
- __balance__: _number_
- __npub__: _string_
### GetAppUserLNURLInfoRequest
- __user_identifier__: _string_
- __base_url_override__: _string_
### NewAddressRequest
- __addressType__: _[AddressType](#AddressType)_
### Product
- __id__: _string_
- __name__: _string_
- __price_sats__: _number_
### GetProductBuyLinkResponse
- __link__: _string_
### OpenChannelRequest
- __destination__: _string_
- __fundingAmount__: _number_
- __pushAmount__: _number_
- __closeAddress__: _string_
### UserOperation
- __paidAtUnix__: _number_
- __type__: _[UserOperationType](#UserOperationType)_
- __inbound__: _boolean_
- __amount__: _number_
- __identifier__: _string_
- __operationId__: _string_
- __service_fee__: _number_
- __network_fee__: _number_
### EncryptionExchangeRequest
- __publicKey__: _string_
- __deviceId__: _string_
### AuthApp
- __app__: _[Application](#Application)_
- __auth_token__: _string_
### AppUser
- __identifier__: _string_
- __info__: _[UserInfo](#UserInfo)_
@ -430,68 +403,38 @@ The nostr server will send back a message response, and inside the body there wi
- __http_callback_url__: _string_
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
### SendAppUserToAppPaymentRequest
- __from_user_identifier__: _string_
- __amount__: _number_
### DecodeInvoiceRequest
- __invoice__: _string_
### LndGetInfoRequest
- __nodeId__: _number_
### PayAddressResponse
- __txId__: _string_
- __operation_id__: _string_
- __service_fee__: _number_
- __network_fee__: _number_
### AddAppRequest
- __name__: _string_
- __allow_user_creation__: _boolean_
### GetAppUserRequest
- __user_identifier__: _string_
### NewInvoiceResponse
- __invoice__: _string_
### SetMockInvoiceAsPaidRequest
- __invoice__: _string_
- __amount__: _number_
### NewInvoiceRequest
- __amountSats__: _number_
- __memo__: _string_
### GetAppUserRequest
- __user_identifier__: _string_
### HandleLnurlPayResponse
- __pr__: _string_
- __routes__: ARRAY of: _[Empty](#Empty)_
### AddAppInvoiceRequest
- __payer_identifier__: _string_
- __http_callback_url__: _string_
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
### PayAddressRequest
- __address__: _string_
- __amoutSats__: _number_
- __satsPerVByte__: _number_
### PayInvoiceRequest
- __invoice__: _string_
### DecodeInvoiceResponse
- __amount__: _number_
### UserOperations
- __fromIndex__: _number_
- __toIndex__: _number_
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
### PayInvoiceResponse
- __preimage__: _string_
- __amount_paid__: _number_
- __operation_id__: _string_
- __service_fee__: _number_
- __network_fee__: _number_
### AddAppUserRequest
- __identifier__: _string_
- __fail_if_exists__: _boolean_
- __balance__: _number_
### OpenChannelResponse
- __channelId__: _string_
### LnurlLinkResponse
- __lnurl__: _string_
- __k1__: _string_
### OpenChannelRequest
- __destination__: _string_
- __fundingAmount__: _number_
- __pushAmount__: _number_
- __closeAddress__: _string_
### LnurlWithdrawInfoResponse
- __tag__: _string_
@ -503,6 +446,71 @@ The nostr server will send back a message response, and inside the body there wi
- __balanceCheck__: _string_
- __payLink__: _string_
### GetUserOperationsResponse
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
- __latestIncomingInvoiceOperations__: _[UserOperations](#UserOperations)_
- __latestOutgoingTxOperations__: _[UserOperations](#UserOperations)_
- __latestIncomingTxOperations__: _[UserOperations](#UserOperations)_
- __latestOutgoingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
- __latestIncomingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
### EncryptionExchangeRequest
- __publicKey__: _string_
- __deviceId__: _string_
### GetProductBuyLinkResponse
- __link__: _string_
### Product
- __id__: _string_
- __name__: _string_
- __price_sats__: _number_
### DecodeInvoiceRequest
- __invoice__: _string_
### UserOperation
- __paidAtUnix__: _number_
- __type__: _[UserOperationType](#UserOperationType)_
- __inbound__: _boolean_
- __amount__: _number_
- __identifier__: _string_
- __operationId__: _string_
- __service_fee__: _number_
- __network_fee__: _number_
- __confirmed__: _boolean_
### AddProductRequest
- __name__: _string_
- __price_sats__: _number_
### SetMockAppUserBalanceRequest
- __user_identifier__: _string_
- __amount__: _number_
### SendAppUserToAppUserPaymentRequest
- __from_user_identifier__: _string_
- __to_user_identifier__: _string_
- __amount__: _number_
### LndGetInfoRequest
- __nodeId__: _number_
### NewInvoiceRequest
- __amountSats__: _number_
- __memo__: _string_
### PayInvoiceRequest
- __invoice__: _string_
- __amount__: _number_
### OpenChannelResponse
- __channelId__: _string_
### LnurlLinkResponse
- __lnurl__: _string_
- __k1__: _string_
### LnurlPayInfoResponse
- __tag__: _string_
- __callback__: _string_
@ -517,53 +525,55 @@ The nostr server will send back a message response, and inside the body there wi
- __balance__: _number_
- __max_withdrawable__: _number_
### PayAddressResponse
- __txId__: _string_
- __operation_id__: _string_
- __service_fee__: _number_
- __network_fee__: _number_
### UserOperations
- __fromIndex__: _number_
- __toIndex__: _number_
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
### DecodeInvoiceResponse
- __amount__: _number_
### LndGetInfoResponse
- __alias__: _string_
### AuthAppRequest
- __name__: _string_
- __allow_user_creation__: _boolean_ *this field is optional
### SendAppUserToAppUserPaymentRequest
- __from_user_identifier__: _string_
- __to_user_identifier__: _string_
- __amount__: _number_
### SetMockAppUserBalanceRequest
- __user_identifier__: _string_
- __amount__: _number_
### SetMockAppBalanceRequest
- __amount__: _number_
### NewAddressResponse
- __address__: _string_
### Empty
### LiveUserOperation
- __operation__: _[UserOperation](#UserOperation)_
### Empty
### SendAppUserToAppPaymentRequest
- __from_user_identifier__: _string_
- __amount__: _number_
### GetAppUserLNURLInfoRequest
- __user_identifier__: _string_
- __base_url_override__: _string_
### PayAddressRequest
- __address__: _string_
- __amoutSats__: _number_
- __satsPerVByte__: _number_
### NewInvoiceResponse
- __invoice__: _string_
### PayAppUserInvoiceRequest
- __user_identifier__: _string_
- __invoice__: _string_
- __amount__: _number_
### PayInvoiceResponse
- __preimage__: _string_
- __amount_paid__: _number_
- __operation_id__: _string_
- __service_fee__: _number_
- __network_fee__: _number_
### AuthAppRequest
- __name__: _string_
- __allow_user_creation__: _boolean_ *this field is optional
### AuthApp
- __app__: _[Application](#Application)_
- __auth_token__: _string_
### AddAppInvoiceRequest
- __payer_identifier__: _string_
- __http_callback_url__: _string_
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
### SetMockAppBalanceRequest
- __amount__: _number_
### NewAddressRequest
- __addressType__: _[AddressType](#AddressType)_
### GetUserOperationsRequest
- __latestIncomingInvoice__: _number_
@ -573,17 +583,8 @@ The nostr server will send back a message response, and inside the body there wi
- __latestIncomingUserToUserPayment__: _number_
- __latestOutgoingUserToUserPayment__: _number_
### GetUserOperationsResponse
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
- __latestIncomingInvoiceOperations__: _[UserOperations](#UserOperations)_
- __latestOutgoingTxOperations__: _[UserOperations](#UserOperations)_
- __latestIncomingTxOperations__: _[UserOperations](#UserOperations)_
- __latestOutgoingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
- __latestIncomingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
### AddProductRequest
- __name__: _string_
- __price_sats__: _number_
### LndGetInfoResponse
- __alias__: _string_
## Enums
### The enumerators used in the messages

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
// @generated by protobuf-ts 2.8.1
// @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3)
// tslint:disable
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
import { ChainNotifier } from "./chainnotifier.js";
import type { BlockEpoch } from "./chainnotifier.js";
import type { SpendEvent } from "./chainnotifier.js";
import type { SpendRequest } from "./chainnotifier.js";
import { stackIntercept } from "@protobuf-ts/runtime-rpc";
import type { ConfEvent } from "./chainnotifier.js";
import type { ConfRequest } from "./chainnotifier.js";
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
/**
* ChainNotifier is a service that can be used to get information about the
* chain backend by registering notifiers for chain events.
*
* @generated from protobuf service chainrpc.ChainNotifier
*/
export interface IChainNotifierClient {
/**
*
* RegisterConfirmationsNtfn is a synchronous response-streaming RPC that
* registers an intent for a client to be notified once a confirmation request
* has reached its required number of confirmations on-chain.
*
* A confirmation request must have a valid output script. It is also possible
* to give a transaction ID. If the transaction ID is not set, a notification
* is sent once the output script confirms. If the transaction ID is also set,
* a notification is sent once the output script confirms in the given
* transaction.
*
* @generated from protobuf rpc: RegisterConfirmationsNtfn(chainrpc.ConfRequest) returns (stream chainrpc.ConfEvent);
*/
registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall<ConfRequest, ConfEvent>;
/**
*
* RegisterSpendNtfn is a synchronous response-streaming RPC that registers an
* intent for a client to be notification once a spend request has been spent
* by a transaction that has confirmed on-chain.
*
* A client can specify whether the spend request should be for a particular
* outpoint or for an output script by specifying a zero outpoint.
*
* @generated from protobuf rpc: RegisterSpendNtfn(chainrpc.SpendRequest) returns (stream chainrpc.SpendEvent);
*/
registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall<SpendRequest, SpendEvent>;
/**
*
* RegisterBlockEpochNtfn is a synchronous response-streaming RPC that
* registers an intent for a client to be notified of blocks in the chain. The
* stream will return a hash and height tuple of a block for each new/stale
* block in the chain. It is the client's responsibility to determine whether
* the tuple returned is for a new or stale block in the chain.
*
* A client can also request a historical backlog of blocks from a particular
* point. This allows clients to be idempotent by ensuring that they do not
* missing processing a single block within the chain.
*
* @generated from protobuf rpc: RegisterBlockEpochNtfn(chainrpc.BlockEpoch) returns (stream chainrpc.BlockEpoch);
*/
registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall<BlockEpoch, BlockEpoch>;
}
/**
* ChainNotifier is a service that can be used to get information about the
* chain backend by registering notifiers for chain events.
*
* @generated from protobuf service chainrpc.ChainNotifier
*/
export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo {
typeName = ChainNotifier.typeName;
methods = ChainNotifier.methods;
options = ChainNotifier.options;
constructor(private readonly _transport: RpcTransport) {
}
/**
*
* RegisterConfirmationsNtfn is a synchronous response-streaming RPC that
* registers an intent for a client to be notified once a confirmation request
* has reached its required number of confirmations on-chain.
*
* A confirmation request must have a valid output script. It is also possible
* to give a transaction ID. If the transaction ID is not set, a notification
* is sent once the output script confirms. If the transaction ID is also set,
* a notification is sent once the output script confirms in the given
* transaction.
*
* @generated from protobuf rpc: RegisterConfirmationsNtfn(chainrpc.ConfRequest) returns (stream chainrpc.ConfEvent);
*/
registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall<ConfRequest, ConfEvent> {
const method = this.methods[0], opt = this._transport.mergeOptions(options);
return stackIntercept<ConfRequest, ConfEvent>("serverStreaming", this._transport, method, opt, input);
}
/**
*
* RegisterSpendNtfn is a synchronous response-streaming RPC that registers an
* intent for a client to be notification once a spend request has been spent
* by a transaction that has confirmed on-chain.
*
* A client can specify whether the spend request should be for a particular
* outpoint or for an output script by specifying a zero outpoint.
*
* @generated from protobuf rpc: RegisterSpendNtfn(chainrpc.SpendRequest) returns (stream chainrpc.SpendEvent);
*/
registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall<SpendRequest, SpendEvent> {
const method = this.methods[1], opt = this._transport.mergeOptions(options);
return stackIntercept<SpendRequest, SpendEvent>("serverStreaming", this._transport, method, opt, input);
}
/**
*
* RegisterBlockEpochNtfn is a synchronous response-streaming RPC that
* registers an intent for a client to be notified of blocks in the chain. The
* stream will return a hash and height tuple of a block for each new/stale
* block in the chain. It is the client's responsibility to determine whether
* the tuple returned is for a new or stale block in the chain.
*
* A client can also request a historical backlog of blocks from a particular
* point. This allows clients to be idempotent by ensuring that they do not
* missing processing a single block within the chain.
*
* @generated from protobuf rpc: RegisterBlockEpochNtfn(chainrpc.BlockEpoch) returns (stream chainrpc.BlockEpoch);
*/
registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall<BlockEpoch, BlockEpoch> {
const method = this.methods[2], opt = this._transport.mergeOptions(options);
return stackIntercept<BlockEpoch, BlockEpoch>("serverStreaming", this._transport, method, opt, input);
}
}

823
proto/lnd/chainnotifier.ts Normal file
View file

@ -0,0 +1,823 @@
// @generated by protobuf-ts 2.8.1
// @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3)
// tslint:disable
import { ServiceType } from "@protobuf-ts/runtime-rpc";
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
/**
* @generated from protobuf message chainrpc.ConfRequest
*/
export interface ConfRequest {
/**
*
* The transaction hash for which we should request a confirmation notification
* for. If set to a hash of all zeros, then the confirmation notification will
* be requested for the script instead.
*
* @generated from protobuf field: bytes txid = 1;
*/
txid: Uint8Array;
/**
*
* An output script within a transaction with the hash above which will be used
* by light clients to match block filters. If the transaction hash is set to a
* hash of all zeros, then a confirmation notification will be requested for
* this script instead.
*
* @generated from protobuf field: bytes script = 2;
*/
script: Uint8Array;
/**
*
* The number of desired confirmations the transaction/output script should
* reach before dispatching a confirmation notification.
*
* @generated from protobuf field: uint32 num_confs = 3;
*/
numConfs: number;
/**
*
* The earliest height in the chain for which the transaction/output script
* could have been included in a block. This should in most cases be set to the
* broadcast height of the transaction/output script.
*
* @generated from protobuf field: uint32 height_hint = 4;
*/
heightHint: number;
/**
*
* If true, then the block that mines the specified txid/script will be
* included in eventual the notification event.
*
* @generated from protobuf field: bool include_block = 5;
*/
includeBlock: boolean;
}
/**
* @generated from protobuf message chainrpc.ConfDetails
*/
export interface ConfDetails {
/**
* The raw bytes of the confirmed transaction.
*
* @generated from protobuf field: bytes raw_tx = 1;
*/
rawTx: Uint8Array;
/**
* The hash of the block in which the confirmed transaction was included in.
*
* @generated from protobuf field: bytes block_hash = 2;
*/
blockHash: Uint8Array;
/**
* The height of the block in which the confirmed transaction was included
* in.
*
* @generated from protobuf field: uint32 block_height = 3;
*/
blockHeight: number;
/**
* The index of the confirmed transaction within the block.
*
* @generated from protobuf field: uint32 tx_index = 4;
*/
txIndex: number;
/**
*
* The raw bytes of the block that mined the transaction. Only included if
* include_block was set in the request.
*
* @generated from protobuf field: bytes raw_block = 5;
*/
rawBlock: Uint8Array;
}
/**
* TODO(wilmer): need to know how the client will use this first.
*
* @generated from protobuf message chainrpc.Reorg
*/
export interface Reorg {
}
/**
* @generated from protobuf message chainrpc.ConfEvent
*/
export interface ConfEvent {
/**
* @generated from protobuf oneof: event
*/
event: {
oneofKind: "conf";
/**
*
* An event that includes the confirmation details of the request
* (txid/ouput script).
*
* @generated from protobuf field: chainrpc.ConfDetails conf = 1;
*/
conf: ConfDetails;
} | {
oneofKind: "reorg";
/**
*
* An event send when the transaction of the request is reorged out of the
* chain.
*
* @generated from protobuf field: chainrpc.Reorg reorg = 2;
*/
reorg: Reorg;
} | {
oneofKind: undefined;
};
}
/**
* @generated from protobuf message chainrpc.Outpoint
*/
export interface Outpoint {
/**
* The hash of the transaction.
*
* @generated from protobuf field: bytes hash = 1;
*/
hash: Uint8Array;
/**
* The index of the output within the transaction.
*
* @generated from protobuf field: uint32 index = 2;
*/
index: number;
}
/**
* @generated from protobuf message chainrpc.SpendRequest
*/
export interface SpendRequest {
/**
*
* The outpoint for which we should request a spend notification for. If set to
* a zero outpoint, then the spend notification will be requested for the
* script instead. A zero or nil outpoint is not supported for Taproot spends
* because the output script cannot reliably be computed from the witness alone
* and the spent output script is not always available in the rescan context.
* So an outpoint must _always_ be specified when registering a spend
* notification for a Taproot output.
*
* @generated from protobuf field: chainrpc.Outpoint outpoint = 1;
*/
outpoint?: Outpoint;
/**
*
* The output script for the outpoint above. This will be used by light clients
* to match block filters. If the outpoint is set to a zero outpoint, then a
* spend notification will be requested for this script instead.
*
* @generated from protobuf field: bytes script = 2;
*/
script: Uint8Array;
/**
*
* The earliest height in the chain for which the outpoint/output script could
* have been spent. This should in most cases be set to the broadcast height of
* the outpoint/output script.
*
* @generated from protobuf field: uint32 height_hint = 3;
*/
heightHint: number;
}
/**
* @generated from protobuf message chainrpc.SpendDetails
*/
export interface SpendDetails {
/**
* The outpoint was that spent.
*
* @generated from protobuf field: chainrpc.Outpoint spending_outpoint = 1;
*/
spendingOutpoint?: Outpoint;
/**
* The raw bytes of the spending transaction.
*
* @generated from protobuf field: bytes raw_spending_tx = 2;
*/
rawSpendingTx: Uint8Array;
/**
* The hash of the spending transaction.
*
* @generated from protobuf field: bytes spending_tx_hash = 3;
*/
spendingTxHash: Uint8Array;
/**
* The input of the spending transaction that fulfilled the spend request.
*
* @generated from protobuf field: uint32 spending_input_index = 4;
*/
spendingInputIndex: number;
/**
* The height at which the spending transaction was included in a block.
*
* @generated from protobuf field: uint32 spending_height = 5;
*/
spendingHeight: number;
}
/**
* @generated from protobuf message chainrpc.SpendEvent
*/
export interface SpendEvent {
/**
* @generated from protobuf oneof: event
*/
event: {
oneofKind: "spend";
/**
*
* An event that includes the details of the spending transaction of the
* request (outpoint/output script).
*
* @generated from protobuf field: chainrpc.SpendDetails spend = 1;
*/
spend: SpendDetails;
} | {
oneofKind: "reorg";
/**
*
* An event sent when the spending transaction of the request was
* reorged out of the chain.
*
* @generated from protobuf field: chainrpc.Reorg reorg = 2;
*/
reorg: Reorg;
} | {
oneofKind: undefined;
};
}
/**
* @generated from protobuf message chainrpc.BlockEpoch
*/
export interface BlockEpoch {
/**
* The hash of the block.
*
* @generated from protobuf field: bytes hash = 1;
*/
hash: Uint8Array;
/**
* The height of the block.
*
* @generated from protobuf field: uint32 height = 2;
*/
height: number;
}
// @generated message type with reflection information, may provide speed optimized methods
class ConfRequest$Type extends MessageType<ConfRequest> {
constructor() {
super("chainrpc.ConfRequest", [
{ no: 1, name: "txid", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 2, name: "script", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 3, name: "num_confs", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 4, name: "height_hint", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 5, name: "include_block", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
]);
}
create(value?: PartialMessage<ConfRequest>): ConfRequest {
const message = { txid: new Uint8Array(0), script: new Uint8Array(0), numConfs: 0, heightHint: 0, includeBlock: false };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ConfRequest>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ConfRequest): ConfRequest {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bytes txid */ 1:
message.txid = reader.bytes();
break;
case /* bytes script */ 2:
message.script = reader.bytes();
break;
case /* uint32 num_confs */ 3:
message.numConfs = reader.uint32();
break;
case /* uint32 height_hint */ 4:
message.heightHint = reader.uint32();
break;
case /* bool include_block */ 5:
message.includeBlock = 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: ConfRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* bytes txid = 1; */
if (message.txid.length)
writer.tag(1, WireType.LengthDelimited).bytes(message.txid);
/* bytes script = 2; */
if (message.script.length)
writer.tag(2, WireType.LengthDelimited).bytes(message.script);
/* uint32 num_confs = 3; */
if (message.numConfs !== 0)
writer.tag(3, WireType.Varint).uint32(message.numConfs);
/* uint32 height_hint = 4; */
if (message.heightHint !== 0)
writer.tag(4, WireType.Varint).uint32(message.heightHint);
/* bool include_block = 5; */
if (message.includeBlock !== false)
writer.tag(5, WireType.Varint).bool(message.includeBlock);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.ConfRequest
*/
export const ConfRequest = new ConfRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ConfDetails$Type extends MessageType<ConfDetails> {
constructor() {
super("chainrpc.ConfDetails", [
{ no: 1, name: "raw_tx", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 2, name: "block_hash", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 3, name: "block_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 4, name: "tx_index", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 5, name: "raw_block", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
]);
}
create(value?: PartialMessage<ConfDetails>): ConfDetails {
const message = { rawTx: new Uint8Array(0), blockHash: new Uint8Array(0), blockHeight: 0, txIndex: 0, rawBlock: new Uint8Array(0) };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ConfDetails>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ConfDetails): ConfDetails {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bytes raw_tx */ 1:
message.rawTx = reader.bytes();
break;
case /* bytes block_hash */ 2:
message.blockHash = reader.bytes();
break;
case /* uint32 block_height */ 3:
message.blockHeight = reader.uint32();
break;
case /* uint32 tx_index */ 4:
message.txIndex = reader.uint32();
break;
case /* bytes raw_block */ 5:
message.rawBlock = reader.bytes();
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: ConfDetails, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* bytes raw_tx = 1; */
if (message.rawTx.length)
writer.tag(1, WireType.LengthDelimited).bytes(message.rawTx);
/* bytes block_hash = 2; */
if (message.blockHash.length)
writer.tag(2, WireType.LengthDelimited).bytes(message.blockHash);
/* uint32 block_height = 3; */
if (message.blockHeight !== 0)
writer.tag(3, WireType.Varint).uint32(message.blockHeight);
/* uint32 tx_index = 4; */
if (message.txIndex !== 0)
writer.tag(4, WireType.Varint).uint32(message.txIndex);
/* bytes raw_block = 5; */
if (message.rawBlock.length)
writer.tag(5, WireType.LengthDelimited).bytes(message.rawBlock);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.ConfDetails
*/
export const ConfDetails = new ConfDetails$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Reorg$Type extends MessageType<Reorg> {
constructor() {
super("chainrpc.Reorg", []);
}
create(value?: PartialMessage<Reorg>): Reorg {
const message = {};
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Reorg>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Reorg): Reorg {
return target ?? this.create();
}
internalBinaryWrite(message: Reorg, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.Reorg
*/
export const Reorg = new Reorg$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ConfEvent$Type extends MessageType<ConfEvent> {
constructor() {
super("chainrpc.ConfEvent", [
{ no: 1, name: "conf", kind: "message", oneof: "event", T: () => ConfDetails },
{ no: 2, name: "reorg", kind: "message", oneof: "event", T: () => Reorg }
]);
}
create(value?: PartialMessage<ConfEvent>): ConfEvent {
const message = { event: { oneofKind: undefined } };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ConfEvent>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ConfEvent): ConfEvent {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* chainrpc.ConfDetails conf */ 1:
message.event = {
oneofKind: "conf",
conf: ConfDetails.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).conf)
};
break;
case /* chainrpc.Reorg reorg */ 2:
message.event = {
oneofKind: "reorg",
reorg: Reorg.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).reorg)
};
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: ConfEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* chainrpc.ConfDetails conf = 1; */
if (message.event.oneofKind === "conf")
ConfDetails.internalBinaryWrite(message.event.conf, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
/* chainrpc.Reorg reorg = 2; */
if (message.event.oneofKind === "reorg")
Reorg.internalBinaryWrite(message.event.reorg, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.ConfEvent
*/
export const ConfEvent = new ConfEvent$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Outpoint$Type extends MessageType<Outpoint> {
constructor() {
super("chainrpc.Outpoint", [
{ no: 1, name: "hash", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 2, name: "index", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
]);
}
create(value?: PartialMessage<Outpoint>): Outpoint {
const message = { hash: new Uint8Array(0), index: 0 };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Outpoint>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Outpoint): Outpoint {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bytes hash */ 1:
message.hash = reader.bytes();
break;
case /* uint32 index */ 2:
message.index = reader.uint32();
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: Outpoint, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* bytes hash = 1; */
if (message.hash.length)
writer.tag(1, WireType.LengthDelimited).bytes(message.hash);
/* uint32 index = 2; */
if (message.index !== 0)
writer.tag(2, WireType.Varint).uint32(message.index);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.Outpoint
*/
export const Outpoint = new Outpoint$Type();
// @generated message type with reflection information, may provide speed optimized methods
class SpendRequest$Type extends MessageType<SpendRequest> {
constructor() {
super("chainrpc.SpendRequest", [
{ no: 1, name: "outpoint", kind: "message", T: () => Outpoint },
{ no: 2, name: "script", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 3, name: "height_hint", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
]);
}
create(value?: PartialMessage<SpendRequest>): SpendRequest {
const message = { script: new Uint8Array(0), heightHint: 0 };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<SpendRequest>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SpendRequest): SpendRequest {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* chainrpc.Outpoint outpoint */ 1:
message.outpoint = Outpoint.internalBinaryRead(reader, reader.uint32(), options, message.outpoint);
break;
case /* bytes script */ 2:
message.script = reader.bytes();
break;
case /* uint32 height_hint */ 3:
message.heightHint = reader.uint32();
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: SpendRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* chainrpc.Outpoint outpoint = 1; */
if (message.outpoint)
Outpoint.internalBinaryWrite(message.outpoint, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
/* bytes script = 2; */
if (message.script.length)
writer.tag(2, WireType.LengthDelimited).bytes(message.script);
/* uint32 height_hint = 3; */
if (message.heightHint !== 0)
writer.tag(3, WireType.Varint).uint32(message.heightHint);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.SpendRequest
*/
export const SpendRequest = new SpendRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class SpendDetails$Type extends MessageType<SpendDetails> {
constructor() {
super("chainrpc.SpendDetails", [
{ no: 1, name: "spending_outpoint", kind: "message", T: () => Outpoint },
{ no: 2, name: "raw_spending_tx", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 3, name: "spending_tx_hash", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 4, name: "spending_input_index", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
{ no: 5, name: "spending_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
]);
}
create(value?: PartialMessage<SpendDetails>): SpendDetails {
const message = { rawSpendingTx: new Uint8Array(0), spendingTxHash: new Uint8Array(0), spendingInputIndex: 0, spendingHeight: 0 };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<SpendDetails>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SpendDetails): SpendDetails {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* chainrpc.Outpoint spending_outpoint */ 1:
message.spendingOutpoint = Outpoint.internalBinaryRead(reader, reader.uint32(), options, message.spendingOutpoint);
break;
case /* bytes raw_spending_tx */ 2:
message.rawSpendingTx = reader.bytes();
break;
case /* bytes spending_tx_hash */ 3:
message.spendingTxHash = reader.bytes();
break;
case /* uint32 spending_input_index */ 4:
message.spendingInputIndex = reader.uint32();
break;
case /* uint32 spending_height */ 5:
message.spendingHeight = reader.uint32();
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: SpendDetails, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* chainrpc.Outpoint spending_outpoint = 1; */
if (message.spendingOutpoint)
Outpoint.internalBinaryWrite(message.spendingOutpoint, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
/* bytes raw_spending_tx = 2; */
if (message.rawSpendingTx.length)
writer.tag(2, WireType.LengthDelimited).bytes(message.rawSpendingTx);
/* bytes spending_tx_hash = 3; */
if (message.spendingTxHash.length)
writer.tag(3, WireType.LengthDelimited).bytes(message.spendingTxHash);
/* uint32 spending_input_index = 4; */
if (message.spendingInputIndex !== 0)
writer.tag(4, WireType.Varint).uint32(message.spendingInputIndex);
/* uint32 spending_height = 5; */
if (message.spendingHeight !== 0)
writer.tag(5, WireType.Varint).uint32(message.spendingHeight);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.SpendDetails
*/
export const SpendDetails = new SpendDetails$Type();
// @generated message type with reflection information, may provide speed optimized methods
class SpendEvent$Type extends MessageType<SpendEvent> {
constructor() {
super("chainrpc.SpendEvent", [
{ no: 1, name: "spend", kind: "message", oneof: "event", T: () => SpendDetails },
{ no: 2, name: "reorg", kind: "message", oneof: "event", T: () => Reorg }
]);
}
create(value?: PartialMessage<SpendEvent>): SpendEvent {
const message = { event: { oneofKind: undefined } };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<SpendEvent>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SpendEvent): SpendEvent {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* chainrpc.SpendDetails spend */ 1:
message.event = {
oneofKind: "spend",
spend: SpendDetails.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).spend)
};
break;
case /* chainrpc.Reorg reorg */ 2:
message.event = {
oneofKind: "reorg",
reorg: Reorg.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).reorg)
};
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: SpendEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* chainrpc.SpendDetails spend = 1; */
if (message.event.oneofKind === "spend")
SpendDetails.internalBinaryWrite(message.event.spend, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
/* chainrpc.Reorg reorg = 2; */
if (message.event.oneofKind === "reorg")
Reorg.internalBinaryWrite(message.event.reorg, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.SpendEvent
*/
export const SpendEvent = new SpendEvent$Type();
// @generated message type with reflection information, may provide speed optimized methods
class BlockEpoch$Type extends MessageType<BlockEpoch> {
constructor() {
super("chainrpc.BlockEpoch", [
{ no: 1, name: "hash", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 2, name: "height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
]);
}
create(value?: PartialMessage<BlockEpoch>): BlockEpoch {
const message = { hash: new Uint8Array(0), height: 0 };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<BlockEpoch>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: BlockEpoch): BlockEpoch {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bytes hash */ 1:
message.hash = reader.bytes();
break;
case /* uint32 height */ 2:
message.height = reader.uint32();
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: BlockEpoch, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* bytes hash = 1; */
if (message.hash.length)
writer.tag(1, WireType.LengthDelimited).bytes(message.hash);
/* uint32 height = 2; */
if (message.height !== 0)
writer.tag(2, WireType.Varint).uint32(message.height);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message chainrpc.BlockEpoch
*/
export const BlockEpoch = new BlockEpoch$Type();
/**
* @generated ServiceType for protobuf service chainrpc.ChainNotifier
*/
export const ChainNotifier = new ServiceType("chainrpc.ChainNotifier", [
{ name: "RegisterConfirmationsNtfn", serverStreaming: true, options: {}, I: ConfRequest, O: ConfEvent },
{ name: "RegisterSpendNtfn", serverStreaming: true, options: {}, I: SpendRequest, O: SpendEvent },
{ name: "RegisterBlockEpochNtfn", serverStreaming: true, options: {}, I: BlockEpoch, O: BlockEpoch }
]);

View file

@ -1,7 +1,7 @@
// @generated by protobuf-ts 2.8.1
// @generated from protobuf file "router.proto" (package "routerrpc", syntax proto3)
// tslint:disable
import { Payment } from "./lightning.js";
import { Payment } from "./lightning";
import { ServiceType } from "@protobuf-ts/runtime-rpc";
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
@ -13,13 +13,13 @@ import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
import { ChannelPoint } from "./lightning.js";
import { HTLCAttempt } from "./lightning.js";
import { Failure_FailureCode } from "./lightning.js";
import { Failure } from "./lightning.js";
import { Route } from "./lightning.js";
import { FeatureBit } from "./lightning.js";
import { RouteHint } from "./lightning.js";
import { ChannelPoint } from "./lightning";
import { HTLCAttempt } from "./lightning";
import { Failure_FailureCode } from "./lightning";
import { Failure } from "./lightning";
import { Route } from "./lightning";
import { FeatureBit } from "./lightning";
import { RouteHint } from "./lightning";
/**
* @generated from protobuf message routerrpc.SendPaymentRequest
*/

View file

@ -0,0 +1,200 @@
syntax = "proto3";
package chainrpc;
option go_package = "github.com/lightningnetwork/lnd/lnrpc/chainrpc";
// ChainNotifier is a service that can be used to get information about the
// chain backend by registering notifiers for chain events.
service ChainNotifier {
/*
RegisterConfirmationsNtfn is a synchronous response-streaming RPC that
registers an intent for a client to be notified once a confirmation request
has reached its required number of confirmations on-chain.
A confirmation request must have a valid output script. It is also possible
to give a transaction ID. If the transaction ID is not set, a notification
is sent once the output script confirms. If the transaction ID is also set,
a notification is sent once the output script confirms in the given
transaction.
*/
rpc RegisterConfirmationsNtfn (ConfRequest) returns (stream ConfEvent);
/*
RegisterSpendNtfn is a synchronous response-streaming RPC that registers an
intent for a client to be notification once a spend request has been spent
by a transaction that has confirmed on-chain.
A client can specify whether the spend request should be for a particular
outpoint or for an output script by specifying a zero outpoint.
*/
rpc RegisterSpendNtfn (SpendRequest) returns (stream SpendEvent);
/*
RegisterBlockEpochNtfn is a synchronous response-streaming RPC that
registers an intent for a client to be notified of blocks in the chain. The
stream will return a hash and height tuple of a block for each new/stale
block in the chain. It is the client's responsibility to determine whether
the tuple returned is for a new or stale block in the chain.
A client can also request a historical backlog of blocks from a particular
point. This allows clients to be idempotent by ensuring that they do not
missing processing a single block within the chain.
*/
rpc RegisterBlockEpochNtfn (BlockEpoch) returns (stream BlockEpoch);
}
message ConfRequest {
/*
The transaction hash for which we should request a confirmation notification
for. If set to a hash of all zeros, then the confirmation notification will
be requested for the script instead.
*/
bytes txid = 1;
/*
An output script within a transaction with the hash above which will be used
by light clients to match block filters. If the transaction hash is set to a
hash of all zeros, then a confirmation notification will be requested for
this script instead.
*/
bytes script = 2;
/*
The number of desired confirmations the transaction/output script should
reach before dispatching a confirmation notification.
*/
uint32 num_confs = 3;
/*
The earliest height in the chain for which the transaction/output script
could have been included in a block. This should in most cases be set to the
broadcast height of the transaction/output script.
*/
uint32 height_hint = 4;
/*
If true, then the block that mines the specified txid/script will be
included in eventual the notification event.
*/
bool include_block = 5;
}
message ConfDetails {
// The raw bytes of the confirmed transaction.
bytes raw_tx = 1;
// The hash of the block in which the confirmed transaction was included in.
bytes block_hash = 2;
// The height of the block in which the confirmed transaction was included
// in.
uint32 block_height = 3;
// The index of the confirmed transaction within the block.
uint32 tx_index = 4;
/*
The raw bytes of the block that mined the transaction. Only included if
include_block was set in the request.
*/
bytes raw_block = 5;
}
message Reorg {
// TODO(wilmer): need to know how the client will use this first.
}
message ConfEvent {
oneof event {
/*
An event that includes the confirmation details of the request
(txid/ouput script).
*/
ConfDetails conf = 1;
/*
An event send when the transaction of the request is reorged out of the
chain.
*/
Reorg reorg = 2;
}
}
message Outpoint {
// The hash of the transaction.
bytes hash = 1;
// The index of the output within the transaction.
uint32 index = 2;
}
message SpendRequest {
/*
The outpoint for which we should request a spend notification for. If set to
a zero outpoint, then the spend notification will be requested for the
script instead. A zero or nil outpoint is not supported for Taproot spends
because the output script cannot reliably be computed from the witness alone
and the spent output script is not always available in the rescan context.
So an outpoint must _always_ be specified when registering a spend
notification for a Taproot output.
*/
Outpoint outpoint = 1;
/*
The output script for the outpoint above. This will be used by light clients
to match block filters. If the outpoint is set to a zero outpoint, then a
spend notification will be requested for this script instead.
*/
bytes script = 2;
/*
The earliest height in the chain for which the outpoint/output script could
have been spent. This should in most cases be set to the broadcast height of
the outpoint/output script.
*/
uint32 height_hint = 3;
// TODO(wilmer): extend to support num confs on spending tx.
}
message SpendDetails {
// The outpoint was that spent.
Outpoint spending_outpoint = 1;
// The raw bytes of the spending transaction.
bytes raw_spending_tx = 2;
// The hash of the spending transaction.
bytes spending_tx_hash = 3;
// The input of the spending transaction that fulfilled the spend request.
uint32 spending_input_index = 4;
// The height at which the spending transaction was included in a block.
uint32 spending_height = 5;
}
message SpendEvent {
oneof event {
/*
An event that includes the details of the spending transaction of the
request (outpoint/output script).
*/
SpendDetails spend = 1;
/*
An event sent when the spending transaction of the request was
reorged out of the chain.
*/
Reorg reorg = 2;
}
}
message BlockEpoch {
// The hash of the block.
bytes hash = 1;
// The height of the block.
uint32 height = 2;
}

View file

@ -231,6 +231,7 @@ message UserOperation {
string operationId = 6;
int64 service_fee = 7;
int64 network_fee = 8;
bool confirmed = 9;
}
message UserOperations {
int64 fromIndex=1;

View file

@ -1,7 +1,7 @@
import * as Types from '../../../proto/autogenerated/ts/types.js'
import { GetInfoResponse, NewAddressResponse, AddInvoiceResponse, PayReq, Payment, SendCoinsResponse, EstimateFeeResponse } from '../../../proto/lnd/lightning.js'
import { GetInfoResponse, NewAddressResponse, AddInvoiceResponse, PayReq, Payment, SendCoinsResponse, EstimateFeeResponse, TransactionDetails } from '../../../proto/lnd/lightning.js'
import { EnvMustBeNonEmptyString, EnvMustBeInteger, EnvCanBeBoolean } from '../helpers/envParser.js'
import { AddressPaidCb, DecodedInvoice, Invoice, InvoicePaidCb, LndSettings, NodeInfo, PaidInvoice } from './settings.js'
import { AddressPaidCb, DecodedInvoice, Invoice, InvoicePaidCb, LndSettings, NewBlockCb, NodeInfo, PaidInvoice } from './settings.js'
import LND from './lnd.js'
import MockLnd from './mock.js'
import { getLogger } from '../helpers/logger.js'
@ -30,14 +30,15 @@ export interface LightningHandler {
OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number): Promise<string>
SetMockInvoiceAsPaid(invoice: string, amount: number): Promise<void>
ChannelBalance(): Promise<{ local: number, remote: number }>
GetTransactions(startHeight: number): Promise<TransactionDetails>
}
export default (settings: LndSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb): LightningHandler => {
export default (settings: LndSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb, newBlockCb: NewBlockCb): LightningHandler => {
if (settings.mockLnd) {
getLogger({})("registering mock lnd handler")
return new MockLnd(settings, addressPaidCb, invoicePaidCb)
return new MockLnd(settings, addressPaidCb, invoicePaidCb, newBlockCb)
} else {
getLogger({})("registering prod lnd handler")
return new LND(settings, addressPaidCb, invoicePaidCb)
return new LND(settings, addressPaidCb, invoicePaidCb, newBlockCb)
}
}

View file

@ -7,12 +7,13 @@ import * as Types from '../../../proto/autogenerated/ts/types.js'
import { LightningClient } from '../../../proto/lnd/lightning.client.js'
import { InvoicesClient } from '../../../proto/lnd/invoices.client.js'
import { RouterClient } from '../../../proto/lnd/router.client.js'
import { GetInfoResponse, AddressType, NewAddressResponse, AddInvoiceResponse, Invoice_InvoiceState, PayReq, Payment_PaymentStatus, Payment, PaymentFailureReason, SendCoinsResponse, EstimateFeeResponse, ChannelBalanceResponse } from '../../../proto/lnd/lightning.js'
import { ChainNotifierClient } from '../../../proto/lnd/chainnotifier.client.js'
import { GetInfoResponse, AddressType, NewAddressResponse, AddInvoiceResponse, Invoice_InvoiceState, PayReq, Payment_PaymentStatus, Payment, PaymentFailureReason, SendCoinsResponse, EstimateFeeResponse, ChannelBalanceResponse, TransactionDetails } from '../../../proto/lnd/lightning.js'
import { OpenChannelReq } from './openChannelReq.js';
import { AddInvoiceReq } from './addInvoiceReq.js';
import { PayInvoiceReq } from './payInvoiceReq.js';
import { SendCoinsReq } from './sendCoinsReq.js';
import { LndSettings, AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice } from './settings.js';
import { LndSettings, AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice, NewBlockCb } from './settings.js';
import { getLogger } from '../helpers/logger.js';
const DeadLineMetadata = (deadline = 10 * 1000) => ({ deadline: Date.now() + deadline })
const deadLndRetrySeconds = 5
@ -20,6 +21,7 @@ export default class {
lightning: LightningClient
invoices: InvoicesClient
router: RouterClient
chainNotifier: ChainNotifierClient
settings: LndSettings
ready = false
latestKnownBlockHeigh = 0
@ -27,11 +29,13 @@ export default class {
abortController = new AbortController()
addressPaidCb: AddressPaidCb
invoicePaidCb: InvoicePaidCb
newBlockCb: NewBlockCb
log = getLogger({})
constructor(settings: LndSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb) {
constructor(settings: LndSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb, newBlockCb: NewBlockCb) {
this.settings = settings
this.addressPaidCb = addressPaidCb
this.invoicePaidCb = invoicePaidCb
this.newBlockCb = newBlockCb
const { lndAddr, lndCertPath, lndMacaroonPath } = this.settings
const lndCert = fs.readFileSync(lndCertPath);
const macaroon = fs.readFileSync(lndMacaroonPath).toString('hex');
@ -51,6 +55,7 @@ export default class {
this.lightning = new LightningClient(transport)
this.invoices = new InvoicesClient(transport)
this.router = new RouterClient(transport)
this.chainNotifier = new ChainNotifierClient(transport)
}
SetMockInvoiceAsPaid(invoice: string, amount: number): Promise<void> {
throw new Error("SetMockInvoiceAsPaid only available in mock mode")
@ -61,6 +66,7 @@ export default class {
async Warmup() {
this.SubscribeAddressPaid()
this.SubscribeInvoicePaid()
this.SubscribeNewBlock()
this.ready = true
}
@ -96,6 +102,20 @@ export default class {
}, deadLndRetrySeconds * 1000)
}
async SubscribeNewBlock() {
const { blockHeight } = await this.GetInfo()
const stream = this.chainNotifier.registerBlockEpochNtfn({ height: blockHeight, hash: Buffer.alloc(0) }, { abort: this.abortController.signal })
stream.responses.onMessage(block => {
this.newBlockCb(block.height)
})
stream.responses.onError(error => {
this.log("Error with onchain tx stream")
})
stream.responses.onComplete(() => {
this.log("onchain tx stream closed")
})
}
SubscribeAddressPaid(): void {
const stream = this.lightning.subscribeTransactions({
account: "",
@ -233,6 +253,12 @@ export default class {
return res.response
}
async GetTransactions(startHeight: number): Promise<TransactionDetails> {
await this.Health()
const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "" }, DeadLineMetadata())
return res.response
}
async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number): Promise<string> {
await this.Health()

View file

@ -7,12 +7,12 @@ import * as Types from '../../../proto/autogenerated/ts/types.js'
import { LightningClient } from '../../../proto/lnd/lightning.client.js'
import { InvoicesClient } from '../../../proto/lnd/invoices.client.js'
import { RouterClient } from '../../../proto/lnd/router.client.js'
import { GetInfoResponse, AddressType, NewAddressResponse, AddInvoiceResponse, Invoice_InvoiceState, PayReq, Payment_PaymentStatus, Payment, PaymentFailureReason, SendCoinsResponse, EstimateFeeResponse } from '../../../proto/lnd/lightning.js'
import { GetInfoResponse, AddressType, NewAddressResponse, AddInvoiceResponse, Invoice_InvoiceState, PayReq, Payment_PaymentStatus, Payment, PaymentFailureReason, SendCoinsResponse, EstimateFeeResponse, TransactionDetails } from '../../../proto/lnd/lightning.js'
import { OpenChannelReq } from './openChannelReq.js';
import { AddInvoiceReq } from './addInvoiceReq.js';
import { PayInvoiceReq } from './payInvoiceReq.js';
import { SendCoinsReq } from './sendCoinsReq.js';
import { LndSettings, AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice } from './settings.js';
import { LndSettings, AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice, NewBlockCb } from './settings.js';
import { getLogger } from '../helpers/logger.js';
export default class {
@ -21,7 +21,7 @@ export default class {
abortController = new AbortController()
addressPaidCb: AddressPaidCb
invoicePaidCb: InvoicePaidCb
constructor(settings: LndSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb) {
constructor(settings: LndSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb, newBlockCb: NewBlockCb) {
this.settings = settings
this.addressPaidCb = addressPaidCb
this.invoicePaidCb = invoicePaidCb
@ -40,7 +40,7 @@ export default class {
async Warmup() { }
async GetInfo(): Promise<NodeInfo> {
return { alias: "mock", syncedToChain: true, syncedToGraph: true }
return { alias: "mock", syncedToChain: true, syncedToGraph: true, blockHeight: 1, blockHash: "" }
}
async Health(): Promise<void> { }
@ -111,6 +111,10 @@ export default class {
async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number): Promise<string> {
throw new Error("OpenChannel disabled in mock mode")
}
async GetTransactions(startHeight: number): Promise<TransactionDetails> {
throw new Error("GetTransactions disabled in mock mode")
}
}

View file

@ -13,11 +13,14 @@ type TxOutput = {
export type AddressPaidCb = (txOutput: TxOutput, address: string, amount: number, internal: boolean) => void
export type InvoicePaidCb = (paymentRequest: string, amount: number, internal: boolean) => void
export type NewBlockCb = (height: number) => void
export type NodeInfo = {
alias: string
syncedToChain: boolean
syncedToGraph: boolean
blockHeight: number
blockHash: string
}
export type Invoice = {
payRequest: string

View file

@ -8,7 +8,7 @@ import ApplicationManager from './applicationManager.js'
import PaymentManager from './paymentManager.js'
import { MainSettings } from './settings.js'
import NewLightningHandler, { LoadLndSettingsFromEnv, LightningHandler } from "../lnd/index.js"
import { AddressPaidCb, InvoicePaidCb } from "../lnd/settings.js"
import { AddressPaidCb, InvoicePaidCb, NewBlockCb } from "../lnd/settings.js"
import { getLogger, PubLogger } from "../helpers/logger.js"
import AppUserManager from "./appUserManager.js"
import { Application } from '../storage/entity/Application.js'
@ -56,7 +56,7 @@ export default class {
constructor(settings: MainSettings) {
this.settings = settings
this.storage = new Storage(settings.storageSettings)
this.lnd = NewLightningHandler(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb)
this.lnd = NewLightningHandler(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb, this.newBlockCb)
this.paymentManager = new PaymentManager(this.storage, this.lnd, this.settings, this.addressPaidCb, this.invoicePaidCb)
this.productManager = new ProductManager(this.storage, this.paymentManager, this.settings)
@ -68,8 +68,29 @@ export default class {
this.nostrSend = f
}
newBlockCb: NewBlockCb = (height) => {
this.NewBlockHandler(height)
}
NewBlockHandler = async (height: number) => {
const confirmed = await this.paymentManager.CheckPendingTransactions(height)
await Promise.all(confirmed.map(async ({ confs, type, tx: t }) => {
const { serial_id } = t
if (type === 'outgoing') {
await this.storage.paymentStorage.UpdateUserTransactionPayment(serial_id, { confs })
} else {
await this.storage.paymentStorage.UpdateAddressReceivingTransaction(serial_id, { confs })
await this.storage.userStorage.IncrementUserBalance(t.user_address.user.user_id, t.paid_amount - t.service_fee)
const operationId = `${Types.UserOperationType.INCOMING_TX}-${t.user_address.serial_id}`
const op = { amount: t.paid_amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_TX, identifier: t.user_address.address, operationId, network_fee: 0, service_fee: t.service_fee, confirmed: true }
this.sendOperationToNostr(t.user_address.linkedApplication!, t.user_address.user.user_id, op)
}
}))
}
addressPaidCb: AddressPaidCb = (txOutput, address, amount, internal) => {
this.storage.StartTransaction(async tx => {
const { blockHeight } = await this.lnd.GetInfo()
const userAddress = await this.storage.paymentStorage.GetAddressOwner(address, tx)
if (!userAddress) { return }
const log = getLogger({})
@ -84,10 +105,11 @@ export default class {
}
try {
// This call will fail if the transaction is already registered
const addedTx = await this.storage.paymentStorage.AddAddressReceivingTransaction(userAddress, txOutput.hash, txOutput.index, amount, fee, internal, tx)
const addedTx = await this.storage.paymentStorage.AddAddressReceivingTransaction(userAddress, txOutput.hash, txOutput.index, amount, fee, internal, blockHeight, tx)
await this.storage.userStorage.IncrementUserBalance(userAddress.user.user_id, addedTx.paid_amount - fee, tx)
const operationId = `${Types.UserOperationType.INCOMING_TX}-${userAddress.serial_id}`
this.sendOperationToNostr(userAddress.linkedApplication, userAddress.user.user_id, { amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_TX, identifier: userAddress.address, operationId, network_fee: 0, service_fee: fee })
const op = { amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_TX, identifier: userAddress.address, operationId, network_fee: 0, service_fee: fee, confirmed: internal }
this.sendOperationToNostr(userAddress.linkedApplication, userAddress.user.user_id, op)
} catch {
}
@ -120,7 +142,8 @@ export default class {
await this.triggerPaidCallback(log, userInvoice.callbackUrl)
const operationId = `${Types.UserOperationType.INCOMING_INVOICE}-${userInvoice.serial_id}`
this.sendOperationToNostr(userInvoice.linkedApplication, userInvoice.user.user_id, { amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_INVOICE, identifier: userInvoice.invoice, operationId, network_fee: 0, service_fee: fee })
const op = { amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_INVOICE, identifier: userInvoice.invoice, operationId, network_fee: 0, service_fee: fee, confirmed: true }
this.sendOperationToNostr(userInvoice.linkedApplication, userInvoice.user.user_id, op)
this.createZapReceipt(userInvoice)
log("paid invoice processed successfully")
} catch (err: any) {

View file

@ -12,6 +12,8 @@ import { AddressPaidCb, InvoicePaidCb, PaidInvoice } from '../lnd/settings.js'
import { UserReceivingInvoice, ZapInfo } from '../storage/entity/UserReceivingInvoice.js'
import { SendCoinsResponse } from '../../../proto/lnd/lightning.js'
import { Event, verifiedSymbol, verifySignature } from '../nostr/tools/event.js'
import { AddressReceivingTransaction } from '../storage/entity/AddressReceivingTransaction.js'
import { UserTransactionPayment } from '../storage/entity/UserTransactionPayment.js'
interface UserOperationInfo {
serial_id: number
paid_amount: number
@ -25,8 +27,10 @@ interface UserOperationInfo {
routing_fees?: number
chain_fees?: number
}
type PendingTx = { type: 'incoming', tx: AddressReceivingTransaction } | { type: 'outgoing', tx: UserTransactionPayment }
const defaultLnurlPayMetadata = `[["text/plain", "lnurl pay to Lightning.pub"]]`
const confInOne = 1000 * 1000
const confInTwo = 100 * 1000 * 1000
export default class {
storage: Storage
@ -179,6 +183,7 @@ export default class {
async PayAddress(ctx: Types.UserContext, req: Types.PayAddressRequest): Promise<Types.PayAddressResponse> {
const { blockHeight } = await this.lnd.GetInfo()
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
const serviceFee = this.getServiceFee(Types.UserOperationType.OUTGOING_TX, req.amoutSats, false)
const isAppUserPayment = ctx.user_id !== app.owner.user_id
@ -208,7 +213,8 @@ export default class {
if (isAppUserPayment && serviceFee > 0) {
await this.storage.userStorage.IncrementUserBalance(app.owner.user_id, serviceFee)
}
const newTx = await this.storage.paymentStorage.AddUserTransactionPayment(ctx.user_id, req.address, txId, 0, req.amoutSats, chainFees, serviceFee, !!internalAddress)
const newTx = await this.storage.paymentStorage.AddUserTransactionPayment(ctx.user_id, req.address, txId, 0, req.amoutSats, chainFees, serviceFee, !!internalAddress, blockHeight)
return {
txId: txId,
operation_id: `${Types.UserOperationType.OUTGOING_TX}-${newTx.serial_id}`,
@ -457,6 +463,31 @@ export default class {
return sentAmount
}
async CheckPendingTransactions(height: number) {
const pending = await this.storage.paymentStorage.GetPendingTransactions()
let lowestHeight = height
const map: Record<string, PendingTx> = {}
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 resolved = await Promise.all(transactions.map(async 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)) {
return { ...t, confs }
}
}))
return resolved.filter(t => t !== undefined) as (PendingTx & { confs: number })[]
}
encodeLnurl(base: string) {
if (!base || typeof base !== 'string') {
throw new Error("provided string for lnurl encode is not a string or is an empty string")

View file

@ -31,6 +31,12 @@ export class AddressReceivingTransaction {
@Column({ default: false })
internal: boolean
@Column({ default: 0 })
confs: number
@Column({ default: 0 })
broadcast_height: number
@CreateDateColumn()
created_at: Date

View file

@ -36,6 +36,12 @@ export class UserTransactionPayment {
@Column({ default: false })
internal: boolean
@Column({ default: 0 })
confs: number
@Column({ default: 0 })
broadcast_height: number
@CreateDateColumn()
created_at: Date

View file

@ -20,7 +20,7 @@ export default class {
this.DB = DB
this.userStorage = userStorage
}
async AddAddressReceivingTransaction(address: UserReceivingAddress, txHash: string, outputIndex: number, amount: number, serviceFee: number, internal: boolean, entityManager = this.DB) {
async AddAddressReceivingTransaction(address: UserReceivingAddress, txHash: string, outputIndex: number, amount: number, serviceFee: number, internal: boolean, height: number, entityManager = this.DB) {
const newAddressTransaction = entityManager.getRepository(AddressReceivingTransaction).create({
user_address: address,
tx_hash: txHash,
@ -28,7 +28,9 @@ export default class {
paid_amount: amount,
service_fee: serviceFee,
paid_at_unix: Math.floor(Date.now() / 1000),
internal
internal,
broadcast_height: height,
confs: internal ? 10 : 0
})
return entityManager.getRepository(AddressReceivingTransaction).save(newAddressTransaction)
}
@ -139,7 +141,7 @@ export default class {
})
}
async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, internal: boolean, entityManager = this.DB): Promise<UserTransactionPayment> {
async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, internal: boolean, height: number, entityManager = this.DB): Promise<UserTransactionPayment> {
const newTx = entityManager.getRepository(UserTransactionPayment).create({
user: await this.userStorage.GetUser(userId),
address,
@ -149,7 +151,9 @@ export default class {
tx_hash: txHash,
service_fees: serviceFees,
paid_at_unix: Math.floor(Date.now() / 1000),
internal
internal,
broadcast_height: height,
confs: internal ? 10 : 0
})
return entityManager.getRepository(UserTransactionPayment).save(newTx)
}
@ -169,6 +173,19 @@ export default class {
})
}
async GetPendingTransactions(entityManager = this.DB) {
const incoming = await entityManager.getRepository(AddressReceivingTransaction).find({ where: { confs: 0 } })
const outgoing = await entityManager.getRepository(UserTransactionPayment).find({ where: { confs: 0 } })
return { incoming, outgoing }
}
async UpdateAddressReceivingTransaction(serialId: number, update: Partial<AddressReceivingTransaction>, entityManager = this.DB) {
await entityManager.getRepository(AddressReceivingTransaction).update(serialId, update)
}
async UpdateUserTransactionPayment(serialId: number, update: Partial<UserTransactionPayment>, entityManager = this.DB) {
await entityManager.getRepository(UserTransactionPayment).update(serialId, update)
}
async AddUserEphemeralKey(userId: string, keyType: EphemeralKeyType, linkedApplication: Application, entityManager = this.DB): Promise<UserEphemeralKey> {
const found = await entityManager.getRepository(UserEphemeralKey).findOne({ where: { type: keyType, user: { user_id: userId }, linkedApplication: { app_id: linkedApplication.app_id } } })