unlock flow
This commit is contained in:
parent
52a27a8ff9
commit
2648f55df0
13 changed files with 1815 additions and 7 deletions
|
|
@ -12,14 +12,17 @@ import { UserReceivingAddress } from "./build/src/services/storage/entity/UserRe
|
|||
import { UserToUserPayment } from "./build/src/services/storage/entity/UserToUserPayment.js"
|
||||
import { UserTransactionPayment } from "./build/src/services/storage/entity/UserTransactionPayment.js"
|
||||
import { LspOrder } from "./build/src/services/storage/entity/LspOrder.js"
|
||||
import { LndNodeInfo } from "./build/src/services/storage/entity/LndNodeInfo.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 { LiquidityProvider1719335699480 } from './build/src/services/storage/migrations/1719335699480-liquidity_provider.js'
|
||||
export default new DataSource({
|
||||
type: "sqlite",
|
||||
database: "db.sqlite",
|
||||
// logging: true,
|
||||
migrations: [Initial1703170309875, LspOrder1718387847693],
|
||||
migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480],
|
||||
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder],
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo],
|
||||
// synchronize: true,
|
||||
})
|
||||
})
|
||||
//npx typeorm migration:generate ./src/services/storage/migrations/lnd_node_info -d ./datasource.js
|
||||
180
proto/lnd/walletunlocker.client.ts
Normal file
180
proto/lnd/walletunlocker.client.ts
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
// @generated by protobuf-ts 2.8.1
|
||||
// @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3)
|
||||
// tslint:disable
|
||||
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
|
||||
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
|
||||
import { WalletUnlocker } from "./walletunlocker.js";
|
||||
import type { ChangePasswordResponse } from "./walletunlocker.js";
|
||||
import type { ChangePasswordRequest } from "./walletunlocker.js";
|
||||
import type { UnlockWalletResponse } from "./walletunlocker.js";
|
||||
import type { UnlockWalletRequest } from "./walletunlocker.js";
|
||||
import type { InitWalletResponse } from "./walletunlocker.js";
|
||||
import type { InitWalletRequest } from "./walletunlocker.js";
|
||||
import { stackIntercept } from "@protobuf-ts/runtime-rpc";
|
||||
import type { GenSeedResponse } from "./walletunlocker.js";
|
||||
import type { GenSeedRequest } from "./walletunlocker.js";
|
||||
import type { UnaryCall } 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
|
||||
|
||||
/**
|
||||
* WalletUnlocker is a service that is used to set up a wallet password for
|
||||
* lnd at first startup, and unlock a previously set up wallet.
|
||||
*
|
||||
* @generated from protobuf service lnrpc.WalletUnlocker
|
||||
*/
|
||||
export interface IWalletUnlockerClient {
|
||||
/**
|
||||
*
|
||||
* GenSeed is the first method that should be used to instantiate a new lnd
|
||||
* instance. This method allows a caller to generate a new aezeed cipher seed
|
||||
* given an optional passphrase. If provided, the passphrase will be necessary
|
||||
* to decrypt the cipherseed to expose the internal wallet seed.
|
||||
*
|
||||
* Once the cipherseed is obtained and verified by the user, the InitWallet
|
||||
* method should be used to commit the newly generated seed, and create the
|
||||
* wallet.
|
||||
*
|
||||
* @generated from protobuf rpc: GenSeed(lnrpc.GenSeedRequest) returns (lnrpc.GenSeedResponse);
|
||||
*/
|
||||
genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall<GenSeedRequest, GenSeedResponse>;
|
||||
/**
|
||||
*
|
||||
* InitWallet is used when lnd is starting up for the first time to fully
|
||||
* initialize the daemon and its internal wallet. At the very least a wallet
|
||||
* password must be provided. This will be used to encrypt sensitive material
|
||||
* on disk.
|
||||
*
|
||||
* In the case of a recovery scenario, the user can also specify their aezeed
|
||||
* mnemonic and passphrase. If set, then the daemon will use this prior state
|
||||
* to initialize its internal wallet.
|
||||
*
|
||||
* Alternatively, this can be used along with the GenSeed RPC to obtain a
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf rpc: InitWallet(lnrpc.InitWalletRequest) returns (lnrpc.InitWalletResponse);
|
||||
*/
|
||||
initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall<InitWalletRequest, InitWalletResponse>;
|
||||
/**
|
||||
* lncli: `unlock`
|
||||
* UnlockWallet is used at startup of lnd to provide a password to unlock
|
||||
* the wallet database.
|
||||
*
|
||||
* @generated from protobuf rpc: UnlockWallet(lnrpc.UnlockWalletRequest) returns (lnrpc.UnlockWalletResponse);
|
||||
*/
|
||||
unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall<UnlockWalletRequest, UnlockWalletResponse>;
|
||||
/**
|
||||
* lncli: `changepassword`
|
||||
* ChangePassword changes the password of the encrypted wallet. This will
|
||||
* automatically unlock the wallet database if successful.
|
||||
*
|
||||
* @generated from protobuf rpc: ChangePassword(lnrpc.ChangePasswordRequest) returns (lnrpc.ChangePasswordResponse);
|
||||
*/
|
||||
changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall<ChangePasswordRequest, ChangePasswordResponse>;
|
||||
}
|
||||
//
|
||||
// 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
|
||||
|
||||
/**
|
||||
* WalletUnlocker is a service that is used to set up a wallet password for
|
||||
* lnd at first startup, and unlock a previously set up wallet.
|
||||
*
|
||||
* @generated from protobuf service lnrpc.WalletUnlocker
|
||||
*/
|
||||
export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo {
|
||||
typeName = WalletUnlocker.typeName;
|
||||
methods = WalletUnlocker.methods;
|
||||
options = WalletUnlocker.options;
|
||||
constructor(private readonly _transport: RpcTransport) {
|
||||
}
|
||||
/**
|
||||
*
|
||||
* GenSeed is the first method that should be used to instantiate a new lnd
|
||||
* instance. This method allows a caller to generate a new aezeed cipher seed
|
||||
* given an optional passphrase. If provided, the passphrase will be necessary
|
||||
* to decrypt the cipherseed to expose the internal wallet seed.
|
||||
*
|
||||
* Once the cipherseed is obtained and verified by the user, the InitWallet
|
||||
* method should be used to commit the newly generated seed, and create the
|
||||
* wallet.
|
||||
*
|
||||
* @generated from protobuf rpc: GenSeed(lnrpc.GenSeedRequest) returns (lnrpc.GenSeedResponse);
|
||||
*/
|
||||
genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall<GenSeedRequest, GenSeedResponse> {
|
||||
const method = this.methods[0], opt = this._transport.mergeOptions(options);
|
||||
return stackIntercept<GenSeedRequest, GenSeedResponse>("unary", this._transport, method, opt, input);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* InitWallet is used when lnd is starting up for the first time to fully
|
||||
* initialize the daemon and its internal wallet. At the very least a wallet
|
||||
* password must be provided. This will be used to encrypt sensitive material
|
||||
* on disk.
|
||||
*
|
||||
* In the case of a recovery scenario, the user can also specify their aezeed
|
||||
* mnemonic and passphrase. If set, then the daemon will use this prior state
|
||||
* to initialize its internal wallet.
|
||||
*
|
||||
* Alternatively, this can be used along with the GenSeed RPC to obtain a
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf rpc: InitWallet(lnrpc.InitWalletRequest) returns (lnrpc.InitWalletResponse);
|
||||
*/
|
||||
initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall<InitWalletRequest, InitWalletResponse> {
|
||||
const method = this.methods[1], opt = this._transport.mergeOptions(options);
|
||||
return stackIntercept<InitWalletRequest, InitWalletResponse>("unary", this._transport, method, opt, input);
|
||||
}
|
||||
/**
|
||||
* lncli: `unlock`
|
||||
* UnlockWallet is used at startup of lnd to provide a password to unlock
|
||||
* the wallet database.
|
||||
*
|
||||
* @generated from protobuf rpc: UnlockWallet(lnrpc.UnlockWalletRequest) returns (lnrpc.UnlockWalletResponse);
|
||||
*/
|
||||
unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall<UnlockWalletRequest, UnlockWalletResponse> {
|
||||
const method = this.methods[2], opt = this._transport.mergeOptions(options);
|
||||
return stackIntercept<UnlockWalletRequest, UnlockWalletResponse>("unary", this._transport, method, opt, input);
|
||||
}
|
||||
/**
|
||||
* lncli: `changepassword`
|
||||
* ChangePassword changes the password of the encrypted wallet. This will
|
||||
* automatically unlock the wallet database if successful.
|
||||
*
|
||||
* @generated from protobuf rpc: ChangePassword(lnrpc.ChangePasswordRequest) returns (lnrpc.ChangePasswordResponse);
|
||||
*/
|
||||
changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall<ChangePasswordRequest, ChangePasswordResponse> {
|
||||
const method = this.methods[3], opt = this._transport.mergeOptions(options);
|
||||
return stackIntercept<ChangePasswordRequest, ChangePasswordResponse>("unary", this._transport, method, opt, input);
|
||||
}
|
||||
}
|
||||
991
proto/lnd/walletunlocker.ts
Normal file
991
proto/lnd/walletunlocker.ts
Normal file
|
|
@ -0,0 +1,991 @@
|
|||
// @generated by protobuf-ts 2.8.1
|
||||
// @generated from protobuf file "walletunlocker.proto" (package "lnrpc", 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";
|
||||
import { ChanBackupSnapshot } from "./lightning.js";
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.GenSeedRequest
|
||||
*/
|
||||
export interface GenSeedRequest {
|
||||
/**
|
||||
*
|
||||
* aezeed_passphrase is an optional user provided passphrase that will be used
|
||||
* to encrypt the generated aezeed cipher seed. When using REST, this field
|
||||
* must be encoded as base64.
|
||||
*
|
||||
* @generated from protobuf field: bytes aezeed_passphrase = 1;
|
||||
*/
|
||||
aezeedPassphrase: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* seed_entropy is an optional 16-bytes generated via CSPRNG. If not
|
||||
* specified, then a fresh set of randomness will be used to create the seed.
|
||||
* When using REST, this field must be encoded as base64.
|
||||
*
|
||||
* @generated from protobuf field: bytes seed_entropy = 2;
|
||||
*/
|
||||
seedEntropy: Uint8Array;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.GenSeedResponse
|
||||
*/
|
||||
export interface GenSeedResponse {
|
||||
/**
|
||||
*
|
||||
* cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed
|
||||
* cipher seed obtained by the user. This field is optional, as if not
|
||||
* provided, then the daemon will generate a new cipher seed for the user.
|
||||
* Otherwise, then the daemon will attempt to recover the wallet state linked
|
||||
* to this cipher seed.
|
||||
*
|
||||
* @generated from protobuf field: repeated string cipher_seed_mnemonic = 1;
|
||||
*/
|
||||
cipherSeedMnemonic: string[];
|
||||
/**
|
||||
*
|
||||
* enciphered_seed are the raw aezeed cipher seed bytes. This is the raw
|
||||
* cipher text before run through our mnemonic encoding scheme.
|
||||
*
|
||||
* @generated from protobuf field: bytes enciphered_seed = 2;
|
||||
*/
|
||||
encipheredSeed: Uint8Array;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.InitWalletRequest
|
||||
*/
|
||||
export interface InitWalletRequest {
|
||||
/**
|
||||
*
|
||||
* wallet_password is the passphrase that should be used to encrypt the
|
||||
* wallet. This MUST be at least 8 chars in length. After creation, this
|
||||
* password is required to unlock the daemon. When using REST, this field
|
||||
* must be encoded as base64.
|
||||
*
|
||||
* @generated from protobuf field: bytes wallet_password = 1;
|
||||
*/
|
||||
walletPassword: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed
|
||||
* cipher seed obtained by the user. This may have been generated by the
|
||||
* GenSeed method, or be an existing seed.
|
||||
*
|
||||
* @generated from protobuf field: repeated string cipher_seed_mnemonic = 2;
|
||||
*/
|
||||
cipherSeedMnemonic: string[];
|
||||
/**
|
||||
*
|
||||
* aezeed_passphrase is an optional user provided passphrase that will be used
|
||||
* to encrypt the generated aezeed cipher seed. When using REST, this field
|
||||
* must be encoded as base64.
|
||||
*
|
||||
* @generated from protobuf field: bytes aezeed_passphrase = 3;
|
||||
*/
|
||||
aezeedPassphrase: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* recovery_window is an optional argument specifying the address lookahead
|
||||
* when restoring a wallet seed. The recovery window applies to each
|
||||
* individual branch of the BIP44 derivation paths. Supplying a recovery
|
||||
* window of zero indicates that no addresses should be recovered, such after
|
||||
* the first initialization of the wallet.
|
||||
*
|
||||
* @generated from protobuf field: int32 recovery_window = 4;
|
||||
*/
|
||||
recoveryWindow: number;
|
||||
/**
|
||||
*
|
||||
* channel_backups is an optional argument that allows clients to recover the
|
||||
* settled funds within a set of channels. This should be populated if the
|
||||
* user was unable to close out all channels and sweep funds before partial or
|
||||
* total data loss occurred. If specified, then after on-chain recovery of
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 5;
|
||||
*/
|
||||
channelBackups?: ChanBackupSnapshot;
|
||||
/**
|
||||
*
|
||||
* stateless_init is an optional argument instructing the daemon NOT to create
|
||||
* any *.macaroon files in its filesystem. If this parameter is set, then 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!
|
||||
*
|
||||
* @generated from protobuf field: bool stateless_init = 6;
|
||||
*/
|
||||
statelessInit: boolean;
|
||||
/**
|
||||
*
|
||||
* extended_master_key is an alternative to specifying cipher_seed_mnemonic and
|
||||
* aezeed_passphrase. Instead of deriving the master root key from the entropy
|
||||
* of an aezeed cipher seed, the given extended master root key is used
|
||||
* directly as the wallet's master key. This allows users to import/use a
|
||||
* master key from another wallet. When doing so, lnd still uses its default
|
||||
* SegWit only (BIP49/84) derivation paths and funds from custom/non-default
|
||||
* derivation paths will not automatically appear in the on-chain wallet. Using
|
||||
* an 'xprv' instead of an aezeed also has the disadvantage that the wallet's
|
||||
* birthday is not known as that is an information that's only encoded in the
|
||||
* aezeed, not the xprv. Therefore a birthday needs to be specified in
|
||||
* extended_master_key_birthday_timestamp or a "safe" default value will be
|
||||
* used.
|
||||
*
|
||||
* @generated from protobuf field: string extended_master_key = 7;
|
||||
*/
|
||||
extendedMasterKey: string;
|
||||
/**
|
||||
*
|
||||
* extended_master_key_birthday_timestamp is the optional unix timestamp in
|
||||
* seconds to use as the wallet's birthday when using an extended master key
|
||||
* to restore the wallet. lnd will only start scanning for funds in blocks that
|
||||
* are after the birthday which can speed up the process significantly. If the
|
||||
* birthday is not known, this should be left at its default value of 0 in
|
||||
* which case lnd will start scanning from the first SegWit block (481824 on
|
||||
* mainnet).
|
||||
*
|
||||
* @generated from protobuf field: uint64 extended_master_key_birthday_timestamp = 8;
|
||||
*/
|
||||
extendedMasterKeyBirthdayTimestamp: bigint;
|
||||
/**
|
||||
*
|
||||
* watch_only is the third option of initializing a wallet: by importing
|
||||
* account xpubs only and therefore creating a watch-only wallet that does not
|
||||
* contain any private keys. That means the wallet won't be able to sign for
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf field: lnrpc.WatchOnly watch_only = 9;
|
||||
*/
|
||||
watchOnly?: WatchOnly;
|
||||
/**
|
||||
*
|
||||
* macaroon_root_key is an optional 32 byte macaroon root key that can be
|
||||
* provided when initializing the wallet rather than letting lnd generate one
|
||||
* on its own.
|
||||
*
|
||||
* @generated from protobuf field: bytes macaroon_root_key = 10;
|
||||
*/
|
||||
macaroonRootKey: Uint8Array;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.InitWalletResponse
|
||||
*/
|
||||
export interface InitWalletResponse {
|
||||
/**
|
||||
*
|
||||
* The binary serialized admin macaroon that can be used to access the daemon
|
||||
* after creating the wallet. If the stateless_init parameter was set to true,
|
||||
* this is the ONLY copy of the macaroon and MUST be stored safely by the
|
||||
* caller. Otherwise a copy of this macaroon is also persisted on disk by the
|
||||
* daemon, together with other macaroon files.
|
||||
*
|
||||
* @generated from protobuf field: bytes admin_macaroon = 1;
|
||||
*/
|
||||
adminMacaroon: Uint8Array;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.WatchOnly
|
||||
*/
|
||||
export interface WatchOnly {
|
||||
/**
|
||||
*
|
||||
* The unix timestamp in seconds of when the master key was created. lnd will
|
||||
* only start scanning for funds in blocks that are after the birthday which
|
||||
* can speed up the process significantly. If the birthday is not known, this
|
||||
* should be left at its default value of 0 in which case lnd will start
|
||||
* scanning from the first SegWit block (481824 on mainnet).
|
||||
*
|
||||
* @generated from protobuf field: uint64 master_key_birthday_timestamp = 1;
|
||||
*/
|
||||
masterKeyBirthdayTimestamp: bigint;
|
||||
/**
|
||||
*
|
||||
* The fingerprint of the root key (also known as the key with derivation path
|
||||
* m/) from which the account public keys were derived from. This may be
|
||||
* required by some hardware wallets for proper identification and signing. The
|
||||
* bytes must be in big-endian order.
|
||||
*
|
||||
* @generated from protobuf field: bytes master_key_fingerprint = 2;
|
||||
*/
|
||||
masterKeyFingerprint: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* The list of accounts to import. There _must_ be an account for all of lnd's
|
||||
* main key scopes: BIP49/BIP84 (m/49'/0'/0', m/84'/0'/0', note that the
|
||||
* coin type is always 0, even for testnet/regtest) and lnd's internal key
|
||||
* scope (m/1017'/<coin_type>'/<account>'), where account is the key family as
|
||||
* defined in `keychain/derivation.go` (currently indices 0 to 9).
|
||||
*
|
||||
* @generated from protobuf field: repeated lnrpc.WatchOnlyAccount accounts = 3;
|
||||
*/
|
||||
accounts: WatchOnlyAccount[];
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.WatchOnlyAccount
|
||||
*/
|
||||
export interface WatchOnlyAccount {
|
||||
/**
|
||||
*
|
||||
* Purpose is the first number in the derivation path, must be either 49, 84
|
||||
* or 1017.
|
||||
*
|
||||
* @generated from protobuf field: uint32 purpose = 1;
|
||||
*/
|
||||
purpose: number;
|
||||
/**
|
||||
*
|
||||
* Coin type is the second number in the derivation path, this is _always_ 0
|
||||
* for purposes 49 and 84. It only needs to be set to 1 for purpose 1017 on
|
||||
* testnet or regtest.
|
||||
*
|
||||
* @generated from protobuf field: uint32 coin_type = 2;
|
||||
*/
|
||||
coinType: number;
|
||||
/**
|
||||
*
|
||||
* Account is the third number in the derivation path. For purposes 49 and 84
|
||||
* at least the default account (index 0) needs to be created but optional
|
||||
* additional accounts are allowed. For purpose 1017 there needs to be exactly
|
||||
* one account for each of the key families defined in `keychain/derivation.go`
|
||||
* (currently indices 0 to 9)
|
||||
*
|
||||
* @generated from protobuf field: uint32 account = 3;
|
||||
*/
|
||||
account: number;
|
||||
/**
|
||||
*
|
||||
* The extended public key at depth 3 for the given account.
|
||||
*
|
||||
* @generated from protobuf field: string xpub = 4;
|
||||
*/
|
||||
xpub: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.UnlockWalletRequest
|
||||
*/
|
||||
export interface UnlockWalletRequest {
|
||||
/**
|
||||
*
|
||||
* wallet_password should be the current valid passphrase for the daemon. This
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf field: bytes wallet_password = 1;
|
||||
*/
|
||||
walletPassword: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* recovery_window is an optional argument specifying the address lookahead
|
||||
* when restoring a wallet seed. The recovery window applies to each
|
||||
* individual branch of the BIP44 derivation paths. Supplying a recovery
|
||||
* window of zero indicates that no addresses should be recovered, such after
|
||||
* the first initialization of the wallet.
|
||||
*
|
||||
* @generated from protobuf field: int32 recovery_window = 2;
|
||||
*/
|
||||
recoveryWindow: number;
|
||||
/**
|
||||
*
|
||||
* channel_backups is an optional argument that allows clients to recover the
|
||||
* settled funds within a set of channels. This should be populated if the
|
||||
* user was unable to close out all channels and sweep funds before partial or
|
||||
* total data loss occurred. If specified, then after on-chain recovery of
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 3;
|
||||
*/
|
||||
channelBackups?: ChanBackupSnapshot;
|
||||
/**
|
||||
*
|
||||
* stateless_init is an optional argument instructing the daemon NOT to create
|
||||
* any *.macaroon files in its file system.
|
||||
*
|
||||
* @generated from protobuf field: bool stateless_init = 4;
|
||||
*/
|
||||
statelessInit: boolean;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.UnlockWalletResponse
|
||||
*/
|
||||
export interface UnlockWalletResponse {
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.ChangePasswordRequest
|
||||
*/
|
||||
export interface ChangePasswordRequest {
|
||||
/**
|
||||
*
|
||||
* current_password should be the current valid passphrase used to unlock the
|
||||
* daemon. When using REST, this field must be encoded as base64.
|
||||
*
|
||||
* @generated from protobuf field: bytes current_password = 1;
|
||||
*/
|
||||
currentPassword: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @generated from protobuf field: bytes new_password = 2;
|
||||
*/
|
||||
newPassword: Uint8Array;
|
||||
/**
|
||||
*
|
||||
* stateless_init is an optional argument instructing the daemon NOT to create
|
||||
* any *.macaroon files in its filesystem. If this parameter is set, then 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!
|
||||
*
|
||||
* @generated from protobuf field: bool stateless_init = 3;
|
||||
*/
|
||||
statelessInit: boolean;
|
||||
/**
|
||||
*
|
||||
* new_macaroon_root_key is an optional argument instructing the daemon to
|
||||
* rotate the macaroon root key when set to true. This will invalidate all
|
||||
* previously generated macaroons.
|
||||
*
|
||||
* @generated from protobuf field: bool new_macaroon_root_key = 4;
|
||||
*/
|
||||
newMacaroonRootKey: boolean;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message lnrpc.ChangePasswordResponse
|
||||
*/
|
||||
export interface ChangePasswordResponse {
|
||||
/**
|
||||
*
|
||||
* The binary serialized admin macaroon that can be used to access the daemon
|
||||
* after rotating the macaroon root key. If both the stateless_init and
|
||||
* new_macaroon_root_key parameter were set to true, this is the ONLY copy of
|
||||
* the macaroon that was created from the new root key and MUST be stored
|
||||
* safely by the caller. Otherwise a copy of this macaroon is also persisted on
|
||||
* disk by the daemon, together with other macaroon files.
|
||||
*
|
||||
* @generated from protobuf field: bytes admin_macaroon = 1;
|
||||
*/
|
||||
adminMacaroon: Uint8Array;
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GenSeedRequest$Type extends MessageType<GenSeedRequest> {
|
||||
constructor() {
|
||||
super("lnrpc.GenSeedRequest", [
|
||||
{ no: 1, name: "aezeed_passphrase", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 2, name: "seed_entropy", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GenSeedRequest>): GenSeedRequest {
|
||||
const message = { aezeedPassphrase: new Uint8Array(0), seedEntropy: new Uint8Array(0) };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GenSeedRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GenSeedRequest): GenSeedRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes aezeed_passphrase */ 1:
|
||||
message.aezeedPassphrase = reader.bytes();
|
||||
break;
|
||||
case /* bytes seed_entropy */ 2:
|
||||
message.seedEntropy = 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: GenSeedRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes aezeed_passphrase = 1; */
|
||||
if (message.aezeedPassphrase.length)
|
||||
writer.tag(1, WireType.LengthDelimited).bytes(message.aezeedPassphrase);
|
||||
/* bytes seed_entropy = 2; */
|
||||
if (message.seedEntropy.length)
|
||||
writer.tag(2, WireType.LengthDelimited).bytes(message.seedEntropy);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.GenSeedRequest
|
||||
*/
|
||||
export const GenSeedRequest = new GenSeedRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GenSeedResponse$Type extends MessageType<GenSeedResponse> {
|
||||
constructor() {
|
||||
super("lnrpc.GenSeedResponse", [
|
||||
{ no: 1, name: "cipher_seed_mnemonic", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "enciphered_seed", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GenSeedResponse>): GenSeedResponse {
|
||||
const message = { cipherSeedMnemonic: [], encipheredSeed: new Uint8Array(0) };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GenSeedResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GenSeedResponse): GenSeedResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* repeated string cipher_seed_mnemonic */ 1:
|
||||
message.cipherSeedMnemonic.push(reader.string());
|
||||
break;
|
||||
case /* bytes enciphered_seed */ 2:
|
||||
message.encipheredSeed = 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: GenSeedResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* repeated string cipher_seed_mnemonic = 1; */
|
||||
for (let i = 0; i < message.cipherSeedMnemonic.length; i++)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.cipherSeedMnemonic[i]);
|
||||
/* bytes enciphered_seed = 2; */
|
||||
if (message.encipheredSeed.length)
|
||||
writer.tag(2, WireType.LengthDelimited).bytes(message.encipheredSeed);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.GenSeedResponse
|
||||
*/
|
||||
export const GenSeedResponse = new GenSeedResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class InitWalletRequest$Type extends MessageType<InitWalletRequest> {
|
||||
constructor() {
|
||||
super("lnrpc.InitWalletRequest", [
|
||||
{ no: 1, name: "wallet_password", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 2, name: "cipher_seed_mnemonic", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "aezeed_passphrase", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 4, name: "recovery_window", kind: "scalar", T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 5, name: "channel_backups", kind: "message", T: () => ChanBackupSnapshot },
|
||||
{ no: 6, name: "stateless_init", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
|
||||
{ no: 7, name: "extended_master_key", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 8, name: "extended_master_key_birthday_timestamp", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
|
||||
{ no: 9, name: "watch_only", kind: "message", T: () => WatchOnly },
|
||||
{ no: 10, name: "macaroon_root_key", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
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) };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<InitWalletRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: InitWalletRequest): InitWalletRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes wallet_password */ 1:
|
||||
message.walletPassword = reader.bytes();
|
||||
break;
|
||||
case /* repeated string cipher_seed_mnemonic */ 2:
|
||||
message.cipherSeedMnemonic.push(reader.string());
|
||||
break;
|
||||
case /* bytes aezeed_passphrase */ 3:
|
||||
message.aezeedPassphrase = reader.bytes();
|
||||
break;
|
||||
case /* int32 recovery_window */ 4:
|
||||
message.recoveryWindow = reader.int32();
|
||||
break;
|
||||
case /* lnrpc.ChanBackupSnapshot channel_backups */ 5:
|
||||
message.channelBackups = ChanBackupSnapshot.internalBinaryRead(reader, reader.uint32(), options, message.channelBackups);
|
||||
break;
|
||||
case /* bool stateless_init */ 6:
|
||||
message.statelessInit = reader.bool();
|
||||
break;
|
||||
case /* string extended_master_key */ 7:
|
||||
message.extendedMasterKey = reader.string();
|
||||
break;
|
||||
case /* uint64 extended_master_key_birthday_timestamp */ 8:
|
||||
message.extendedMasterKeyBirthdayTimestamp = reader.uint64().toBigInt();
|
||||
break;
|
||||
case /* lnrpc.WatchOnly watch_only */ 9:
|
||||
message.watchOnly = WatchOnly.internalBinaryRead(reader, reader.uint32(), options, message.watchOnly);
|
||||
break;
|
||||
case /* bytes macaroon_root_key */ 10:
|
||||
message.macaroonRootKey = 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: InitWalletRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes wallet_password = 1; */
|
||||
if (message.walletPassword.length)
|
||||
writer.tag(1, WireType.LengthDelimited).bytes(message.walletPassword);
|
||||
/* repeated string cipher_seed_mnemonic = 2; */
|
||||
for (let i = 0; i < message.cipherSeedMnemonic.length; i++)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.cipherSeedMnemonic[i]);
|
||||
/* bytes aezeed_passphrase = 3; */
|
||||
if (message.aezeedPassphrase.length)
|
||||
writer.tag(3, WireType.LengthDelimited).bytes(message.aezeedPassphrase);
|
||||
/* int32 recovery_window = 4; */
|
||||
if (message.recoveryWindow !== 0)
|
||||
writer.tag(4, WireType.Varint).int32(message.recoveryWindow);
|
||||
/* lnrpc.ChanBackupSnapshot channel_backups = 5; */
|
||||
if (message.channelBackups)
|
||||
ChanBackupSnapshot.internalBinaryWrite(message.channelBackups, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
|
||||
/* bool stateless_init = 6; */
|
||||
if (message.statelessInit !== false)
|
||||
writer.tag(6, WireType.Varint).bool(message.statelessInit);
|
||||
/* string extended_master_key = 7; */
|
||||
if (message.extendedMasterKey !== "")
|
||||
writer.tag(7, WireType.LengthDelimited).string(message.extendedMasterKey);
|
||||
/* uint64 extended_master_key_birthday_timestamp = 8; */
|
||||
if (message.extendedMasterKeyBirthdayTimestamp !== 0n)
|
||||
writer.tag(8, WireType.Varint).uint64(message.extendedMasterKeyBirthdayTimestamp);
|
||||
/* lnrpc.WatchOnly watch_only = 9; */
|
||||
if (message.watchOnly)
|
||||
WatchOnly.internalBinaryWrite(message.watchOnly, writer.tag(9, WireType.LengthDelimited).fork(), options).join();
|
||||
/* bytes macaroon_root_key = 10; */
|
||||
if (message.macaroonRootKey.length)
|
||||
writer.tag(10, WireType.LengthDelimited).bytes(message.macaroonRootKey);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.InitWalletRequest
|
||||
*/
|
||||
export const InitWalletRequest = new InitWalletRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class InitWalletResponse$Type extends MessageType<InitWalletResponse> {
|
||||
constructor() {
|
||||
super("lnrpc.InitWalletResponse", [
|
||||
{ no: 1, name: "admin_macaroon", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<InitWalletResponse>): InitWalletResponse {
|
||||
const message = { adminMacaroon: new Uint8Array(0) };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<InitWalletResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: InitWalletResponse): InitWalletResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes admin_macaroon */ 1:
|
||||
message.adminMacaroon = 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: InitWalletResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes admin_macaroon = 1; */
|
||||
if (message.adminMacaroon.length)
|
||||
writer.tag(1, WireType.LengthDelimited).bytes(message.adminMacaroon);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.InitWalletResponse
|
||||
*/
|
||||
export const InitWalletResponse = new InitWalletResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class WatchOnly$Type extends MessageType<WatchOnly> {
|
||||
constructor() {
|
||||
super("lnrpc.WatchOnly", [
|
||||
{ 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: 3, name: "accounts", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => WatchOnlyAccount }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<WatchOnly>): WatchOnly {
|
||||
const message = { masterKeyBirthdayTimestamp: 0n, masterKeyFingerprint: new Uint8Array(0), accounts: [] };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<WatchOnly>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: WatchOnly): WatchOnly {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint64 master_key_birthday_timestamp */ 1:
|
||||
message.masterKeyBirthdayTimestamp = reader.uint64().toBigInt();
|
||||
break;
|
||||
case /* bytes master_key_fingerprint */ 2:
|
||||
message.masterKeyFingerprint = reader.bytes();
|
||||
break;
|
||||
case /* repeated lnrpc.WatchOnlyAccount accounts */ 3:
|
||||
message.accounts.push(WatchOnlyAccount.internalBinaryRead(reader, reader.uint32(), 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;
|
||||
}
|
||||
internalBinaryWrite(message: WatchOnly, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint64 master_key_birthday_timestamp = 1; */
|
||||
if (message.masterKeyBirthdayTimestamp !== 0n)
|
||||
writer.tag(1, WireType.Varint).uint64(message.masterKeyBirthdayTimestamp);
|
||||
/* bytes master_key_fingerprint = 2; */
|
||||
if (message.masterKeyFingerprint.length)
|
||||
writer.tag(2, WireType.LengthDelimited).bytes(message.masterKeyFingerprint);
|
||||
/* repeated lnrpc.WatchOnlyAccount accounts = 3; */
|
||||
for (let i = 0; i < message.accounts.length; i++)
|
||||
WatchOnlyAccount.internalBinaryWrite(message.accounts[i], writer.tag(3, 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 lnrpc.WatchOnly
|
||||
*/
|
||||
export const WatchOnly = new WatchOnly$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class WatchOnlyAccount$Type extends MessageType<WatchOnlyAccount> {
|
||||
constructor() {
|
||||
super("lnrpc.WatchOnlyAccount", [
|
||||
{ no: 1, name: "purpose", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 2, name: "coin_type", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 3, name: "account", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 4, name: "xpub", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<WatchOnlyAccount>): WatchOnlyAccount {
|
||||
const message = { purpose: 0, coinType: 0, account: 0, xpub: "" };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<WatchOnlyAccount>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: WatchOnlyAccount): WatchOnlyAccount {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 purpose */ 1:
|
||||
message.purpose = reader.uint32();
|
||||
break;
|
||||
case /* uint32 coin_type */ 2:
|
||||
message.coinType = reader.uint32();
|
||||
break;
|
||||
case /* uint32 account */ 3:
|
||||
message.account = reader.uint32();
|
||||
break;
|
||||
case /* string xpub */ 4:
|
||||
message.xpub = reader.string();
|
||||
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: WatchOnlyAccount, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 purpose = 1; */
|
||||
if (message.purpose !== 0)
|
||||
writer.tag(1, WireType.Varint).uint32(message.purpose);
|
||||
/* uint32 coin_type = 2; */
|
||||
if (message.coinType !== 0)
|
||||
writer.tag(2, WireType.Varint).uint32(message.coinType);
|
||||
/* uint32 account = 3; */
|
||||
if (message.account !== 0)
|
||||
writer.tag(3, WireType.Varint).uint32(message.account);
|
||||
/* string xpub = 4; */
|
||||
if (message.xpub !== "")
|
||||
writer.tag(4, WireType.LengthDelimited).string(message.xpub);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.WatchOnlyAccount
|
||||
*/
|
||||
export const WatchOnlyAccount = new WatchOnlyAccount$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class UnlockWalletRequest$Type extends MessageType<UnlockWalletRequest> {
|
||||
constructor() {
|
||||
super("lnrpc.UnlockWalletRequest", [
|
||||
{ no: 1, name: "wallet_password", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 2, name: "recovery_window", kind: "scalar", T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 3, name: "channel_backups", kind: "message", T: () => ChanBackupSnapshot },
|
||||
{ no: 4, name: "stateless_init", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<UnlockWalletRequest>): UnlockWalletRequest {
|
||||
const message = { walletPassword: new Uint8Array(0), recoveryWindow: 0, statelessInit: false };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<UnlockWalletRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UnlockWalletRequest): UnlockWalletRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes wallet_password */ 1:
|
||||
message.walletPassword = reader.bytes();
|
||||
break;
|
||||
case /* int32 recovery_window */ 2:
|
||||
message.recoveryWindow = reader.int32();
|
||||
break;
|
||||
case /* lnrpc.ChanBackupSnapshot channel_backups */ 3:
|
||||
message.channelBackups = ChanBackupSnapshot.internalBinaryRead(reader, reader.uint32(), options, message.channelBackups);
|
||||
break;
|
||||
case /* bool stateless_init */ 4:
|
||||
message.statelessInit = 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: UnlockWalletRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes wallet_password = 1; */
|
||||
if (message.walletPassword.length)
|
||||
writer.tag(1, WireType.LengthDelimited).bytes(message.walletPassword);
|
||||
/* int32 recovery_window = 2; */
|
||||
if (message.recoveryWindow !== 0)
|
||||
writer.tag(2, WireType.Varint).int32(message.recoveryWindow);
|
||||
/* lnrpc.ChanBackupSnapshot channel_backups = 3; */
|
||||
if (message.channelBackups)
|
||||
ChanBackupSnapshot.internalBinaryWrite(message.channelBackups, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
/* bool stateless_init = 4; */
|
||||
if (message.statelessInit !== false)
|
||||
writer.tag(4, WireType.Varint).bool(message.statelessInit);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.UnlockWalletRequest
|
||||
*/
|
||||
export const UnlockWalletRequest = new UnlockWalletRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class UnlockWalletResponse$Type extends MessageType<UnlockWalletResponse> {
|
||||
constructor() {
|
||||
super("lnrpc.UnlockWalletResponse", []);
|
||||
}
|
||||
create(value?: PartialMessage<UnlockWalletResponse>): UnlockWalletResponse {
|
||||
const message = {};
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<UnlockWalletResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UnlockWalletResponse): UnlockWalletResponse {
|
||||
return target ?? this.create();
|
||||
}
|
||||
internalBinaryWrite(message: UnlockWalletResponse, 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 lnrpc.UnlockWalletResponse
|
||||
*/
|
||||
export const UnlockWalletResponse = new UnlockWalletResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ChangePasswordRequest$Type extends MessageType<ChangePasswordRequest> {
|
||||
constructor() {
|
||||
super("lnrpc.ChangePasswordRequest", [
|
||||
{ no: 1, name: "current_password", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 2, name: "new_password", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 3, name: "stateless_init", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
|
||||
{ no: 4, name: "new_macaroon_root_key", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ChangePasswordRequest>): ChangePasswordRequest {
|
||||
const message = { currentPassword: new Uint8Array(0), newPassword: new Uint8Array(0), statelessInit: false, newMacaroonRootKey: false };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ChangePasswordRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ChangePasswordRequest): ChangePasswordRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes current_password */ 1:
|
||||
message.currentPassword = reader.bytes();
|
||||
break;
|
||||
case /* bytes new_password */ 2:
|
||||
message.newPassword = reader.bytes();
|
||||
break;
|
||||
case /* bool stateless_init */ 3:
|
||||
message.statelessInit = reader.bool();
|
||||
break;
|
||||
case /* bool new_macaroon_root_key */ 4:
|
||||
message.newMacaroonRootKey = 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: ChangePasswordRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes current_password = 1; */
|
||||
if (message.currentPassword.length)
|
||||
writer.tag(1, WireType.LengthDelimited).bytes(message.currentPassword);
|
||||
/* bytes new_password = 2; */
|
||||
if (message.newPassword.length)
|
||||
writer.tag(2, WireType.LengthDelimited).bytes(message.newPassword);
|
||||
/* bool stateless_init = 3; */
|
||||
if (message.statelessInit !== false)
|
||||
writer.tag(3, WireType.Varint).bool(message.statelessInit);
|
||||
/* bool new_macaroon_root_key = 4; */
|
||||
if (message.newMacaroonRootKey !== false)
|
||||
writer.tag(4, WireType.Varint).bool(message.newMacaroonRootKey);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.ChangePasswordRequest
|
||||
*/
|
||||
export const ChangePasswordRequest = new ChangePasswordRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ChangePasswordResponse$Type extends MessageType<ChangePasswordResponse> {
|
||||
constructor() {
|
||||
super("lnrpc.ChangePasswordResponse", [
|
||||
{ no: 1, name: "admin_macaroon", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ChangePasswordResponse>): ChangePasswordResponse {
|
||||
const message = { adminMacaroon: new Uint8Array(0) };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ChangePasswordResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ChangePasswordResponse): ChangePasswordResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* bytes admin_macaroon */ 1:
|
||||
message.adminMacaroon = 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: ChangePasswordResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* bytes admin_macaroon = 1; */
|
||||
if (message.adminMacaroon.length)
|
||||
writer.tag(1, WireType.LengthDelimited).bytes(message.adminMacaroon);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message lnrpc.ChangePasswordResponse
|
||||
*/
|
||||
export const ChangePasswordResponse = new ChangePasswordResponse$Type();
|
||||
/**
|
||||
* @generated ServiceType for protobuf service lnrpc.WalletUnlocker
|
||||
*/
|
||||
export const WalletUnlocker = new ServiceType("lnrpc.WalletUnlocker", [
|
||||
{ name: "GenSeed", options: {}, I: GenSeedRequest, O: GenSeedResponse },
|
||||
{ name: "InitWallet", options: {}, I: InitWalletRequest, O: InitWalletResponse },
|
||||
{ name: "UnlockWallet", options: {}, I: UnlockWalletRequest, O: UnlockWalletResponse },
|
||||
{ name: "ChangePassword", options: {}, I: ChangePasswordRequest, O: ChangePasswordResponse }
|
||||
]);
|
||||
338
proto/others/walletunlocker.proto
Normal file
338
proto/others/walletunlocker.proto
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package lnrpc;
|
||||
|
||||
import "lightning.proto";
|
||||
|
||||
option go_package = "github.com/lightningnetwork/lnd/lnrpc";
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
// WalletUnlocker is a service that is used to set up a wallet password for
|
||||
// lnd at first startup, and unlock a previously set up wallet.
|
||||
service WalletUnlocker {
|
||||
/*
|
||||
GenSeed is the first method that should be used to instantiate a new lnd
|
||||
instance. This method allows a caller to generate a new aezeed cipher seed
|
||||
given an optional passphrase. If provided, the passphrase will be necessary
|
||||
to decrypt the cipherseed to expose the internal wallet seed.
|
||||
|
||||
Once the cipherseed is obtained and verified by the user, the InitWallet
|
||||
method should be used to commit the newly generated seed, and create the
|
||||
wallet.
|
||||
*/
|
||||
rpc GenSeed (GenSeedRequest) returns (GenSeedResponse);
|
||||
|
||||
/*
|
||||
InitWallet is used when lnd is starting up for the first time to fully
|
||||
initialize the daemon and its internal wallet. At the very least a wallet
|
||||
password must be provided. This will be used to encrypt sensitive material
|
||||
on disk.
|
||||
|
||||
In the case of a recovery scenario, the user can also specify their aezeed
|
||||
mnemonic and passphrase. If set, then the daemon will use this prior state
|
||||
to initialize its internal wallet.
|
||||
|
||||
Alternatively, this can be used along with the GenSeed RPC to obtain a
|
||||
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.
|
||||
*/
|
||||
rpc InitWallet (InitWalletRequest) returns (InitWalletResponse);
|
||||
|
||||
/* lncli: `unlock`
|
||||
UnlockWallet is used at startup of lnd to provide a password to unlock
|
||||
the wallet database.
|
||||
*/
|
||||
rpc UnlockWallet (UnlockWalletRequest) returns (UnlockWalletResponse);
|
||||
|
||||
/* lncli: `changepassword`
|
||||
ChangePassword changes the password of the encrypted wallet. This will
|
||||
automatically unlock the wallet database if successful.
|
||||
*/
|
||||
rpc ChangePassword (ChangePasswordRequest) returns (ChangePasswordResponse);
|
||||
}
|
||||
|
||||
message GenSeedRequest {
|
||||
/*
|
||||
aezeed_passphrase is an optional user provided passphrase that will be used
|
||||
to encrypt the generated aezeed cipher seed. When using REST, this field
|
||||
must be encoded as base64.
|
||||
*/
|
||||
bytes aezeed_passphrase = 1;
|
||||
|
||||
/*
|
||||
seed_entropy is an optional 16-bytes generated via CSPRNG. If not
|
||||
specified, then a fresh set of randomness will be used to create the seed.
|
||||
When using REST, this field must be encoded as base64.
|
||||
*/
|
||||
bytes seed_entropy = 2;
|
||||
}
|
||||
message GenSeedResponse {
|
||||
/*
|
||||
cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed
|
||||
cipher seed obtained by the user. This field is optional, as if not
|
||||
provided, then the daemon will generate a new cipher seed for the user.
|
||||
Otherwise, then the daemon will attempt to recover the wallet state linked
|
||||
to this cipher seed.
|
||||
*/
|
||||
repeated string cipher_seed_mnemonic = 1;
|
||||
|
||||
/*
|
||||
enciphered_seed are the raw aezeed cipher seed bytes. This is the raw
|
||||
cipher text before run through our mnemonic encoding scheme.
|
||||
*/
|
||||
bytes enciphered_seed = 2;
|
||||
}
|
||||
|
||||
message InitWalletRequest {
|
||||
/*
|
||||
wallet_password is the passphrase that should be used to encrypt the
|
||||
wallet. This MUST be at least 8 chars in length. After creation, this
|
||||
password is required to unlock the daemon. When using REST, this field
|
||||
must be encoded as base64.
|
||||
*/
|
||||
bytes wallet_password = 1;
|
||||
|
||||
/*
|
||||
cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed
|
||||
cipher seed obtained by the user. This may have been generated by the
|
||||
GenSeed method, or be an existing seed.
|
||||
*/
|
||||
repeated string cipher_seed_mnemonic = 2;
|
||||
|
||||
/*
|
||||
aezeed_passphrase is an optional user provided passphrase that will be used
|
||||
to encrypt the generated aezeed cipher seed. When using REST, this field
|
||||
must be encoded as base64.
|
||||
*/
|
||||
bytes aezeed_passphrase = 3;
|
||||
|
||||
/*
|
||||
recovery_window is an optional argument specifying the address lookahead
|
||||
when restoring a wallet seed. The recovery window applies to each
|
||||
individual branch of the BIP44 derivation paths. Supplying a recovery
|
||||
window of zero indicates that no addresses should be recovered, such after
|
||||
the first initialization of the wallet.
|
||||
*/
|
||||
int32 recovery_window = 4;
|
||||
|
||||
/*
|
||||
channel_backups is an optional argument that allows clients to recover the
|
||||
settled funds within a set of channels. This should be populated if the
|
||||
user was unable to close out all channels and sweep funds before partial or
|
||||
total data loss occurred. If specified, then after on-chain recovery of
|
||||
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.
|
||||
*/
|
||||
ChanBackupSnapshot channel_backups = 5;
|
||||
|
||||
/*
|
||||
stateless_init is an optional argument instructing the daemon NOT to create
|
||||
any *.macaroon files in its filesystem. If this parameter is set, then 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!
|
||||
*/
|
||||
bool stateless_init = 6;
|
||||
|
||||
/*
|
||||
extended_master_key is an alternative to specifying cipher_seed_mnemonic and
|
||||
aezeed_passphrase. Instead of deriving the master root key from the entropy
|
||||
of an aezeed cipher seed, the given extended master root key is used
|
||||
directly as the wallet's master key. This allows users to import/use a
|
||||
master key from another wallet. When doing so, lnd still uses its default
|
||||
SegWit only (BIP49/84) derivation paths and funds from custom/non-default
|
||||
derivation paths will not automatically appear in the on-chain wallet. Using
|
||||
an 'xprv' instead of an aezeed also has the disadvantage that the wallet's
|
||||
birthday is not known as that is an information that's only encoded in the
|
||||
aezeed, not the xprv. Therefore a birthday needs to be specified in
|
||||
extended_master_key_birthday_timestamp or a "safe" default value will be
|
||||
used.
|
||||
*/
|
||||
string extended_master_key = 7;
|
||||
|
||||
/*
|
||||
extended_master_key_birthday_timestamp is the optional unix timestamp in
|
||||
seconds to use as the wallet's birthday when using an extended master key
|
||||
to restore the wallet. lnd will only start scanning for funds in blocks that
|
||||
are after the birthday which can speed up the process significantly. If the
|
||||
birthday is not known, this should be left at its default value of 0 in
|
||||
which case lnd will start scanning from the first SegWit block (481824 on
|
||||
mainnet).
|
||||
*/
|
||||
uint64 extended_master_key_birthday_timestamp = 8;
|
||||
|
||||
/*
|
||||
watch_only is the third option of initializing a wallet: by importing
|
||||
account xpubs only and therefore creating a watch-only wallet that does not
|
||||
contain any private keys. That means the wallet won't be able to sign for
|
||||
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.
|
||||
*/
|
||||
WatchOnly watch_only = 9;
|
||||
|
||||
/*
|
||||
macaroon_root_key is an optional 32 byte macaroon root key that can be
|
||||
provided when initializing the wallet rather than letting lnd generate one
|
||||
on its own.
|
||||
*/
|
||||
bytes macaroon_root_key = 10;
|
||||
}
|
||||
message InitWalletResponse {
|
||||
/*
|
||||
The binary serialized admin macaroon that can be used to access the daemon
|
||||
after creating the wallet. If the stateless_init parameter was set to true,
|
||||
this is the ONLY copy of the macaroon and MUST be stored safely by the
|
||||
caller. Otherwise a copy of this macaroon is also persisted on disk by the
|
||||
daemon, together with other macaroon files.
|
||||
*/
|
||||
bytes admin_macaroon = 1;
|
||||
}
|
||||
|
||||
message WatchOnly {
|
||||
/*
|
||||
The unix timestamp in seconds of when the master key was created. lnd will
|
||||
only start scanning for funds in blocks that are after the birthday which
|
||||
can speed up the process significantly. If the birthday is not known, this
|
||||
should be left at its default value of 0 in which case lnd will start
|
||||
scanning from the first SegWit block (481824 on mainnet).
|
||||
*/
|
||||
uint64 master_key_birthday_timestamp = 1;
|
||||
|
||||
/*
|
||||
The fingerprint of the root key (also known as the key with derivation path
|
||||
m/) from which the account public keys were derived from. This may be
|
||||
required by some hardware wallets for proper identification and signing. The
|
||||
bytes must be in big-endian order.
|
||||
*/
|
||||
bytes master_key_fingerprint = 2;
|
||||
|
||||
/*
|
||||
The list of accounts to import. There _must_ be an account for all of lnd's
|
||||
main key scopes: BIP49/BIP84 (m/49'/0'/0', m/84'/0'/0', note that the
|
||||
coin type is always 0, even for testnet/regtest) and lnd's internal key
|
||||
scope (m/1017'/<coin_type>'/<account>'), where account is the key family as
|
||||
defined in `keychain/derivation.go` (currently indices 0 to 9).
|
||||
*/
|
||||
repeated WatchOnlyAccount accounts = 3;
|
||||
}
|
||||
|
||||
message WatchOnlyAccount {
|
||||
/*
|
||||
Purpose is the first number in the derivation path, must be either 49, 84
|
||||
or 1017.
|
||||
*/
|
||||
uint32 purpose = 1;
|
||||
|
||||
/*
|
||||
Coin type is the second number in the derivation path, this is _always_ 0
|
||||
for purposes 49 and 84. It only needs to be set to 1 for purpose 1017 on
|
||||
testnet or regtest.
|
||||
*/
|
||||
uint32 coin_type = 2;
|
||||
|
||||
/*
|
||||
Account is the third number in the derivation path. For purposes 49 and 84
|
||||
at least the default account (index 0) needs to be created but optional
|
||||
additional accounts are allowed. For purpose 1017 there needs to be exactly
|
||||
one account for each of the key families defined in `keychain/derivation.go`
|
||||
(currently indices 0 to 9)
|
||||
*/
|
||||
uint32 account = 3;
|
||||
|
||||
/*
|
||||
The extended public key at depth 3 for the given account.
|
||||
*/
|
||||
string xpub = 4;
|
||||
}
|
||||
|
||||
message UnlockWalletRequest {
|
||||
/*
|
||||
wallet_password should be the current valid passphrase for the daemon. This
|
||||
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.
|
||||
*/
|
||||
bytes wallet_password = 1;
|
||||
|
||||
/*
|
||||
recovery_window is an optional argument specifying the address lookahead
|
||||
when restoring a wallet seed. The recovery window applies to each
|
||||
individual branch of the BIP44 derivation paths. Supplying a recovery
|
||||
window of zero indicates that no addresses should be recovered, such after
|
||||
the first initialization of the wallet.
|
||||
*/
|
||||
int32 recovery_window = 2;
|
||||
|
||||
/*
|
||||
channel_backups is an optional argument that allows clients to recover the
|
||||
settled funds within a set of channels. This should be populated if the
|
||||
user was unable to close out all channels and sweep funds before partial or
|
||||
total data loss occurred. If specified, then after on-chain recovery of
|
||||
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.
|
||||
*/
|
||||
ChanBackupSnapshot channel_backups = 3;
|
||||
|
||||
/*
|
||||
stateless_init is an optional argument instructing the daemon NOT to create
|
||||
any *.macaroon files in its file system.
|
||||
*/
|
||||
bool stateless_init = 4;
|
||||
}
|
||||
message UnlockWalletResponse {
|
||||
}
|
||||
|
||||
message ChangePasswordRequest {
|
||||
/*
|
||||
current_password should be the current valid passphrase used to unlock the
|
||||
daemon. When using REST, this field must be encoded as base64.
|
||||
*/
|
||||
bytes current_password = 1;
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
bytes new_password = 2;
|
||||
|
||||
/*
|
||||
stateless_init is an optional argument instructing the daemon NOT to create
|
||||
any *.macaroon files in its filesystem. If this parameter is set, then 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!
|
||||
*/
|
||||
bool stateless_init = 3;
|
||||
|
||||
/*
|
||||
new_macaroon_root_key is an optional argument instructing the daemon to
|
||||
rotate the macaroon root key when set to true. This will invalidate all
|
||||
previously generated macaroons.
|
||||
*/
|
||||
bool new_macaroon_root_key = 4;
|
||||
}
|
||||
message ChangePasswordResponse {
|
||||
/*
|
||||
The binary serialized admin macaroon that can be used to access the daemon
|
||||
after rotating the macaroon root key. If both the stateless_init and
|
||||
new_macaroon_root_key parameter were set to true, this is the ONLY copy of
|
||||
the macaroon that was created from the new root key and MUST be stored
|
||||
safely by the caller. Otherwise a copy of this macaroon is also persisted on
|
||||
disk by the daemon, together with other macaroon files.
|
||||
*/
|
||||
bytes admin_macaroon = 1;
|
||||
}
|
||||
15
src/services/lnd/initWalletReq.ts
Normal file
15
src/services/lnd/initWalletReq.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { InitWalletRequest } from "../../../proto/lnd/walletunlocker";
|
||||
|
||||
|
||||
export const InitWalletReq = (secret: Buffer, cipherSeedMnemonic: string[]): InitWalletRequest => ({
|
||||
aezeedPassphrase: Buffer.alloc(0),
|
||||
walletPassword: secret,
|
||||
cipherSeedMnemonic,
|
||||
extendedMasterKey: "",
|
||||
extendedMasterKeyBirthdayTimestamp: 0n,
|
||||
macaroonRootKey: Buffer.alloc(0),
|
||||
recoveryWindow: 0,
|
||||
statelessInit: false,
|
||||
channelBackups: undefined,
|
||||
watchOnly: undefined,
|
||||
})
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { PubLogger, getLogger } from "../helpers/logger.js"
|
||||
import { LiquidityProvider } from "../lnd/liquidityProvider.js"
|
||||
import { Unlocker } from "./unlocker.js"
|
||||
import Storage from "../storage/index.js"
|
||||
import { TypeOrmMigrationRunner } from "../storage/migrations/runner.js"
|
||||
import Main from "./index.js"
|
||||
|
|
@ -17,6 +18,8 @@ export const initMainHandler = async (log: PubLogger, mainSettings: MainSettings
|
|||
if (manualMigration) {
|
||||
return
|
||||
}
|
||||
const unlocker = new Unlocker(mainSettings, storageManager)
|
||||
await unlocker.Unlock()
|
||||
|
||||
const mainHandler = new Main(mainSettings, storageManager)
|
||||
await mainHandler.lnd.Warmup()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export type MainSettings = {
|
|||
watchDogSettings: WatchdogSettings,
|
||||
liquiditySettings: LiquiditySettings,
|
||||
jwtSecret: string
|
||||
walletSecretPath: string
|
||||
incomingTxFee: number
|
||||
outgoingTxFee: number
|
||||
incomingAppInvoiceFee: number
|
||||
|
|
@ -27,11 +28,13 @@ export type MainSettings = {
|
|||
skipSanityCheck: boolean
|
||||
disableExternalPayments: boolean
|
||||
}
|
||||
|
||||
export type BitcoinCoreSettings = {
|
||||
port: number
|
||||
user: string
|
||||
pass: string
|
||||
}
|
||||
|
||||
export type TestSettings = MainSettings & { lndSettings: { otherNode: NodeSettings, thirdNode: NodeSettings, fourthNode: NodeSettings }, bitcoinCoreSettings: BitcoinCoreSettings }
|
||||
export const LoadMainSettingsFromEnv = (): MainSettings => {
|
||||
const storageSettings = LoadStorageSettingsFromEnv()
|
||||
|
|
@ -41,6 +44,7 @@ export const LoadMainSettingsFromEnv = (): MainSettings => {
|
|||
storageSettings: storageSettings,
|
||||
liquiditySettings: LoadLiquiditySettingsFromEnv(),
|
||||
jwtSecret: loadJwtSecret(storageSettings.dataDir),
|
||||
walletSecretPath: process.env.WALLET_SECRET_PATH || getDataPath(storageSettings.dataDir, ".wallet_secret"),
|
||||
incomingTxFee: EnvCanBeInteger("INCOMING_CHAIN_FEE_ROOT_BPS", 0) / 10000,
|
||||
outgoingTxFee: EnvCanBeInteger("OUTGOING_CHAIN_FEE_ROOT_BPS", 60) / 10000,
|
||||
incomingAppInvoiceFee: EnvCanBeInteger("INCOMING_INVOICE_FEE_ROOT_BPS", 0) / 10000,
|
||||
|
|
@ -101,7 +105,7 @@ export const loadJwtSecret = (dataDir: string): string => {
|
|||
return secret
|
||||
}
|
||||
log("JWT_SECRET not set in env, checking .jwt_secret file")
|
||||
const secretPath = dataDir !== "" ? `${dataDir}/.jwt_secret` : ".jwt_secret"
|
||||
const secretPath = getDataPath(dataDir, ".jwt_secret")
|
||||
try {
|
||||
const fileContent = fs.readFileSync(secretPath, "utf-8")
|
||||
return fileContent.trim()
|
||||
|
|
@ -111,4 +115,8 @@ export const loadJwtSecret = (dataDir: string): string => {
|
|||
fs.writeFileSync(secretPath, secret)
|
||||
return secret
|
||||
}
|
||||
}
|
||||
|
||||
export const getDataPath = (dataDir: string, dataPath: string) => {
|
||||
return dataDir !== "" ? `${dataDir}/${dataPath}` : dataPath
|
||||
}
|
||||
210
src/services/main/unlocker.ts
Normal file
210
src/services/main/unlocker.ts
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
import fs from 'fs'
|
||||
import crypto from 'crypto'
|
||||
import { GrpcTransport } from "@protobuf-ts/grpc-transport";
|
||||
import { credentials, Metadata } from '@grpc/grpc-js'
|
||||
import { getLogger } from '../helpers/logger.js';
|
||||
import { WalletUnlockerClient } from '../../../proto/lnd/walletunlocker.client.js';
|
||||
import { MainSettings } from '../main/settings.js';
|
||||
import { InitWalletReq } from '../lnd/initWalletReq.js';
|
||||
import Storage from '../storage/index.js'
|
||||
import { LightningClient } from '../../../proto/lnd/lightning.client.js';
|
||||
const DeadLineMetadata = (deadline = 10 * 1000) => ({ deadline: Date.now() + deadline })
|
||||
export class Unlocker {
|
||||
settings: MainSettings
|
||||
storage: Storage
|
||||
abortController = new AbortController()
|
||||
log = getLogger({ component: "unlocker" })
|
||||
constructor(settings: MainSettings, storage: Storage) {
|
||||
this.settings = settings
|
||||
this.storage = storage
|
||||
}
|
||||
|
||||
Stop = () => {
|
||||
this.abortController.abort()
|
||||
}
|
||||
|
||||
Unlock = async () => {
|
||||
const macroonPath = this.settings.lndSettings.mainNode.lndMacaroonPath
|
||||
const certPath = this.settings.lndSettings.mainNode.lndCertPath
|
||||
let macaroon = ""
|
||||
let lndCert: Buffer
|
||||
try {
|
||||
lndCert = fs.readFileSync(certPath)
|
||||
} catch (err: any) {
|
||||
throw new Error("failed to access lnd cert, make sure to set LND_CERT_PATH in .env, that the path is correct, and that lnd is running")
|
||||
}
|
||||
try {
|
||||
macaroon = fs.readFileSync(macroonPath).toString('hex');
|
||||
} catch (err: any) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
const { ln, pub } = macaroon === "" ? await this.InitFlow(lndCert) : await this.UnlockFlow(lndCert, macaroon)
|
||||
this.subscribeToBackups(ln, pub)
|
||||
}
|
||||
|
||||
UnlockFlow = async (lndCert: Buffer, macaroon: string) => {
|
||||
const ln = this.GetLightningClient(lndCert, macaroon)
|
||||
const info = await this.GetLndInfo(ln)
|
||||
if (info.ok) {
|
||||
this.log("the wallet is already unlocked with pub:", info.pub)
|
||||
return { ln, pub: info.pub }
|
||||
}
|
||||
if (info.failure !== 'locked') {
|
||||
throw new Error("failed to get lnd info for reason: " + info.failure)
|
||||
}
|
||||
this.log("wallet is locked, unlocking...")
|
||||
const secret = this.GetWalletSecret(false)
|
||||
if (!secret) {
|
||||
throw new Error("wallet secret not found to unlock wallet")
|
||||
}
|
||||
const unlocker = this.GetUnlockerClient(lndCert)
|
||||
await unlocker.unlockWallet({ walletPassword: Buffer.from(secret, 'hex'), recoveryWindow: 0, statelessInit: false, channelBackups: undefined }, DeadLineMetadata())
|
||||
const infoAfter = await this.GetLndInfo(ln)
|
||||
if (!infoAfter.ok) {
|
||||
throw new Error("failed to init lnd wallet " + infoAfter.failure)
|
||||
}
|
||||
this.log("unlocked wallet with pub:", infoAfter.pub)
|
||||
return { ln, pub: infoAfter.pub }
|
||||
}
|
||||
|
||||
InitFlow = async (lndCert: Buffer) => {
|
||||
this.log("macaroon not found, creating wallet...")
|
||||
const unlocker = this.GetUnlockerClient(lndCert)
|
||||
const entropy = crypto.randomBytes(16)
|
||||
const seedRes = await unlocker.genSeed({
|
||||
aezeedPassphrase: Buffer.alloc(0),
|
||||
seedEntropy: entropy
|
||||
}, DeadLineMetadata())
|
||||
console.log(seedRes.response.cipherSeedMnemonic)
|
||||
console.log(seedRes.response.encipheredSeed)
|
||||
this.log("seed created, encrypting and saving...")
|
||||
const { encryptedData, secret } = this.EncryptWalletSeed(seedRes.response.cipherSeedMnemonic)
|
||||
const req = InitWalletReq(secret, seedRes.response.cipherSeedMnemonic)
|
||||
const initRes = await unlocker.initWallet(req, DeadLineMetadata(60 * 1000))
|
||||
const adminMacaroon = Buffer.from(initRes.response.adminMacaroon).toString('hex')
|
||||
const ln = this.GetLightningClient(lndCert, adminMacaroon)
|
||||
const info = await this.GetLndInfo(ln)
|
||||
if (!info.ok) {
|
||||
throw new Error("failed to init lnd wallet " + info.failure)
|
||||
}
|
||||
await this.storage.liquidityStorage.SaveNodeSeed(info.pub, JSON.stringify(encryptedData))
|
||||
this.log("created wallet with pub:", info.pub)
|
||||
return { ln, pub: info.pub }
|
||||
}
|
||||
|
||||
GetLndInfo = async (ln: LightningClient): Promise<{ ok: false, failure: 'locked' | 'unknown' } | { ok: true, pub: string }> => {
|
||||
while (true) {
|
||||
try {
|
||||
const info = await ln.getInfo({}, DeadLineMetadata())
|
||||
return { ok: true, pub: info.response.identityPubkey }
|
||||
} catch (err: any) {
|
||||
if (err.message === '2 UNKNOWN: wallet locked, unlock it to enable full RPC access') {
|
||||
this.log("wallet is locked")
|
||||
return { ok: false, failure: 'locked' }
|
||||
} else if (err.message === '2 UNKNOWN: the RPC server is in the process of starting up, but not yet ready to accept calls') {
|
||||
this.log("lnd is not ready yet, waiting...")
|
||||
await new Promise((res) => setTimeout(res, 1000))
|
||||
} else {
|
||||
this.log("failed to get lnd info", err.message)
|
||||
return { ok: false, failure: 'unknown' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EncryptWalletSeed = (seed: string[]) => {
|
||||
return this.encrypt(seed.join('+'))
|
||||
}
|
||||
|
||||
DecryptWalletSeed = (data: { iv: string, encrypted: string }) => {
|
||||
return this.decrypt(data).split('+')
|
||||
}
|
||||
EncryptBackup = (backup: Buffer) => {
|
||||
return this.encrypt(backup.toString('hex'))
|
||||
}
|
||||
|
||||
DecryptBackup = (data: { iv: string, encrypted: string }) => {
|
||||
return Buffer.from(this.decrypt(data), 'hex')
|
||||
}
|
||||
|
||||
encrypt = (text: string) => {
|
||||
const sec = this.GetWalletSecret(true)
|
||||
const secret = Buffer.from(sec, 'hex')
|
||||
const iv = crypto.randomBytes(16)
|
||||
const cipher = crypto.createCipheriv('aes-256-cbc', secret, iv)
|
||||
const rawData = Buffer.from(text, 'utf-8')
|
||||
const cyData = cipher.update(rawData)
|
||||
const encrypted = Buffer.concat([cyData, cipher.final()])
|
||||
const encryptedData = { iv: iv.toString('hex'), encrypted: encrypted.toString('hex') }
|
||||
return { encryptedData, secret }
|
||||
}
|
||||
|
||||
decrypt = (data: { iv: string, encrypted: string }) => {
|
||||
const sec = this.GetWalletSecret(false)
|
||||
if (!sec) {
|
||||
throw new Error("wallet secret not found to decrypt seed")
|
||||
}
|
||||
const secret = Buffer.from(sec, 'hex')
|
||||
const iv = Buffer.from(data.iv, 'hex')
|
||||
const encrypted = Buffer.from(data.encrypted, 'hex')
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', secret, iv)
|
||||
const decrypted = decipher.update(encrypted)
|
||||
const raw = Buffer.concat([decrypted, decipher.final()])
|
||||
return raw.toString('utf-8')
|
||||
}
|
||||
|
||||
GetWalletSecret = (create: boolean) => {
|
||||
const path = this.settings.walletSecretPath
|
||||
let secret = ""
|
||||
try {
|
||||
secret = fs.readFileSync(path, 'utf-8')
|
||||
} catch {
|
||||
this.log("the wallet secret file was not found")
|
||||
}
|
||||
if (secret === "" && create) {
|
||||
secret = crypto.randomBytes(32).toString('hex')
|
||||
fs.writeFileSync(path, secret)
|
||||
}
|
||||
return secret
|
||||
}
|
||||
|
||||
subscribeToBackups = async (ln: LightningClient, pub: string) => {
|
||||
this.log("subscribing to channel backups for: ", pub)
|
||||
const stream = ln.subscribeChannelBackups({}, { abort: this.abortController.signal })
|
||||
stream.responses.onMessage((msg) => {
|
||||
if (msg.multiChanBackup) {
|
||||
this.log("received backup, saving")
|
||||
const { encryptedData } = this.EncryptBackup(Buffer.from(msg.multiChanBackup.multiChanBackup))
|
||||
this.storage.liquidityStorage.SaveNodeBackup(pub, JSON.stringify(encryptedData))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
GetUnlockerClient = (cert: Buffer) => {
|
||||
const host = this.settings.lndSettings.mainNode.lndAddr
|
||||
const channelCredentials = credentials.createSsl(cert)
|
||||
const transport = new GrpcTransport({ host, channelCredentials })
|
||||
const client = new WalletUnlockerClient(transport)
|
||||
return client
|
||||
}
|
||||
GetLightningClient = (cert: Buffer, macaroon: string) => {
|
||||
const host = this.settings.lndSettings.mainNode.lndAddr
|
||||
const sslCreds = credentials.createSsl(cert)
|
||||
const macaroonCreds = credentials.createFromMetadataGenerator(
|
||||
function (args: any, callback: any) {
|
||||
let metadata = new Metadata();
|
||||
metadata.add('macaroon', macaroon);
|
||||
callback(null, metadata);
|
||||
},
|
||||
);
|
||||
const channelCredentials = credentials.combineChannelCredentials(
|
||||
sslCreds,
|
||||
macaroonCreds,
|
||||
);
|
||||
const transport = new GrpcTransport({ host, channelCredentials })
|
||||
const client = new LightningClient(transport)
|
||||
return client
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import { EnvMustBeNonEmptyString } from "../helpers/envParser.js"
|
|||
import { UserTransactionPayment } from "./entity/UserTransactionPayment.js"
|
||||
import { UserBasicAuth } from "./entity/UserBasicAuth.js"
|
||||
import { UserEphemeralKey } from "./entity/UserEphemeralKey.js"
|
||||
import { Product } from "./entity/Product.js"
|
||||
import { UserToUserPayment } from "./entity/UserToUserPayment.js"
|
||||
import { Application } from "./entity/Application.js"
|
||||
import { ApplicationUser } from "./entity/ApplicationUser.js"
|
||||
|
|
@ -18,6 +17,8 @@ import { ChannelBalanceEvent } from "./entity/ChannelsBalanceEvent.js"
|
|||
import { getLogger } from "../helpers/logger.js"
|
||||
import { ChannelRouting } from "./entity/ChannelRouting.js"
|
||||
import { LspOrder } from "./entity/LspOrder.js"
|
||||
import { Product } from "./entity/Product.js"
|
||||
import { LndNodeInfo } from "./entity/LndNodeInfo.js"
|
||||
|
||||
|
||||
export type DbSettings = {
|
||||
|
|
@ -57,7 +58,7 @@ export default async (settings: DbSettings, migrations: Function[]): Promise<{ s
|
|||
database: settings.databaseFile,
|
||||
// logging: true,
|
||||
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder],
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo],
|
||||
//synchronize: true,
|
||||
migrations
|
||||
}).initialize()
|
||||
|
|
|
|||
24
src/services/storage/entity/LndNodeInfo.ts
Normal file
24
src/services/storage/entity/LndNodeInfo.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
||||
import { User } from "./User.js"
|
||||
|
||||
@Entity()
|
||||
export class LndNodeInfo {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
serial_id: number
|
||||
|
||||
@Column()
|
||||
pubkey: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
seed?: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
backup?: string
|
||||
|
||||
@CreateDateColumn()
|
||||
created_at: Date
|
||||
|
||||
@UpdateDateColumn()
|
||||
updated_at: Date
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { DataSource, EntityManager, MoreThan } from "typeorm"
|
||||
import { LspOrder } from "./entity/LspOrder.js";
|
||||
import TransactionsQueue, { TX } from "./transactionsQueue.js";
|
||||
import { LndNodeInfo } from "./entity/LndNodeInfo.js";
|
||||
export class LiquidityStorage {
|
||||
DB: DataSource | EntityManager
|
||||
txQueue: TransactionsQueue
|
||||
|
|
@ -17,4 +18,23 @@ export class LiquidityStorage {
|
|||
const entry = this.DB.getRepository(LspOrder).create(order)
|
||||
return this.txQueue.PushToQueue<LspOrder>({ exec: async db => db.getRepository(LspOrder).save(entry), dbTx: false })
|
||||
}
|
||||
|
||||
async SaveNodeSeed(pubkey: string, seed: string) {
|
||||
const existing = await this.DB.getRepository(LndNodeInfo).findOne({ where: { pubkey } })
|
||||
if (existing) {
|
||||
throw new Error("A seed already exists for this pub key")
|
||||
}
|
||||
const entry = this.DB.getRepository(LndNodeInfo).create({ pubkey, seed })
|
||||
return this.txQueue.PushToQueue<LndNodeInfo>({ exec: async db => db.getRepository(LndNodeInfo).save(entry), dbTx: false })
|
||||
}
|
||||
|
||||
async SaveNodeBackup(pubkey: string, backup: string) {
|
||||
const existing = await this.DB.getRepository(LndNodeInfo).findOne({ where: { pubkey } })
|
||||
if (existing) {
|
||||
await this.DB.getRepository(LndNodeInfo).update(existing.serial_id, { backup })
|
||||
return
|
||||
}
|
||||
const entry = this.DB.getRepository(LndNodeInfo).create({ pubkey, backup })
|
||||
await this.txQueue.PushToQueue<LndNodeInfo>({ exec: async db => db.getRepository(LndNodeInfo).save(entry), dbTx: false })
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class LndNodeInfo1720187506189 implements MigrationInterface {
|
||||
name = 'LndNodeInfo1720187506189'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "lnd_node_info" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "pubkey" varchar NOT NULL, "seed" varchar, "backup" varchar, "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 "lnd_node_info"`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,7 +6,8 @@ import { LndMetrics1703170330183 } from './1703170330183-lnd_metrics.js'
|
|||
import { ChannelRouting1709316653538 } from './1709316653538-channel_routing.js'
|
||||
import { LspOrder1718387847693 } from './1718387847693-lsp_order.js'
|
||||
import { LiquidityProvider1719335699480 } from './1719335699480-liquidity_provider.js'
|
||||
const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480]
|
||||
import { LndNodeInfo1720187506189 } from './1720187506189-lnd_node_info.js'
|
||||
const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189]
|
||||
const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538]
|
||||
export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
|
||||
if (arg === 'fake_initial_migration') {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue