Skip to content

Commit

Permalink
lndmobile: Use the new SubscribeState API
Browse files Browse the repository at this point in the history
  • Loading branch information
hsjoberg committed Apr 7, 2021
1 parent ce78a1e commit 1478351
Show file tree
Hide file tree
Showing 29 changed files with 369 additions and 303 deletions.
16 changes: 1 addition & 15 deletions android/app/src/main/java/com/blixtwallet/LndMobile.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,12 @@ public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put("STATUS_SERVICE_BOUND", LndStatus.SERVICE_BOUND.flag);
constants.put("STATUS_PROCESS_STARTED", LndStatus.PROCESS_STARTED.flag);
constants.put("STATUS_WALLET_UNLOCKED", LndStatus.WALLET_UNLOCKED.flag);
constants.put("STATUS_WALLET_UNLOCKED", LndStatus.WALLET_UNLOCKED.flag); // NOT IN USE

return constants;
}

class IncomingHandler extends Handler {

@Override
public void handleMessage(Message msg) {
HyperLog.d(TAG, "New incoming message from LndMobileService, msg id: " + msg.what);
Expand Down Expand Up @@ -177,18 +176,6 @@ public void handleMessage(Message msg) {
promise.resolve(flags);
break;
}
case LndMobileService.MSG_WALLETUNLOCKED: {
final int request = msg.arg1;
final Promise promise = requests.remove(request);
if (promise != null) {
promise.resolve(null);
}

getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("WalletUnlocked", null);
break;
}
case LndMobileService.MSG_GRPC_STREAM_STARTED: {
final int request = msg.arg1;
final Promise promise = requests.remove(request);
Expand Down Expand Up @@ -455,7 +442,6 @@ void unlockWallet(String password, Promise promise) {
}
}


@ReactMethod
void initWallet(ReadableArray seed, String password, int recoveryWindow, String channelBackupsBase64, Promise promise) {
int req = new Random().nextInt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@

import com.hypertrack.hyperlog.HyperLog;

import lnrpc.Rpc;

public class LndMobileScheduledSyncWorker extends ListenableWorker {
private final String TAG = "LndScheduledSyncWorker";
private final String HANDLERTHREAD_NAME = "blixt_lndmobile_sync";
Expand Down Expand Up @@ -177,8 +175,36 @@ public void handleMessage(Message msg) {
}
case LndMobileService.MSG_START_LND_RESULT: {
lndStarted = true;
HyperLog.i(TAG, "LndMobileService reports lnd is started. Sending UnlockWallet request");
unlockWalletRequest(password);
subscribeStateRequest();
break;
}
case LndMobileService.MSG_GRPC_STREAM_RESULT: {
bundle = msg.getData();
final byte[] response = bundle.getByteArray("response");
final String method = bundle.getString("method");

if (method.equals("SubscribeState")) {
try {
lnrpc.Stateservice.SubscribeStateResponse state = lnrpc.Stateservice.SubscribeStateResponse.parseFrom(response);
lnrpc.Stateservice.WalletState currentState = state.getState();
if (currentState == lnrpc.Stateservice.WalletState.LOCKED) {
HyperLog.i(TAG, "Got WalletState.LOCKED");
HyperLog.i(TAG, "SubscribeState reports wallet is locked. Sending UnlockWallet request");
unlockWalletRequest(password);
} else if (currentState == lnrpc.Stateservice.WalletState.UNLOCKED) {
HyperLog.i(TAG, "Got WalletState.UNLOCKED");
HyperLog.i(TAG, "Waiting for WalletState.RPC_ACTIVE");
} else if (currentState == lnrpc.Stateservice.WalletState.RPC_ACTIVE) {
HyperLog.i(TAG, "Got WalletState.RPC_ACTIVE");
HyperLog.i(TAG, "LndMobileService reports RPC server ready. Sending GetInfo request");
getInfoRequest();
} else {
HyperLog.w(TAG, "SubscribeState got unknown state " + currentState);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
break;
}
case LndMobileService.MSG_GRPC_COMMAND_RESULT: {
Expand All @@ -187,10 +213,10 @@ public void handleMessage(Message msg) {
final String method = bundle.getString("method");

if (method.equals("UnlockWallet")) {
HyperLog.i(TAG, "Got MSG_GRPC_COMMAND_RESULT for UnlockWallet. Waiting for MSG_WALLETUNLOCKED before doing anything");
HyperLog.i(TAG, "Got MSG_GRPC_COMMAND_RESULT for UnlockWallet. Waiting for SubscribeState to send event before doing anything");
} else if (method.equals("GetInfo")) {
try {
Rpc.GetInfoResponse res = Rpc.GetInfoResponse.parseFrom(response);
lnrpc.Rpc.GetInfoResponse res = lnrpc.Rpc.GetInfoResponse.parseFrom(response);
HyperLog.d(TAG, "GetInfo response");
HyperLog.v(TAG, "blockHash: " + res.getBlockHash());
HyperLog.d(TAG, "blockHeight: " + Integer.toString(res.getBlockHeight()));
Expand Down Expand Up @@ -255,11 +281,6 @@ public void run() {
}
break;
}
case LndMobileService.MSG_WALLETUNLOCKED: {
HyperLog.i(TAG, "LndMobileService reports RPC server ready. Sending GetInfo request");
getInfoRequest();
break;
}
default:
super.handleMessage(msg);
}
Expand Down Expand Up @@ -337,6 +358,20 @@ private void startLnd() {
}
}

private void subscribeStateRequest() {
try {
Message message = Message.obtain(null, LndMobileService.MSG_GRPC_STREAM_COMMAND, 0, 0);
message.replyTo = messenger;
Bundle bundle = new Bundle();
bundle.putString("method", "SubscribeState");
bundle.putByteArray("payload", lnrpc.Stateservice.SubscribeStateRequest.newBuilder().build().toByteArray());
message.setData(bundle);
messengerService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}

private void unlockWalletRequest(String password) {
try {
Message message = Message.obtain(null, LndMobileService.MSG_GRPC_COMMAND, 0, 0);
Expand All @@ -357,7 +392,7 @@ private void getInfoRequest() {
message.replyTo = messenger;
Bundle getinfoBundle = new Bundle();
getinfoBundle.putString("method", "GetInfo");
getinfoBundle.putByteArray("payload", Rpc.GetInfoRequest.newBuilder().build().toByteArray());
getinfoBundle.putByteArray("payload", lnrpc.Rpc.GetInfoRequest.newBuilder().build().toByteArray());
message.setData(getinfoBundle);
messengerService.send(message);
} catch (RemoteException e) {
Expand Down
39 changes: 2 additions & 37 deletions android/app/src/main/java/com/blixtwallet/LndMobileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
public class LndMobileService extends Service {
private static final String TAG = "LndMobileService";
boolean lndStarted = false;
boolean walletUnlocked = false;
boolean subscribeInvoicesStreamActive = false;
Set<String> streamsStarted = new HashSet<String>();

Expand All @@ -55,7 +54,7 @@ public class LndMobileService extends Service {
static final int MSG_GRPC_STREAM_WRITE = 10;
static final int MSG_CHECKSTATUS = 11;
static final int MSG_CHECKSTATUS_RESPONSE = 12;
static final int MSG_WALLETUNLOCKED = 13;
static final int MSG_WALLETUNLOCKED = 13; // NOT IN USE
static final int MSG_UNLOCKWALLET = 14;
static final int MSG_INITWALLET = 15;
static final int MSG_GRPC_STREAM_STARTED = 16;
Expand All @@ -64,8 +63,6 @@ public class LndMobileService extends Service {
static final int MSG_PING = 19;
static final int MSG_PONG = 20;

int unlockWalletRequest = -1;

private Map<String, Method> syncMethods = new HashMap<>();
private Map<String, Method> streamMethods = new HashMap<>();

Expand Down Expand Up @@ -195,18 +192,13 @@ public void handleMessage(Message msg) {
flags += LndMobile.LndStatus.PROCESS_STARTED.flag;
}

if (walletUnlocked) {
flags += LndMobile.LndStatus.WALLET_UNLOCKED.flag;
}

HyperLog.d(TAG, "MSG_CHECKSTATUS sending " + flags);
sendToClient(msg.replyTo, Message.obtain(null, MSG_CHECKSTATUS_RESPONSE, request, flags));
//sendToClients(Message.obtain(null, MSG_CHECKSTATUS_RESPONSE, request, flags));
break;

case MSG_UNLOCKWALLET: {
HyperLog.d(TAG, "Got MSG_UNLOCKWALLET");
// unlockWalletRequest = request;

String password = bundle.getString("password");

Expand All @@ -222,12 +214,6 @@ public void handleMessage(Message msg) {

case MSG_INITWALLET:
HyperLog.d(TAG, "Got MSG_INITWALLET");
// Promise should be resolved
// when the RPC ready callback
// from LndMobile's start is called,
// not when the InitWallet RPC call is done
// TODO(hsjoberg): document this more clearly
unlockWalletRequest = request;

ArrayList<String> seed = bundle.getStringArrayList("seed");
String password = bundle.getString("password");
Expand All @@ -253,7 +239,7 @@ public void handleMessage(Message msg) {

Lndmobile.initWallet(
initWallet.build().toByteArray(),
new LndCallback(msg.replyTo, "InitWallet", -1)
new LndCallback(msg.replyTo, "InitWallet", request)
);
break;

Expand Down Expand Up @@ -427,26 +413,6 @@ public void onResponse(byte[] bytes) {
sendToClient(recipient, msg);
// sendToClients(msg);
}
}, new lndmobile.Callback() {

@Override
public void onError(Exception e) {
HyperLog.e(TAG, "wallet unlock onError callback", e);
}

@Override
public void onResponse(byte[] bytes) {
HyperLog.i(TAG, "wallet unlock onResponse callback");
walletUnlocked = true;

Message msg = Message.obtain(null, MSG_WALLETUNLOCKED, unlockWalletRequest, 0);

Bundle bundle = new Bundle();
bundle.putByteArray("response", bytes);
msg.setData(bundle);

sendToClient(recipient, msg);
}
});
}
};
Expand Down Expand Up @@ -501,7 +467,6 @@ public boolean onUnbind(Intent intent) {
}

lndStarted = false;
walletUnlocked = false;

return false;
}
Expand Down
16 changes: 3 additions & 13 deletions ios/LndMobile/Lnd.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ open class Lnd {
static let shared = Lnd()

var lndStarted = false
var walletUnlocked = false
var activeStreams: [String] = []

static let syncMethods = [
Expand Down Expand Up @@ -123,6 +122,7 @@ open class Lnd {
// index
//
"RouterSendPaymentV2": { req, cb in return LndmobileRouterSendPaymentV2(req, cb) },
"SubscribeState": { req, cb in return LndmobileSubscribeState(req, cb) },
// channel
//
"CloseChannel": { req, cb in return LndmobileCloseChannel(req, cb)},
Expand All @@ -141,14 +141,10 @@ open class Lnd {
flags += LndStatusCodes.STATUS_PROCESS_STARTED.rawValue.int32Value
}

if (self.walletUnlocked) {
flags += LndStatusCodes.STATUS_WALLET_UNLOCKED.rawValue.int32Value
}

return flags
}

func startLnd(_ torEnabled: Bool, lndStartedCallback: @escaping Callback, walletUnlockedCallback: @escaping Callback) -> Void {
func startLnd(_ torEnabled: Bool, lndStartedCallback: @escaping Callback) -> Void {
let applicationSupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
let lndPath = applicationSupport.appendingPathComponent("lnd", isDirectory: true)
let args = "--lnddir=\"\(lndPath.path)\""
Expand All @@ -158,15 +154,9 @@ open class Lnd {
lndStartedCallback(data, error)
}()}

let unlocked: Callback = {(data: Data?, error: Error?) in {
self.walletUnlocked = true
walletUnlockedCallback(data, error)
}()}

LndmobileStart(
args,
LndmobileCallback(method: "start", callback: started),
LndmobileCallback(method: "start2", callback: unlocked)
LndmobileCallback(method: "start", callback: started)
)
}

Expand Down
25 changes: 4 additions & 21 deletions ios/LndMobile/LndMobile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ class LndMobile: RCTEventEmitter {
"LndMobile"
}

var walletUnlockedResolver: RCTPromiseResolveBlock? = nil

override func supportedEvents() -> [String]! {
var events = Lnd.streamMethods.map{ $0.key }
events.append("WalletUnlocked")
return events
return Lnd.streamMethods.map{ $0.key }
}

@objc
Expand Down Expand Up @@ -105,18 +101,6 @@ class LndMobile: RCTEventEmitter {
resolve([
"data": data?.base64EncodedString()
])
} walletUnlockedCallback: { (data, error) in
if let e = error {
NSLog("unlock error" + e.localizedDescription)
return
}
self.sendEvent(withName: "WalletUnlocked", body: [
"data": data?.base64EncodedString()
])
if (self.walletUnlockedResolver != nil) {
NSLog("Resolving walletUnlockedResolver")
self.walletUnlockedResolver!("done")
}
}
}

Expand All @@ -135,7 +119,6 @@ class LndMobile: RCTEventEmitter {

@objc(initWallet:password:recoveryWindow:channelsBackupBase64:resolver:rejecter:)
func initWallet(_ seed: [AnyHashable], password: String, recoveryWindow: Int, channelsBackupBase64: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
self.walletUnlockedResolver = resolve
Lnd.shared.initWallet(
seed as! [String],
password: password,
Expand All @@ -146,9 +129,9 @@ class LndMobile: RCTEventEmitter {
reject("error", e.localizedDescription, e)
return
}
// IMPORTANT:
// Promise resolve is happening in startLnd
// by self.walletUnlockerResolver
resolve([
"data": data?.base64EncodedString()
])
}
}

Expand Down
2 changes: 2 additions & 0 deletions jestSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ ReactNative.UIManager.configureNextLayoutAnimation = jest.fn();
ReactNative.InteractionManager.runAfterInteractions = ((cb) => {
cb && cb();
});
ReactNative.Linking.addListener = jest.fn();

const NativeBase = require("native-base");
NativeBase.Toast.show = jest.fn();
NativeBase.Root = ({ children }) => (<>{children}</>);
Expand Down
20 changes: 19 additions & 1 deletion mocks/lndmobile/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { lnrpc } from "../../proto/proto";
import { timeout } from "./utils";
import { decodeStreamResult, timeout } from "./utils";
import { DeviceEventEmitter } from "react-native";
import * as base64 from "base64-js";
import payReq from "bolt11";
Expand Down Expand Up @@ -31,6 +31,24 @@ export const writeConfigFile = jest.fn(async () => {
return "File written:";
});

export const subscribeStateEmitter = (data: Uint8Array) => DeviceEventEmitter.emit("SubscribeState", { data: base64.fromByteArray(data) });
export const subscribeState = async () => {
setTimeout(async () => {
subscribeStateEmitter(
lnrpc.SubscribeStateResponse.encode({
state: lnrpc.WalletState.LOCKED,
}).finish()
);
}, 10)
}

export const decodeState = (data: string): lnrpc.SubscribeStateResponse => {
return decodeStreamResult<lnrpc.SubscribeStateResponse>({
response: lnrpc.SubscribeStateResponse,
base64Result: data,
});
};

export const startLnd = jest.fn(async (): Promise<string> => {
await timeout(100);
return "started";
Expand Down
Loading

0 comments on commit 1478351

Please sign in to comment.