var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { NativeModules } from 'react-native';
import GrpcAction from './grpc';
import { err, ok } from './result';
import { EGrpcStreamMethods, EGrpcSyncMethods, ENetworks, EStreamEventTypes } from './types';
import { lnrpc } from './rpc';
import { lnrpc as walletunlocker_lnrpc } from './walletunlocker';
import { bytesToHexString, hexStringToBytes, stringToBytes } from './helpers';
import base64 from 'base64-js';
class LND {
    constructor() {
        this.currentConf = undefined;
        this.lnd = NativeModules.ReactNativeLightning;
        this.grpc = new GrpcAction(this.lnd);
        this.logListeners = [];
        this.grpc.lndEvent.addListener(EStreamEventTypes.Logs, this.processLogListeners.bind(this));
    }
    start(conf) {
        return __awaiter(this, void 0, void 0, function* () {
            const stateRes = yield this.currentState();
            if (stateRes.isErr()) {
                return err(stateRes.error);
            }
            const { lndRunning } = stateRes.value;
            if (lndRunning) {
                return ok('LND already running');
            }
            try {
                const res = yield this.lnd.start(conf.build(), conf.network);
                this.currentConf = conf;
                return ok(res);
            }
            catch (e) {
                return err(e);
            }
        });
    }
    addLogListener(callback) {
        const id = new Date().valueOf().toString() + Math.random().toString();
        this.logListeners.push({ id, callback });
        return id;
    }
    removeLogListener(id) {
        let removeIndex = -1;
        this.logListeners.forEach((listener, index) => {
            if (listener.id === id) {
                removeIndex = index;
            }
        });
        if (removeIndex > -1) {
            this.logListeners.splice(removeIndex, 1);
        }
    }
    processLogListeners(log) {
        if (!log) {
            return;
        }
        if (__DEV__) {
            console.log(log);
        }
        this.logListeners.forEach((listener) => listener.callback(log));
    }
    getLogFileContent(limit = 100) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            let network = (_a = this.currentConf) === null || _a === void 0 ? void 0 : _a.network;
            if (!network) {
                network = ENetworks.testnet;
            }
            try {
                const content = yield this.lnd.logFileContent(network, limit);
                return ok(content);
            }
            catch (e) {
                return err(e);
            }
        });
    }
    genSeed() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const { data: serializedResponse } = yield this.lnd.genSeed();
                if (serializedResponse === undefined) {
                    throw new Error('Missing response');
                }
                return ok(walletunlocker_lnrpc.GenSeedResponse.decode(base64.toByteArray(serializedResponse))
                    .cipherSeedMnemonic);
            }
            catch (e) {
                return err(e);
            }
        });
    }
    createWallet(password, seed, multiChanBackup) {
        return __awaiter(this, void 0, void 0, function* () {
            const message = walletunlocker_lnrpc.InitWalletRequest.create();
            message.cipherSeedMnemonic = seed;
            message.walletPassword = stringToBytes(password);
            if (multiChanBackup) {
                message.channelBackups = lnrpc.ChanBackupSnapshot.create({
                    multiChanBackup: lnrpc.MultiChanBackup.create({
                        multiChanBackup: hexStringToBytes(multiChanBackup)
                    })
                });
            }
            try {
                const res = yield this.lnd.createWallet(base64.fromByteArray(walletunlocker_lnrpc.InitWalletRequest.encode(message).finish()));
                return ok(res);
            }
            catch (e) {
                return err(e);
            }
        });
    }
    unlockWallet(password) {
        return __awaiter(this, void 0, void 0, function* () {
            const message = walletunlocker_lnrpc.UnlockWalletRequest.create();
            message.walletPassword = stringToBytes(password);
            try {
                const res = yield this.lnd.unlockWallet(base64.fromByteArray(walletunlocker_lnrpc.InitWalletRequest.encode(message).finish()));
                return ok(res);
            }
            catch (e) {
                return err(e);
            }
        });
    }
    walletExists(network) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const exists = yield this.lnd.walletExists(network);
                return ok(exists);
            }
            catch (e) {
                return err(e);
            }
        });
    }
    currentState() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                return ok(yield this.lnd.currentState());
            }
            catch (e) {
                return err(e);
            }
        });
    }
    subscribeToCurrentState(onUpdate) {
        this.grpc.lndEvent.addListener(EStreamEventTypes.LndStateUpdate, onUpdate);
        this.currentState()
            .then((res) => {
            if (res.isOk()) {
                onUpdate(res.value);
            }
        })
            .catch(() => { });
    }
    getInfo() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.GetInfoRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.GetInfo, lnrpc.GetInfoRequest.encode(message).finish());
                return ok(lnrpc.GetInfoResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    getAddress(type) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.NewAddressRequest.create({ type });
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.NewAddress, lnrpc.NewAddressRequest.encode(message).finish());
                return ok(lnrpc.NewAddressResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    getWalletBalance() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.WalletBalanceRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.WalletBalance, lnrpc.WalletBalanceRequest.encode(message).finish());
                return ok(lnrpc.WalletBalanceResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    getChannelBalance() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ChannelBalanceRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ChannelBalance, lnrpc.ChannelBalanceRequest.encode(message).finish());
                return ok(lnrpc.ChannelBalanceResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    connectPeer(pubkey, host) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ConnectPeerRequest.create();
                message.addr = lnrpc.LightningAddress.create({ pubkey, host });
                message.perm = true;
                message.timeout = 10;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ConnectPeer, lnrpc.ConnectPeerRequest.encode(message).finish());
                return ok(lnrpc.ConnectPeerResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    openChannel(fundingAmount, nodePubkey, closeAddress = undefined) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.OpenChannelRequest.create();
                message.localFundingAmount = fundingAmount;
                if (closeAddress === undefined) {
                    const newAddressRes = yield this.getAddress();
                    if (newAddressRes.isErr()) {
                        return err(newAddressRes.error);
                    }
                    message.closeAddress = newAddressRes.value.address;
                }
                else {
                    message.closeAddress = closeAddress;
                }
                message.nodePubkeyString = nodePubkey;
                message.pushSat = 0;
                message.minConfs = 2;
                message.targetConf = 2;
                message.spendUnconfirmed = false;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.OpenChannelSync, lnrpc.OpenChannelRequest.encode(message).finish());
                return ok(lnrpc.ChannelPoint.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    closeChannelStream(channel, onUpdate, onDone) {
        const channelPoint = channel.channelPoint;
        if (!channelPoint) {
            onDone(err(new Error('Missing channel point')));
            return;
        }
        try {
            const message = lnrpc.CloseChannelRequest.create();
            const point = lnrpc.ChannelPoint.create();
            point.fundingTxid = 'fundingTxidStr';
            const [txid, txIndex] = channelPoint.split(':');
            point.outputIndex = Number(txIndex);
            point.fundingTxidStr = txid;
            message.channelPoint = point;
            const onStateUpdate = (res) => {
                if (res.isErr()) {
                    onUpdate(err(res.error));
                    return;
                }
                onUpdate(ok(lnrpc.ClosedChannelsResponse.decode(res.value)));
            };
            this.grpc.sendStreamCommand(EGrpcStreamMethods.CloseChannel, lnrpc.CloseChannelRequest.encode(message).finish(), onStateUpdate, onDone);
        }
        catch (e) {
            onDone(err(e));
        }
    }
    subscribeToOnChainTransactions(onUpdate, onDone) {
        try {
            const onStateUpdate = (res) => {
                if (res.isErr()) {
                    onUpdate(err(res.error));
                    return;
                }
                onUpdate(ok(lnrpc.Transaction.decode(res.value)));
            };
            const message = lnrpc.GetTransactionsRequest.create();
            this.grpc.sendStreamCommand(EGrpcStreamMethods.SubscribeTransactions, lnrpc.GetTransactionsRequest.encode(message).finish(), onStateUpdate, onDone);
        }
        catch (e) {
            onUpdate(err(e));
        }
    }
    subscribeToInvoices(onUpdate, onDone) {
        try {
            const message = lnrpc.ListInvoiceRequest.create();
            const onStateUpdate = (res) => {
                if (res.isErr()) {
                    onUpdate(err(res.error));
                    return;
                }
                onUpdate(ok(lnrpc.Invoice.decode(res.value)));
            };
            this.grpc.sendStreamCommand(EGrpcStreamMethods.SubscribeInvoices, lnrpc.ListInvoiceRequest.encode(message).finish(), onStateUpdate, onDone);
        }
        catch (e) {
            onUpdate(err(e));
        }
    }
    listPayments() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ListPaymentsRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ListPayments, lnrpc.ListPaymentsRequest.encode(message).finish());
                return ok(lnrpc.ListPaymentsResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    listChannels() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ListChannelsRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ListChannels, lnrpc.ListChannelsRequest.encode(message).finish());
                return ok(lnrpc.ListChannelsResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    decodeInvoice(invoice) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.PayReqString.create();
                message.payReq = invoice;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.DecodePayReq, lnrpc.PayReqString.encode(message).finish());
                return ok(lnrpc.PayReq.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    payInvoice(invoice) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.SendRequest.create();
                message.paymentRequest = invoice;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.SendPaymentSync, lnrpc.SendRequest.encode(message).finish());
                return ok(lnrpc.SendResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    createInvoice(value, memo, expiry = 172800) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.Invoice.create();
                message.value = value;
                message.memo = memo;
                message.expiry = expiry;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.AddInvoice, lnrpc.Invoice.encode(message).finish());
                return ok(lnrpc.AddInvoiceResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    listInvoices(indexOffset = 0, numMaxInvoices = -1, pendingOnly = false, reversed = false) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ListInvoiceRequest.create();
                message.indexOffset = indexOffset;
                if (numMaxInvoices > 0) {
                    message.numMaxInvoices = numMaxInvoices;
                }
                message.pendingOnly = pendingOnly;
                message.reversed = reversed;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ListInvoices, lnrpc.ListInvoiceRequest.encode(message).finish());
                return ok(lnrpc.ListInvoiceResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    listPeers() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ListPeersRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ListPeers, lnrpc.ListPeersRequest.encode(message).finish());
                return ok(lnrpc.ListPeersResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    feeEstimate(address, amount, targetConf = 1) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.EstimateFeeRequest.create();
                message.targetConf = targetConf;
                message.AddrToAmount = { [address]: amount };
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.EstimateFee, lnrpc.EstimateFeeRequest.encode(message).finish());
                return ok(lnrpc.EstimateFeeResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    sign(msg) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.SignMessageRequest.create();
                message.msg = stringToBytes(msg);
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.SignMessage, lnrpc.SignMessageRequest.encode(message).finish());
                return ok(lnrpc.SignMessageResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    stop() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.StopRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.StopDaemon, lnrpc.StopRequest.encode(message).finish());
                return ok(lnrpc.StopResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    subscribeToBackups(onUpdate, onDone) {
        try {
            const onBackupUpdate = (res) => {
                if (res.isErr()) {
                    onUpdate(err(res.error));
                    return;
                }
                onUpdate(ok(lnrpc.ChanBackupSnapshot.decode(res.value)));
            };
            const message = lnrpc.ExportChannelBackupRequest.create();
            this.grpc.sendStreamCommand(EGrpcStreamMethods.SubscribeChannelBackups, lnrpc.ExportChannelBackupRequest.encode(message).finish(), onBackupUpdate, onDone);
        }
        catch (e) {
            onUpdate(err(e));
        }
    }
    exportAllChannelBackups() {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ExportChannelBackupRequest.create();
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.ExportAllChannelBackups, lnrpc.ExportChannelBackupRequest.encode(message).finish());
                return ok(bytesToHexString((_b = (_a = lnrpc.ChanBackupSnapshot.decode(serializedResponse).multiChanBackup) === null || _a === void 0 ? void 0 : _a.multiChanBackup) !== null && _b !== void 0 ? _b : new Uint8Array()));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    verifyChannelBackupSnapshot(backupSnapshot) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ChanBackupSnapshot.create();
                message.multiChanBackup = backupSnapshot.multiChanBackup;
                const serializedResponse = yield this.grpc.sendCommand(EGrpcSyncMethods.VerifyChanBackup, lnrpc.ChanBackupSnapshot.encode(message).finish());
                return ok(lnrpc.VerifyChanBackupResponse.decode(serializedResponse));
            }
            catch (e) {
                return err(e);
            }
        });
    }
    verifyMultiChannelBackup(multiChanBackup) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const message = lnrpc.ChanBackupSnapshot.create({
                    multiChanBackup: lnrpc.MultiChanBackup.create({
                        multiChanBackup: hexStringToBytes(multiChanBackup)
                    })
                });
                yield this.grpc.sendCommand(EGrpcSyncMethods.VerifyChanBackup, lnrpc.ChanBackupSnapshot.encode(message).finish());
                return ok(true);
            }
            catch (e) {
                return err(e);
            }
        });
    }
}
export default new LND();
//# sourceMappingURL=lnd.js.map