Last active
May 11, 2021 04:20
-
-
Save saltyskip/c305a91a6bfca767b177ca81d93824ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let wif = "" | |
let pubkeyCompressed = "028013a81902a823dec80b54b5e1591b8d2fa359e9024934dae604aaa3be7dc020" | |
let pubkeyUncompressed = "048013a81902a823dec80b54b5e1591b8d2fa359e9024934dae604aaa3be7dc0202c487e634ab286179f6fefd9689e30465b6bbf658408928ddb01a419a81bf168" | |
let addressCompressed = "1KM68pTTgD172nJqykCUPpMA7hT7aGnn7w" | |
let addressUncompressed = "1KRhiKNai3ke3hZgSPZ5TpJoSJvs1aZfWo" //funds are here | |
var allAvailableUtxos = [ | |
InputUtxo( | |
txid: "fd1ea8178228e825d4106df0acb61a4fb14a8f04f30cd7c1f39c665c9427bf13" | |
satoshis: 10098, | |
vout: 0, | |
x: 0, | |
y: 0 | |
), | |
InputUtxo( | |
txid: "6ae3f1d245521b0ea7627231d27d613d58c237d6bf97a1471341a3532e31906c" | |
satoshis: 16874, | |
vout: 0, | |
x: 0, | |
y: 0 | |
) | |
] | |
func lockScriptForAddress(wif: String) -> Data { | |
let isCompressed = wif.starts(with: "K") || wif.starts(with: "L") | |
let privKey = PrivateKey(wif: wif)! | |
let publicKey = privKey.getPublicKeySecp256k1(compressed: isCompressed) | |
let hashedMainnet = [0x00] + Hash.sha256RIPEMD(data: publicKey.data) | |
let doubleSha = Hash.sha256SHA256(data: Data(hashedMainnet)) | |
let doubleShaChecked = hashedMainnet + doubleSha[0..<4] | |
let address = Base58.encodeNoCheck(data: Data(doubleShaChecked)) | |
let scriptp2pkh = BitcoinScript.buildPayToPublicKeyHash(hash: Hash.ripemd(data: publicKey.data)) | |
let scriptAddr = BitcoinScript.lockScriptForAddress(address: address, coin: .bitcoin) | |
debugPrint(scriptp2pkh.data.hex) | |
debugPrint(scriptAddr.data.hex) | |
return scriptAddr | |
} | |
func createTx() throws { | |
let masterKey = PrivateKey(wif: wif)! | |
let utxos: [TW_Bitcoin_Proto_UnspentTransaction] = allAvailableUTXOs.map { utxo in | |
BitcoinUnspentTransaction.with { | |
$0.outPoint.hash = utxo.hash | |
$0.outPoint.index = UInt32(utxo.vout) | |
$0.outPoint.sequence = UINT32_MAX | |
$0.amount = NSDecimalNumber(decimal: utxo.satoshis).int64Value | |
$0.script = lockScriptForAddress(wif: wif) | |
} | |
} | |
var keys: [Data] = [] | |
for _ in utxos { | |
keys.append(masterKey.data) | |
} | |
var hashType = BitcoinSigHashType.all.rawValue | |
if chainAssetProtocol.toChain() == .bitcoinCash { | |
hashType = BitcoinSigHashType.all.rawValue | BitcoinSigHashType.fork.rawValue | |
} | |
let input = BitcoinSigningInput.with { | |
$0.hashType = hashType | |
$0.byteFee = satsPerByteFee | |
$0.toAddress = destination | |
$0.coinType = chainAssetProtocol.toChain().toTrustCoin().rawValue | |
$0.utxo = utxos | |
$0.privateKey = keys | |
$0.useMaxAmount = true | |
} | |
let output: BitcoinSigningOutput = AnySigner.sign(input: input, coin: chainAssetProtocol.toChain().toTrustCoin()) | |
guard output.error == .ok else { | |
throw SendTxError(output.error) //throws missing input here | |
} | |
} | |
extension CoinType { | |
var keyPrefix: UInt8 { | |
switch self { | |
case .bitcoin: | |
return 0x80 | |
case .litecoin: | |
return 0xb0 | |
case .dash: | |
return 0xcc | |
case .zcoin: | |
return 0xd2 | |
default: | |
fatalError("no private prefix: \(self)") | |
} | |
} | |
} | |
extension PrivateKey { | |
/// Creates a `PrivateKey` from a Bitcoin WIF (wallet import format) string. | |
static let prefixSet = Set<UInt8>([CoinType.bitcoin, .litecoin, .dash, .zcoin].map {$0.keyPrefix}) | |
public convenience init?(wif: String) { | |
guard let decoded = Base58.decode(string: wif) else { | |
return nil | |
} | |
guard PrivateKey.prefixSet.contains(decoded[0]) else { | |
return nil | |
} | |
if decoded.count == 34 && decoded.last != 0x01 { | |
return nil | |
} | |
self.init(data: Data(decoded[1 ..< 33])) | |
} | |
public func wif(for coin: CoinType = .bitcoin) -> String { | |
let result = Data(bytes: [coin.keyPrefix]) + data | |
let check = Hash.sha256SHA256(data: result)[0..<4] | |
return Base58.encodeNoCheck(data: result + check) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment