StorageProgram - Unified storage solution for Demos Network

Supports both JSON (structured) and Binary (raw) data storage with robust access control and size-based pricing.

Features:

  • Deterministic address derivation (stor-{sha256})
  • Dual encoding: JSON key-value or raw binary
  • Robust ACL: owner, allowed, blacklisted, public, groups
  • Size limit: 1MB for both encodings
  • Pricing: 1 DEM per 10KB
  • Permanent storage, owner/ACL-deletable only
  • IPFS-ready (stubs for future hybrid storage)
import { StorageProgram } from '@kynesyslabs/demosdk'

// Create JSON storage program (nonce required for unique address)
const jsonPayload = StorageProgram.createStorageProgram(
'demos1abc...',
'myConfig',
{ apiKey: 'secret', settings: { theme: 'dark' } },
'json',
{ mode: 'public' },
{ nonce: 42 } // sender's current nonce
)

// Create Binary storage program
const binaryPayload = StorageProgram.createStorageProgram(
'demos1abc...',
'myImage',
Buffer.from(imageData).toString('base64'),
'binary',
{ mode: 'restricted', allowed: ['demos1user1...'] },
{ nonce: 43, metadata: { filename: 'avatar.png', mimeType: 'image/png' } }
)

Constructors

Methods

  • Append an item to an array field (JSON encoding only)

    Creates a payload for the APPEND_ITEM operation. The field must exist and be an array, or the operation will create a new array with the item as its first element.

    Parameters

    • storageAddress: string

      The storage program address

    • field: string

      The array field name

    • value: unknown

      The value to append

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // Add new user to users array
    const payload = StorageProgram.appendItem(
    'stor-7a8b9c...',
    'users',
    { name: 'New User', role: 'viewer' }
    )
  • Create an ACL with a blacklist

    Parameters

    • mode: StorageACLMode

      Base mode ('public' or 'restricted')

    • blacklisted: string[]

      Addresses to block

    • Optionalallowed: string[]

      Optional allowed addresses (for restricted mode)

    Returns StorageProgramACL

    StorageProgramACL with blacklist configured

    // Public but block spam addresses
    const acl = StorageProgram.blacklistACL('public', ['demos1spam...'])
  • Calculate storage fee based on data size

    Pricing: 1 DEM per 10KB (minimum 1 DEM)

    Parameters

    • data: string | Record<string, any>

      Data to calculate fee for (JSON object or base64 string)

    • encoding: StorageEncoding = "json"

      Encoding type ("json" or "binary")

    Returns bigint

    Fee in DEM (bigint)

    const fee = StorageProgram.calculateStorageFee({ key: 'value' }, 'json')
    console.log(`Storage fee: ${fee} DEM`)

    // Examples:
    // 5KB -> 1 DEM
    // 15KB -> 2 DEM
    // 100KB -> 10 DEM
    // 1MB -> 103 DEM
  • Check if an address has permission for an operation

    ACL Resolution Priority:

    1. Owner -> FULL ACCESS (always)
    2. Blacklisted -> DENIED (even if in allowed/groups)
    3. Allowed -> permissions granted
    4. Groups -> check group permissions
    5. Mode fallback: owner/restricted -> DENIED, public -> READ only

    Parameters

    • acl: StorageProgramACL

      Access control configuration

    • ownerAddress: string

      Owner address of the storage program

    • requestingAddress: string

      Address requesting permission

    • permission: "read" | "write" | "delete"

      Permission type to check

    Returns boolean

    true if permission is granted

    const acl = { mode: 'public', blacklisted: ['demos1spam...'] }
    const canRead = StorageProgram.checkPermission(acl, owner, user, 'read')
  • Create a new Storage Program

    Parameters

    • deployerAddress: string

      Address creating the storage program (becomes owner)

    • programName: string

      Unique name for the program

    • data: string | Record<string, any>

      Initial data (JSON object or base64 binary string)

    • encoding: StorageEncoding = "json"

      "json" or "binary" (default: "json")

    • Optionalacl: Partial<StorageProgramACL>

      Access control configuration (default: owner-only)

    • Optionaloptions: {
          metadata?: Record<string, unknown>;
          nonce: number;
          salt?: string;
          storageLocation?: StorageLocation;
      }

      Options including nonce (required), salt, metadata, storageLocation

      • Optionalmetadata?: Record<string, unknown>
      • nonce: number
      • Optionalsalt?: string
      • OptionalstorageLocation?: StorageLocation

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // JSON storage with public read access
    const payload = StorageProgram.createStorageProgram(
    'demos1abc...',
    'appConfig',
    { version: '1.0', features: ['auth', 'storage'] },
    'json',
    { mode: 'public' },
    { nonce: 42 } // Required: sender's current nonce
    )

    // Binary storage with group access
    const payload = StorageProgram.createStorageProgram(
    'demos1abc...',
    'teamDocument',
    base64EncodedPdf,
    'binary',
    {
    mode: 'restricted',
    groups: {
    editors: { members: ['demos1a...', 'demos1b...'], permissions: ['read', 'write'] },
    viewers: { members: ['demos1c...'], permissions: ['read'] }
    }
    },
    { nonce: 43, metadata: { filename: 'report.pdf', mimeType: 'application/pdf' } }
    )
  • Parameters

    • deployerAddress: string
    • programName: string
    • initialData: Record<string, any>
    • nonce: number
    • accessControl: StorageProgramAccessControl = "private"
    • Optionalsalt: string
    • OptionalallowedAddresses: string[]

    Returns StorageProgramPayload

    Use createStorageProgram with acl parameter instead. Kept for backward compatibility.

    Create a new Storage Program with legacy access control

  • Delete a field from a storage program (JSON encoding only)

    Creates a payload for the DELETE_FIELD operation. Completely removes the field from the stored data.

    Parameters

    • storageAddress: string

      The storage program address

    • field: string

      The field name to delete

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // Remove deprecated config field
    const payload = StorageProgram.deleteField(
    'stor-7a8b9c...',
    'legacyConfig'
    )
  • Delete an item from an array field by index (JSON encoding only)

    Creates a payload for the DELETE_ITEM operation. Supports negative indexing (-1 = last item). The array will be compacted after deletion.

    Parameters

    • storageAddress: string

      The storage program address

    • field: string

      The array field name

    • index: number

      The array index to delete (0-based, supports negative)

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // Delete first user
    const payload = StorageProgram.deleteItem(
    'stor-7a8b9c...',
    'users',
    0
    )

    // Delete last user
    const payload = StorageProgram.deleteItem(
    'stor-7a8b9c...',
    'users',
    -1
    )
  • Delete a Storage Program (owner/ACL-permissioned only)

    WARNING: This operation is irreversible and will delete all stored data.

    Parameters

    • storageAddress: string

      The storage program address to delete

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    const payload = StorageProgram.deleteStorageProgram('stor-7a8b9c...')
    
  • Derive a deterministic storage program address

    Parameters

    • deployerAddress: string

      Address of the program deployer (will be owner)

    • programName: string

      Name of the storage program

    • nonce: number

      Sender's nonce for uniqueness (ensures unique address per transaction)

    • salt: string = ""

      Optional random salt for additional uniqueness (default: empty string)

    Returns string

    Storage address in format: stor-{first 40 chars of sha256}

    const address = StorageProgram.deriveStorageAddress(
    'demos1abc...',
    'myConfig',
    42, // nonce
    'salt123'
    )
    // Returns: 'stor-7a8b9c...' (40 chars after prefix)
  • Get all data from a storage program (alias for getByAddress with full data)

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • storageAddress: string

      The storage program address

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramData>

    Full storage program data or null if not found

    const program = await StorageProgram.getAll(
    'https://node.demos.sh',
    'stor-7a8b9c...'
    )
    if (program) {
    console.log(`Data: ${JSON.stringify(program.data)}`)
    }
  • Get a storage program by address

    Parameters

    • rpcUrl: string

      The RPC endpoint URL (e.g., "https://node.demos.sh")

    • storageAddress: string

      The storage program address (stor-{hash})

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramData>

    Storage program data or null if not found

    const program = await StorageProgram.getByAddress(
    'https://node.demos.sh',
    'stor-7a8b9c...'
    )
    if (program) {
    console.log(`Found: ${program.programName}`)
    }
  • Get all storage programs owned by an address

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • owner: string

      The owner's address

    • Optionalidentity: string

      Optional requester identity for ACL filtering

    Returns Promise<StorageProgramListItem[]>

    Array of storage program list items

    const programs = await StorageProgram.getByOwner(
    'https://node.demos.sh',
    'demos1abc...'
    )
    console.log(`Found ${programs.length} programs`)
  • Get data size in bytes

    Parameters

    • data: string | Record<string, any>

      Data to measure (JSON object or base64 string)

    • encoding: StorageEncoding = "json"

      Encoding type ("json" or "binary")

    Returns number

    Size in bytes

    const size = StorageProgram.getDataSize({ key: 'value' }, 'json')
    console.log(`Data size: ${size} bytes`)
  • Get all field names from a storage program (JSON encoding only)

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • storageAddress: string

      The storage program address

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramFieldsResponse>

    Object with field names array and count

    const result = await StorageProgram.getFields(
    'https://node.demos.sh',
    'stor-7a8b9c...'
    )
    console.log(`Fields: ${result.fields.join(', ')}`)
    // Fields: name, settings, users
  • Get the type of a field in a storage program (JSON encoding only)

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • storageAddress: string

      The storage program address

    • field: string

      The field name

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramFieldTypeResponse>

    Object with field name and type

    const result = await StorageProgram.getFieldType(
    'https://node.demos.sh',
    'stor-7a8b9c...',
    'users'
    )
    if (result?.type === 'array') {
    // Safe to use array operations
    }
  • Get an item from an array field by index (JSON encoding only)

    Type Parameters

    • T = unknown

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • storageAddress: string

      The storage program address

    • field: string

      The array field name

    • index: number

      The array index (0-based, supports negative indexing)

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramItemResponse<T>>

    Object with field name, index, value, and array length

    // Get first item
    const first = await StorageProgram.getItem(
    'https://node.demos.sh',
    'stor-7a8b9c...',
    'users',
    0
    )

    // Get last item (negative indexing)
    const last = await StorageProgram.getItem(
    'https://node.demos.sh',
    'stor-7a8b9c...',
    'users',
    -1
    )
  • Get a specific field value from a storage program (JSON encoding only)

    Type Parameters

    • T = unknown

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • storageAddress: string

      The storage program address

    • field: string

      The field name to retrieve

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramValueResponse<T>>

    Object with field name, value, and type

    const result = await StorageProgram.getValue(
    'https://node.demos.sh',
    'stor-7a8b9c...',
    'settings'
    )
    if (result) {
    console.log(`${result.field} = ${JSON.stringify(result.value)} (${result.type})`)
    }
  • Create a group-based ACL

    Parameters

    Returns StorageProgramACL

    StorageProgramACL configured for group-based access

    const acl = StorageProgram.groupACL({
    admins: { members: ['demos1admin...'], permissions: ['read', 'write', 'delete'] },
    editors: { members: ['demos1ed1...', 'demos1ed2...'], permissions: ['read', 'write'] },
    viewers: { members: ['demos1view...'], permissions: ['read'] }
    })
  • Check if a field exists in a storage program (JSON encoding only)

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • storageAddress: string

      The storage program address

    • field: string

      The field name to check

    • Optionalidentity: string

      Optional requester identity for ACL-protected programs

    Returns Promise<StorageProgramHasFieldResponse>

    Object with field name and exists boolean

    const result = await StorageProgram.hasField(
    'https://node.demos.sh',
    'stor-7a8b9c...',
    'apiKey'
    )
    if (result?.exists) {
    console.log('API key is configured')
    }
  • Read data from a Storage Program (creates payload for RPC)

    Note: This creates a payload for validation purposes. Actual reads should use RPC endpoints like GET /storage-program/:address

    Parameters

    • storageAddress: string

      The storage program address to read from

    Returns StorageProgramPayload

    StorageProgramPayload for validation

    // For transaction validation (not typical usage)
    const payload = StorageProgram.readStorage('stor-7a8b9c...')

    // Typical usage: Use RPC endpoint
    // fetch(`${rpcUrl}/storage-program/${storageAddress}`)
  • Create a restricted ACL with allowed addresses

    Parameters

    • allowed: string[]

      List of addresses allowed to access

    Returns StorageProgramACL

    StorageProgramACL configured for restricted access

    const acl = StorageProgram.restrictedACL(['demos1a...', 'demos1b...'])
    // { mode: 'restricted', allowed: ['demos1a...', 'demos1b...'] }
  • Search storage programs by name (supports partial matching)

    Parameters

    • rpcUrl: string

      The RPC endpoint URL

    • nameQuery: string

      The name or partial name to search for

    • Optionaloptions: {
          exactMatch?: boolean;
          identity?: string;
          limit?: number;
          offset?: number;
      }

      Search options (exactMatch, limit, offset, identity)

      • OptionalexactMatch?: boolean
      • Optionalidentity?: string
      • Optionallimit?: number
      • Optionaloffset?: number

    Returns Promise<StorageProgramListItem[]>

    Array of storage program list items

    // Partial match search
    const results = await StorageProgram.searchByName(
    'https://node.demos.sh',
    'config' // matches "appConfig", "myConfig", etc.
    )

    // Exact match search
    const exact = await StorageProgram.searchByName(
    'https://node.demos.sh',
    'myConfig',
    { exactMatch: true }
    )

    // Paginated search
    const page2 = await StorageProgram.searchByName(
    'https://node.demos.sh',
    'config',
    { limit: 10, offset: 10 }
    )
  • Set a specific field value in a storage program (JSON encoding only)

    Creates a payload for the SET_FIELD operation. Use this with transaction submission flow.

    Parameters

    • storageAddress: string

      The storage program address

    • field: string

      The field name to set

    • value: unknown

      The value to set (any JSON-serializable value)

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    const payload = StorageProgram.setField(
    'stor-7a8b9c...',
    'theme',
    'dark'
    )
    // Submit via standard transaction flow
  • Set an item at a specific index in an array field (JSON encoding only)

    Creates a payload for the SET_ITEM operation. Supports negative indexing (-1 = last item).

    Parameters

    • storageAddress: string

      The storage program address

    • field: string

      The array field name

    • index: number

      The array index (0-based, supports negative)

    • value: unknown

      The value to set at the index

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // Update first user
    const payload = StorageProgram.setItem(
    'stor-7a8b9c...',
    'users',
    0,
    { name: 'Updated User', role: 'admin' }
    )

    // Update last user (negative indexing)
    const payload = StorageProgram.setItem(
    'stor-7a8b9c...',
    'users',
    -1,
    { name: 'Last User', role: 'user' }
    )
  • Update access control settings for a Storage Program (owner only)

    Parameters

    • storageAddress: string

      The storage program address

    • acl: Partial<StorageProgramACL>

      New access control configuration

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // Change to public access
    const payload = StorageProgram.updateAccessControl(
    'stor-7a8b9c...',
    { mode: 'public' }
    )

    // Add users to blacklist
    const payload = StorageProgram.updateAccessControl(
    'stor-7a8b9c...',
    {
    mode: 'public',
    blacklisted: ['demos1bad...', 'demos1spam...']
    }
    )

    // Set up group-based access
    const payload = StorageProgram.updateAccessControl(
    'stor-7a8b9c...',
    {
    mode: 'restricted',
    groups: {
    admins: { members: ['demos1admin...'], permissions: ['read', 'write', 'delete'] },
    users: { members: ['demos1user1...', 'demos1user2...'], permissions: ['read'] }
    }
    }
    )
  • Validate JSON nesting depth (max 64 levels)

    Only applicable for JSON encoding.

    Parameters

    • data: any

      The data object to validate

    • maxDepth: number = STORAGE_PROGRAM_CONSTANTS.MAX_JSON_NESTING_DEPTH

      Maximum allowed nesting depth (default: 64)

    Returns boolean

    true if nesting depth is within limit

    const data = { level1: { level2: { level3: 'value' } } }
    if (StorageProgram.validateNestingDepth(data)) {
    // Safe nesting depth
    }
  • Validate data size against 1MB limit

    Parameters

    • data: string | Record<string, any>

      Data to validate (JSON object or base64 string)

    • encoding: StorageEncoding = "json"

      Encoding type ("json" or "binary")

    Returns boolean

    true if size is within 1MB limit, false otherwise

    // Validate JSON data
    if (StorageProgram.validateSize({ key: 'value' }, 'json')) {
    // Safe to store
    }

    // Validate binary data
    if (StorageProgram.validateSize(base64String, 'binary')) {
    // Safe to store
    }
  • Write/update data in a Storage Program

    Parameters

    • storageAddress: string

      The storage program address (stor-{hash})

    • data: string | Record<string, any>

      Data to write (JSON object or base64 binary string)

    • encoding: StorageEncoding = "json"

      "json" or "binary" (default: "json")

    Returns StorageProgramPayload

    StorageProgramPayload for transaction creation

    // Update JSON data
    const payload = StorageProgram.writeStorage(
    'stor-7a8b9c...',
    { newKey: 'value', existingKey: 'updatedValue' },
    'json'
    )

    // Update binary data
    const payload = StorageProgram.writeStorage(
    'stor-7a8b9c...',
    newBase64Content,
    'binary'
    )