Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locally funded channels #268

Merged
merged 8 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode/
.idea/
**/.DS_Store
example/.watchman*
Expand Down
35 changes: 24 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ This library hopes to simplify the process of adding Lightning via LDK to any Re
yarn add @synonymdev/react-native-ldk
#or
npm i -S @synonymdev/react-native-ldk
````
```

### iOS installation
```bash
cd ios && pod install && cd ../
````
```

### Android installation
1. Add the following line to `dependencies` in `/android/app/build.gradle`
```
dependencies {
...
implementation files("../../node_modules/@synonymdev/react-native-ldk/android/libs/LDK-release.aar")
}
```
```groovy
dependencies {
//...
implementation files("../../node_modules/@synonymdev/react-native-ldk/android/libs/LDK-release.aar") // <- this
}
```
2. Ensure `minSdkVersion` is set to at least `24` in `/android/build.gradle`

## Development
Expand All @@ -40,19 +40,32 @@ dependencies {
5. In the popup that appears select `JavaDocs` and tap `OK` then `OK` again

## Running example app
See also [`./example/README.md`](./example/README.md)
```bash

#Build dist files
# Build dist files
git clone https://github.com/synonymdev/react-native-ldk.git
cd react-native-ldk/lib/ && yarn install && yarn build && cd ../

cd example/ && yarn install && yarn rn-setup

