github.com/0chain/gosdk@v1.17.11/znft/znft.go (about)

     1  package znft
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/0chain/gosdk/core/logger"
     9  
    10  	storageerc721 "github.com/0chain/gosdk/znft/contracts/dstorageerc721/binding"
    11  	storageerc721fixed "github.com/0chain/gosdk/znft/contracts/dstorageerc721fixed/binding"
    12  	storageerc721pack "github.com/0chain/gosdk/znft/contracts/dstorageerc721pack/binding"
    13  	storageerc721random "github.com/0chain/gosdk/znft/contracts/dstorageerc721random/binding"
    14  
    15  	factoryerc721 "github.com/0chain/gosdk/znft/contracts/factorymoduleerc721/binding"
    16  	factoryerc721fixed "github.com/0chain/gosdk/znft/contracts/factorymoduleerc721fixed/binding"
    17  	factoryerc721pack "github.com/0chain/gosdk/znft/contracts/factorymoduleerc721pack/binding"
    18  	factoryerc721random "github.com/0chain/gosdk/znft/contracts/factorymoduleerc721random/binding"
    19  
    20  	"github.com/ethereum/go-ethereum/accounts/abi/bind"
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/pkg/errors"
    23  )
    24  
    25  var defaultLogLevel = logger.DEBUG
    26  var Logger logger.Logger
    27  
    28  const (
    29  	ConfigFile = "config.yaml"
    30  	WalletDir  = "wallets"
    31  )
    32  
    33  type Configuration struct {
    34  	FactoryAddress                   string // FactoryAddress address
    35  	FactoryModuleERC721Address       string // FactoryModuleERC721Address address
    36  	FactoryModuleERC721PackedAddress string // FactoryModuleERC721PackedAddress address
    37  	FactoryModuleERC721FixedAddress  string // FactoryModuleERC721FixedAddress address
    38  	FactoryModuleERC721RandomAddress string // FactoryModuleERC721RandomAddress address
    39  	EthereumNodeURL                  string // EthereumNodeURL URL of ethereum RPC node (infura or alchemy)
    40  	WalletAddress                    string // WalletAddress client address
    41  	VaultPassword                    string // VaultPassword used to sign transactions on behalf of the client
    42  	Homedir                          string // Homedir is a client config folder
    43  	Value                            int64  // Value to execute Ethereum smart contracts (default = 0)
    44  }
    45  
    46  type Znft struct {
    47  	cfg *Configuration
    48  }
    49  
    50  func init() {
    51  	Logger.Init(defaultLogLevel, "0chain-znft-sdk")
    52  }
    53  
    54  func NewNFTApplication(c *Configuration) *Znft {
    55  	return &Znft{c}
    56  }
    57  
    58  func GetConfigDir() string {
    59  	var configDir string
    60  	home, err := os.UserHomeDir()
    61  	if err != nil {
    62  		fmt.Println(err)
    63  		os.Exit(1)
    64  	}
    65  	configDir = home + "/.zcn"
    66  	return configDir
    67  }
    68  
    69  // Functions used by session factories to create session
    70  
    71  func (app *Znft) constructFactoryERC721(ctx context.Context, address string) (*factoryerc721.Binding, *bind.TransactOpts, error) {
    72  	storage, err := app.createFactoryERC721(address)
    73  	if err != nil {
    74  		return nil, nil, errors.Wrapf(err, "failed to construct %s", "FactoryERC721")
    75  	}
    76  
    77  	transaction, err := app.createTransactOpts(ctx)
    78  
    79  	return storage, transaction, err
    80  }
    81  
    82  func (app *Znft) constructFactoryERC721Fixed(ctx context.Context, address string) (*factoryerc721fixed.Binding, *bind.TransactOpts, error) {
    83  	storage, err := app.createFactoryERC721Fixed(address)
    84  	if err != nil {
    85  		return nil, nil, errors.Wrapf(err, "failed to construct %s", "FactoryERC721Fixed")
    86  	}
    87  
    88  	transaction, err := app.createTransactOpts(ctx)
    89  
    90  	return storage, transaction, err
    91  }
    92  
    93  func (app *Znft) constructFactoryERC721Pack(ctx context.Context, address string) (*factoryerc721pack.Binding, *bind.TransactOpts, error) {
    94  	storage, err := app.createFactoryERC721Pack(address)
    95  	if err != nil {
    96  		return nil, nil, errors.Wrapf(err, "failed to construct %s", "FactoryERC721Pack")
    97  	}
    98  
    99  	transaction, err := app.createTransactOpts(ctx)
   100  
   101  	return storage, transaction, err
   102  }
   103  
   104  func (app *Znft) constructFactoryERC721Random(ctx context.Context, address string) (*factoryerc721random.Binding, *bind.TransactOpts, error) {
   105  	storage, err := app.createFactoryERC721Random(address)
   106  	if err != nil {
   107  		return nil, nil, errors.Wrapf(err, "failed to construct %s", "FactoryERC721Random")
   108  	}
   109  
   110  	transaction, err := app.createTransactOpts(ctx)
   111  
   112  	return storage, transaction, err
   113  }
   114  
   115  func (app *Znft) constructStorageERC721Random(ctx context.Context, address string) (*storageerc721random.Binding, *bind.TransactOpts, error) {
   116  	storage, err := app.createStorageERC721Random(address)
   117  	if err != nil {
   118  		return nil, nil, errors.Wrapf(err, "failed to construct %s", ContractStorageERC721RandomName)
   119  	}
   120  
   121  	transaction, err := app.createTransactOpts(ctx)
   122  
   123  	return storage, transaction, err
   124  }
   125  
   126  func (app *Znft) constructStorageERC721Pack(ctx context.Context, address string) (*storageerc721pack.Binding, *bind.TransactOpts, error) {
   127  	storage, err := app.createStorageERC721Pack(address)
   128  	if err != nil {
   129  		return nil, nil, errors.Wrapf(err, "failed to construct %s", ContractStorageERC721PackName)
   130  	}
   131  
   132  	transaction, err := app.createTransactOpts(ctx)
   133  
   134  	return storage, transaction, err
   135  }
   136  
   137  func (app *Znft) constructStorageERC721Fixed(ctx context.Context, address string) (*storageerc721fixed.Binding, *bind.TransactOpts, error) {
   138  	storage, err := app.createStorageERC721Fixed(address)
   139  	if err != nil {
   140  		return nil, nil, errors.Wrapf(err, "failed to construct %s", ContractStorageERC721FixedName)
   141  	}
   142  
   143  	transaction, err := app.createTransactOpts(ctx)
   144  
   145  	return storage, transaction, err
   146  }
   147  
   148  func (app *Znft) constructStorageERC721(ctx context.Context, address string) (*storageerc721.Binding, *bind.TransactOpts, error) {
   149  	storage, err := app.createStorageERC721(address)
   150  	if err != nil {
   151  		return nil, nil, errors.Wrapf(err, "failed to construct %s", ContractStorageERC721Name)
   152  	}
   153  
   154  	transaction, err := app.createTransactOpts(ctx)
   155  
   156  	return storage, transaction, err
   157  }
   158  
   159  // Used to create StorageERC721 with preliminary gas estimation
   160  func (app *Znft) constructWithEstimation( //nolint
   161  	ctx context.Context,
   162  	address string,
   163  	method string,
   164  	params ...interface{},
   165  ) (*storageerc721.Binding, *bind.TransactOpts, error) {
   166  	erc721, err := app.createStorageERC721(address)
   167  	if err != nil {
   168  		return nil, nil, errors.Wrapf(err, "failed to create %s in method: %s", ContractStorageERC721Name, method)
   169  	}
   170  
   171  	transaction, err := app.createTransactOptsWithEstimation(ctx, address, method, params)
   172  
   173  	return erc721, transaction, err
   174  }
   175  
   176  // Create transaction opts with sender signature
   177  func (app *Znft) createTransactOpts(ctx context.Context) (*bind.TransactOpts, error) {
   178  	transaction, err := app.createTransaction(ctx)
   179  	if err != nil {
   180  		return nil, errors.Wrapf(err, "failed to create createTransactOpts in %s", ContractStorageERC721Name)
   181  	}
   182  
   183  	return transaction, nil
   184  }
   185  
   186  func (app *Znft) createTransactOptsWithEstimation( //nolint
   187  	ctx context.Context,
   188  	address, method string,
   189  	params ...interface{},
   190  ) (*bind.TransactOpts, error) {
   191  	// Get ABI of the contract
   192  	abi, err := storageerc721.BindingMetaData.GetAbi()
   193  	if err != nil {
   194  		return nil, errors.Wrapf(err, "failed to get ABI in %s, method: %s", ContractStorageERC721Name, method)
   195  	}
   196  
   197  	// Pack the method arguments
   198  	pack, err := abi.Pack(method, params...)
   199  	if err != nil {
   200  		return nil, errors.Wrapf(err, "failed to pack arguments in %s, method: %s", ContractStorageERC721Name, method)
   201  	}
   202  
   203  	transaction, err := app.createTransactionWithGasPrice(ctx, address, pack)
   204  	if err != nil {
   205  		return nil, errors.Wrapf(err, "failed to create createTransaction in %s, method: %s", ContractStorageERC721Name, method)
   206  	}
   207  
   208  	return transaction, nil
   209  }
   210  
   211  // Session factories
   212  
   213  // Factory Sessions
   214  
   215  func (app *Znft) CreateFactoryERC721Session(ctx context.Context, addr string) (IFactoryERC721, error) {
   216  	contract, transact, err := app.constructFactoryERC721(ctx, addr)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  
   221  	session := &factoryerc721.BindingSession{
   222  		Contract: contract,
   223  		CallOpts: bind.CallOpts{
   224  			Pending: true,
   225  			From:    transact.From,
   226  			Context: ctx,
   227  		},
   228  		TransactOpts: *transact,
   229  	}
   230  
   231  	storage := &FactoryERC721{
   232  		session: session,
   233  		ctx:     ctx,
   234  	}
   235  
   236  	return storage, nil
   237  }
   238  
   239  func (app *Znft) CreateFactoryERC721PackSession(ctx context.Context, addr string) (IFactoryPack, error) {
   240  	contract, transact, err := app.constructFactoryERC721Pack(ctx, addr)
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  
   245  	session := &factoryerc721pack.BindingSession{
   246  		Contract: contract,
   247  		CallOpts: bind.CallOpts{
   248  			Pending: true,
   249  			From:    transact.From,
   250  			Context: ctx,
   251  		},
   252  		TransactOpts: *transact,
   253  	}
   254  
   255  	storage := &FactoryPack{
   256  		session: session,
   257  		ctx:     ctx,
   258  	}
   259  
   260  	return storage, nil
   261  }
   262  
   263  func (app *Znft) CreateFactoryERC721FixedSession(ctx context.Context, addr string) (IFactoryFixed, error) {
   264  	contract, transact, err := app.constructFactoryERC721Fixed(ctx, addr)
   265  	if err != nil {
   266  		return nil, err
   267  	}
   268  
   269  	session := &factoryerc721fixed.BindingSession{
   270  		Contract: contract,
   271  		CallOpts: bind.CallOpts{
   272  			Pending: true,
   273  			From:    transact.From,
   274  			Context: ctx,
   275  		},
   276  		TransactOpts: *transact,
   277  	}
   278  
   279  	storage := &FactoryFixed{
   280  		session: session,
   281  		ctx:     ctx,
   282  	}
   283  
   284  	return storage, nil
   285  }
   286  
   287  func (app *Znft) CreateFactoryERC721RandomSession(ctx context.Context, addr string) (IFactoryRandom, error) {
   288  	contract, transact, err := app.constructFactoryERC721Random(ctx, addr)
   289  	if err != nil {
   290  		return nil, err
   291  	}
   292  
   293  	session := &factoryerc721random.BindingSession{
   294  		Contract: contract,
   295  		CallOpts: bind.CallOpts{
   296  			Pending: true,
   297  			From:    transact.From,
   298  			Context: ctx,
   299  		},
   300  		TransactOpts: *transact,
   301  	}
   302  
   303  	storage := &FactoryRandom{
   304  		session: session,
   305  		ctx:     ctx,
   306  	}
   307  
   308  	return storage, nil
   309  }
   310  
   311  // Storage Sessions
   312  
   313  func (app *Znft) CreateStorageERC721PackSession(ctx context.Context, addr string) (IStorageECR721Pack, error) {
   314  	contract, transact, err := app.constructStorageERC721Pack(ctx, addr)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  
   319  	session := &storageerc721pack.BindingSession{
   320  		Contract: contract,
   321  		CallOpts: bind.CallOpts{
   322  			Pending: true,
   323  			From:    transact.From,
   324  			Context: ctx,
   325  		},
   326  		TransactOpts: *transact,
   327  	}
   328  
   329  	storage := &StorageECR721Pack{
   330  		session: session,
   331  		ctx:     ctx,
   332  	}
   333  
   334  	return storage, nil
   335  }
   336  
   337  func (app *Znft) CreateStorageERC721RandomSession(ctx context.Context, addr string) (IStorageECR721Random, error) {
   338  	contract, transact, err := app.constructStorageERC721Random(ctx, addr)
   339  	if err != nil {
   340  		return nil, err
   341  	}
   342  
   343  	session := &storageerc721random.BindingSession{
   344  		Contract: contract,
   345  		CallOpts: bind.CallOpts{
   346  			Pending: true,
   347  			From:    transact.From,
   348  			Context: ctx,
   349  		},
   350  		TransactOpts: *transact,
   351  	}
   352  
   353  	storage := &StorageECR721Random{
   354  		session: session,
   355  		ctx:     ctx,
   356  	}
   357  
   358  	return storage, nil
   359  }
   360  
   361  func (app *Znft) CreateStorageERC721FixedSession(ctx context.Context, addr string) (IStorageECR721Fixed, error) {
   362  	contract, transact, err := app.constructStorageERC721Fixed(ctx, addr)
   363  	if err != nil {
   364  		return nil, err
   365  	}
   366  
   367  	session := &storageerc721fixed.BindingSession{
   368  		Contract: contract,
   369  		CallOpts: bind.CallOpts{
   370  			Pending: true,
   371  			From:    transact.From,
   372  			Context: ctx,
   373  		},
   374  		TransactOpts: *transact,
   375  	}
   376  
   377  	storage := &StorageECR721Fixed{
   378  		session: session,
   379  		ctx:     ctx,
   380  	}
   381  
   382  	return storage, nil
   383  }
   384  
   385  func (app *Znft) CreateStorageERC721Session(ctx context.Context, addr string) (IStorageECR721, error) {
   386  	contract, transact, err := app.constructStorageERC721(ctx, addr)
   387  	if err != nil {
   388  		return nil, err
   389  	}
   390  
   391  	session := &storageerc721.BindingSession{
   392  		Contract: contract,
   393  		CallOpts: bind.CallOpts{
   394  			Pending: true,
   395  			From:    transact.From,
   396  			Context: ctx,
   397  		},
   398  		TransactOpts: *transact,
   399  	}
   400  
   401  	storage := &StorageECR721{
   402  		session: session,
   403  		ctx:     ctx,
   404  	}
   405  
   406  	return storage, nil
   407  }
   408  
   409  // Binding factories
   410  
   411  func (app *Znft) createStorageERC721(address string) (*storageerc721.Binding, error) {
   412  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   413  	if err != nil {
   414  		return nil, err
   415  	}
   416  
   417  	addr := common.HexToAddress(address)
   418  	instance, err := storageerc721.NewBinding(addr, client)
   419  
   420  	return instance, err
   421  }
   422  
   423  func (app *Znft) createStorageERC721Fixed(address string) (*storageerc721fixed.Binding, error) {
   424  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  
   429  	addr := common.HexToAddress(address)
   430  	instance, err := storageerc721fixed.NewBinding(addr, client)
   431  
   432  	return instance, err
   433  }
   434  
   435  func (app *Znft) createStorageERC721Random(address string) (*storageerc721random.Binding, error) {
   436  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   437  	if err != nil {
   438  		return nil, err
   439  	}
   440  
   441  	addr := common.HexToAddress(address)
   442  	instance, err := storageerc721random.NewBinding(addr, client)
   443  
   444  	return instance, err
   445  }
   446  
   447  func (app *Znft) createStorageERC721Pack(address string) (*storageerc721pack.Binding, error) {
   448  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   449  	if err != nil {
   450  		return nil, err
   451  	}
   452  
   453  	addr := common.HexToAddress(address)
   454  	instance, err := storageerc721pack.NewBinding(addr, client)
   455  
   456  	return instance, err
   457  }
   458  
   459  func (app *Znft) createFactoryERC721(address string) (*factoryerc721.Binding, error) {
   460  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   461  	if err != nil {
   462  		return nil, err
   463  	}
   464  
   465  	addr := common.HexToAddress(address)
   466  	instance, err := factoryerc721.NewBinding(addr, client)
   467  
   468  	return instance, err
   469  }
   470  
   471  func (app *Znft) createFactoryERC721Pack(address string) (*factoryerc721pack.Binding, error) {
   472  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   473  	if err != nil {
   474  		return nil, err
   475  	}
   476  
   477  	addr := common.HexToAddress(address)
   478  	instance, err := factoryerc721pack.NewBinding(addr, client)
   479  
   480  	return instance, err
   481  }
   482  
   483  func (app *Znft) createFactoryERC721Random(address string) (*factoryerc721random.Binding, error) {
   484  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   485  	if err != nil {
   486  		return nil, err
   487  	}
   488  
   489  	addr := common.HexToAddress(address)
   490  	instance, err := factoryerc721random.NewBinding(addr, client)
   491  
   492  	return instance, err
   493  }
   494  
   495  func (app *Znft) createFactoryERC721Fixed(address string) (*factoryerc721fixed.Binding, error) {
   496  	client, err := CreateEthClient(app.cfg.EthereumNodeURL)
   497  	if err != nil {
   498  		return nil, err
   499  	}
   500  
   501  	addr := common.HexToAddress(address)
   502  	instance, err := factoryerc721fixed.NewBinding(addr, client)
   503  
   504  	return instance, err
   505  }