@zerochain/sdk
Version:
The Züs JS SDK is a JavaScript client library that provides a convenient interface for interacting with the Züs Network. It allows developers to perform various operations such as creating and managing allocations, uploading and downloading files, executi
904 lines (862 loc) • 25.8 kB
text/typescript
// TODO: not used in webapps: updateAllocationWithRepair, getUpdateAllocTicket, collectRewards, getStakePoolInfo, lockStakePool, unlockStakePool (not used anywhere:- getAllocationBlobbers, getBlobberIds, reloadAllocation, getStakePoolInfo. lockWritePool, allocationRepair, repairSize)
import {
getProviderTypeId,
type StakePoolInfo,
type ActiveWallet,
type NetworkDomain,
type ProviderType,
type Transaction,
} from '@/types/wallet'
import { getWasm } from '@/setup/wasm'
import { errorOut } from '@/sdk/utils/misc'
import type { Allocation } from '@/types/allocation'
/**
* Creates an allocation with the specified allocation terms and preferred blobber IDs.
*
* To determine `minReadPrice`, `maxReadPrice`, `minWritePrice`, and `maxWritePrice`, use the `makeSCRestAPICall` SDK method to call the `/storage-config` endpoint of the sharder smart contract.
*/
export const createAllocation = async ({
wallet,
domain,
dataShards,
parityShards,
size,
minReadPrice,
maxReadPrice,
minWritePrice,
maxWritePrice,
lock,
blobberIds = [],
blobberAuthTickets,
setThirdPartyExtendable,
isEnterprise,
force = false,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Number of data shards. Data uploaded to the allocation will be split and distributed across these shards. */
dataShards: number
/** Number of parity shards. Parity shards are used to replicate datashards for redundancy. */
parityShards: number
/** Size of the allocation in bytes */
size: number
/** Minimum read price */
minReadPrice: number
/** Maximum read price */
maxReadPrice: number
/** Minimum write price */
minWritePrice: number
/** Maximum write price */
maxWritePrice: number
/** Lock value to add to the allocation */
lock: number
/** List of blobber IDs of your preferred blobbers for the allocation */
blobberIds?: string[]
/** List of blobber auth tickets in case of using restricted blobbers */
blobberAuthTickets: string[]
/**
* setThirdPartyExtendable is a flag that determines whether third-parties are allowed to update the allocation's size and expiration property.
*
* When set to `true`, third-parties / a non-owner client (e.g., 0box) can update or modify the allocation
*/
setThirdPartyExtendable: boolean
/** Whether it's an enterprise allocation */
isEnterprise: boolean
/**
* The `force` parameter determines whether the allocation creation should proceed even if the available blobbers are insufficient to meet the required data + parity conditions.
*
* By default, when `force` is `false`, the API will return a "Not enough blobbers" error if the number of available blobbers is less than the required data + parity. This ensures that the allocation meets the necessary redundancy and reliability conditions.
*
* When `force` is set to `true`, the API will bypass this check and proceed with the allocation creation using the available blobbers, even if they are fewer than the required data + parity shards. This can be useful in scenarios where you want to proceed with the allocation despite the reduced redundancy.
*
* Use this parameter with caution, as it may result in allocations with lower fault tolerance and reliability.
*/
force: boolean
}): Promise<Transaction> => {
const goWasm = await getWasm({ domain, wallet })
const transactionData = await goWasm.sdk.createAllocation(
dataShards,
parityShards,
size,
minReadPrice,
maxReadPrice,
minWritePrice,
maxWritePrice,
lock,
blobberIds,
blobberAuthTickets,
setThirdPartyExtendable,
isEnterprise,
force
)
return transactionData
}
/**
* Retrieves list of blobber IDs of blobber which match your allocation terms
*
* To determine `minReadPrice`, `maxReadPrice`, `minWritePrice`, and `maxWritePrice`, use the `makeSCRestAPICall` SDK method to call the `/storage-config` endpoint of the sharder smart contract.
*/
export const getAllocationBlobbers = async ({
wallet,
domain,
preferredBlobberURLs = [],
dataShards,
parityShards,
size,
minReadPrice,
maxReadPrice,
minWritePrice,
maxWritePrice,
restrictedLevel,
force = false,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** List of preferred blobber URLs */
preferredBlobberURLs?: string[] // TODO: check if we can keep this optional or not
/** Number of data shards */
dataShards: number
/** Number of parity shards */
parityShards: number
/** Size of the allocation in bytes */
size: number
/** Minimum read price */
minReadPrice: number
/** Maximum read price */
maxReadPrice: number
/** Minimum write price */
minWritePrice: number
/** Maximum write price */
maxWritePrice: number
/**
* Specifies the type of blobbers to query.
*
* - `0`: Use all blobbers (both restricted and non-restricted).
* - `1`: Use only restricted blobbers (require permission for allocation creation).
* - `2`: Use only non-restricted blobbers (do not require permission for allocation creation).
*/
restrictedLevel: number
/**
* @deprecated For internal use only
* @default false
*/
force: boolean
}): Promise<string[]> => {
const goWasm = await getWasm({ domain, wallet })
const blobberIds = await goWasm.sdk.getAllocationBlobbers(
preferredBlobberURLs,
dataShards,
parityShards,
size,
minReadPrice,
maxReadPrice,
minWritePrice,
maxWritePrice,
restrictedLevel,
force
)
return blobberIds
}
/** List all the allocations */
export const listAllocations = async ({
wallet,
domain,
}: {
domain: NetworkDomain
wallet: ActiveWallet
}): Promise<Allocation[]> => {
const goWasm = await getWasm({ domain, wallet })
const allocations = await goWasm.sdk.listAllocations()
return allocations
}
/** getAllocation gets allocation details using `allocationId` from cache
* - if not found in cache, fetch from blockchain and store in cache */
export const getAllocation = async ({
wallet,
domain,
allocationId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
}): Promise<Allocation> => {
const goWasm = await getWasm({ domain, wallet })
return await goWasm.sdk.getAllocation(allocationId)
}
/** reloadAllocation reload allocation details using `allocationId` from blockchain and updates cache */
export const reloadAllocation = async ({
wallet,
domain,
allocationId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
}): Promise<Allocation> => {
const goWasm = await getWasm({ domain, wallet })
return await goWasm.sdk.reloadAllocation(allocationId)
}
/**
* transferAllocation transfers the ownership of an allocation to a new owner
* @deprecated
*/
export const transferAllocation = async ({
wallet,
domain,
allocationId,
newOwnerId,
newOwnerPublicKey,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
/** New owner ID */
newOwnerId: string
/** New owner public key */
newOwnerPublicKey: string
}): Promise<void> => {
const goWasm = await getWasm({ domain, wallet })
return goWasm.sdk.transferAllocation(
allocationId,
newOwnerId,
newOwnerPublicKey
)
}
/**
* freezeAllocation freezes one of the client's allocations, given its ID
*
* Freezing the allocation will forbid all the operations on the files in the allocation.
*
* @returns the hash of the transaction
*/
export const freezeAllocation = async ({
wallet,
domain,
allocationId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Allocation ID to freeze */
allocationId: string
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.freezeAllocation(allocationId)
return txnHash
}
/**
* cancelAllocation cancels an allocation using `allocationId`
*
* @returns the hash of the transaction
*/
export const cancelAllocation = async ({
wallet,
domain,
allocationId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Allocation ID to cancel */
allocationId: string
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.cancelAllocation(allocationId)
return txnHash
}
/** updateAllocation updates the allocation settings */
export const updateAllocation = async ({
wallet,
domain,
allocationId,
size,
extend,
lock,
addBlobberId = '',
addBlobberAuthTicket = '',
removeBlobberId = '',
ownerSigningPublicKey = '',
setThirdPartyExtendable,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Allocation ID to update */
allocationId: string
/** New size of the allocation in bytes */
size: number
/** Extend flag, whether to extend the allocation's expiration date */
extend: boolean
/** Lock value to add to the allocation */
lock: number
/** Blobber ID to add to the allocation */
addBlobberId?: string
/** Blobber auth ticket to add to the allocation, in case of restricted blobbers */
addBlobberAuthTicket?: string
/** Blobber ID to remove from the allocation */
removeBlobberId?: string
/** Optional ECDSA Public key of the user who created that allocation. It’s used for signature verification. If not provided, GoSDK will generate one */
ownerSigningPublicKey?: string
/**
* setThirdPartyExtendable is a flag that determines whether third-parties are allowed to update the allocation's size and expiration property.
*
* When set to `true`, third-parties / a non-owner client (e.g., 0box) can update or modify the allocation
*/
setThirdPartyExtendable: boolean
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.updateAllocation(
allocationId,
size,
extend,
lock,
addBlobberId,
addBlobberAuthTicket,
removeBlobberId,
ownerSigningPublicKey,
setThirdPartyExtendable
)
return txnHash
}
/** Updates your allocation settings and repairs the allocation if any blobber was replaced or added to the allocation */
export const updateAllocationWithRepair = async ({
wallet,
domain,
allocationId,
size,
extend = false,
lock,
addBlobberId = '',
addBlobberAuthTicket = '',
removeBlobberId = '',
ownerSigningPublicKey = '',
updateAllocTicket = '',
callback,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Allocation ID to update */
allocationId: string
/** New size of the allocation in bytes */
size: number
/**
* Extend flag, whether to extend the allocation's expiration date
* @default false
*/
extend: boolean
/** Lock value to add to the allocation */
lock: number
/** Blobber ID to add to the allocation */
addBlobberId?: string
/** Blobber auth ticket to add to the allocation, in case of restricted blobbers */
addBlobberAuthTicket?: string
/** Blobber ID to remove from the allocation */
removeBlobberId?: string
/** Optional ECDSA Public key of the user who created that allocation. It’s used for signature verification. If not provided, GoSDK will generate one */
ownerSigningPublicKey?: string
/** Update allocation ticket */
updateAllocTicket?: string
/** Callback function will be invoked with repair progress updates */
callback?: (
totalBytes: number,
completedBytes: number,
fileName: string,
blobURL: string,
error: string
) => void
}): Promise<string> => {
let callbackFuncName = ''
if (callback) {
callbackFuncName = `updateAllocationWithRepairCallback_${Date.now()}`
window[callbackFuncName] = callback
}
const goWasm = await getWasm({ domain, wallet })
try {
const txnHash = await goWasm.sdk.updateAllocationWithRepair(
allocationId,
size,
extend,
lock,
addBlobberId,
addBlobberAuthTicket,
removeBlobberId,
ownerSigningPublicKey,
updateAllocTicket,
callbackFuncName
)
return txnHash
} catch (e) {
throw errorOut('updateAllocationWithRepair', e)
} finally {
// TODO: check if this is to be avoided or not
delete window[callbackFuncName]
}
}
/**
* getAllocationMinLock retrieves the minimum lock value for the allocation creation
*
* Lock value is the amount of tokens that the client needs to lock in the allocation's write pool to be able to pay for the write operations.
*
* To determine `maxWritePrice`, use the `makeSCRestAPICall` SDK method to call the `/storage-config` endpoint of the sharder smart contract.
*
* @returns the minimum lock value (in SAS)
*/
export const getAllocationMinLock = async ({
domain,
wallet,
dataShards,
parityShards,
size,
maxWritePrice,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Number of data shards */
dataShards: number
/** Number of parity shards */
parityShards: number
/** Size of the allocation in bytes */
size: number
/** Maximum write price */
maxWritePrice: number
}): Promise<number> => {
const goWasm = await getWasm({ domain, wallet })
const minLockDemand = await goWasm.sdk.getAllocationMinLock(
dataShards,
parityShards,
size,
maxWritePrice
)
return minLockDemand
}
/**
* getUpdateAllocationMinLock retrieves the minimum lock value for the allocation after update, as calculated by the network based on the update parameters.
*
* Lock value is the amount of tokens that the client needs to lock in the allocation's write pool to be able to pay for the write operations.
*
* @returns the minimum lock value (in SAS)
*/
export const getUpdateAllocationMinLock = async ({
domain,
wallet,
allocationId,
size,
extend,
addBlobberId,
removeBlobberId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Allocation ID to update */
allocationId: string
/** New size of the allocation in bytes */
size: number
/** Extend flag, whether to extend the allocation's expiration date */
extend: boolean
/** Blobber ID to add to the allocation */
addBlobberId?: string
/** Blobber ID to remove from the allocation */
removeBlobberId?: string
}): Promise<number> => {
const goWasm = await getWasm({ domain, wallet })
const minLockDemand = await goWasm.sdk.getUpdateAllocationMinLock(
allocationId,
size,
extend,
addBlobberId,
removeBlobberId
)
return minLockDemand
}
/**
* UpdateForbidAllocation updates the permissions of an allocation.
*
* @returns The transaction hash
*/
export const updateForbidAllocation = async ({
wallet,
domain,
allocationId,
forbidUpload,
forbidDelete,
forbidUpdate,
forbidMove,
forbidCopy,
forbidRename,
}: {
wallet: ActiveWallet
domain: NetworkDomain
/** Allocation ID to update */
allocationId: string
/** If true, uploading files to the allocation is forbidden */
forbidUpload: boolean
/** If true, deleting files from the allocation is forbidden */
forbidDelete: boolean
/** If true, updating files in the allocation is forbidden */
forbidUpdate: boolean
/** If true, moving files in the allocation is forbidden */
forbidMove: boolean
/** If true, copying files in the allocation is forbidden */
forbidCopy: boolean
/** If true, renaming files in the allocation is forbidden */
forbidRename: boolean
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.updateForbidAllocation(
allocationId,
forbidUpload,
forbidDelete,
forbidUpdate,
forbidMove,
forbidCopy,
forbidRename
)
return txnHash
}
/**
* getAllocationWith retrieves the information of a free or a shared allocation given the auth ticket.
* - **Free allocation** is an allocation that is created to the user using Vult app for the first time with no fees.
* - **Shared allocation** is an allocation that has some shared files. The user who needs to access those files first needs to read the information of this allocation using an auth ticket.
*/
export const getAllocationWith = async ({
domain,
wallet,
authTicket,
}: {
domain: NetworkDomain
wallet: ActiveWallet
/** Auth ticket, used by a non-owner to access a shared allocation */
authTicket: string
}): Promise<Allocation> => {
const goWasm = await getWasm({ domain, wallet })
return await goWasm.sdk.getAllocationWith(authTicket)
}
/** createFreeAllocation creates a free allocation */
export const createFreeAllocation = async ({
domain,
wallet,
freeStorageMarker,
}: {
domain: NetworkDomain
wallet: ActiveWallet
// TODO
freeStorageMarker: string
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.createxfreeallocation(freeStorageMarker)
return txnHash
}
/**
* Generates and signs an "Update Allocation ticket", which authorizes the "add blobber" or "replace blobber" operation from other wallets. This ticket must be signed by the allocation owner.
*/
export const getUpdateAllocTicket = async ({
domain,
wallet,
allocationId,
userId,
operationType,
roundExpiry,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
// TODO: get from zcnContracts? Check for other zcnContracts teamWallet mentions too. Are they valid?
/** UserID is the wallet ID which will be allowed to update your allocation */
userId: string // TODO: Should we directly add teamWallet here
operationType: 'replace_blobber' | 'add_blobber'
/** Round expiry is the round after which the auth ticket will no longer be valid. */
roundExpiry: number
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const ticket = await goWasm.sdk.getUpdateAllocTicket(
allocationId,
userId,
operationType,
roundExpiry
)
return ticket
}
// ----------------------------------------
// Rewards sdk methods
// ----------------------------------------
/**
* CollectRewards collect all rewards which are available for delegate & provider pair. (txn: `storagesc.collect_reward`)
*
* @returns the hash of the transaction
*/
export const collectRewards = async ({
domain,
wallet,
providerType,
providerId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
providerType: ProviderType
providerId: string
}): Promise<string> => {
const providerTypeId = getProviderTypeId(providerType)
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.collectRewards(providerTypeId, providerId)
return txnHash
}
// ----------------------------------------
// Stakepool & Writepool sdk methods
// ----------------------------------------
/** getSkatePoolInfo is to get information about the stake pool for the allocation */
export const getStakePoolInfo = async ({
domain,
wallet,
providerType,
providerId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
providerType: ProviderType
providerId: string
}): Promise<StakePoolInfo> => {
const providerTypeId = getProviderTypeId(providerType)
const goWasm = await getWasm({ domain, wallet })
const info = await goWasm.sdk.getSkatePoolInfo(providerTypeId, providerId)
return info
}
/**
* Stake number of tokens for a given provider given its type and ID
* @returns the hash of the transaction
*/
export const lockStakePool = async ({
domain,
wallet,
providerType,
tokens,
fee,
providerId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
providerType: ProviderType
/** Number of tokens to lock (in SAS) */
tokens: number
/** Transaction fee (in SAS) */
fee: number
providerId: string
}): Promise<string> => {
const providerTypeId = getProviderTypeId(providerType)
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.lockStakePool(
providerTypeId,
tokens,
fee,
providerId
)
return txnHash
}
/**
* unlockStakePool unlocks the write pool
* @returns the hash of the transaction
*/
export const unlockStakePool = async ({
domain,
wallet,
providerType,
fee,
providerId,
clientId,
}: {
domain: NetworkDomain
wallet: ActiveWallet
providerType: ProviderType
/** Transaction fee (in SAS) */
fee: number
providerId: string
/** Wallet ID */
clientId: string
}): Promise<string> => {
const providerTypeId = getProviderTypeId(providerType)
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.unlockStakePool(
providerTypeId,
fee,
providerId,
clientId
)
return txnHash
}
/**
* lockWritePool locks given number of tokes for given duration in write pool
* @returns the hash of the transaction
*/
export const lockWritePool = async ({
domain,
wallet,
allocationId,
tokens,
fee,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
/** Number of tokens to lock (in SAS) */
tokens: number
/** Transaction fee (in SAS) */
fee: number
}): Promise<string> => {
const goWasm = await getWasm({ domain, wallet })
const txnHash = await goWasm.sdk.lockWritePool(allocationId, tokens, fee)
return txnHash
}
// ----------------------------------------
// Other sdk methods
// ----------------------------------------
/**
* Issues the repair process for an allocation, *starting from a specific path*.
*
* Repair synchronizes the user's data within the allocation across all blobbers and restores any missing data on blobbers where it is incomplete.
*
* @deprecated
*/
export const allocationRepair = async ({
domain,
wallet,
allocationId,
remotePath,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
remotePath: string
}): Promise<void> => {
const goWasm = await getWasm({ domain, wallet })
return goWasm.sdk.allocationRepair(allocationId, remotePath)
}
/** Repairs the allocation.
*
* Allocation repair is a process to repair the allocation files on its blobbers by re-uploading the missing blocks. */
export const repairAllocation = async ({
wallet,
domain,
allocationId,
callback,
}: {
wallet: ActiveWallet
domain: NetworkDomain
allocationId: string
/** Callback function will be invoked with repair progress updates */
callback?: (
totalBytes: number,
completedBytes: number,
fileName: string,
blobURL: string,
error: string
) => void
}): Promise<void> => {
const goWasm = await getWasm({ domain, wallet })
let callbackFuncName = ''
if (callback) {
callbackFuncName = `repairAllocationCallback_${Date.now()}`
window[callbackFuncName] = callback
}
try {
await goWasm.sdk.repairAllocation(allocationId, callbackFuncName)
return
} catch (e) {
throw errorOut('repairAllocation', e)
} finally {
// TODO: check if this is to be avoided or not
if (callbackFuncName) delete window[callbackFuncName]
}
}
/**
* repairSize retrieves the repair size for a specific path in an allocation
*
* Repair size is the size of the data that needs to be repaired in the allocation.
*/
export const repairSize = async ({
domain,
wallet,
allocationId,
remotePath,
}: {
domain: NetworkDomain
wallet: ActiveWallet
allocationId: string
remotePath: string
}): Promise<{ upload_size: number; download_size: number }> => {
const goWasm = await getWasm({ domain, wallet })
const resp = await goWasm.sdk.repairSize(allocationId, remotePath)
return resp
}
type AllocStatus = {
/**
* The health `status` of the allocation has one of the following values:
* - `ok`: The allocation is healthy and fully functional.
* - `repair`: The allocation needs to be repaired. Repair using the `repairAllocation` method.
* - `broken`: The allocation is irreparably broken. This occurs when critical data blocks are missing or when blobbers are offline, making recovery impossible.
*/
status: 'ok' | 'repair' | 'broken'
blobberStatus: {
ID: string
Status: 'available' | 'unavailable'
}[]
error: string
}
/** Check the health status of the allocation. */
export const checkAllocStatus = async ({
wallet,
domain,
allocationId,
}: {
wallet: ActiveWallet
domain: NetworkDomain
allocationId: string
}): Promise<AllocStatus> => {
const goWasm = await getWasm({ domain, wallet })
try {
const jsonResponse = await goWasm.sdk.checkAllocStatus(allocationId)
const response = JSON.parse(jsonResponse)
const { status, blobberStatus, error } = response as AllocStatus
if (error) throw new Error(error)
return { status, blobberStatus, error }
} catch (e) {
throw errorOut('checkAllocStatus', e)
}
}
/** Skip the health status check of the allocation. */
export const skipStatusCheck = async ({
wallet,
domain,
allocationId,
checkStatus,
}: {
wallet: ActiveWallet
domain: NetworkDomain
allocationId: string
/** Flag to enable or disable status check */
checkStatus: boolean
}): Promise<void> => {
const goWasm = await getWasm({ domain, wallet })
return goWasm.sdk.skipStatusCheck(allocationId, checkStatus)
}
/** Remove local workers for a particular allocation. This is useful when switching between allocations and we don't need workers for the old allocation. */
export const terminateWorkers = async ({
wallet,
domain,
allocationId,
}: {
wallet: ActiveWallet
domain: NetworkDomain
allocationId: string
}): Promise<void> => {
const goWasm = await getWasm({ domain, wallet })
return goWasm.sdk.terminateWorkers(allocationId)
}
/** Create local workers for an allocation. Terminate workers if the allocation is no longer needed using `terminateWorkers`. */
export const createWorkers = async ({
wallet,
domain,
allocationId,
}: {
wallet: ActiveWallet
domain: NetworkDomain
allocationId: string
}): Promise<void> => {
const goWasm = await getWasm({ domain, wallet })
return goWasm.sdk.createWorkers(allocationId)
}