yarn ios
#or
# or
yarn android
```

### Update config to match your local setup
In `constants.ts` update `peers.lnd` if you're using Polar locally.
### Example for Android
```ts
// export const peers = {
// lnd: {
pubKey:
'_033f4d3032ce7f54224f4bd9747b50b7cd72074a859758e40e1ca46ffa79a34324_',
address: '10.0.2.2',
port: 9737,
// },
```

## Notes
- It is important to not mix and match account names and seeds when starting LDK. Doing so can result in a corrupt save.

Expand Down
100 changes: 80 additions & 20 deletions example/Dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@
TChannelUpdate,
} from '@synonymdev/react-native-ldk';
import { backupServerDetails, peers } from './utils/constants';
import { createNewAccount, getAccount, getAddress } from './utils/helpers';
import {
createNewAccount,
getAccount,
getAddress,
getAddressFromScriptPubKey,
} from './utils/helpers';
import RNFS from 'react-native-fs';

let logSubscription: EmitterSubscription | undefined;
Expand All @@ -41,6 +46,7 @@
const [nodeStarted, setNodeStarted] = useState(false);
const [showLogs, setShowLogs] = useState(false);
const [logContent, setLogContent] = useState('');
const [temporaryChannelId, setTemporaryChannelId] = useState(''); //For funding channels locally

useEffect(() => {
//Restarting LDK on each code update causes constant errors.
Expand Down Expand Up @@ -97,7 +103,7 @@
// @ts-ignore
paymentSubscription = ldk.onEvent(
EEventTypes.channel_manager_payment_claimed,
(res: TChannelManagerClaim) => alert(`Received ${res.amount_sat} sats`),

Check warning on line 106 in example/Dev.tsx

View workflow job for this annotation

GitHub Actions / Run lint check

Unexpected alert
);
}

Expand Down Expand Up @@ -128,7 +134,7 @@
onChannelSubscription = ldk.onEvent(
EEventTypes.new_channel,
(res: TChannelUpdate) =>
alert(

Check warning on line 137 in example/Dev.tsx

View workflow job for this annotation

GitHub Actions / Run lint check

Unexpected alert
`Channel received from ${res.counterparty_node_id} Channel ${res.channel_id}`,
),
);
Expand Down Expand Up @@ -231,7 +237,6 @@
}
}}
/>

<Button
title={'Get Node ID'}
onPress={async (): Promise<void> => {
Expand All @@ -246,7 +251,6 @@
setMessage(`Node ID: ${nodeIdRes.value}`);
}}
/>

<Button
title={'Sync LDK'}
onPress={async (): Promise<void> => {
Expand All @@ -258,7 +262,6 @@
setMessage(syncRes.value);
}}
/>

<View style={styles.buttonRow}>
<Button
title={'Add Peers'}
Expand Down Expand Up @@ -299,7 +302,6 @@
}}
/>
</View>

<View style={styles.buttonRow}>
<Button
title={'List channels'}
Expand Down Expand Up @@ -393,7 +395,6 @@
}}
/>
</View>

<View style={styles.buttonRow}>
<Button
title={'List watch transactions'}
Expand All @@ -409,7 +410,6 @@
}}
/>
</View>

<Button
title={'🤑Get Address Balance'}
onPress={async (): Promise<void> => {
Expand All @@ -421,7 +421,6 @@
);
}}
/>

<Button
title={'Recover all outputs attempt'}
onPress={async (): Promise<void> => {
Expand All @@ -435,7 +434,6 @@
setMessage(res.value);
}}
/>

<View style={styles.buttonRow}>
<Button
title={'Get claimed payments'}
Expand All @@ -454,7 +452,6 @@
}}
/>
</View>

<View style={styles.buttonRow}>
<Button
title={'Create invoice'}
Expand Down Expand Up @@ -548,7 +545,6 @@
}}
/>
</View>

<Button
title={'Get network graph nodes'}
onPress={async (): Promise<void> => {
Expand All @@ -574,7 +570,6 @@
setMessage(`${msg}`);
}}
/>

<Button
title={'Show claimable balances for closed/closing channels'}
onPress={async (): Promise<void> => {
Expand All @@ -586,7 +581,6 @@
setMessage(JSON.stringify(balances.value));
}}
/>

<Button
title={'List channel monitors'}
onPress={async (): Promise<void> => {
Expand All @@ -604,6 +598,79 @@
}}
/>

<Button
title={'Start manual channel open ⛓️'}
onPress={async (): Promise<void> => {
try {
const res = await lm.createChannel({
counterPartyNodeId: peers.lnd.pubKey,
channelValueSats: 20000,
pushSats: 5000,
});
if (res.isErr()) {
setMessage(res.error.message);
return;
}

const { value_satoshis, output_script, temp_channel_id } =
res.value;

setTemporaryChannelId(temp_channel_id);

console.log(res.value);

const address = getAddressFromScriptPubKey(output_script);
const btc = value_satoshis / 100000000;

console.log('***BITCOIND CLI***');
console.log('bitcoin-cli listunspent');
console.log(
`bitcoin-cli createrawtransaction '[{"txid":"<tx-id>","vout":<index>}]' '{"${address}":${btc}}'`,
);
console.log(
'bitcoin-cli signrawtransactionwithwallet "<raw-transaction-hex>"',
);
console.log('********');

setMessage(
`Create tx with ${value_satoshis} for address ${address}. See logs for bitcoin-cli commands needed to create funding tx.`,
);
} catch (e) {
setMessage(JSON.stringify(e));
}
}}
/>

{temporaryChannelId ? (
<Button
title={'Fund channel (paste psbt)'}
onPress={async (): Promise<void> => {
try {
if (!temporaryChannelId) {
return setMessage('Create channel first');
}

const pastedSignedTx = await Clipboard.getString();

const res = await ldk.fundChannel({
temporaryChannelId,
counterPartyNodeId: peers.lnd.pubKey,
fundingTransaction: pastedSignedTx,
});
if (res.isErr()) {
setMessage(res.error.message);
return;
}

setMessage('Channel funded');
setTemporaryChannelId('');
} catch (e) {
setMessage(JSON.stringify(e));
}
}}
/>
) : null}

<Button
title={'Show version'}
onPress={async (): Promise<void> => {
Expand All @@ -615,7 +682,6 @@
setMessage(ldkVersion.value.ldk);
}}
/>

<Button
title={'Show LDK logs'}
onPress={async (): Promise<void> => {
Expand All @@ -631,7 +697,6 @@
}
}}
/>

<Button
title={'Restore backup from server'}
onPress={async (): Promise<void> => {
Expand All @@ -658,7 +723,6 @@
setMessage('Successfully restored wallet');
}}
/>

<Button
title={'Backup self check'}
onPress={async (): Promise<void> => {
Expand All @@ -671,7 +735,6 @@
setMessage('Backup server check passed ✅');
}}
/>

<Button
title={'Restart node'}
onPress={async (): Promise<void> => {
Expand Down Expand Up @@ -699,7 +762,6 @@
setMessage(res.value);
}}
/>

<Button
title={'Node state'}
onPress={async (): Promise<void> => {
Expand All @@ -712,7 +774,6 @@
setMessage(res.value);
}}
/>

<Button
title={'List backed up files'}
onPress={async (): Promise<void> => {
Expand All @@ -726,7 +787,6 @@
setMessage(JSON.stringify(res.value));
}}
/>

<Button
title={'Test file backup'}
onPress={async (): Promise<void> => {
Expand Down
5 changes: 5 additions & 0 deletions example/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
['@babel/plugin-transform-class-properties', { loose: false }],
['@babel/plugin-proposal-private-methods', { loose: false }],
['@babel/plugin-transform-private-property-in-object', { loose: false }],
],
};
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ PODS:
- React-jsinspector (0.72.4)
- React-logger (0.72.4):
- glog
- react-native-ldk (0.0.148):
- react-native-ldk (0.0.150):
- React
- react-native-randombytes (3.6.1):
- React-Core
Expand Down Expand Up @@ -621,7 +621,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: c7f826e40fa9cab5d37cab6130b1af237332b594
React-jsinspector: aaed4cf551c4a1c98092436518c2d267b13a673f
React-logger: da1ebe05ae06eb6db4b162202faeafac4b435e77
react-native-ldk: fda4d4381d40401bdc5c3a9965937d19b232ed08
react-native-ldk: 2b19de9eb94dcfd46f3f2a7191502292b75a5d7a
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-tcp-socket: c1b7297619616b4c9caae6889bcb0aba78086989
React-NativeModulesApple: edb5ace14f73f4969df6e7b1f3e41bef0012740f
Expand Down
21 changes: 18 additions & 3 deletions example/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const path = require('path');

/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = {};
const defaultConfig = getDefaultConfig(__dirname);

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
const config = {
resolver: {
extraNodeModules: {
stream: path.resolve(__dirname, 'node_modules/stream-browserify'),
buffer: path.resolve(__dirname, 'node_modules/buffer/'),
assert: path.resolve(__dirname, 'node_modules/assert/'),
events: path.resolve(__dirname, 'node_modules/events/'),
crypto: path.resolve(__dirname, 'node_modules/crypto-browserify/'),
vm: path.resolve(__dirname, 'node_modules/vm-browserify/'),
process: path.resolve(__dirname, 'node_modules/process/'),
},
},
};

module.exports = mergeConfig(defaultConfig, config);
Loading
Loading