github.com/jiajun1992/watercarver@v0.0.0-20191031150618-dfc2b17c0c4a/go-ethereum/mobile/bind.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains all the wrappers from the bind package. 18 19 package geth 20 21 import ( 22 "errors" 23 "math/big" 24 "strings" 25 26 "github.com/ethereum/go-ethereum/accounts/abi" 27 "github.com/ethereum/go-ethereum/accounts/abi/bind" 28 "github.com/ethereum/go-ethereum/accounts/keystore" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/crypto" 32 ) 33 34 // Signer is an interface defining the callback when a contract requires a 35 // method to sign the transaction before submission. 36 type Signer interface { 37 Sign(*Address, *Transaction) (tx *Transaction, _ error) 38 } 39 40 type MobileSigner struct { 41 sign bind.SignerFn 42 } 43 44 func (s *MobileSigner) Sign(addr *Address, unsignedTx *Transaction) (signedTx *Transaction, _ error) { 45 sig, err := s.sign(types.EIP155Signer{}, addr.address, unsignedTx.tx) 46 if err != nil { 47 return nil, err 48 } 49 return &Transaction{sig}, nil 50 } 51 52 // CallOpts is the collection of options to fine tune a contract call request. 53 type CallOpts struct { 54 opts bind.CallOpts 55 } 56 57 // NewCallOpts creates a new option set for contract calls. 58 func NewCallOpts() *CallOpts { 59 return new(CallOpts) 60 } 61 62 func (opts *CallOpts) IsPending() bool { return opts.opts.Pending } 63 func (opts *CallOpts) GetGasLimit() int64 { return 0 /* TODO(karalabe) */ } 64 65 // GetContext cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876) 66 // Even then it's awkward to unpack the subtleties of a Go context out to Java. 67 // func (opts *CallOpts) GetContext() *Context { return &Context{opts.opts.Context} } 68 69 func (opts *CallOpts) SetPending(pending bool) { opts.opts.Pending = pending } 70 func (opts *CallOpts) SetGasLimit(limit int64) { /* TODO(karalabe) */ } 71 func (opts *CallOpts) SetContext(context *Context) { opts.opts.Context = context.context } 72 73 // TransactOpts is the collection of authorization data required to create a 74 // valid Ethereum transaction. 75 type TransactOpts struct { 76 opts bind.TransactOpts 77 } 78 79 // NewTransactOpts creates a new option set for contract transaction. 80 func NewTransactOpts() *TransactOpts { 81 return new(TransactOpts) 82 } 83 84 // NewKeyedTransactor is a utility method to easily create a transaction signer 85 // from a single private key. 86 func NewKeyedTransactOpts(keyJson []byte, passphrase string) (*TransactOpts, error) { 87 key, err := keystore.DecryptKey(keyJson, passphrase) 88 if err != nil { 89 return nil, err 90 } 91 keyAddr := crypto.PubkeyToAddress(key.PrivateKey.PublicKey) 92 opts := bind.TransactOpts{ 93 From: keyAddr, 94 Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) { 95 if address != keyAddr { 96 return nil, errors.New("not authorized to sign this account") 97 } 98 signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key.PrivateKey) 99 if err != nil { 100 return nil, err 101 } 102 return tx.WithSignature(signer, signature) 103 }, 104 } 105 return &TransactOpts{opts}, nil 106 } 107 108 func (opts *TransactOpts) GetFrom() *Address { return &Address{opts.opts.From} } 109 func (opts *TransactOpts) GetNonce() int64 { return opts.opts.Nonce.Int64() } 110 func (opts *TransactOpts) GetValue() *BigInt { return &BigInt{opts.opts.Value} } 111 func (opts *TransactOpts) GetGasPrice() *BigInt { return &BigInt{opts.opts.GasPrice} } 112 func (opts *TransactOpts) GetGasLimit() int64 { return int64(opts.opts.GasLimit) } 113 114 // GetSigner cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876) 115 // func (opts *TransactOpts) GetSigner() Signer { return &signer{opts.opts.Signer} } 116 117 // GetContext cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876) 118 // Even then it's awkward to unpack the subtleties of a Go context out to Java. 119 //func (opts *TransactOpts) GetContext() *Context { return &Context{opts.opts.Context} } 120 121 func (opts *TransactOpts) SetFrom(from *Address) { opts.opts.From = from.address } 122 func (opts *TransactOpts) SetNonce(nonce int64) { opts.opts.Nonce = big.NewInt(nonce) } 123 func (opts *TransactOpts) SetSigner(s Signer) { 124 opts.opts.Signer = func(signer types.Signer, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { 125 sig, err := s.Sign(&Address{addr}, &Transaction{tx}) 126 if err != nil { 127 return nil, err 128 } 129 return sig.tx, nil 130 } 131 } 132 func (opts *TransactOpts) SetValue(value *BigInt) { opts.opts.Value = value.bigint } 133 func (opts *TransactOpts) SetGasPrice(price *BigInt) { opts.opts.GasPrice = price.bigint } 134 func (opts *TransactOpts) SetGasLimit(limit int64) { opts.opts.GasLimit = uint64(limit) } 135 func (opts *TransactOpts) SetContext(context *Context) { opts.opts.Context = context.context } 136 137 // BoundContract is the base wrapper object that reflects a contract on the 138 // Ethereum network. It contains a collection of methods that are used by the 139 // higher level contract bindings to operate. 140 type BoundContract struct { 141 contract *bind.BoundContract 142 address common.Address 143 deployer *types.Transaction 144 } 145 146 // DeployContract deploys a contract onto the Ethereum blockchain and binds the 147 // deployment address with a wrapper. 148 func DeployContract(opts *TransactOpts, abiJSON string, bytecode []byte, client *EthereumClient, args *Interfaces) (contract *BoundContract, _ error) { 149 // Deploy the contract to the network 150 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 151 if err != nil { 152 return nil, err 153 } 154 addr, tx, bound, err := bind.DeployContract(&opts.opts, parsed, common.CopyBytes(bytecode), client.client, args.objects...) 155 if err != nil { 156 return nil, err 157 } 158 return &BoundContract{ 159 contract: bound, 160 address: addr, 161 deployer: tx, 162 }, nil 163 } 164 165 // BindContract creates a low level contract interface through which calls and 166 // transactions may be made through. 167 func BindContract(address *Address, abiJSON string, client *EthereumClient) (contract *BoundContract, _ error) { 168 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 169 if err != nil { 170 return nil, err 171 } 172 return &BoundContract{ 173 contract: bind.NewBoundContract(address.address, parsed, client.client, client.client, client.client), 174 address: address.address, 175 }, nil 176 } 177 178 func (c *BoundContract) GetAddress() *Address { return &Address{c.address} } 179 func (c *BoundContract) GetDeployer() *Transaction { 180 if c.deployer == nil { 181 return nil 182 } 183 return &Transaction{c.deployer} 184 } 185 186 // Call invokes the (constant) contract method with params as input values and 187 // sets the output to result. 188 func (c *BoundContract) Call(opts *CallOpts, out *Interfaces, method string, args *Interfaces) error { 189 if len(out.objects) == 1 { 190 result := out.objects[0] 191 if err := c.contract.Call(&opts.opts, result, method, args.objects...); err != nil { 192 return err 193 } 194 out.objects[0] = result 195 } else { 196 results := make([]interface{}, len(out.objects)) 197 copy(results, out.objects) 198 if err := c.contract.Call(&opts.opts, &results, method, args.objects...); err != nil { 199 return err 200 } 201 copy(out.objects, results) 202 } 203 return nil 204 } 205 206 // Transact invokes the (paid) contract method with params as input values. 207 func (c *BoundContract) Transact(opts *TransactOpts, method string, args *Interfaces) (tx *Transaction, _ error) { 208 rawTx, err := c.contract.Transact(&opts.opts, method, args.objects...) 209 if err != nil { 210 return nil, err 211 } 212 return &Transaction{rawTx}, nil 213 } 214 215 // Transfer initiates a plain transaction to move funds to the contract, calling 216 // its default method if one is available. 217 func (c *BoundContract) Transfer(opts *TransactOpts) (tx *Transaction, _ error) { 218 rawTx, err := c.contract.Transfer(&opts.opts) 219 if err != nil { 220 return nil, err 221 } 222 return &Transaction{rawTx}, nil 223 }