# Documentation ## **File: `externalStorage.go`** ### **Package: `storage`** This package provides an interface and implementation for handling external storage in a WebAssembly (WASM) environment, enabling key-value persistence across external storage solutions. #### **Interface: `ExternalStorage`** Defines methods for managing persistent state in key-value format. - **`Get(key string) ([]byte, error)`** Retrieves and decodes a value from external storage using the given key. Returns `os.ErrNotExist` if the key does not exist. - **`Set(key string, value []byte) error`** Encodes a byte array into a string and stores it in external storage under the given key. Returns an error if storage quota is exceeded. - **`Delete(keyName string) error`** Removes the value associated with the given key from external storage. Does nothing if the key does not exist. - **`Clear() (int, error)`** Deletes all keys stored by this WASM binary. Returns the number of keys cleared. - **`ClearPrefix(prefix string) (int, error)`** Deletes all keys that start with the given prefix. Returns the number of keys cleared. - **`Key(n int) (string, error)`** Retrieves the name of the nth key stored. Returns `os.ErrNotExist` if no such key exists. - **`Keys() ([]string, error)`** Returns a list of all key names stored in external storage. - **`ExternalStorageUNSAFE() *HavenStorageJS`** Returns a low-level access wrapper for the external storage. This is **unsafe** and should be used cautiously. --- ### **Implementation: `externalStorage`** Provides a concrete implementation of the `ExternalStorage` interface. - **`newExternalStorage(prefix string) *externalStorage`** Initializes an `externalStorage` instance with a given prefix. - **`GetExternalStorage() ExternalStorage`** Returns a global instance of `externalStorage`. - **`(ls *externalStorage) Get(keyName string) ([]byte, error)`** Fetches a value from external storage, decoding it using Base32768 encoding. - **`(ls *externalStorage) Set(keyName string, keyValue []byte) error`** Encodes data in Base32768 and stores it in external storage. - **`(ls *externalStorage) Delete(keyName string) error`** Removes a key from external storage. - **`(ls *externalStorage) Clear() (int, error)`** Clears all keys in storage. - **`(ls *externalStorage) ClearPrefix(prefix string) (int, error)`** Clears all keys with a specific prefix. - **`(ls *externalStorage) Key(n int) (string, error)`** Retrieves the nth key stored. - **`(ls *externalStorage) Keys() ([]string, error)`** Retrieves a list of all keys. - **`(ls *externalStorage) ExternalStorageUNSAFE() *HavenStorageJS`** Returns direct access to the external storage JavaScript wrapper. --- ### **JavaScript Wrapper: `HavenStorageJS`** Encapsulates JavaScript’s `window.havenStorage` object. - **`(ls *HavenStorageJS) GetItem(keyName string) (string, error)`** Fetches an item from external storage. - **`(ls *HavenStorageJS) SetItem(keyName, keyValue string) error`** Stores an item in external storage. - **`(ls *HavenStorageJS) Delete(keyName string) error`** Removes an item from external storage. - **`(ls *HavenStorageJS) Clear() error`** Clears all stored keys. - **`(ls *HavenStorageJS) Key(n int) (string, error)`** Retrieves the nth key. - **`(ls *HavenStorageJS) Keys() ([]string, error)`** Fetches a list of all keys. - **`(ls *HavenStorageJS) KeysPrefix(prefix string) ([]string, error)`** Fetches all keys that match a specific prefix. --- #### **Helper Functions** - **`checkUnimplementedErr(jsErr []js.Value) error`** Checks if an error is an "Unimplemented" error and returns a standardized error. - **`callStorage(op StorageOperation, args ...interface{}) js.Value`** Calls JavaScript’s storage API with the given operation and arguments. ## **Test File: `externalStorage_test.go`** This file contains unit tests for the `storage` package, verifying the correctness of the `ExternalStorage` interface and its implementation. --- ### **Setup Function** #### **`setupMockHavenStorage(t *testing.T)`** - Initializes a mock version of `havenStorage` in the JavaScript environment using `localStorage`. - Defines the following JavaScript functions: - `getItem(key)`: Retrieves an item from `localStorage`. - `setItem(key, value)`: Stores an item in `localStorage`. - `delete(key)`: Removes an item from `localStorage`. - `clear()`: Clears `localStorage`. - `getKeys()`: Retrieves all stored keys. - `key(index)`: Always rejects with a "not implemented" error. - Calls `newExternalStorage` to initialize the global storage instance. --- ### **Unit Tests** #### **`TestGetExternalStorage(t *testing.T)`** - Ensures that `GetExternalStorage()` correctly returns an instance of `externalStorage`. #### **`TestExternalStorage_Get_Set(t *testing.T)`** - Tests setting and retrieving values from storage. - Stores different data types (`string`, `byte slices`). - Verifies that retrieved values match the original input. #### **`TestExternalStorage_Delete(t *testing.T)`** - Tests that deleting a key removes it from storage. - Verifies that attempting to retrieve the deleted key returns `os.ErrNotExist`. #### **`TestExternalStorage_Clear(t *testing.T)`** - Ensures that `Clear()` removes all keys stored by the WASM binary. - Differentiates between prefixed and non-prefixed keys. - Verifies that only the prefixed keys are deleted. #### **`TestExternalStorage_ClearPrefix(t *testing.T)`** - Ensures that `ClearPrefix(prefix)` removes only keys with the specified prefix. - Confirms that non-matching keys remain in storage. #### **`TestExternalStorage_Key(t *testing.T)`** - Tests that calling `Key(n)` returns `UnimplementedErr`, as the mock implementation does not support this operation. #### **`TestExternalStorage_Get_NotExistError(t *testing.T)`** - Ensures that attempting to retrieve a non-existent key returns `os.ErrNotExist`. #### **`TestExternalStorage_Keys(t *testing.T)`** - Verifies that `Keys()` returns all stored key names. - Checks that the number of retrieved keys matches expectations. - Ensures that all expected keys exist in the returned list. ---