Skip to content

Commit 1c8da2a

Browse files
author
Conor Okus
committed
Adds Swift code snippets
1 parent f2ceb14 commit 1c8da2a

File tree

6 files changed

+908
-453
lines changed

6 files changed

+908
-453
lines changed

docs/tutorials/building-a-node-with-ldk/connect-to-peers.md

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Connect to Peers
22

3-
In this section you'll learn how to join the lightning network.
3+
In this section you'll learn how to join the lightning network.
44

55
Firstly we need to have the ability to do high performance I/O operations. LDK provides default implementations for initializing all of your networking needs. If you are using Rust, you can use our simple socket handling library `lightning_net_tokio`. In Kotlin/Java you can use the `NioPeerHandler` which uses Java's NIO I/O interface.
66

77
**What it's used for**: making peer connections, facilitating peer data to and from LDK
88

9-
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin'}">
10-
<template v-slot:rust>
9+
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin', swift:'Swift'}">
10+
<template v-slot:rust>
1111

1212
```rust
1313
use lightning_net_tokio; // use LDK's sample networking module
@@ -40,13 +40,23 @@ nioPeerHandler.bind_listener(InetSocketAddress("127.0.0.1", port))
4040
```
4141

4242
</template>
43-
</CodeSwitcher>
4443

44+
<template v-slot:swift>
45+
46+
```Swift
47+
let peerHandler = channelManagerConstructor.getTCPPeerHandler()
48+
let port = 9777
49+
peerHandler.bind(address: "127.0.0.1", port: port)
50+
```
51+
52+
</template>
53+
54+
</CodeSwitcher>
4555

4656
Connections to other peers are established with `PeerManager`. You'll need to know the pubkey and address of another node that you want as a peer. Once the connection is established and the handshake is complete, `PeerManager` will show the peer's pubkey in its list of peers.
4757

48-
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin'}">
49-
<template v-slot:rust>
58+
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin', swift:'Swift'}">
59+
<template v-slot:rust>
5060

5161
```rust
5262
match lightning_net_tokio::connect_outbound(Arc::clone(&peer_manager), pubkey, address).await {
@@ -88,20 +98,32 @@ try {
8898

8999
} catch (e: IOException) {
90100
// Handle failure when connecting to a peer.
91-
}
92-
```
93-
94-
</template>
95-
</CodeSwitcher>
96101

97-
**Dependencies:** `PeerManager`
102+
}
98103

99-
**References:** [Rust `lightning-net-tokio` docs](https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/), [Rust `PeerManager` docs](https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html), [Java `NioPeerHandler` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/batteries/NioPeerHandler.java),
100-
[Java `PeerManager` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/PeerManager.java),
104+
````
101105

106+
</template>
102107

108+
<template v-slot:swift>
103109

