Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TransactionBuilder help please #96

Open
Fonta1n3 opened this issue Feb 11, 2018 · 16 comments
Open

TransactionBuilder help please #96

Fonta1n3 opened this issue Feb 11, 2018 · 16 comments

Comments

@Fonta1n3
Copy link

Hi,

I am struggling to build a raw unsigned and signed transaction and was hoping you could help give me a bit of advise.

I am getting this error after i try and print the result of BTCTransactionBuilder:

error = Error Domain=com.oleganza.CoreBitcoin.TransactionBuilder Code=3 "(null)"

Here is the full function:

`func parseAddress(address: String) {
print("getAddressTransactionInputs")

    var url:NSURL!
    url = NSURL(string: "https://testnet.blockchain.info/unspent?active=\(address)")
    
    let task = URLSession.shared.dataTask(with: url! as URL) { (data, response, error) -> Void in
        
        do {
            
            if error != nil {
                
                print(error as Any)
                
            } else {
                
                if let urlContent = data {
                    
                    do {
                        
                        let jsonAddressResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableLeaves) as! NSDictionary
                        
                        if let utxoCheck = jsonAddressResult["unspent_outputs"] as? NSArray {
                            
                            var balance:Double = 0
                            
                            for utxo in utxoCheck {
                                
                                let utxoDictionary:NSDictionary! = utxo as! NSDictionary
                                print("utxo = \(utxoDictionary)")
                                
                                var amount = Double()
                                var transactionHash = String()
                                var transactionOutputN = Double()
                                var lockingScript = String()
                                var transactionIndex = Double()
                            
                                amount = utxoDictionary["value"] as! Double
                                transactionHash = utxoDictionary["tx_hash"] as! String
                                transactionOutputN = utxoDictionary["tx_output_n"] as! Double
                                lockingScript = utxoDictionary["script"] as! String
                                transactionIndex = utxoDictionary["tx_index"] as! Double
                           /*
                                print("transactionHash =\(transactionHash)")
                                print("transactionOutputN =\(transactionOutputN)")
                                print("lockingScript =\(lockingScript)")
                                print("transactionIndex =\(transactionIndex)")
                            */
                                balance = balance + amount
                            
                                let script = BTCScript.init(hex: lockingScript)
                                let txId = transactionHash.data(using: .utf8)
                            
                                let newInput = BTCTransactionInput()
                                newInput.previousHash = txId
                                newInput.previousIndex = UInt32(transactionIndex)
                                newInput.value = BTCAmount(balance)
                                newInput.signatureScript = script
                            
                            
                                let address = BTCAddress.init(string: "mxxky7EDvEVa4z9pwenveSMcj6L3CJ85di")
                                let primaryOutput = BTCTransactionOutput(value: 129870000, address: address)
                            
                            
                                let newTransaction = BTCTransactionBuilder()
                                newTransaction.shouldSign = false
                            
                                let transaction = BTCTransaction()
                                transaction.addInput(newInput)
                                transaction.addOutput(primaryOutput)
                                transaction.fee = 130000
                            
                                do {
                                    
                                    let transactionRaw = try newTransaction.buildTransaction()
                                    print("transactionRaw = \(transactionRaw)")
                            
                                } catch {
                            
                                    print("error = \(error as Any)")
                            
                                }
                            }
                        }
                        
                    } catch {
                        
                        print("JSon processing failed")
                        
                    }
                }
            }
        }
    }
    
    task.resume()
}`

Thanks to anyone very much for any help or letting me know what i'm doing wrong.

@mariusgab
Copy link

how you managed to install the library in the first place? for me it gives an error when running pod install: "target has transitive dependencies that include static binaries"

@vladislav-k
Copy link

Hi @TripKey , did you solve it?

@Fonta1n3
Copy link
Author

Fonta1n3 commented Mar 7, 2018

