@ -27,20 +27,45 @@ var (
const (
errStrDeploy = "deployment of %s failed: %w"
errStrWaitReceipt = "wait receipt of %s deploy failed: %w"
// default values
defaultCallGasLimit = 300000
defaultDeployGasLimit = 1000000
defaultGasPriceDiv = 100
defaultReceiptTimeout = 60
defaultIntervalReceiptLoop = 200
)
type Config struct {
CallGasLimit uint64
DeployGasLimit uint64
GasPriceDiv uint64
ReceiptTimeout time . Duration // in seconds
IntervalReceiptLoop time . Duration // in milliseconds
}
// Client is an ethereum client to call Smart Contract methods.
type Client struct {
client * ethclient . Client
account * accounts . Account
ks * ethKeystore . KeyStore
ReceiptTimeout time . Duration
config * Config
}
// NewClient creates a Client instance. The account is not mandatory (it can
// be nil). If the account is nil, CallAuth will fail with ErrAccountNil.
func NewClient ( client * ethclient . Client , account * accounts . Account , ks * ethKeystore . KeyStore ) * Client {
return & Client { client : client , account : account , ks : ks , ReceiptTimeout : 60 * time . Second }
func NewClient ( client * ethclient . Client , account * accounts . Account , ks * ethKeystore . KeyStore , config * Config ) * Client {
if config == nil {
config = & Config {
CallGasLimit : defaultCallGasLimit ,
DeployGasLimit : defaultDeployGasLimit ,
GasPriceDiv : defaultGasPriceDiv ,
ReceiptTimeout : defaultReceiptTimeout ,
IntervalReceiptLoop : defaultIntervalReceiptLoop ,
}
}
return & Client { client : client , account : account , ks : ks , ReceiptTimeout : config . ReceiptTimeout * time . Second , config : config }
}
// BalanceAt retieves information about the default account
@ -67,7 +92,7 @@ func (c *Client) CallAuth(gasLimit uint64,
return nil , err
}
inc := new ( big . Int ) . Set ( gasPrice )
inc . Div ( inc , new ( big . Int ) . SetUint64 ( 100 ) )
inc . Div ( inc , new ( big . Int ) . SetUint64 ( c . config . GasPriceDiv ) )
gasPrice . Add ( gasPrice , inc )
log . Debug ( "Transaction metadata" , "gasPrice" , gasPrice )
@ -77,7 +102,7 @@ func (c *Client) CallAuth(gasLimit uint64,
}
auth . Value = big . NewInt ( 0 ) // in wei
if gasLimit == 0 {
auth . GasLimit = uint64 ( 300000 ) // in units
auth . GasLimit = c . config . CallGasLimit // in units
} else {
auth . GasLimit = gasLimit // in units
}
@ -99,14 +124,13 @@ type ContractData struct {
// Deploy a smart contract. `name` is used to log deployment information. fn
// is a wrapper to the deploy function generated by abigen. In case of error,
// the returned `ContractData` may have some parameters filled depending on the
// kind of error that ocurred.
// successfull.
// kind of error that occurred.
func ( c * Client ) Deploy ( name string ,
fn func ( c * ethclient . Client , auth * bind . TransactOpts ) ( ethCommon . Address , * types . Transaction , interface { } , error ) ) ( ContractData , error ) {
var contractData ContractData
log . Info ( "Deploying" , "contract" , name )
tx , err := c . CallAuth (
1000000 ,
c . config . DeployGasLimit ,
func ( client * ethclient . Client , auth * bind . TransactOpts ) ( * types . Transaction , error ) {
addr , tx , _ , err := fn ( client , auth )
if err != nil {
@ -162,7 +186,7 @@ func (c *Client) waitReceipt(tx *types.Transaction, ctx context.Context, timeout
if receipt != nil || time . Since ( start ) >= timeout {
break
}
time . Sleep ( 200 * time . Millisecond )
time . Sleep ( c . config . IntervalReceiptLoop * time . Millisecond )
}
if receipt != nil && receipt . Status == types . ReceiptStatusFailed {
@ -174,7 +198,7 @@ func (c *Client) waitReceipt(tx *types.Transaction, ctx context.Context, timeout
log . Debug ( "Pendingtransaction / Wait receipt timeout" , "tx" , txid . Hex ( ) , "lasterr" , err )
return receipt , ErrReceiptNotReceived
}
log . Debug ( "Successfull transaction" , "tx" , txid . Hex ( ) )
log . Debug ( "Successful transaction" , "tx" , txid . Hex ( ) )
return receipt , err
}