├── Store.sol ├── main.go └── store.go /Store.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | contract Store { 4 | event ItemSet(bytes32 key, bytes32 value); 5 | 6 | string public version; 7 | mapping (bytes32 => bytes32) public items; 8 | 9 | constructor(string _version) public { 10 | version = _version; 11 | } 12 | 13 | function setItem(bytes32 key, bytes32 value) external { 14 | items[key] = value; 15 | emit ItemSet(key, value); 16 | } 17 | } -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "fmt" 7 | "log" 8 | "math/big" 9 | 10 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 11 | "github.com/ethereum/go-ethereum/crypto" 12 | "github.com/ethereum/go-ethereum/ethclient" 13 | ) 14 | 15 | func main() { 16 | client, err := ethclient.Dial("http://localhost:9545") 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | 21 | privateKey, err := crypto.HexToECDSA("...") 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | 26 | publicKey := privateKey.Public() 27 | publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) 28 | if !ok { 29 | log.Fatal("error casting public key to ECDSA") 30 | } 31 | 32 | fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) 33 | nonce, err := client.PendingNonceAt(context.Background(), fromAddress) 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | 38 | gasPrice, err := client.SuggestGasPrice(context.Background()) 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | 43 | auth := bind.NewKeyedTransactor(privateKey) 44 | auth.Nonce = big.NewInt(int64(nonce)) 45 | auth.Value = big.NewInt(0) // in wei 46 | auth.GasLimit = uint64(300000) // in units 47 | auth.GasPrice = gasPrice 48 | 49 | input := "1.0" 50 | address, tx, instance, err := DeployStore(auth, client, input) 51 | if err != nil { 52 | log.Fatal(err) 53 | } 54 | 55 | fmt.Println(address.Hex()) 56 | fmt.Println(tx.Hash().Hex()) 57 | 58 | _ = instance 59 | } 60 | -------------------------------------------------------------------------------- /store.go: -------------------------------------------------------------------------------- 1 | // Code generated - DO NOT EDIT. 2 | // This file is a generated binding and any manual changes will be lost. 3 | 4 | package main 5 | 6 | import ( 7 | "strings" 8 | 9 | ethereum "github.com/ethereum/go-ethereum" 10 | "github.com/ethereum/go-ethereum/accounts/abi" 11 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 12 | "github.com/ethereum/go-ethereum/common" 13 | "github.com/ethereum/go-ethereum/core/types" 14 | "github.com/ethereum/go-ethereum/event" 15 | ) 16 | 17 | // StoreABI is the input ABI used to generate the binding from. 18 | const StoreABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"items\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"key\",\"type\":\"bytes32\"},{\"name\":\"value\",\"type\":\"bytes32\"}],\"name\":\"setItem\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_version\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"key\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"bytes32\"}],\"name\":\"ItemSet\",\"type\":\"event\"}]" 19 | 20 | // StoreBin is the compiled bytecode used for deploying new contracts. 21 | const StoreBin = `0x608060405234801561001057600080fd5b5060405161033438038061033483398101604052805101805161003a906000906020840190610041565b50506100dc565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008257805160ff19168380011785556100af565b828001600101855582156100af579182015b828111156100af578251825591602001919060010190610094565b506100bb9291506100bf565b5090565b6100d991905b808211156100bb57600081556001016100c5565b90565b610249806100eb6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166348f343f3811461005b57806354fd4d5014610085578063f56256c71461010f575b600080fd5b34801561006757600080fd5b5061007360043561012c565b60408051918252519081900360200190f35b34801561009157600080fd5b5061009a61013e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100d45781810151838201526020016100bc565b50505050905090810190601f1680156101015780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011b57600080fd5b5061012a6004356024356101cc565b005b60016020526000908152604090205481565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b505050505081565b600082815260016020908152604091829020839055815184815290810183905281517fe79e73da417710ae99aa2088575580a60415d359acfad9cdd3382d59c80281d4929181900390910190a150505600a165627a7a72305820ca5aa0aac3589e4f07c568b11cd3267ccf3b0613aa68bd51a8b11b92f54f46360029` 22 | 23 | // DeployStore deploys a new Ethereum contract, binding an instance of Store to it. 24 | func DeployStore(auth *bind.TransactOpts, backend bind.ContractBackend, _version string) (common.Address, *types.Transaction, *Store, error) { 25 | parsed, err := abi.JSON(strings.NewReader(StoreABI)) 26 | if err != nil { 27 | return common.Address{}, nil, nil, err 28 | } 29 | address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(StoreBin), backend, _version) 30 | if err != nil { 31 | return common.Address{}, nil, nil, err 32 | } 33 | return address, tx, &Store{StoreCaller: StoreCaller{contract: contract}, StoreTransactor: StoreTransactor{contract: contract}, StoreFilterer: StoreFilterer{contract: contract}}, nil 34 | } 35 | 36 | // Store is an auto generated Go binding around an Ethereum contract. 37 | type Store struct { 38 | StoreCaller // Read-only binding to the contract 39 | StoreTransactor // Write-only binding to the contract 40 | StoreFilterer // Log filterer for contract events 41 | } 42 | 43 | // StoreCaller is an auto generated read-only Go binding around an Ethereum contract. 44 | type StoreCaller struct { 45 | contract *bind.BoundContract // Generic contract wrapper for the low level calls 46 | } 47 | 48 | // StoreTransactor is an auto generated write-only Go binding around an Ethereum contract. 49 | type StoreTransactor struct { 50 | contract *bind.BoundContract // Generic contract wrapper for the low level calls 51 | } 52 | 53 | // StoreFilterer is an auto generated log filtering Go binding around an Ethereum contract events. 54 | type StoreFilterer struct { 55 | contract *bind.BoundContract // Generic contract wrapper for the low level calls 56 | } 57 | 58 | // StoreSession is an auto generated Go binding around an Ethereum contract, 59 | // with pre-set call and transact options. 60 | type StoreSession struct { 61 | Contract *Store // Generic contract binding to set the session for 62 | CallOpts bind.CallOpts // Call options to use throughout this session 63 | TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session 64 | } 65 | 66 | // StoreCallerSession is an auto generated read-only Go binding around an Ethereum contract, 67 | // with pre-set call options. 68 | type StoreCallerSession struct { 69 | Contract *StoreCaller // Generic contract caller binding to set the session for 70 | CallOpts bind.CallOpts // Call options to use throughout this session 71 | } 72 | 73 | // StoreTransactorSession is an auto generated write-only Go binding around an Ethereum contract, 74 | // with pre-set transact options. 75 | type StoreTransactorSession struct { 76 | Contract *StoreTransactor // Generic contract transactor binding to set the session for 77 | TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session 78 | } 79 | 80 | // StoreRaw is an auto generated low-level Go binding around an Ethereum contract. 81 | type StoreRaw struct { 82 | Contract *Store // Generic contract binding to access the raw methods on 83 | } 84 | 85 | // StoreCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. 86 | type StoreCallerRaw struct { 87 | Contract *StoreCaller // Generic read-only contract binding to access the raw methods on 88 | } 89 | 90 | // StoreTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. 91 | type StoreTransactorRaw struct { 92 | Contract *StoreTransactor // Generic write-only contract binding to access the raw methods on 93 | } 94 | 95 | // NewStore creates a new instance of Store, bound to a specific deployed contract. 96 | func NewStore(address common.Address, backend bind.ContractBackend) (*Store, error) { 97 | contract, err := bindStore(address, backend, backend, backend) 98 | if err != nil { 99 | return nil, err 100 | } 101 | return &Store{StoreCaller: StoreCaller{contract: contract}, StoreTransactor: StoreTransactor{contract: contract}, StoreFilterer: StoreFilterer{contract: contract}}, nil 102 | } 103 | 104 | // NewStoreCaller creates a new read-only instance of Store, bound to a specific deployed contract. 105 | func NewStoreCaller(address common.Address, caller bind.ContractCaller) (*StoreCaller, error) { 106 | contract, err := bindStore(address, caller, nil, nil) 107 | if err != nil { 108 | return nil, err 109 | } 110 | return &StoreCaller{contract: contract}, nil 111 | } 112 | 113 | // NewStoreTransactor creates a new write-only instance of Store, bound to a specific deployed contract. 114 | func NewStoreTransactor(address common.Address, transactor bind.ContractTransactor) (*StoreTransactor, error) { 115 | contract, err := bindStore(address, nil, transactor, nil) 116 | if err != nil { 117 | return nil, err 118 | } 119 | return &StoreTransactor{contract: contract}, nil 120 | } 121 | 122 | // NewStoreFilterer creates a new log filterer instance of Store, bound to a specific deployed contract. 123 | func NewStoreFilterer(address common.Address, filterer bind.ContractFilterer) (*StoreFilterer, error) { 124 | contract, err := bindStore(address, nil, nil, filterer) 125 | if err != nil { 126 | return nil, err 127 | } 128 | return &StoreFilterer{contract: contract}, nil 129 | } 130 | 131 | // bindStore binds a generic wrapper to an already deployed contract. 132 | func bindStore(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { 133 | parsed, err := abi.JSON(strings.NewReader(StoreABI)) 134 | if err != nil { 135 | return nil, err 136 | } 137 | return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil 138 | } 139 | 140 | // Call invokes the (constant) contract method with params as input values and 141 | // sets the output to result. The result type might be a single field for simple 142 | // returns, a slice of interfaces for anonymous returns and a struct for named 143 | // returns. 144 | func (_Store *StoreRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { 145 | return _Store.Contract.StoreCaller.contract.Call(opts, result, method, params...) 146 | } 147 | 148 | // Transfer initiates a plain transaction to move funds to the contract, calling 149 | // its default method if one is available. 150 | func (_Store *StoreRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { 151 | return _Store.Contract.StoreTransactor.contract.Transfer(opts) 152 | } 153 | 154 | // Transact invokes the (paid) contract method with params as input values. 155 | func (_Store *StoreRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { 156 | return _Store.Contract.StoreTransactor.contract.Transact(opts, method, params...) 157 | } 158 | 159 | // Call invokes the (constant) contract method with params as input values and 160 | // sets the output to result. The result type might be a single field for simple 161 | // returns, a slice of interfaces for anonymous returns and a struct for named 162 | // returns. 163 | func (_Store *StoreCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { 164 | return _Store.Contract.contract.Call(opts, result, method, params...) 165 | } 166 | 167 | // Transfer initiates a plain transaction to move funds to the contract, calling 168 | // its default method if one is available. 169 | func (_Store *StoreTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { 170 | return _Store.Contract.contract.Transfer(opts) 171 | } 172 | 173 | // Transact invokes the (paid) contract method with params as input values. 174 | func (_Store *StoreTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { 175 | return _Store.Contract.contract.Transact(opts, method, params...) 176 | } 177 | 178 | // Items is a free data retrieval call binding the contract method 0x48f343f3. 179 | // 180 | // Solidity: function items( bytes32) constant returns(bytes32) 181 | func (_Store *StoreCaller) Items(opts *bind.CallOpts, arg0 [32]byte) ([32]byte, error) { 182 | var ( 183 | ret0 = new([32]byte) 184 | ) 185 | out := ret0 186 | err := _Store.contract.Call(opts, out, "items", arg0) 187 | return *ret0, err 188 | } 189 | 190 | // Items is a free data retrieval call binding the contract method 0x48f343f3. 191 | // 192 | // Solidity: function items( bytes32) constant returns(bytes32) 193 | func (_Store *StoreSession) Items(arg0 [32]byte) ([32]byte, error) { 194 | return _Store.Contract.Items(&_Store.CallOpts, arg0) 195 | } 196 | 197 | // Items is a free data retrieval call binding the contract method 0x48f343f3. 198 | // 199 | // Solidity: function items( bytes32) constant returns(bytes32) 200 | func (_Store *StoreCallerSession) Items(arg0 [32]byte) ([32]byte, error) { 201 | return _Store.Contract.Items(&_Store.CallOpts, arg0) 202 | } 203 | 204 | // Version is a free data retrieval call binding the contract method 0x54fd4d50. 205 | // 206 | // Solidity: function version() constant returns(string) 207 | func (_Store *StoreCaller) Version(opts *bind.CallOpts) (string, error) { 208 | var ( 209 | ret0 = new(string) 210 | ) 211 | out := ret0 212 | err := _Store.contract.Call(opts, out, "version") 213 | return *ret0, err 214 | } 215 | 216 | // Version is a free data retrieval call binding the contract method 0x54fd4d50. 217 | // 218 | // Solidity: function version() constant returns(string) 219 | func (_Store *StoreSession) Version() (string, error) { 220 | return _Store.Contract.Version(&_Store.CallOpts) 221 | } 222 | 223 | // Version is a free data retrieval call binding the contract method 0x54fd4d50. 224 | // 225 | // Solidity: function version() constant returns(string) 226 | func (_Store *StoreCallerSession) Version() (string, error) { 227 | return _Store.Contract.Version(&_Store.CallOpts) 228 | } 229 | 230 | // SetItem is a paid mutator transaction binding the contract method 0xf56256c7. 231 | // 232 | // Solidity: function setItem(key bytes32, value bytes32) returns() 233 | func (_Store *StoreTransactor) SetItem(opts *bind.TransactOpts, key [32]byte, value [32]byte) (*types.Transaction, error) { 234 | return _Store.contract.Transact(opts, "setItem", key, value) 235 | } 236 | 237 | // SetItem is a paid mutator transaction binding the contract method 0xf56256c7. 238 | // 239 | // Solidity: function setItem(key bytes32, value bytes32) returns() 240 | func (_Store *StoreSession) SetItem(key [32]byte, value [32]byte) (*types.Transaction, error) { 241 | return _Store.Contract.SetItem(&_Store.TransactOpts, key, value) 242 | } 243 | 244 | // SetItem is a paid mutator transaction binding the contract method 0xf56256c7. 245 | // 246 | // Solidity: function setItem(key bytes32, value bytes32) returns() 247 | func (_Store *StoreTransactorSession) SetItem(key [32]byte, value [32]byte) (*types.Transaction, error) { 248 | return _Store.Contract.SetItem(&_Store.TransactOpts, key, value) 249 | } 250 | 251 | // StoreItemSetIterator is returned from FilterItemSet and is used to iterate over the raw logs and unpacked data for ItemSet events raised by the Store contract. 252 | type StoreItemSetIterator struct { 253 | Event *StoreItemSet // Event containing the contract specifics and raw log 254 | 255 | contract *bind.BoundContract // Generic contract to use for unpacking event data 256 | event string // Event name to use for unpacking event data 257 | 258 | logs chan types.Log // Log channel receiving the found contract events 259 | sub ethereum.Subscription // Subscription for errors, completion and termination 260 | done bool // Whether the subscription completed delivering logs 261 | fail error // Occurred error to stop iteration 262 | } 263 | 264 | // Next advances the iterator to the subsequent event, returning whether there 265 | // are any more events found. In case of a retrieval or parsing error, false is 266 | // returned and Error() can be queried for the exact failure. 267 | func (it *StoreItemSetIterator) Next() bool { 268 | // If the iterator failed, stop iterating 269 | if it.fail != nil { 270 | return false 271 | } 272 | // If the iterator completed, deliver directly whatever's available 273 | if it.done { 274 | select { 275 | case log := <-it.logs: 276 | it.Event = new(StoreItemSet) 277 | if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { 278 | it.fail = err 279 | return false 280 | } 281 | it.Event.Raw = log 282 | return true 283 | 284 | default: 285 | return false 286 | } 287 | } 288 | // Iterator still in progress, wait for either a data or an error event 289 | select { 290 | case log := <-it.logs: 291 | it.Event = new(StoreItemSet) 292 | if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { 293 | it.fail = err 294 | return false 295 | } 296 | it.Event.Raw = log 297 | return true 298 | 299 | case err := <-it.sub.Err(): 300 | it.done = true 301 | it.fail = err 302 | return it.Next() 303 | } 304 | } 305 | 306 | // Error returns any retrieval or parsing error occurred during filtering. 307 | func (it *StoreItemSetIterator) Error() error { 308 | return it.fail 309 | } 310 | 311 | // Close terminates the iteration process, releasing any pending underlying 312 | // resources. 313 | func (it *StoreItemSetIterator) Close() error { 314 | it.sub.Unsubscribe() 315 | return nil 316 | } 317 | 318 | // StoreItemSet represents a ItemSet event raised by the Store contract. 319 | type StoreItemSet struct { 320 | Key [32]byte 321 | Value [32]byte 322 | Raw types.Log // Blockchain specific contextual infos 323 | } 324 | 325 | // FilterItemSet is a free log retrieval operation binding the contract event 0xe79e73da417710ae99aa2088575580a60415d359acfad9cdd3382d59c80281d4. 326 | // 327 | // Solidity: e ItemSet(key bytes32, value bytes32) 328 | func (_Store *StoreFilterer) FilterItemSet(opts *bind.FilterOpts) (*StoreItemSetIterator, error) { 329 | 330 | logs, sub, err := _Store.contract.FilterLogs(opts, "ItemSet") 331 | if err != nil { 332 | return nil, err 333 | } 334 | return &StoreItemSetIterator{contract: _Store.contract, event: "ItemSet", logs: logs, sub: sub}, nil 335 | } 336 | 337 | // WatchItemSet is a free log subscription operation binding the contract event 0xe79e73da417710ae99aa2088575580a60415d359acfad9cdd3382d59c80281d4. 338 | // 339 | // Solidity: e ItemSet(key bytes32, value bytes32) 340 | func (_Store *StoreFilterer) WatchItemSet(opts *bind.WatchOpts, sink chan<- *StoreItemSet) (event.Subscription, error) { 341 | 342 | logs, sub, err := _Store.contract.WatchLogs(opts, "ItemSet") 343 | if err != nil { 344 | return nil, err 345 | } 346 | return event.NewSubscription(func(quit <-chan struct{}) error { 347 | defer sub.Unsubscribe() 348 | for { 349 | select { 350 | case log := <-logs: 351 | // New log arrived, parse the event and forward to the user 352 | event := new(StoreItemSet) 353 | if err := _Store.contract.UnpackLog(event, "ItemSet", log); err != nil { 354 | return err 355 | } 356 | event.Raw = log 357 | 358 | select { 359 | case sink <- event: 360 | case err := <-sub.Err(): 361 | return err 362 | case <-quit: 363 | return nil 364 | } 365 | case err := <-sub.Err(): 366 | return err 367 | case <-quit: 368 | return nil 369 | } 370 | } 371 | }), nil 372 | } 373 | --------------------------------------------------------------------------------