@vladislav-k no :( I gave up and have been putting my attention elsewhere. Maybe you can play with my code and see if you can get it to work. Please let me know if you do.

@tbsiosdev
Copy link

If anyone resolves it please help to make a transaction. with Proper Code.

@TBSMobile
Copy link

TBSMobile commented Mar 27, 2018

Here I got Solution. if you implement this method you can get transaction raw.

func callBTCTransaction()
{
let address = BTCAddress(string: receiverAddress)
let newTransaction = BTCTransactionBuilder()
newTransaction.dataSource = self
newTransaction.shouldSign = false
newTransaction.changeAddress = BTCAddress(string: newAddress)
newTransaction.outputs = [BTCTransactionOutput(value: BTCAmount(5000000), address: address)]
newTransaction.feeRate = BTCAmount(5000)
var result:BTCTransactionBuilderResult? = nil
do {
result = try newTransaction.buildTransaction()
print("transactionRaw = (String(describing: result?.transaction))")
} catch {
print("error = (error as Any)")
}
}

Datasource Methods:

func unspentOutputs(for txbuilder: BTCTransactionBuilder!) -> NSEnumerator!
{
let outputs = NSMutableArray()
for item in inputData {
let txout = BTCTransactionOutput()
txout.value = BTCAmount((item as! NSDictionary).value(forKey: "value") as! Int64)
txout.script = BTCScript.init(hex: (item as! NSDictionary).value(forKey: "script") as! String)
txout.index = UInt32((item as! NSDictionary).value(forKey: "tx_output_n") as! Int)
txout.confirmations = UInt((item as! NSDictionary).value(forKey: "confirmations") as! Int)
let transactionHash = (item as! NSDictionary)["tx_hash"] as! String
txout.transactionHash = transactionHash.data(using: .utf8)
outputs.add(txout)
}
return outputs.objectEnumerator()
}

Hope you get This Answer.

@Fonta1n3
Copy link
Author

Thank you so very much I was able to build the transaction succesfully! :)

@TBSMobile
Copy link

TBSMobile commented Mar 28, 2018

Hi TripKey,
Can you please share remaining transaction broadcast method?
we have an issue to make a transaction complete?

can you please help us.

we are using API: "https://testnet.blockchain.info/pushtx"
in body part passing: "tx=transaction data"

we are implementing in swift4.0.

@Fonta1n3
Copy link
Author

Hi Saz,

My goal was to get a successful raw transaction output in hex form which i was able to do, unfortunately when i go to decode it on the testnet at https://live.blockcypher.com/btc-testnet/decodetx/ it returns the error:

{
"error": "sequence too long"
}

So i don't have any code yet for signing the transaction or broadcasting it yet.

Could you please share with me your code for creating/signing the transaction so we can compare?

I am going to keep trying and will update when I figure out what i'm doing wrong.

@Fonta1n3 Fonta1n3 reopened this Mar 28, 2018
@Fonta1n3
Copy link
Author

Here is my full code, again when I put the result of:
print("transactionRaw = (String(describing: result?.transaction))")

in hex form of raw transaction into the decoder at https://live.blockcypher.com/btc-testnet/decodetx/it returns

"error": "sequence too long"

Here is full code:

