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