github.com/0xsequence/ethkit@v1.25.0/ethdeploy/ethdeploy.go (about)

     1  package ethdeploy
     2  
     3  import (
     4  	"context"
     5  	"math/big"
     6  	"strings"
     7  
     8  	"github.com/0xsequence/ethkit/ethrpc"
     9  	"github.com/0xsequence/ethkit/ethwallet"
    10  	"github.com/0xsequence/ethkit/go-ethereum/accounts/abi"
    11  	"github.com/0xsequence/ethkit/go-ethereum/accounts/abi/bind"
    12  	"github.com/0xsequence/ethkit/go-ethereum/common"
    13  	"github.com/0xsequence/ethkit/go-ethereum/core/types"
    14  )
    15  
    16  // Deploy any contract with just the abi and its bytecode
    17  //
    18  // Sample usage:
    19  //
    20  // auth, err := wallet.Transactor()
    21  // assert.NoError(t, err)
    22  // auth.Nonce = big.NewInt(int64(nonce)) // next nonce for the account
    23  // auth.Value = big.NewInt(0)            // in wei
    24  // auth.GasLimit = uint64(5000000)       // in units
    25  // auth.GasPrice = gasPrice
    26  //
    27  // // deploy transaction
    28  // contractAddress, tx, contract, err := ethdeploy.DeployContract(auth, service.ETHRPC, contractABIJSONString, contractBytecodeHex)
    29  //
    30  // // get another account from the list
    31  // wallet2, _ := ethwallet.NewETHWallet(cfg.Wallet.PrivateKeyMnemonic)
    32  // wallet2.SetAccountIndex(1)
    33  // address2, _ := wallet2.Address()
    34  //
    35  // var out = new(*big.Int)
    36  // err := contract.Call(&bind.CallOpts{Context: context.Background()}, out, "balanceOf", address2, big.NewInt(1))
    37  // assert.NoError(t, err)
    38  // fmt.Println("=======>", *out) // <---<< returns `balanceOf(address2)` output from the chain
    39  //
    40  
    41  type Deployer struct {
    42  	Provider *ethrpc.Provider
    43  }
    44  
    45  func NewDeployer(provider *ethrpc.Provider) *Deployer {
    46  	return &Deployer{Provider: provider}
    47  }
    48  
    49  // TODO: accept optional *TransactOpts argument, can be nil and we'll populate ourselves
    50  // or make our own structs like DeployOpts with nonce, gasPrice and gasLimit
    51  func (d *Deployer) DeployContract(ctx context.Context, wallet *ethwallet.Wallet, contractABI, contractBytecodeHex string, contractConstructorArgs ...interface{}) (common.Address, *types.Transaction, *bind.BoundContract, error) {
    52  	address := wallet.Address()
    53  
    54  	nonce, err := d.Provider.PendingNonceAt(ctx, address)
    55  	if err != nil {
    56  		return common.Address{}, nil, nil, err
    57  	}
    58  
    59  	gasPrice, err := d.Provider.SuggestGasPrice(ctx)
    60  	if err != nil {
    61  		return common.Address{}, nil, nil, err
    62  	}
    63  
    64  	auth, err := wallet.Transactor(ctx)
    65  	if err != nil {
    66  		return common.Address{}, nil, nil, err
    67  	}
    68  
    69  	auth.Nonce = big.NewInt(int64(nonce))
    70  	auth.Value = big.NewInt(0)
    71  	auth.GasLimit = uint64(5000000)
    72  	auth.GasPrice = gasPrice
    73  
    74  	return DeployContract(auth, d.Provider, contractABI, contractBytecodeHex)
    75  }
    76  
    77  func DeployContract(auth *bind.TransactOpts, backend bind.ContractBackend, contractABI, contractBytecodeHex string, contractConstructorArgs ...interface{}) (common.Address, *types.Transaction, *bind.BoundContract, error) {
    78  	parsed, err := abi.JSON(strings.NewReader(contractABI))
    79  	if err != nil {
    80  		return common.Address{}, nil, nil, err
    81  	}
    82  
    83  	address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(contractBytecodeHex), backend, contractConstructorArgs...)
    84  	if err != nil {
    85  		return common.Address{}, nil, nil, err
    86  	}
    87  
    88  	return address, tx, contract, nil
    89  }