github.com/0chain/gosdk@v1.17.11/mobilesdk/sdk/sdk.go (about) 1 //go:build mobile 2 // +build mobile 3 4 package sdk 5 6 import ( 7 "encoding/base64" 8 "encoding/json" 9 "fmt" 10 "math" 11 "strconv" 12 "strings" 13 14 "github.com/0chain/gosdk/core/sys" 15 "github.com/pkg/errors" 16 17 "github.com/0chain/gosdk/core/util" 18 "github.com/0chain/gosdk/core/version" 19 "github.com/0chain/gosdk/zboxcore/client" 20 l "github.com/0chain/gosdk/zboxcore/logger" 21 "github.com/0chain/gosdk/zboxcore/sdk" 22 23 "github.com/0chain/gosdk/mobilesdk/zbox" 24 "github.com/0chain/gosdk/mobilesdk/zboxapi" 25 "github.com/0chain/gosdk/zcncore" 26 ) 27 28 var nonce = int64(0) 29 30 type Autorizer interface { 31 Auth(msg string) (string, error) 32 } 33 34 // ChainConfig - blockchain config 35 type ChainConfig struct { 36 ChainID string `json:"chain_id,omitempty"` 37 PreferredBlobbers []string `json:"preferred_blobbers"` 38 BlockWorker string `json:"block_worker"` 39 SignatureScheme string `json:"signature_scheme"` 40 // ZboxHost 0box api host host: "https://0box.dev.0chain.net" 41 ZboxHost string `json:"zbox_host"` 42 // ZboxAppType app type name 43 ZboxAppType string `json:"zbox_app_type"` 44 } 45 46 // StorageSDK - storage SDK config 47 type StorageSDK struct { 48 chainconfig *ChainConfig 49 client *client.Client 50 } 51 52 // SetLogFile setup log level for core libraries 53 // - logFile: the output file of logs 54 // - verbose: output detail logs 55 func SetLogFile(logFile string, verbose bool) { 56 zcncore.SetLogFile(logFile, verbose) 57 sdk.SetLogFile(logFile, verbose) 58 } 59 60 // SetLogLevel set the log level. 61 // 62 // `lvl` - 0 disabled; higher number (upto 4) more verbosity 63 func SetLogLevel(logLevel int) { 64 sdk.SetLogLevel(logLevel) 65 } 66 67 // Init init the sdk with chain config 68 // - chainConfigJson: chain config json string 69 func Init(chainConfigJson string) error { 70 return zcncore.Init(chainConfigJson) 71 } 72 73 // InitStorageSDK init storage sdk from config 74 // - clientJson example 75 // { 76 // "client_id":"8f6ce6457fc04cfb4eb67b5ce3162fe2b85f66ef81db9d1a9eaa4ffe1d2359e0", 77 // "client_key":"c8c88854822a1039c5a74bdb8c025081a64b17f52edd463fbecb9d4a42d15608f93b5434e926d67a828b88e63293b6aedbaf0042c7020d0a96d2e2f17d3779a4", 78 // "keys":[ 79 // { 80 // "public_key":"c8c88854822a1039c5a74bdb8c025081a64b17f52edd463fbecb9d4a42d15608f93b5434e926d67a828b88e63293b6aedbaf0042c7020d0a96d2e2f17d3779a4", 81 // "private_key":"72f480d4b1e7fb76e04327b7c2348a99a64f0ff2c5ebc3334a002aa2e66e8506" 82 // }], 83 // "mnemonics":"abandon mercy into make powder fashion butter ignore blade vanish plastic shock learn nephew matrix indoor surge document motor group barely offer pottery antenna", 84 // "version":"1.0", 85 // "date_created":"1668667145", 86 // "nonce":0 87 // } 88 // - configJson example 89 // { 90 // "block_worker": "https://dev.0chain.net/dns", 91 // "signature_scheme": "bls0chain", 92 // "min_submit": 50, 93 // "min_confirmation": 50, 94 // "confirmation_chain_length": 3, 95 // "max_txn_query": 5, 96 // "query_sleep_time": 5, 97 // "preferred_blobbers": ["https://dev.0chain.net/blobber02","https://dev.0chain.net/blobber03"], 98 // "chain_id":"0afc093ffb509f059c55478bc1a60351cef7b4e9c008a53a6cc8241ca8617dfe", 99 // "ethereum_node":"https://ropsten.infura.io/v3/xxxxxxxxxxxxxxx", 100 // "zbox_host":"https://0box.dev.0chain.net", 101 // "zbox_app_type":"vult", 102 // } 103 func InitStorageSDK(clientJson string, configJson string) (*StorageSDK, error) { 104 l.Logger.Info("Start InitStorageSDK") 105 configObj := &ChainConfig{} 106 err := json.Unmarshal([]byte(configJson), configObj) 107 if err != nil { 108 l.Logger.Error(err) 109 return nil, err 110 } 111 err = zcncore.InitZCNSDK(configObj.BlockWorker, configObj.SignatureScheme) 112 if err != nil { 113 l.Logger.Error(err) 114 return nil, err 115 } 116 l.Logger.Info("InitZCNSDK success") 117 l.Logger.Info(configObj.BlockWorker) 118 l.Logger.Info(configObj.ChainID) 119 l.Logger.Info(configObj.SignatureScheme) 120 l.Logger.Info(configObj.PreferredBlobbers) 121 if err = sdk.InitStorageSDK(clientJson, 122 configObj.BlockWorker, 123 configObj.ChainID, 124 configObj.SignatureScheme, 125 configObj.PreferredBlobbers, 126 0); err != nil { 127 l.Logger.Error(err) 128 return nil, err 129 } 130 131 l.Logger.Info("InitStorageSDK success") 132 133 if configObj.ZboxHost != "" && configObj.ZboxAppType != "" { 134 zboxapi.Init(configObj.ZboxHost, configObj.ZboxAppType) 135 l.Logger.Info("InitZboxApi success") 136 } else { 137 l.Logger.Info("InitZboxApi skipped") 138 } 139 140 l.Logger.Info("Init successful") 141 142 return &StorageSDK{client: client.GetClient(), chainconfig: configObj}, nil 143 } 144 145 // CreateAllocation creating new allocation 146 // - datashards: number of data shards, effects upload and download speeds 147 // - parityshards: number of parity shards, effects availability 148 // - size: size of space reserved on blobbers 149 // - expiration: duration to allocation expiration 150 // - lock: lock write pool with given number of tokens 151 // - blobberAuthTickets: list of blobber auth tickets needed for the restricted blobbers 152 func (s *StorageSDK) CreateAllocation(datashards, parityshards int, size, expiration int64, lock string, blobberAuthTickets []string) (*zbox.Allocation, error) { 153 readPrice := sdk.PriceRange{Min: 0, Max: math.MaxInt64} 154 writePrice := sdk.PriceRange{Min: 0, Max: math.MaxInt64} 155 156 l, err := util.ParseCoinStr(lock) 157 if err != nil { 158 return nil, err 159 } 160 161 options := sdk.CreateAllocationOptions{ 162 DataShards: datashards, 163 ParityShards: parityshards, 164 Size: size, 165 ReadPrice: readPrice, 166 WritePrice: writePrice, 167 Lock: uint64(l), 168 BlobberIds: []string{}, 169 FileOptionsParams: &sdk.FileOptionsParameters{}, 170 BlobberAuthTickets: blobberAuthTickets, 171 } 172 173 sdkAllocationID, _, _, err := sdk.CreateAllocationWith(options) 174 if err != nil { 175 return nil, err 176 } 177 sdkAllocation, err := sdk.GetAllocation(sdkAllocationID) 178 if err != nil { 179 return nil, err 180 } 181 return zbox.ToAllocation(sdkAllocation), nil 182 } 183 184 // CreateAllocationWithBlobbers - creating new allocation with list of blobbers 185 // - name: allocation name 186 // - datashards: number of data shards, effects upload and download speeds 187 // - parityshards: number of parity shards, effects availability 188 // - size: size of space reserved on blobbers 189 // - expiration: duration to allocation expiration 190 // - lock: lock write pool with given number of tokens 191 // - blobberUrls: concat blobber urls with comma. leave it as empty if you don't have any preferred blobbers 192 // - blobberIds: concat blobber ids with comma. leave it as empty if you don't have any preferred blobbers 193 func (s *StorageSDK) CreateAllocationWithBlobbers(name string, datashards, parityshards int, size int64, lock string, blobberUrls, blobberIds string, blobberAuthTickets []string) (*zbox.Allocation, error) { 194 readPrice := sdk.PriceRange{Min: 0, Max: math.MaxInt64} 195 writePrice := sdk.PriceRange{Min: 0, Max: math.MaxInt64} 196 197 l, err := util.ParseCoinStr(lock) 198 if err != nil { 199 return nil, err 200 } 201 202 options := sdk.CreateAllocationOptions{ 203 DataShards: datashards, 204 ParityShards: parityshards, 205 Size: size, 206 Lock: l, 207 WritePrice: writePrice, 208 ReadPrice: readPrice, 209 BlobberAuthTickets: blobberAuthTickets, 210 } 211 212 if blobberUrls != "" { 213 urls := strings.Split(blobberUrls, ",") 214 if len(urls) > 0 { 215 ids, err := sdk.GetBlobberIds(urls) 216 if err != nil { 217 return nil, err 218 } 219 options.BlobberIds = ids 220 } 221 } 222 223 if blobberIds != "" { 224 ids := strings.Split(blobberIds, ",") 225 if len(ids) > 0 { 226 options.BlobberIds = ids 227 } 228 } 229 230 sdkAllocationID, _, _, err := sdk.CreateAllocationWith(options) 231 if err != nil { 232 return nil, err 233 } 234 235 sdkAllocation, err := sdk.GetAllocation(sdkAllocationID) 236 if err != nil { 237 return nil, err 238 } 239 240 return zbox.ToAllocation(sdkAllocation), nil 241 } 242 243 // GetAllocation retrieve allocation from ID 244 // - allocationID: allocation ID 245 func (s *StorageSDK) GetAllocation(allocationID string) (*zbox.Allocation, error) { 246 sdkAllocation, err := sdk.GetAllocation(allocationID) 247 if err != nil { 248 return nil, err 249 } 250 251 stats := sdkAllocation.GetStats() 252 retBytes, err := json.Marshal(stats) 253 if err != nil { 254 return nil, err 255 } 256 257 alloc := zbox.ToAllocation(sdkAllocation) 258 alloc.Stats = string(retBytes) 259 260 return alloc, nil 261 } 262 263 // GetAllocations retrieve list of allocations owned by the wallet 264 func (s *StorageSDK) GetAllocations() (string, error) { 265 sdkAllocations, err := sdk.GetAllocations() 266 if err != nil { 267 return "", err 268 } 269 result := make([]*zbox.Allocation, len(sdkAllocations)) 270 for i, sdkAllocation := range sdkAllocations { 271 allocationObj := zbox.ToAllocation(sdkAllocation) 272 result[i] = allocationObj 273 } 274 retBytes, err := json.Marshal(result) 275 if err != nil { 276 return "", err 277 } 278 return string(retBytes), nil 279 } 280 281 // GetAllocationFromAuthTicket retrieve allocation from Auth ticket 282 // AuthTicket is a signed message from the blobber authorizing the client to access the allocation. 283 // It's issued by the allocation owner and can be used by a non-owner to access the allocation. 284 // - authTicket: auth ticket 285 func (s *StorageSDK) GetAllocationFromAuthTicket(authTicket string) (*zbox.Allocation, error) { 286 sdkAllocation, err := sdk.GetAllocationFromAuthTicket(authTicket) 287 if err != nil { 288 return nil, err 289 } 290 return zbox.ToAllocation(sdkAllocation), nil 291 } 292 293 // GetAllocationStats retrieve allocation stats by allocation ID 294 // - allocationID: allocation ID 295 func (s *StorageSDK) GetAllocationStats(allocationID string) (string, error) { 296 allocationObj, err := sdk.GetAllocation(allocationID) 297 if err != nil { 298 return "", err 299 } 300 stats := allocationObj.GetStats() 301 retBytes, err := json.Marshal(stats) 302 if err != nil { 303 return "", err 304 } 305 return string(retBytes), nil 306 } 307 308 // FinalizeAllocation finalize allocation 309 // - allocationID: allocation ID 310 func (s *StorageSDK) FinalizeAllocation(allocationID string) (string, error) { 311 hash, _, err := sdk.FinalizeAllocation(allocationID) 312 return hash, err 313 } 314 315 // CancelAllocation cancel allocation by ID 316 // - allocationID: allocation ID 317 func (s *StorageSDK) CancelAllocation(allocationID string) (string, error) { 318 hash, _, err := sdk.CancelAllocation(allocationID) 319 return hash, err 320 } 321 322 // GetReadPoolInfo is to get information about the read pool for the allocation 323 // - clientID: client ID 324 func (s *StorageSDK) GetReadPoolInfo(clientID string) (string, error) { 325 readPool, err := sdk.GetReadPoolInfo(clientID) 326 if err != nil { 327 return "", err 328 } 329 330 retBytes, err := json.Marshal(readPool) 331 if err != nil { 332 return "", err 333 } 334 return string(retBytes), nil 335 } 336 337 // WRITE POOL METHODS 338 // WritePoolLock lock write pool with given number of tokens 339 // - durInSeconds: duration in seconds 340 // - tokens: number of tokens 341 // - fee: fee of the transaction 342 // - allocID: allocation ID 343 func (s *StorageSDK) WritePoolLock(durInSeconds int64, tokens, fee float64, allocID string) error { 344 _, _, err := sdk.WritePoolLock( 345 allocID, 346 strconv.FormatUint(zcncore.ConvertTokenToSAS(tokens), 10), 347 strconv.FormatUint(zcncore.ConvertTokenToSAS(fee), 10)) 348 return err 349 } 350 351 // GetVersion getting current version for gomobile lib 352 func (s *StorageSDK) GetVersion() string { 353 return version.VERSIONSTR 354 } 355 356 // UpdateAllocation update allocation settings with new expiry and size 357 // - size: size of space reserved on blobbers 358 // - extend: extend allocation 359 // - allocationID: allocation ID 360 // - lock: Number of tokens to lock to the allocation after the update 361 func (s *StorageSDK) UpdateAllocation(size int64, extend bool, allocationID string, lock uint64) (hash string, err error) { 362 if lock > math.MaxInt64 { 363 return "", errors.Errorf("int64 overflow in lock") 364 } 365 366 hash, _, err = sdk.UpdateAllocation(size, extend, allocationID, lock, "", "", "", false, &sdk.FileOptionsParameters{}) 367 return hash, err 368 } 369 370 // GetBlobbersList get list of active blobbers, and format them as array json string 371 func (s *StorageSDK) GetBlobbersList() (string, error) { 372 blobbs, err := sdk.GetBlobbers(true, false) 373 if err != nil { 374 return "", err 375 } 376 retBytes, err := json.Marshal(blobbs) 377 if err != nil { 378 return "", err 379 } 380 return string(retBytes), nil 381 } 382 383 // GetAllocations return back list of allocations for the wallet 384 // Extracted from main method, bcz of class fields 385 func GetAllocations() (string, error) { 386 allocs, err := sdk.GetAllocations() 387 if err != nil { 388 return "", err 389 } 390 retBytes, err := json.Marshal(allocs) 391 if err != nil { 392 return "", err 393 } 394 return string(retBytes), nil 395 } 396 397 // RedeeemFreeStorage given a free storage ticket, create a new free allocation 398 // - ticket: free storage ticket 399 func (s *StorageSDK) RedeemFreeStorage(ticket string) (string, error) { 400 recipientPublicKey, marker, lock, err := decodeTicket(ticket) 401 if err != nil { 402 return "", err 403 } 404 405 if recipientPublicKey != client.GetClientPublicKey() { 406 return "", fmt.Errorf("invalid_free_marker: free marker is not assigned to your wallet") 407 } 408 409 hash, _, err := sdk.CreateFreeAllocation(marker, strconv.FormatUint(lock, 10)) 410 return hash, err 411 } 412 413 func decodeTicket(ticket string) (string, string, uint64, error) { 414 decoded, err := base64.StdEncoding.DecodeString(ticket) 415 if err != nil { 416 return "", "", 0, err 417 } 418 419 input := make(map[string]interface{}) 420 if err = json.Unmarshal(decoded, &input); err != nil { 421 return "", "", 0, err 422 } 423 424 str := fmt.Sprintf("%v", input["marker"]) 425 decodedMarker, _ := base64.StdEncoding.DecodeString(str) 426 markerInput := make(map[string]interface{}) 427 if err = json.Unmarshal(decodedMarker, &markerInput); err != nil { 428 return "", "", 0, err 429 } 430 431 recipientPublicKey, ok := input["recipient_public_key"].(string) 432 if !ok { 433 return "", "", 0, fmt.Errorf("recipient_public_key is required") 434 } 435 436 lock := markerInput["free_tokens"] 437 markerStr, _ := json.Marshal(markerInput) 438 439 s, _ := strconv.ParseFloat(string(fmt.Sprintf("%v", lock)), 64) 440 return string(recipientPublicKey), string(markerStr), zcncore.ConvertTokenToSAS(s), nil 441 } 442 443 // RegisterAuthorizer Client can extend interface and FaSS implementation to this register like this: 444 // 445 // public class Autorizer extends Pkg.Autorizer { 446 // public void Auth() { 447 // // do something here 448 // } 449 // } 450 func RegisterAuthorizer(auth Autorizer) { 451 sys.Authorize = auth.Auth 452 }