Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/blockchaincommons/bcswiftfoundation

A collection of useful primitives for cryptocurrency wallets.
https://github.com/blockchaincommons/bcswiftfoundation

Last synced: 3 months ago
JSON representation

A collection of useful primitives for cryptocurrency wallets.

Awesome Lists containing this project

README

        

# BCSwiftFoundation

A collection of useful primitives for cryptocurrency wallets.

Opinionated Swift wrapper around [LibWally](https://github.com/ElementsProject/libwally-core).

Supports particular enhancements used by Blockchain Commons from our fork of libwally-core: [bc-libwally-core](https://github.com/blockchaincommons/bc-libwally-core), in the [bc-maintenance](https://github.com/BlockchainCommons/bc-libwally-core/tree/bc-maintenance) branch.

# Dependencies

Depends on [BCSwiftWally](https://github.com/BlockchainCommons/BCSwiftWally), which is a thin wrapper around LibWally that has a new build system for building a universal XCFramework for use with MacOSX, Mac Catalyst, iOS devices, and the iOS simulator across Intel and Apple Silicon (ARM).

# Building

Add to your project like any other Swift Package.

# Usage

### Derive address from a seed:

```swift
import BCFoundation

let mnemonic = BIP39(mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about")!
let seed = BIP39.Seed(bip39: mnemonic, passphrase: "bip39 passphrase")
let masterKey = try! HDKey(bip39Seed: seed)
assert(masterKey.keyFingerprint.hex == "7b343b65")
let path = DerivationPath(string: "m/44'/0'/0'")!
let accountKey = try! HDKey(parent: masterKey, childDerivationPath: path)
assert(accountKey.base58PrivateKey == "xprv9z3bixmawU269r5jUAbWbVFDY3qN6LZdHH7r28C7gmZMXPfbN8o39622JvuyvQxBYPBMEtJNetWBCyy6hZXcAEubReyb95MnJQR5bAMiR2d")
assert(accountKey.base58PublicKey == "xpub6D2x8UJUmqaPNLACaC8WxdBx65frVoHUeW3SpWbjF76LQBzjug7HgtLWACEbNoRubqXqM9y7t822g9RpEPPxmALG8tiZYVw5Ec66swihmUy")
assert(Bitcoin.Address(hdKey: accountKey, type: .payToWitnessPubKeyHash).description == "bc1qtqq3hzwgswm56tt3h04ss8qmmttt6py9yj8h6c")
```

### Derive address from an xpub:

```swift
import BCFoundation

let accountKey = try! HDKey(base58: "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ")
let receivePath = DerivationPath(string: "0/0")!
let receiveKey = try! HDKey(parent: accountKey, childDerivationPath: receivePath)
let address = Bitcoin.Address(hdKey: receiveKey, type: .payToPubKeyHash)
assert(address.description == "1BiCdXSDHyeXSzmx2paVPFVTrmyx7BeCGD")
assert(address.scriptPubKey.description == "pkh:[OP_DUP OP_HASH160 757c05317fcb85e910c5f3e6cd9dc4d06b5d8321 OP_EQUALVERIFY OP_CHECKSIG]")
```

### Parse an address:

```swift
import BCFoundation

let address = Bitcoin.Address(string: "bc1q6zwjfmhdl4pvhvfpv8pchvtanlar8hrhqdyv0t")!
assert(address.scriptPubKey.hex == "0014d09d24eeedfd42cbb12161c38bb17d9ffa33dc77")
assert(address.scriptPubKey.type! == .wpkh)
assert(address.scriptPubKey.description == "wpkh:[OP_0 d09d24eeedfd42cbb12161c38bb17d9ffa33dc77]")
```

### Create and sign a transaction:

```swift
import BCFoundation

let pubKey = ECCompressedPublicKey(hex: "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c")!
let prevTx = TxHash(hex: "0000000000000000000000000000000000000000000000000000000000000000")!
let vout: UInt32 = 0
let legacyInputBytes: Int = 192
let amount1: Satoshi = 1000 + Satoshi(legacyInputBytes)
let scriptSig = ScriptSig(type: .payToPubKeyHash(pubKey))
let scriptPubKey1 = ScriptPubKey(hex: "76a914bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe88ac")!
let txInput1 = TxInput(prevTx: prevTx, vout: vout, amount: amount1, sig: .scriptSig(scriptSig), scriptPubKey: scriptPubKey1)
let hdKey = try! HDKey(base58: "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs")
let txOutput = TxOutput(scriptPubKey: scriptPubKey1, amount: 1000)
let tx1 = Transaction(inputs: [txInput1], outputs: [txOutput])
let signedTx = tx1.signed(with: [hdKey])!
assert(signedTx.inputs![0].isSigned)
assert(signedTx.description == "01000000010000000000000000000000000000000000000000000000000000000000000000000000006a47304402203d274300310c06582d0186fc197106120c4838fa5d686fe3aa0478033c35b97802205379758b11b869ede2f5ab13a738493a93571268d66b2a875ae148625bd20578012103501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711cffffffff01e8030000000000001976a914bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe88ac00000000")
assert(signedTx.vbytes == legacyInputBytes - 1)
```