`import UIKit

class TransactionBuilderViewController: UIViewController, BTCTransactionBuilderDataSource {

var unspentOutputs = NSMutableArray()
let btcAddress = "mo7WCetPLw6yMkT7MdzYfQ1L4eWqAuT2j7"

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    print("TransactionBuilderViewController")
    parseAddress(address: btcAddress)
    
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func parseAddress(address: String) {
    print("getAddressTransactionInputs")
    
    var url:NSURL!
    url = NSURL(string: "https://testnet.blockchain.info/unspent?active=\(address)")
    
    let task = URLSession.shared.dataTask(with: url! as URL) { (data, response, error) -> Void in
        
        do {
            
            if error != nil {
                
                print(error as Any)
                
             } else {
                
                if let urlContent = data {
                    
                    do {
                        
                        let jsonAddressResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableLeaves) as! NSDictionary
                        
                        if let utxoCheck = jsonAddressResult["unspent_outputs"] as? NSArray {
                            
                            print("utxoCheck = \(utxoCheck)")
                            
                            self.unspentOutputs = utxoCheck.mutableCopy() as! NSMutableArray
                            
                            self.callBTCTransaction()
                            
                        }
                        
                    } catch {
                        
                        print("JSon processing failed")
                        
                    }
                }
            }
        }
    }
    
    task.resume()
    
}



func callBTCTransaction() {
    
    let address = BTCAddress(string: "mxxky7EDvEVa4z9pwenveSMcj6L3CJ85di")
    let newTransaction = BTCTransactionBuilder()
    newTransaction.dataSource = self
    newTransaction.shouldSign = true
    newTransaction.changeAddress = BTCAddress(string: self.btcAddress)
    newTransaction.outputs = [BTCTransactionOutput(value: BTCAmount(50000), address: address)]
    newTransaction.feeRate = BTCAmount(5000)
    var result:BTCTransactionBuilderResult? = nil
    do {
        result = try newTransaction.buildTransaction()
        print("transactionRaw = \(String(describing: result?.transaction))")
        
    } catch {
        print("error = \(error as Any)")
    }
}

func unspentOutputs(for txbuilder: BTCTransactionBuilder!) -> NSEnumerator! {
    
    let outputs = NSMutableArray()
    
    for item in self.unspentOutputs {
        
        print("item = \(item)")
        
        let txout = BTCTransactionOutput()
        txout.value = BTCAmount((item as! NSDictionary).value(forKey: "value") as! Int64)
        txout.script = BTCScript.init(hex: (item as! NSDictionary).value(forKey: "script") as! String)
        txout.index = UInt32((item as! NSDictionary).value(forKey: "tx_output_n") as! Int)
        txout.confirmations = UInt((item as! NSDictionary).value(forKey: "confirmations") as! Int)
        let transactionHash = (item as! NSDictionary)["tx_hash"] as! String
        txout.transactionHash = transactionHash.data(using: .utf8)
        outputs.add(txout)
        
    }

    return outputs.objectEnumerator()
    
}

}
`

I know I am missing something dumb and obvious but I can't figure it out. Any help much appreciated.

@TBSMobile
Copy link

Hi Trip,
let me figure out this problem once I will complete it after that provide full code.

@tbsiosdev
Copy link

Hi, FontaineDenton
can please refer this class you can get your answer. just read carefully.

https://github.com/oleganza/CoreBitcoin/blob/master/CoreBitcoin/BTCTransaction%2BTests.m

@Fonta1n3
Copy link
Author

I appreciate you reaching out tbsiosdev, unfortunately I only know swift and its just too confusing reading obj-c.. Ive looked it over many times and tried and tried but my raw transaction data doesn't seem to be valid. If you have a swift example id very appreciative.

@tbsiosdev
Copy link

tbsiosdev commented Jun 29, 2018

Hi Fontaine,
I am working both the language in one common project. Making a raw transaction, I am using swift and objC Class. I am passing value from swift class to objC and objC Class Provides me Raw transaction.
So, My suggestion is that please try to learn basic of objC then implement it You will succeed it.

@iceshard899
Copy link

I guess you can just add an output with the OP_RETURN followed by the hex.

BTCScript *script = [[BTCScript alloc]init];
[script appendOpcode:OP_RETURN];
[script appendData:BTCDataFromHex(@"4d454c4f4e530a0a")];

@AlleniCode
Copy link

@FontaineDenton @Kampeone @vladislav-k @tbsiosdev @sazzadiproliya

How to sig a transaction with P2SH script UTXOs? Thx!

@tbsiosdev
Copy link

For that transaction witness class is missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants