Skip to content
This repository was archived by the owner on Feb 9, 2026. It is now read-only.

Commit 5e6ce7f

Browse files
authored
Merge pull request #169 from synonymdev/node-signing
feat: node signing
2 parents 6f053a4 + 9157aa8 commit 5e6ce7f

9 files changed

Lines changed: 80 additions & 3 deletions

File tree

example/Dev.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,21 @@ const Dev = (): ReactElement => {
643643
setMessage('Node Restarted');
644644
}}
645645
/>
646+
<Button
647+
title={'Sign message'}
648+
onPress={async (): Promise<void> => {
649+
setMessage('Signing...');
650+
const res = await ldk.nodeSign({
651+
message: 'Hello Bitcoin',
652+
});
653+
if (res.isErr()) {
654+
setMessage(res.error.message);
655+
return;
656+
}
657+
658+
setMessage(res.value);
659+
}}
660+
/>
646661
</View>
647662
</ScrollView>
648663

example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ PODS:
302302
- React-jsinspector (0.70.6)
303303
- React-logger (0.70.6):
304304
- glog
305-
- react-native-ldk (0.0.106):
305+
- react-native-ldk (0.0.109):
306306
- React
307307
- react-native-randombytes (3.6.1):
308308
- React-Core
@@ -593,7 +593,7 @@ SPEC CHECKSUMS:
593593
React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f
594594
React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b
595595
React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0
596-
react-native-ldk: 9cbe6586e65697322126c6475547a55e2c12bf1c
596+
react-native-ldk: 3c1cd457a2372ef3eda9fbe144f4cdf6bc1fd6c3
597597
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
598598
react-native-tcp-socket: c1b7297619616b4c9caae6889bcb0aba78086989
599599
React-perflogger: 8c79399b0500a30ee8152d0f9f11beae7fc36595

example/ldk/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export const setupLdk = async (
119119
highPriority: 10,
120120
normal: 5,
121121
background: 1,
122+
mempoolMinimum: 1,
122123
}),
123124
getTransactionData,
124125
getTransactionPosition,

lib/android/src/main/java/com/reactnativeldk/LdkModule.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.ldk.structs.*
1414
import org.ldk.structs.Result_Bolt11InvoiceParseOrSemanticErrorZ.Result_Bolt11InvoiceParseOrSemanticErrorZ_OK
1515
import org.ldk.structs.Result_Bolt11InvoiceSignOrCreationErrorZ.Result_Bolt11InvoiceSignOrCreationErrorZ_OK
1616
import org.ldk.structs.Result_PaymentIdPaymentErrorZ.Result_PaymentIdPaymentErrorZ_OK
17+
import org.ldk.structs.Result_StringErrorZ.Result_StringErrorZ_OK
1718
import org.ldk.util.UInt128
1819
import java.io.File
1920
import java.net.InetSocketAddress
@@ -81,6 +82,7 @@ enum class LdkErrors {
8182
channel_close_fail,
8283
channel_accept_fail,
8384
spend_outputs_fail,
85+
failed_signing_request,
8486
write_fail,
8587
read_fail,
8688
file_does_not_exist,
@@ -1088,6 +1090,20 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
10881090

10891091
promise.resolve((res as Result_TransactionNoneZ.Result_TransactionNoneZ_OK).res.hexEncodedString())
10901092
}
1093+
1094+
1095+
@ReactMethod
1096+
fun nodeSign(message: String, promise: Promise) {
1097+
keysManager ?: return handleReject(promise, LdkErrors.init_keys_manager)
1098+
1099+
val res = UtilMethods.sign(message.toByteArray(Charsets.UTF_8), keysManager!!._node_secret_key)
1100+
1101+
if (!res.is_ok) {
1102+
return handleReject(promise, LdkErrors.failed_signing_request)
1103+
}
1104+
1105+
promise.resolve((res as Result_StringErrorZ_OK).res)
1106+
}
10911107
}
10921108

10931109
object LdkEventEmitter {

lib/ios/Ldk.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ @interface RCT_EXTERN_MODULE(Ldk, NSObject)
155155
changeDestinationScript:(NSString *)changeDestinationScript
156156
resolve:(RCTPromiseResolveBlock)resolve
157157
reject:(RCTPromiseRejectBlock)reject)
158+
RCT_EXTERN_METHOD(nodeSign:(NSString *)message
159+
resolve:(RCTPromiseResolveBlock)resolve
160+
reject:(RCTPromiseRejectBlock)reject)
158161
@end
159162

160163
//MARK: Events

lib/ios/Ldk.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum LdkErrors: String {
6060
case channel_close_fail = "channel_close_fail"
6161
case channel_accept_fail = "channel_accept_fail"
6262
case spend_outputs_fail = "spend_outputs_fail"
63+
case failed_signing_request = "failed_signing_request"
6364
case write_fail = "write_fail"
6465
case read_fail = "read_fail"
6566
case file_does_not_exist = "file_does_not_exist"
@@ -1177,6 +1178,20 @@ class Ldk: NSObject {
11771178

11781179
return resolve(Data(res.getValue()!).hexEncodedString())
11791180
}
1181+
1182+
@objc
1183+
func nodeSign(_ message: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
1184+
guard let keysManager = keysManager else {
1185+
return handleReject(reject, .init_keys_manager)
1186+
}
1187+
1188+
let signed = Bindings.swiftSign(msg: Array(String(message).utf8), sk: keysManager.getNodeSecretKey())
1189+
if let _ = signed.getError() {
1190+
handleReject(reject, .failed_signing_request)
1191+
}
1192+
1193+
return resolve(signed.getValue()!)
1194+
}
11801195
}
11811196

11821197
//MARK: Singleton react native event emitter

lib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@synonymdev/react-native-ldk",
33
"title": "React Native LDK",
4-
"version": "0.0.106",
4+
"version": "0.0.109",
55
"description": "React Native wrapper for LDK",
66
"main": "./dist/index.js",
77
"types": "./dist/index.d.ts",

lib/src/ldk.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
TReconstructAndSpendOutputsReq,
3333
THeader,
3434
TAcceptChannelReq,
35+
TNodeSignReq,
3536
} from './utils/types';
3637
import { extractPaymentRequest } from './utils/helpers';
3738

@@ -1163,6 +1164,27 @@ class LDK {
11631164
return err(e);
11641165
}
11651166
}
1167+
1168+
/**
1169+
* Creates a digital signature of a message the node's secret key.
1170+
* A receiver knowing the PublicKey (e.g. the node's id) and the message can be sure that the signature was generated by the caller.
1171+
* Signatures are EC recoverable, meaning that given the message and the signature the PublicKey of the signer can be extracted.
1172+
* @param message
1173+
* @param messagePrefix
1174+
*/
1175+
async nodeSign({
1176+
message,
1177+
messagePrefix = 'Lightning Signed Message:',
1178+
}: TNodeSignReq): Promise<Result<string>> {
1179+
try {
1180+
const res = await NativeLDK.nodeSign(`${messagePrefix}${message}`);
1181+
this.writeDebugToLog('nodeSign', res);
1182+
return ok(res);
1183+
} catch (e) {
1184+
this.writeErrorToLog('nodeSign', e);
1185+
return err(e);
1186+
}
1187+
}
11661188
}
11671189

11681190
export default new LDK();

lib/src/utils/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,8 @@ export type TReconstructAndSpendOutputsReq = {
574574
feeRate: number;
575575
changeDestinationScript: string;
576576
};
577+
578+
export type TNodeSignReq = {
579+
message: string;
580+
messagePrefix?: string;
581+
};

0 commit comments

Comments
 (0)