UNPKG

@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

179 lines (152 loc) 5.61 kB
import { createWasm } from '../createWasm' import debounce from 'lodash.debounce' import type { OnLog } from '@/types/log' import type { Config } from '../createWasm/bridge' import { sleep } from '@/utils' import { resetGoWasm } from '@/setup/wasm/wasm' import type { WasmType } from '@/types' const DEBOUNCE_TIMEOUT = 500 const MAX_RETRIES = 3 export type WasmLoaderOptions = { onLog?: OnLog | undefined debounceTimeout?: number | undefined setIsWasmLoaded?: ((isWasmLoaded: boolean) => void) | undefined getRetries: () => number incrementRetries: () => void resetRetries: () => void } export type InitializeWasm = ( config: Config, isSwitchingWasm?: boolean ) => Promise<void> | undefined export const createWasmLoader = ({ onLog, debounceTimeout = DEBOUNCE_TIMEOUT, setIsWasmLoaded = () => {}, getRetries, incrementRetries, resetRetries, }: WasmLoaderOptions): InitializeWasm => { const initializeWasm: InitializeWasm = debounce( async (config: Config, isSwitchingWasm = false) => { if (!config) { onLog?.('error', { message: 'Unable to initialize WASM. Invalid config.', code: 'INVALID_WASM_CONFIG', data: config, }) return } setIsWasmLoaded(false) if (await checkIfWasmLoaded()) { onLog?.('debug', { message: 'Wasm already initialized.', code: 'WASM_LOADED', data: { isSwitchingWasm }, }) setIsWasmLoaded(true) return } onLog?.('info', { message: 'Initializing WASM...', code: 'WASM_LOADING', data: { isSwitchingWasm }, }) createWasm(config, setIsWasmLoaded) await awaitWasmLoad() if (!isDesiredWasmInitialized()) { if (getRetries() >= MAX_RETRIES) { resetRetries() const msg = 'Wasm type mismatch: Unable to reset. Exiting.' console.warn(msg) onLog?.('debug', { message: msg, code: 'WASM_TYPE_MISMATCH' }) const desiredMode = getDesiredMode() onLog?.('error', { message: `Unable to switch to ${desiredMode} mode. Please reload.`, code: 'WASM_TYPE_MISMATCH', }) setIsWasmLoaded(true) return } incrementRetries() const msg = `Wasm type mismatch: ${ window.__zcn_wasm__?.wasmType }. Resetting ${getRetries()}/${MAX_RETRIES}` console.warn(msg) onLog?.('error', { message: msg, code: 'WASM_TYPE_MISMATCH_RETRY' }) initializeWasm(config) // Retry initializeWasm due to WASM type mismatch } }, debounceTimeout ) return initializeWasm } // ---------------------------------------- // Utils // ---------------------------------------- /** Updates the "desired mode" value of the GoSDK WASM. */ export const updateWasmMode = (desiredAllocationType: WasmType): void => { resetGoWasm() if (desiredAllocationType === 'enterprise') { localStorage.setItem('enterpriseAlloc', 'enabled') } else localStorage.removeItem('enterpriseAlloc') } /** Returns the "desired mode" value of the GoSDK WASM. */ export const getDesiredMode = (): WasmType => { const isEnterpriseModeDesired = localStorage.getItem('enterpriseAlloc') === 'enabled' return isEnterpriseModeDesired ? 'enterprise' : 'normal' } /** * Checks if the desired GoSDK WASM mode is initialized. Returns `true` if the WASM is initialized, `false` otherwise. * @param onLog Optional logger, e.g., console.log */ export const isDesiredWasmInitialized = (onLog?: OnLog): boolean => { const isEnterpriseModeDesired = localStorage.getItem('enterpriseAlloc') === 'enabled' const wasmType = window.__zcn_wasm__?.wasmType if (wasmType === undefined) { // This is for old WASM versions which don't have wasmType onLog?.('debug', { message: 'Wasm type: undefined', code: 'OUTDATED_WASM_VERSION', }) return true } return isEnterpriseModeDesired ? wasmType === 'enterprise' : wasmType === 'normal' } /** * Waits until the GoSDK WASM is loaded and initialized. * * Unlike `checkIfWasmLoaded` method, this method doesn't check if the desired WASM mode is initialized. It just returns a promise that will only resolve once the GoSDK WASM is loaded and initialized. * * @param onLog Optional logger, e.g., console.log */ export const awaitWasmLoad = async (onLog?: OnLog): Promise<void> => { while (!window.__zcn_wasm__?.__wasm_initialized__) { onLog?.('debug', { message: 'Wasm: Waiting...', code: 'WASM_LOADING' }) await sleep(500) } onLog?.('info', { message: `Wasm: Loaded. Type: ${window.__zcn_wasm__.wasmType}`, code: 'WASM_LOADED', }) await sleep(1000) // This avoids the error shown here: https://0chain.slack.com/archives/G01EXH6EYC9/p1729268246489569?thread_ts=1729214879.267689&cid=G01EXH6EYC9 } /** * `checkIfWasmLoaded` Waits for the "desired mode" GoSDK WASM to be loaded and initialized. * @returns {Promise<boolean>} Returns a promise that resolves to `true` until the "desired mode" GoSDK WASM is loaded and initialized. If the desired WASM mode is not initialized, it resolves to `false`. */ export const checkIfWasmLoaded = async (): Promise<boolean> => { if (window.__zcn_wasm__?.__wasm_initialized__) { await sleep(300) // This avoids the error shown here: https://0chain.slack.com/archives/G01EXH6EYC9/p1729268246489569?thread_ts=1729214879.267689&cid=G01EXH6EYC9 if (!isDesiredWasmInitialized()) { resetGoWasm() return false } return true } return false }