github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/blobber_operations_mobile.go (about)

     1  //go:build mobile
     2  // +build mobile
     3  
     4  package sdk
     5  
     6  import (
     7  	"encoding/json"
     8  	"math"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/0chain/errors"
    13  	"github.com/0chain/gosdk/core/transaction"
    14  	"github.com/0chain/gosdk/zboxcore/client"
    15  )
    16  
    17  // CreateAllocationForOwner creates a new allocation with the given options (txn: `storagesc.new_allocation_request`).
    18  //
    19  //   - owner is the client id of the owner of the allocation.
    20  //   - ownerpublickey is the public key of the owner of the allocation.
    21  //   - datashards is the number of data shards for the allocation.
    22  //   - parityshards is the number of parity shards for the allocation.
    23  //   - size is the size of the allocation.
    24  //   - readPrice is the read price range for the allocation (Reads in Züs are free!).
    25  //   - writePrice is the write price range for the allocation.
    26  //   - lock is the lock value for the transaction (how much tokens to lock to the allocation, in SAS).
    27  //   - preferredBlobberIds is a list of preferred blobber ids for the allocation.
    28  //   - thirdPartyExtendable is a flag indicating whether the allocation can be extended by a third party.
    29  //   - fileOptionsParams is the file options parameters for the allocation, which control the usage permissions of the files in the allocation.
    30  //
    31  // returns the hash of the transaction, the nonce of the transaction, the transaction object and an error if any.
    32  func CreateAllocationForOwner(
    33  	owner, ownerpublickey string,
    34  	datashards, parityshards int, size int64,
    35  	readPrice, writePrice PriceRange,
    36  	lock uint64, preferredBlobberIds, blobberAuthTickets []string, thirdPartyExtendable, IsEnterprise, force bool, fileOptionsParams *FileOptionsParameters,
    37  ) (hash string, nonce int64, txn *transaction.Transaction, err error) {
    38  
    39  	if lock > math.MaxInt64 {
    40  		return "", 0, nil, errors.New("invalid_lock", "int64 overflow on lock value")
    41  	}
    42  
    43  	if datashards < 1 || parityshards < 1 {
    44  		return "", 0, nil, errors.New("allocation_validation_failed", "atleast 1 data and 1 parity shards are required")
    45  	}
    46  
    47  	allocationRequest, err := getNewAllocationBlobbers(
    48  		datashards, parityshards, size, readPrice, writePrice, preferredBlobberIds, blobberAuthTickets, force)
    49  	if err != nil {
    50  		return "", 0, nil, errors.New("failed_get_allocation_blobbers", "failed to get blobbers for allocation: "+err.Error())
    51  	}
    52  
    53  	if !sdkInitialized {
    54  		return "", 0, nil, sdkNotInitialized
    55  	}
    56  
    57  	allocationRequest["owner_id"] = owner
    58  	allocationRequest["owner_public_key"] = ownerpublickey
    59  	allocationRequest["third_party_extendable"] = thirdPartyExtendable
    60  	allocationRequest["file_options_changed"], allocationRequest["file_options"] = calculateAllocationFileOptions(63 /*0011 1111*/, fileOptionsParams)
    61  	allocationRequest["is_enterprise"] = IsEnterprise
    62  
    63  	var sn = transaction.SmartContractTxnData{
    64  		Name:      transaction.NEW_ALLOCATION_REQUEST,
    65  		InputArgs: allocationRequest,
    66  	}
    67  	hash, _, nonce, txn, err = storageSmartContractTxnValue(sn, strconv.FormatUint(lock, 10))
    68  	return
    69  }
    70  
    71  // CreateFreeAllocation creates a new free allocation (txn: `storagesc.free_allocation_request`).
    72  //   - marker is the marker for the free allocation.
    73  //   - value is the value of the free allocation.
    74  //
    75  // returns the hash of the transaction, the nonce of the transaction and an error if any.
    76  func CreateFreeAllocation(marker string, value string) (string, int64, error) {
    77  	if !sdkInitialized {
    78  		return "", 0, sdkNotInitialized
    79  	}
    80  
    81  	recipientPublicKey := client.GetClientPublicKey()
    82  
    83  	var input = map[string]interface{}{
    84  		"recipient_public_key": recipientPublicKey,
    85  		"marker":               marker,
    86  	}
    87  
    88  	blobbers, err := GetFreeAllocationBlobbers(input)
    89  	if err != nil {
    90  		return "", 0, err
    91  	}
    92  
    93  	input["blobbers"] = blobbers
    94  
    95  	var sn = transaction.SmartContractTxnData{
    96  		Name:      transaction.NEW_FREE_ALLOCATION,
    97  		InputArgs: input,
    98  	}
    99  	hash, _, n, _, err := storageSmartContractTxnValue(sn, value)
   100  	return hash, n, err
   101  }
   102  
   103  // UpdateAllocation sends an update request for an allocation (txn: `storagesc.update_allocation_request`)
   104  //
   105  //   - size is the size of the allocation.
   106  //   - extend is a flag indicating whether to extend the allocation.
   107  //   - allocationID is the id of the allocation.
   108  //   - lock is the lock value for the transaction (how much tokens to lock to the allocation, in SAS).
   109  //   - addBlobberId is the id of the blobber to add to the allocation.
   110  //   - addBlobberAuthTicket is the auth ticket of the blobber to add to the allocation, in case the blobber is restricted.
   111  //   - removeBlobberId is the id of the blobber to remove from the allocation.
   112  //   - setThirdPartyExtendable is a flag indicating whether the allocation can be extended by a third party.
   113  //   - fileOptionsParams is the file options parameters for the allocation, which control the usage permissions of the files in the allocation.
   114  //
   115  // returns the hash of the transaction, the nonce of the transaction and an error if any.
   116  func UpdateAllocation(
   117  	size int64,
   118  	extend bool,
   119  	allocationID string,
   120  	lock uint64,
   121  	addBlobberId, addBlobberAuthTicket, removeBlobberId string,
   122  	setThirdPartyExtendable bool, fileOptionsParams *FileOptionsParameters,
   123  ) (hash string, nonce int64, err error) {
   124  
   125  	if lock > math.MaxInt64 {
   126  		return "", 0, errors.New("invalid_lock", "int64 overflow on lock value")
   127  	}
   128  
   129  	if !sdkInitialized {
   130  		return "", 0, sdkNotInitialized
   131  	}
   132  
   133  	alloc, err := GetAllocation(allocationID)
   134  	if err != nil {
   135  		return "", 0, allocationNotFound
   136  	}
   137  
   138  	updateAllocationRequest := make(map[string]interface{})
   139  	updateAllocationRequest["owner_id"] = client.GetClientID()
   140  	updateAllocationRequest["owner_public_key"] = ""
   141  	updateAllocationRequest["id"] = allocationID
   142  	updateAllocationRequest["size"] = size
   143  	updateAllocationRequest["extend"] = extend
   144  	updateAllocationRequest["add_blobber_id"] = addBlobberId
   145  	updateAllocationRequest["add_blobber_auth_ticket"] = addBlobberAuthTicket
   146  	updateAllocationRequest["remove_blobber_id"] = removeBlobberId
   147  	updateAllocationRequest["set_third_party_extendable"] = setThirdPartyExtendable
   148  	updateAllocationRequest["file_options_changed"], updateAllocationRequest["file_options"] = calculateAllocationFileOptions(alloc.FileOptions, fileOptionsParams)
   149  
   150  	sn := transaction.SmartContractTxnData{
   151  		Name:      transaction.STORAGESC_UPDATE_ALLOCATION,
   152  		InputArgs: updateAllocationRequest,
   153  	}
   154  	hash, _, nonce, _, err = storageSmartContractTxnValue(sn, strconv.FormatUint(lock, 10))
   155  	return
   156  }
   157  
   158  // StakePoolLock locks tokens in a stake pool.
   159  // This function is the entry point for the staking operation.
   160  // Provided the provider type and provider ID, the value is locked in the stake pool between the SDK client and the provider.
   161  // Based on the locked amount, the client will get rewards as share of the provider's rewards.
   162  //   - providerType: provider type
   163  //   - providerID: provider ID
   164  //   - value: value to lock
   165  //   - fee: transaction fee
   166  func StakePoolLock(providerType ProviderType, providerID string, value, fee string) (hash string, nonce int64, err error) {
   167  	if !sdkInitialized {
   168  		return "", 0, sdkNotInitialized
   169  	}
   170  
   171  	if providerType == 0 {
   172  		return "", 0, errors.New("stake_pool_lock", "provider is required")
   173  	}
   174  
   175  	if providerID == "" {
   176  		return "", 0, errors.New("stake_pool_lock", "provider_id is required")
   177  	}
   178  
   179  	spr := stakePoolRequest{
   180  		ProviderType: providerType,
   181  		ProviderID:   providerID,
   182  	}
   183  
   184  	var sn = transaction.SmartContractTxnData{
   185  		InputArgs: &spr,
   186  	}
   187  
   188  	var scAddress string
   189  	switch providerType {
   190  	case ProviderBlobber, ProviderValidator:
   191  		scAddress = STORAGE_SCADDRESS
   192  		sn.Name = transaction.STORAGESC_STAKE_POOL_LOCK
   193  	case ProviderMiner, ProviderSharder:
   194  		scAddress = MINERSC_SCADDRESS
   195  		sn.Name = transaction.MINERSC_LOCK
   196  	case ProviderAuthorizer:
   197  		scAddress = ZCNSC_SCADDRESS
   198  		sn.Name = transaction.ZCNSC_LOCK
   199  	default:
   200  		return "", 0, errors.Newf("stake_pool_lock", "unsupported provider type: %v", providerType)
   201  	}
   202  
   203  	hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(scAddress, sn, value, fee)
   204  	return
   205  }
   206  
   207  // StakePoolUnlock unlocks a stake pool tokens. If tokens can't be unlocked due
   208  // to opened offers, then it returns time where the tokens can be unlocked,
   209  // marking the pool as 'want to unlock' to avoid its usage in offers in the
   210  // future. The time is maximal time that can be lesser in some cases. To
   211  // unlock tokens can't be unlocked now, wait the time and unlock them (call
   212  // this function again).
   213  //   - providerType: provider type
   214  //   - providerID: provider ID
   215  //   - fee: transaction fee
   216  func StakePoolUnlock(providerType ProviderType, providerID string, fee string) (unstake int64, nonce int64, err error) {
   217  	if !sdkInitialized {
   218  		return 0, 0, sdkNotInitialized
   219  	}
   220  
   221  	if providerType == 0 {
   222  		return 0, 0, errors.New("stake_pool_lock", "provider is required")
   223  	}
   224  
   225  	if providerID == "" {
   226  		return 0, 0, errors.New("stake_pool_lock", "provider_id is required")
   227  	}
   228  
   229  	spr := stakePoolRequest{
   230  		ProviderType: providerType,
   231  		ProviderID:   providerID,
   232  	}
   233  
   234  	var sn = transaction.SmartContractTxnData{
   235  		InputArgs: &spr,
   236  	}
   237  
   238  	var scAddress string
   239  	switch providerType {
   240  	case ProviderBlobber, ProviderValidator:
   241  		scAddress = STORAGE_SCADDRESS
   242  		sn.Name = transaction.STORAGESC_STAKE_POOL_UNLOCK
   243  	case ProviderMiner, ProviderSharder:
   244  		scAddress = MINERSC_SCADDRESS
   245  		sn.Name = transaction.MINERSC_UNLOCK
   246  	case ProviderAuthorizer:
   247  		scAddress = ZCNSC_SCADDRESS
   248  		sn.Name = transaction.ZCNSC_UNLOCK
   249  	default:
   250  		return 0, 0, errors.Newf("stake_pool_unlock", "unsupported provider type: %v", providerType)
   251  	}
   252  
   253  	var out string
   254  	if _, out, nonce, _, err = smartContractTxnValueFeeWithRetry(scAddress, sn, "0", fee); err != nil {
   255  		return // an error
   256  	}
   257  
   258  	var spuu stakePoolLock
   259  	if err = json.Unmarshal([]byte(out), &spuu); err != nil {
   260  		return
   261  	}
   262  
   263  	return spuu.Amount, nonce, nil
   264  }
   265  
   266  // ReadPoolLock locks given number of tokes for given duration in read pool.
   267  //   - tokens: number of tokens to lock
   268  //   - fee: transaction fee
   269  func ReadPoolLock(tokens, fee string) (hash string, nonce int64, err error) {
   270  	if !sdkInitialized {
   271  		return "", 0, sdkNotInitialized
   272  	}
   273  
   274  	var sn = transaction.SmartContractTxnData{
   275  		Name:      transaction.STORAGESC_READ_POOL_LOCK,
   276  		InputArgs: nil,
   277  	}
   278  	hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, tokens, fee)
   279  	return
   280  }
   281  
   282  // ReadPoolUnlock unlocks tokens in expired read pool
   283  //   - fee: transaction fee
   284  func ReadPoolUnlock(fee string) (hash string, nonce int64, err error) {
   285  	if !sdkInitialized {
   286  		return "", 0, sdkNotInitialized
   287  	}
   288  
   289  	var sn = transaction.SmartContractTxnData{
   290  		Name:      transaction.STORAGESC_READ_POOL_UNLOCK,
   291  		InputArgs: nil,
   292  	}
   293  	hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, "0", fee)
   294  	return
   295  }
   296  
   297  //
   298  // write pool
   299  //
   300  
   301  // WritePoolLock locks given number of tokes for given duration in read pool.
   302  //   - allocID: allocation ID
   303  //   - tokens: number of tokens to lock
   304  //   - fee: transaction fee
   305  func WritePoolLock(allocID string, tokens, fee string) (hash string, nonce int64, err error) {
   306  	if !sdkInitialized {
   307  		return "", 0, sdkNotInitialized
   308  	}
   309  
   310  	type lockRequest struct {
   311  		AllocationID string `json:"allocation_id"`
   312  	}
   313  
   314  	var req lockRequest
   315  	req.AllocationID = allocID
   316  
   317  	var sn = transaction.SmartContractTxnData{
   318  		Name:      transaction.STORAGESC_WRITE_POOL_LOCK,
   319  		InputArgs: &req,
   320  	}
   321  
   322  	hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, tokens, fee)
   323  	return
   324  }
   325  
   326  // WritePoolUnlock unlocks ALL tokens of a write pool. Needs to be cancelled first.
   327  //   - allocID: allocation ID
   328  //   - fee: transaction fee
   329  func WritePoolUnlock(allocID string, fee string) (hash string, nonce int64, err error) {
   330  	if !sdkInitialized {
   331  		return "", 0, sdkNotInitialized
   332  	}
   333  
   334  	type unlockRequest struct {
   335  		AllocationID string `json:"allocation_id"`
   336  	}
   337  
   338  	var req unlockRequest
   339  	req.AllocationID = allocID
   340  
   341  	var sn = transaction.SmartContractTxnData{
   342  		Name:      transaction.STORAGESC_WRITE_POOL_UNLOCK,
   343  		InputArgs: &req,
   344  	}
   345  	hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, "0", fee)
   346  	return
   347  }
   348  
   349  func smartContractTxn(scAddress string, sn transaction.SmartContractTxnData) (
   350  	hash, out string, nonce int64, txn *transaction.Transaction, err error) {
   351  	return smartContractTxnValue(scAddress, sn, "0")
   352  }
   353  
   354  func StorageSmartContractTxn(sn transaction.SmartContractTxnData) (
   355  	hash, out string, nonce int64, txn *transaction.Transaction, err error) {
   356  
   357  	return storageSmartContractTxnValue(sn, "0")
   358  }
   359  
   360  func storageSmartContractTxn(sn transaction.SmartContractTxnData) (
   361  	hash, out string, nonce int64, txn *transaction.Transaction, err error) {
   362  
   363  	return storageSmartContractTxnValue(sn, "0")
   364  }
   365  
   366  func smartContractTxnValue(scAddress string, sn transaction.SmartContractTxnData, value string) (
   367  	hash, out string, nonce int64, txn *transaction.Transaction, err error) {
   368  
   369  	return smartContractTxnValueFeeWithRetry(scAddress, sn, value, strconv.FormatUint(client.TxnFee(), 10))
   370  }
   371  
   372  func storageSmartContractTxnValue(sn transaction.SmartContractTxnData, value string) (
   373  	hash, out string, nonce int64, txn *transaction.Transaction, err error) {
   374  
   375  	// Fee is set during sdk initialization.
   376  	return smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, value, strconv.FormatUint(client.TxnFee(), 10))
   377  }
   378  
   379  func smartContractTxnValueFeeWithRetry(scAddress string, sn transaction.SmartContractTxnData,
   380  	value, fee string) (hash, out string, nonce int64, t *transaction.Transaction, err error) {
   381  	hash, out, nonce, t, err = smartContractTxnValueFee(scAddress, sn, value, fee)
   382  
   383  	if err != nil && strings.Contains(err.Error(), "invalid transaction nonce") {
   384  		return smartContractTxnValueFee(scAddress, sn, value, fee)
   385  	}
   386  
   387  	return
   388  }
   389  
   390  func smartContractTxnValueFee(scAddress string, sn transaction.SmartContractTxnData,
   391  	value, fee string) (hash, out string, nonce int64, t *transaction.Transaction, err error) {
   392  	t, err = ExecuteSmartContract(scAddress, sn, value, fee)
   393  	if err != nil {
   394  		if t != nil {
   395  			return "", "", t.TransactionNonce, nil, err
   396  		}
   397  
   398  		return "", "", 0, nil, err
   399  	}
   400  
   401  	return t.Hash, t.TransactionOutput, t.TransactionNonce, t, nil
   402  }