· 6 years ago · Sep 12, 2019, 08:58 AM
1func getLitecoinTransactionHex(for coin: BTMCoin, destination: String, amount: Int64) -> Single<String> {
2 return walletStorage.get()
3 .map { HDWallet(mnemonic: $0.seedPhrase, passphrase: "") }
4 .map { ($0.getExtendedPubKey(purpose: coin.type.purpose, coin: coin.type, version: coin.type.xpubVersion), $0) }
5 .flatMap { [api] xpub, wallet in api.getUtxos(xpub: xpub).map { ($0, wallet) } }
6 .map { [unowned self] utxos, wallet in
7 return try self.getLitecoinTransactionId(changeAddress: coin.publicKey,
8 toAddress: destination,
9 amount: amount,
10 utxos: utxos,
11 wallet: wallet)
12 }
13 }
14
15 private func getLitecoinTransactionId(changeAddress: String,
16 toAddress: String,
17 amount: Int64,
18 utxos: [Utxo],
19 wallet: HDWallet) throws -> String {
20 var input = BitcoinSigningInput.with {
21 $0.hashType = TWSignatureHashTypeAll
22 $0.amount = amount
23 $0.byteFee = 1
24 $0.changeAddress = toAddress
25 $0.toAddress = toAddress
26 }
27
28 utxos.compactMap { DerivationPath($0.path) }.forEach {
29 let privateKey = wallet.getKey(at: $0)
30 input.privateKey.append(privateKey.data)
31 }
32
33 utxos.forEach {
34 let redeemScript = BitcoinScript.buildForAddress(address: $0.address, coin: .litecoin)
35 var keyHash = redeemScript.matchPayToPubkeyHash()
36
37 if (redeemScript.isPayToWitnessScriptHash) {
38 keyHash = redeemScript.matchPayToWitnessPublicKeyHash()
39 }
40
41 if let key = keyHash?.hexString {
42 input.scripts[key] = redeemScript.data
43 }
44 }
45
46 try utxos.enumerated().forEach { (currentIndex, utxo) in
47 guard let hash = Data(hexString: utxo.txid) else {
48 throw CreateTransactionError.cantConvertOutput
49 }
50 let reversedHash = Data(hash.reversed())
51 let index = UInt32(utxo.vout)
52 let sequence = UInt32.max - UInt32(utxos.count) + UInt32(currentIndex)
53
54 let outpoint = BitcoinOutPoint.with {
55 $0.hash = reversedHash
56 $0.index = index
57 $0.sequence = sequence
58 }
59
60 guard let amount = Int64(utxo.value) else {
61 throw CreateTransactionError.cantConvertOutput
62 }
63 let redeemScript = BitcoinScript.buildForAddress(address: utxo.address, coin: .litecoin)
64
65 let utxo0 = BitcoinUnspentTransaction.with {
66 $0.script = redeemScript.data
67 $0.amount = amount
68 $0.outPoint = outpoint
69 }
70 input.utxo.append(utxo0)
71 }
72
73 let signer = BitcoinTransactionSigner(input: input)
74 let result = signer.sign()
75
76 guard let output = try? BitcoinSigningOutput(unpackingAny: result.objects[0]) else {
77 throw CreateTransactionError.cantConvertOutput
78 }
79
80 return output.encoded.hexString
81 }