Add unsigned transact function

This commit is contained in:
Georgios Konstantopoulos 2019-03-07 15:06:05 +02:00
parent f9c0669567
commit db869ea400

View file

@ -164,6 +164,63 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
return c.abi.Unpack(result, method, output) return c.abi.Unpack(result, method, output)
} }
func (c *BoundContract) UnsignedTransact(opts *TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
// Otherwise pack up the parameters and invoke the contract
input, err := c.abi.Pack(method, params...)
if err != nil {
return nil, err
}
// Ensure a valid value field and resolve the account nonce
value := opts.Value
if value == nil {
value = new(big.Int)
}
var nonce uint64
if opts.Nonce == nil {
nonce, err = c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
if err != nil {
return nil, fmt.Errorf("failed to retrieve account nonce: %v", err)
}
} else {
nonce = opts.Nonce.Uint64()
}
// Figure out the gas allowance and gas price values
gasPrice := opts.GasPrice
if gasPrice == nil {
gasPrice, err = c.transactor.SuggestGasPrice(ensureContext(opts.Context))
if err != nil {
return nil, fmt.Errorf("failed to suggest gas price: %v", err)
}
}
gasLimit := opts.GasLimit
if gasLimit == 0 {
// Gas estimation cannot succeed without code for method invocations
if &c.address != nil {
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {
return nil, err
} else if len(code) == 0 {
return nil, ErrNoCode
}
}
// If the contract surely has code (or code is not needed), estimate the transaction
msg := ethereum.CallMsg{From: opts.From, To: &c.address, Value: value, Data: input}
gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg)
if err != nil {
return nil, fmt.Errorf("failed to estimate gas needed: %v", err)
}
}
// Create the transaction, sign it and schedule it for execution
var rawTx *types.Transaction
if &c.address == nil {
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
} else {
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
}
return rawTx, nil
}
// Transact invokes the (paid) contract method with params as input values. // Transact invokes the (paid) contract method with params as input values.
func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
// Otherwise pack up the parameters and invoke the contract // Otherwise pack up the parameters and invoke the contract
@ -232,7 +289,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input) rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
} }
if opts.Signer == nil { if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with") return rawTx, errors.New("no signer to authorize the transaction with")
} }
signedTx, err := opts.Signer(types.HomesteadSigner{}, opts.From, rawTx) signedTx, err := opts.Signer(types.HomesteadSigner{}, opts.From, rawTx)
if err != nil { if err != nil {