· 6 years ago · Sep 12, 2019, 01:52 PM
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 = changeAddress
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 let keyHash: Data?
36
37 if (redeemScript.isPayToWitnessScriptHash) {
38 keyHash = redeemScript.matchPayToWitnessPublicKeyHash()
39 } else {
40 keyHash = redeemScript.matchPayToPubkeyHash()
41 }
42
43 if let key = keyHash?.hexString {
44 input.scripts[key] = redeemScript.data
45 }
46 }
47
48 try utxos.enumerated().forEach { (currentIndex, utxo) in
49 guard let hash = Data(hexString: utxo.txid) else {
50 throw CreateTransactionError.cantConvertOutput
51 }
52 let reversedHash = Data(hash.reversed())
53 let index = UInt32(utxo.vout)
54 let sequence = UInt32.max - UInt32(utxos.count) + UInt32(currentIndex)
55
56 let outpoint = BitcoinOutPoint.with {
57 $0.hash = reversedHash
58 $0.index = index
59 $0.sequence = sequence
60 }
61
62 guard let amount = Int64(utxo.value) else {
63 throw CreateTransactionError.cantConvertOutput
64 }
65 let redeemScript = BitcoinScript.buildForAddress(address: utxo.address, coin: .litecoin)
66
67 let utxo0 = BitcoinUnspentTransaction.with {
68 $0.script = redeemScript.data
69 $0.amount = amount
70 $0.outPoint = outpoint
71 }
72 input.utxo.append(utxo0)
73 }
74
75 let signer = BitcoinTransactionSigner(input: input)
76 let result = signer.sign()
77
78 guard let output = try? BitcoinSigningOutput(unpackingAny: result.objects[0]) else {
79 throw CreateTransactionError.cantConvertOutput
80 }
81
82 return output.encoded.hexString
83 }