110+
```Swift
111+
// Connect and wait for the handshake to complete.
112+
let pubKey = // Insert code to retrieve peer's pubKey as byte array
113+
let address = // Insert code to retrieve peer's address
114+
let port = // Insert code to retrieve peer's port
115+
let _ = peerHandler.connect(address: address, port: port, theirNodeId: pubKey)
104116

117+
// The peer's pubkey will be present in the list of peer ids.
118+
let peerManager: PeerManager = channelManagerConstructor.peerManager
119+
let peerNodeIds = peerManager.getPeerNodeIds()
120+
````
105121

122+
</template>
123+
124+
</CodeSwitcher>
106125

126+
**Dependencies:** `PeerManager`
107127

128+
**References:** [Rust `lightning-net-tokio` docs](https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/), [Rust `PeerManager` docs](https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html), [Java `NioPeerHandler` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/batteries/NioPeerHandler.java),
129+
[Java `PeerManager` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/PeerManager.java),

docs/tutorials/building-a-node-with-ldk/handling-events.md

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,67 @@ LDK requires that you handle many different events throughout your app's life cy
44

55
To start handling events in your application, run:
66

7-
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin'}">
7+
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin', swift:'Swift'}">
88
<template v-slot:rust>
99

10-
```rust
11-
use lightning::util::events::{Event};
12-
13-
// In the event handler passed to BackgroundProcessor::start
14-
match event {
15-
Event::PaymentSent { payment_preimage } => {
16-
// Handle successful payment
17-
}
18-
Event::PaymentFailed { payment_hash, rejected_by_dest } => {
19-
// Handle failed payment
20-
}
21-
Event::FundingGenerationReady { .. } =>
10+
```rust
11+
use lightning::util::events::{Event};
12+
13+
// In the event handler passed to BackgroundProcessor::start
14+
match event {
15+
Event::PaymentSent { payment_preimage } => {
16+
// Handle successful payment
17+
}
18+
Event::PaymentFailed { payment_hash, rejected_by_dest } => {
19+
// Handle failed payment
20+
}
21+
Event::FundingGenerationReady { .. } =>
2222
}
23-
```
23+
```
24+
2425
</template>
2526

2627
<template v-slot:kotlin>
2728

2829
```java
2930
import org.ldk.structs.Event
3031

31-
if (event is Event.PaymentSent) {
32-
// Handle successful payment
33-
}
32+
if (event is Event.PaymentSent) {
33+
// Handle successful payment
34+
}
3435

35-
if (event is Event.PaymentFailed) {
36-
// Handle failed payment
37-
}
36+
if (event is Event.PaymentFailed) {
37+
// Handle failed payment
38+
}
3839

39-
if (event is Event.FundingGenerationReady) {
40-
// Create a funding tx to be broadcast
41-
}
42-
```
40+
if (event is Event.FundingGenerationReady) {
41+
// Create a funding tx to be broadcast
42+
}
43+
44+
````
45+
46+
</template>
47+
48+
<template v-slot:swift>
49+
50+
```Swift
51+
import LightningDevKit
52+
53+
if let event = event.getValueAsPaymentSent() {
54+
// Handle successful payment
55+
}
56+
57+
if let event = event.getValueAsPaymentFailed() {
58+
// Handle failed payment
59+
}
60+
61+
if let event = event.getValueAsFundingGenerationReady() {
62+
// Create a funding tx to be broadcast
63+
}
64+
````
4365

4466
</template>
67+
4568
</CodeSwitcher>
4669

47-
References: [Rust `Event` docs](https://docs.rs/lightning/0.0.114/lightning/util/events/enum.Event.html), [Java `Event` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java)
70+
References: [Rust `Event` docs](https://docs.rs/lightning/0.0.114/lightning/util/events/enum.Event.html), [Java `Event` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java)

docs/tutorials/building-a-node-with-ldk/opening-a-channel.md

Lines changed: 94 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Now that you have a peer, you can open a channel with them using `ChannelManager
1111

1212
Channels can be announced to the network or can remain private, which is controlled via `UserConfig::announced_channel`.
1313

14-
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin'}">
14+
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin', swift:'Swift'}">
1515
<template v-slot:rust>
1616

1717
```rust
@@ -51,19 +51,45 @@ val createChannelResult = channelManager.create_channel(
5151
```
5252

5353
</template>
54+
55+
<template v-slot:swift>
56+
57+
```Swift
58+
let amount: UInt64 = 100000
59+
let pushMsat: UInt64 = 1000
60+
let userId: [UInt8] = toBytesArray(UUID().uuid)
61+
62+
// public aka announced channel
63+
let userConfig = UserConfig.initWithDefault()
64+
let channelHandshakeConfig = ChannelHandshakeConfig.initWithDefault()
65+
channelConfig.setAnnouncedChannel(val: true)
66+
67+
userConfig.setChannelHandshakeConfig(val: channelConfig)
68+
69+
let createChannelResults = channelManager.createChannel(
70+
theirNetworkKey: pubKey,
71+
channelValueSatoshis: amount,
72+
pushMsat: pushMsat,
73+
userChannelId: userId,
74+
overrideConfig: userConfig
75+
)
76+
```
77+
78+
</template>
79+
5480
</CodeSwitcher>
5581

5682
# FundingGenerationReady Event Handling
5783

58-
At this point, an outbound channel has been initiated with your peer and it will appear in `ChannelManager::list_channels`. However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a `FundingGenerationReady` event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.
84+
At this point, an outbound channel has been initiated with your peer and it will appear in `ChannelManager::list_channels`. However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a `FundingGenerationReady` event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.
5985

6086
::: tip Note
6187

6288
Remember that the funding transaction must only spend SegWit inputs.
6389

6490
:::
6591

66-
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin'}">
92+
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin', swift:'Swift'}">
6793
<template v-slot:rust>
6894

6995
```rust
@@ -142,14 +168,52 @@ fun buildFundingTx(value: Long, script: ByteArray): Transaction {
142168

143169
</template>
144170

171+
<template v-slot:swift>
172+
173+
```Swift
174+
// After the peer responds with an `accept_channel` message, an
175+
// Event.FundingGenerationReady event will be generated.
176+
177+
if let event = event.getValueAsFundingGenerationReady() {
178+
let script = Script(rawOutputScript: event.getOutputScript())
179+
let channelValue = event.getChannelValueSatoshis()
180+
let rawTx = buildFundingTx(script: script, amount: channelValue)
181+
if let rawTx = rawTx {
182+
channelManager.fundingTransactionGenerated(
183+
temporaryChannelId: event.getTemporaryChannelId(),
184+
counterpartyNodeId: event.getCounterpartyNodeId(),
185+
fundingTransaction: rawTx.serialize()
186+
)
187+
}
188+
}
189+
190+
// Building transaction using BDK
191+
func buildFundingTx(script: Script, amount: UInt64) -> Transaction? {
192+
do {
193+
let transaction = try TxBuilder().addRecipient(
194+
script: script,
195+
amount: amount)
196+
.feeRate(satPerVbyte: 4.0)
197+
.finish(wallet: onchainWallet)
198+
let _ = try onchainWallet.sign(psbt: transaction.psbt, signOptions: nil)
199+
return transaction.psbt.extractTx()
200+
} catch {
201+
return nil
202+
}
203+
}
204+
```
205+
206+
</template>
207+
145208
</CodeSwitcher>
146209

147210
**References:** [Rust `FundingGenerationReady` docs](https://docs.rs/lightning/*/lightning/util/events/enum.Event.html#variant.FundingGenerationReady), [Java `FundingGenerationReady` bindings](https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L95)
211+
148212
# Broadcasting the Funding Transaction
149213

150214
After crafting the funding transaction you'll need to send it to the Bitcoin network where it will hopefully be mined and added to the blockchain. You'll need to watch this transaction and wait for a minimum of 6 confirmations before the channel is ready to use.
151215

152-
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin'}">
216+
<CodeSwitcher :languages="{rust:'Rust', kotlin:'Kotlin', swift:'Swift'}">
153217
<template v-slot:rust>
154218

155219
```rust
@@ -197,8 +261,8 @@ object YourTxBroadcaster : BroadcasterInterface.BroadcasterInterfaceInterface {
197261
val transaction = Transaction(uByteArray.toList())
198262

199263
tx?.let {
200-
CoroutineScope(Dispatchers.IO).launch {
201-
blockchain.broadcast(transaction)
264+
CoroutineScope(Dispatchers.IO).launch {
265+
blockchain.broadcast(transaction)
202266
}
203267
} ?: throw(IllegalStateException("Broadcaster attempted to broadcast a null transaction"))
204268

@@ -208,16 +272,34 @@ object YourTxBroadcaster : BroadcasterInterface.BroadcasterInterfaceInterface {
208272
```
209273

210274
</template>
211-
</CodeSwitcher>
212-
213-
::: tip Keep LDK in sync
214275

215-
Remember if you are restarting and have open channels then you should [let LDK know about the latest channel state.](./setting-up-a-channel-manager/#sync-channelmonitors-and-channelmanager-to-chain-tip)
216-
217-
:::
276+
<template v-slot:swift>
218277

278+
```Swift
279+
// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client
280+
class MyBroacaster: BroadcasterInterface {
281+
override func broadcastTransaction(tx: [UInt8]) {
282+
let esploraURL = "esploraUrl"
283+
let esploraConfig = EsploraConfig(baseUrl: esploraURL, proxy: nil, concurrency: 5, stopGap: 20, timeout: nil)
284+
let blockchainConfig = BlockchainConfig.esplora(config: esploraConfig)
285+
let blockchain = Blockchain(config: blockchainConfig)
286+
287+
do {
288+
let transaction = try Transaction(transactionBytes: tx)
289+
try blockchain.broadcast(transaction: transaction)
290+
} catch {
291+
print("Failed to broadcast transaction: \(error.localizedDescription)")
292+
}
293+
}
294+
}
295+
```
219296

297+
</template>
220298

299+
</CodeSwitcher>
221300

301+
::: tip Keep LDK in sync
222302

303+
Remember if you are restarting and have open channels then you should [let LDK know about the latest channel state.](./setting-up-a-channel-manager/#sync-channelmonitors-and-channelmanager-to-chain-tip)
223304

305+
:::

0 commit comments

Comments
 (0)