Browse Source

storage-node-v2: Refactor the code.

- add code comments
- move file info detection in a separate module
Shamil Gadelshin 3 years ago
parent
commit
5b01decf23

+ 78 - 1
storage-node-v2/src/services/helpers/auth.ts

@@ -3,36 +3,99 @@ import { u8aToHex } from '@polkadot/util'
 import { signatureVerify } from '@polkadot/util-crypto'
 import base64url from 'base64url'
 
+/**
+ * Represents an upload token request.
+ */
 export interface UploadTokenRequest {
+  /**
+   * Request data to sign.
+   */
   data: UploadTokenRequestBody
+  /**
+   * Request body signature.
+   */
   signature: string
 }
 
+/**
+ * Represents upload token request data.
+ */
 export interface UploadTokenRequestBody extends RequestData {
+  /**
+   * Joystream runtime Member ID (number).
+   */
   memberId: number
+
+  /**
+   * Joystream runtime Account ID (public key).
+   */
   accountId: string
 }
 
+/**
+ * Represents request data.
+ */
 export interface RequestData {
+  /**
+   * Runtime data object ID.
+   */
   dataObjectId: number
+  /**
+   * Runtime storage bucket ID.
+   */
   storageBucketId: number
+  /**
+   * Bag ID in the string format.
+   */
   bagId: string
 }
 
+/**
+ * Represents upload token data.
+ */
 export interface UploadTokenBody extends RequestData {
-  validUntil: number // timestamp
+  /**
+   * Expiration time for the token (timestamp).
+   */
+  validUntil: number
+  /**
+   * Nonce for the request.
+   */
   nonce: string
 }
 
+/**
+ * Represents an upload token.
+ */
 export interface UploadToken {
+  /**
+   * Upload token data to sign.
+   */
   data: UploadTokenBody
+  /**
+   * Upload token data signature.
+   */
   signature: string
 }
 
+/**
+ * Parses upload token from the token string.
+ *
+ * @param tokenString - token string
+ * @param bagType - dynamic bag type string
+ * @returns The UploadToken instance.
+ */
 export function parseUploadToken(tokenString: string): UploadToken {
   return JSON.parse(base64url.decode(tokenString))
 }
 
+/**
+ * Verifies UploadToken or UploadTokenRequest using its signatures.
+ *
+ * @param token - object to verify
+ * @param address - public key(account ID)
+ * @returns The UploadToken instance.
+ */
 export function verifyTokenSignature(
   token: UploadToken | UploadTokenRequest,
   address: string
@@ -43,6 +106,13 @@ export function verifyTokenSignature(
   return isValid
 }
 
+/**
+ * Signs UploadToken or UploadTokenRequest.
+ *
+ * @param token - object to verify
+ * @param account - KeyringPair instance
+ * @returns object signature.
+ */
 export function signTokenBody(
   tokenBody: UploadTokenBody | UploadTokenRequestBody,
   account: KeyringPair
@@ -53,6 +123,13 @@ export function signTokenBody(
   return signature
 }
 
+/**
+ * Creates an upload token.
+ *
+ * @param tokenBody - upload token data
+ * @param account - KeyringPair instance
+ * @returns object signature.
+ */
 export function createUploadToken(
   tokenBody: UploadTokenBody,
   account: KeyringPair

+ 14 - 3
storage-node-v2/src/services/helpers/bagTypes.ts

@@ -19,7 +19,6 @@ import { CLIError } from '@oclif/errors'
  * @param api - runtime API promise
  * @param bagType - dynamic bag type string
  * @returns The DynamicBagType instance.
- *
  */
 export function parseDynamicBagType(
   api: ApiPromise,
@@ -36,9 +35,8 @@ export function parseDynamicBagType(
  * on invalid string format.
  *
  * @param api - runtime API promise
- * @param bagId - bag id in string format
+ * @param bagId - bag ID in string format
  * @returns The BagId instance.
- *
  */
 export function parseBagId(api: ApiPromise, bagId: string): BagId {
   const parser = new BagIdParser(api, bagId)
@@ -46,6 +44,9 @@ export function parseBagId(api: ApiPromise, bagId: string): BagId {
   return parser.parse()
 }
 
+/**
+ * Class-helper for actual bag ID parsing.
+ */
 class BagIdParser {
   bagId: string
   api: ApiPromise
@@ -64,6 +65,10 @@ class BagIdParser {
     }
   }
 
+  /**
+   * Tries to parse the bag ID using given bag ID in string format, throws an
+   * exception on failure.
+   */
   parse(): BagId {
     if (this.bagIdParts[0] === 'static') {
       return this.parseStaticBagId()
@@ -78,6 +83,9 @@ class BagIdParser {
     })
   }
 
+  /**
+   * Tries to parse the static bag ID, throws an exception on failure.
+   */
   parseStaticBagId(): BagId {
     // Try to construct static council bag ID.
     if (this.bagIdParts[1] === 'council') {
@@ -121,6 +129,9 @@ class BagIdParser {
     })
   }
 
+  /**
+   * Tries to parse the dynamic bag ID, throws an exception on failure.
+   */
   parseDynamicBagId(): BagId {
     if (this.bagIdParts.length === 3) {
       const idString = this.bagIdParts[2]

+ 50 - 0
storage-node-v2/src/services/helpers/fileInfo.ts

@@ -0,0 +1,50 @@
+import FileType from 'file-type'
+import readChunk from 'read-chunk'
+
+/**
+ * Represents information about the file.
+ */
+export type FileInfo = {
+  /**
+   * File MIME-type.
+   */
+  mimeType: string
+
+  /**
+   * Possible file extension.
+   */
+  ext: string
+}
+
+// Number in bytes to read. Minimum number for file info detection.
+const MINIMUM_FILE_CHUNK = 4100
+
+/**
+ * Returns MIME-type and file extension by file content.
+ *
+ * @remarks
+ * It reads the file chunck and tries to determine its MIME-type and extension.
+ * It returns 'application/octet-stream' and 'bin' as default values.
+ *
+ * @param fullPath - file path
+ * @returns promise with file information.
+ */
+export async function getFileInfo(fullPath: string): Promise<FileInfo> {
+  // Default file info if nothing could be detected.
+  const DEFAULT_FILE_INFO = {
+    mimeType: 'application/octet-stream',
+    ext: 'bin',
+  }
+
+  const buffer = readChunk.sync(fullPath, 0, MINIMUM_FILE_CHUNK)
+  const fileType = await FileType.fromBuffer(buffer)
+
+  if (fileType === undefined) {
+    return DEFAULT_FILE_INFO
+  }
+
+  return {
+    mimeType: fileType.mime.toString(),
+    ext: fileType.ext.toString(),
+  }
+}

+ 0 - 1
storage-node-v2/src/services/helpers/hashing.ts

@@ -8,7 +8,6 @@ import { createHash } from 'blake3'
  *
  * @param filename - file name
  * @returns hash promise.
- *
  */
 export function hashFile(filename: string): Promise<string> {
   const fileStream = fs.createReadStream(filename).pipe(createHash())

+ 12 - 3
storage-node-v2/src/services/helpers/tokenNonceKeeper.ts

@@ -1,20 +1,30 @@
 import NodeCache from 'node-cache'
 
-export const TokenExpirationPeriod: number = 30 * 1000 // seconds
+// Expiration period in seconds for the local nonce cache.
+const TokenExpirationPeriod: number = 30 * 1000 // seconds
+
+// Max nonce number in local cache
 const MaxNonces = 100000
 
+// Local in-memory cache for nonces.
 const nonceCache = new NodeCache({
   stdTTL: TokenExpirationPeriod,
   deleteOnExpire: true,
   maxKeys: MaxNonces,
 })
 
+/**
+ * Constructs and returns an expiration time for a token.
+ */
+export function getTokenExpirationTime(): number {
+  return Date.now() + TokenExpirationPeriod
+}
+
 /**
  * Creates nonce string using the high precision process time and registers
  * it in the local in-memory cache with expiration time.
  *
  * @returns nonce string.
- *
  */
 export function createNonce(): string {
   const nonce = process.hrtime.bigint().toString()
@@ -29,7 +39,6 @@ export function createNonce(): string {
  *
  * @param nonce - nonce string.
  * @returns true if nonce was present in local cache.
- *
  */
 export function checkRemoveNonce(nonce: string): boolean {
   const deletedEntries = nonceCache.del(nonce)

+ 8 - 2
storage-node-v2/src/services/runtime/accounts.ts

@@ -10,7 +10,6 @@ import ExitCodes from '../../command-base/ExitCodes'
  *
  * @param jsonBackupFilePath - JSON-file path
  * @returns KeyPair instance.
- *
  */
 export function getAccountFromJsonFile(
   jsonBackupFilePath: string
@@ -56,7 +55,14 @@ export function getAccountFromJsonFile(
   return account
 }
 
-// Returns 'Alice' keypair. Should be use in dev-mode only.
+/**
+ * Returns 'Alice' KeyPair instance.
+ *
+ * @remarks
+ * This method should be used in the development mode only.
+ *
+ * @returns 'Alice' KeyPair instance.
+ */
 export function getAlicePair(): KeyringPair {
   const keyring = new Keyring({ type: 'sr25519' })
   return keyring.addFromUri('//Alice')

+ 3 - 0
storage-node-v2/src/services/runtime/api.ts

@@ -14,6 +14,9 @@ import logger from '../../services/logger'
 import ExitCodes from '../../command-base/ExitCodes'
 import { CLIError } from '@oclif/errors'
 
+/**
+ * Dedicated error for the failed extrinsics.
+ */
 export class ExtrinsicFailedError extends CLIError {}
 
 /**

+ 230 - 0
storage-node-v2/src/services/runtime/extrinsics.ts

@@ -6,6 +6,21 @@ import { ApiPromise } from '@polkadot/api'
 import { BagId, DynamicBagType } from '@joystream/types/storage'
 import logger from '../../services/logger'
 
+/**
+ * Creates storage bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param invitedWorker - defines whether the storage provider should be
+ * invited on the bucket creation (optional)
+ * @param allowedNewBags - bucket allows new bag assignments
+ * @param sizeLimit - size limit in bytes for the new bucket (default 0)
+ * @param objectsLimit - object number limit for the new bucket (default 0)
+ * @returns promise with a success flag.
+ */
 export async function createStorageBucket(
   api: ApiPromise,
   account: KeyringPair,
@@ -27,6 +42,18 @@ export async function createStorageBucket(
   })
 }
 
+/**
+ * Accepts the storage provider invitation for a bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
 export async function acceptStorageBucketInvitation(
   api: ApiPromise,
   account: KeyringPair,
@@ -44,6 +71,20 @@ export async function acceptStorageBucketInvitation(
   )
 }
 
+/**
+ * Updates storage bucket to bags relationships.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @param removeBucket - defines whether to remove bucket. If set to false
+ * the bucket will be added instead.
+ * @returns promise with a success flag.
+ */
 export async function updateStorageBucketsForBag(
   api: ApiPromise,
   bagId: BagId,
@@ -71,6 +112,18 @@ export async function updateStorageBucketsForBag(
   })
 }
 
+/**
+ * Uploads a data object info.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param objectSize - object size in bytes
+ * @param objectCid - object CID (Content ID - multihash)
+ * @returns promise with a success flag.
+ */
 export async function uploadDataObjects(
   api: ApiPromise,
   objectSize: number,
@@ -99,6 +152,20 @@ export async function uploadDataObjects(
   })
 }
 
+/**
+ * Accepts pending data objects by storage provider.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @param dataObjects - runtime data objects IDs
+ * @returns promise with a success flag.
+ */
 export async function acceptPendingDataObjects(
   api: ApiPromise,
   bagId: BagId,
@@ -123,6 +190,17 @@ export async function acceptPendingDataObjects(
   }, true)
 }
 
+/**
+ * Updates a 'StorageBucketsPerBag' limit.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param newLimit - new limit
+ * @returns promise with a success flag.
+ */
 export async function updateStorageBucketsPerBagLimit(
   api: ApiPromise,
   account: KeyringPair,
@@ -139,6 +217,18 @@ export async function updateStorageBucketsPerBagLimit(
   )
 }
 
+/**
+ * Updates a 'StorageBucketsVoucherMaxLimits' variables.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param newSizeLimit - new size limit
+ * @param newObjectLimit - new object limit
+ * @returns promise with a success flag.
+ */
 export async function updateStorageBucketsVoucherMaxLimits(
   api: ApiPromise,
   account: KeyringPair,
@@ -156,6 +246,17 @@ export async function updateStorageBucketsVoucherMaxLimits(
   )
 }
 
+/**
+ * Deletes a storage bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
 export async function deleteStorageBucket(
   api: ApiPromise,
   account: KeyringPair,
@@ -168,6 +269,18 @@ export async function deleteStorageBucket(
   )
 }
 
+/**
+ * Invites a storage provider for a bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @param operatorId - runtime storage operator ID (worker ID)
+ * @returns promise with a success flag.
+ */
 export async function inviteStorageBucketOperator(
   api: ApiPromise,
   account: KeyringPair,
@@ -185,6 +298,14 @@ export async function inviteStorageBucketOperator(
   )
 }
 
+/**
+ * Helper-function. It catches the error, logs it and returns a success flag.
+ *
+ * @param extrinsic - extrinsic promise
+ * @param throwErr - disables the default error catch and rethrows an error
+ * after logging.
+ * @returns promise with a success flag.
+ */
 async function extrinsicWrapper(
   extrinsic: () => Promise<void>,
   throwErr = false
@@ -203,6 +324,17 @@ async function extrinsicWrapper(
   return true
 }
 
+/**
+ * Cancels the invite for the storage provider.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
 export async function cancelStorageBucketOperatorInvite(
   api: ApiPromise,
   account: KeyringPair,
@@ -219,6 +351,17 @@ export async function cancelStorageBucketOperatorInvite(
   )
 }
 
+/**
+ * Removes a storage provider association with a bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
 export async function removeStorageBucketOperator(
   api: ApiPromise,
   account: KeyringPair,
@@ -235,6 +378,17 @@ export async function removeStorageBucketOperator(
   )
 }
 
+/**
+ * Updates a 'DataSizeFee' variable.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param fee - new fee
+ * @returns promise with a success flag.
+ */
 export async function updateDataSizeFee(
   api: ApiPromise,
   account: KeyringPair,
@@ -245,6 +399,19 @@ export async function updateDataSizeFee(
   )
 }
 
+/**
+ * Sets a metadata for the storage provider.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param operatorId - runtime storage operator ID (worker ID)
+ * @param bucketId - runtime storage bucket ID
+ * @param metadata - new metadata
+ * @returns promise with a success flag.
+ */
 export async function setStorageOperatorMetadata(
   api: ApiPromise,
   account: KeyringPair,
@@ -263,6 +430,17 @@ export async function setStorageOperatorMetadata(
   )
 }
 
+/**
+ * Updates the 'UploadingBlocked' variable.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param newStatus - new block status
+ * @returns promise with a success flag.
+ */
 export async function updateUploadingBlockedStatus(
   api: ApiPromise,
   account: KeyringPair,
@@ -279,6 +457,19 @@ export async function updateUploadingBlockedStatus(
   )
 }
 
+/**
+ * Updates the storage bucket status (whether it accepts new bags).
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @param newStatus - new storage bucket status status (accepts new bag)
+ * @returns promise with a success flag.
+ */
 export async function updateStorageBucketStatus(
   api: ApiPromise,
   account: KeyringPair,
@@ -295,6 +486,20 @@ export async function updateStorageBucketStatus(
   )
 }
 
+/**
+ * Updates a 'StorageBucketVoucherLimits' variable for a storage bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @param newSizeLimit - new size limit
+ * @param newObjectLimit - new object limit
+ * @returns promise with a success flag.
+ */
 export async function setStorageBucketVoucherLimits(
   api: ApiPromise,
   account: KeyringPair,
@@ -314,6 +519,18 @@ export async function setStorageBucketVoucherLimits(
   )
 }
 
+/**
+ * Updates the number of storage buckets in the dynamic bag creation policy.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param dynamicBagType - dynamic bag type
+ * @param newNumber - new number
+ * @returns promise with a success flag.
+ */
 export async function updateNumberOfStorageBucketsInDynamicBagCreationPolicy(
   api: ApiPromise,
   account: KeyringPair,
@@ -331,6 +548,19 @@ export async function updateNumberOfStorageBucketsInDynamicBagCreationPolicy(
   )
 }
 
+/**
+ * Updates the blacklist for the storage.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param cid - content ID (multihash)
+ * @param removeCid - defines wether the cid should be removed from the cid,
+ * a cid is added when 'false'
+ * @returns promise with a success flag.
+ */
 export async function updateBlacklist(
   api: ApiPromise,
   account: KeyringPair,

+ 70 - 40
storage-node-v2/src/services/webApi/controllers/publicApi.ts

@@ -1,5 +1,6 @@
 import { acceptPendingDataObjects } from '../../runtime/extrinsics'
 import {
+  RequestData,
   UploadTokenRequest,
   UploadTokenBody,
   createUploadToken,
@@ -8,12 +9,11 @@ import {
 import { hashFile } from '../../../services/helpers/hashing'
 import {
   createNonce,
-  TokenExpirationPeriod,
+  getTokenExpirationTime,
 } from '../../../services/helpers/tokenNonceKeeper'
+import { getFileInfo } from '../../../services/helpers/fileInfo'
 import { parseBagId } from '../../helpers/bagTypes'
 
-import FileType from 'file-type'
-import readChunk from 'read-chunk'
 import { KeyringPair } from '@polkadot/keyring/types'
 import { ApiPromise } from '@polkadot/api'
 import { Membership } from '@joystream/types/members'
@@ -23,12 +23,9 @@ import path from 'path'
 import send from 'send'
 const fsPromises = fs.promises
 
-interface UploadRequest {
-  dataObjectId: number
-  storageBucketId: number
-  bagId: string
-}
-
+/**
+ * A public endpoint: serves files by CID.
+ */
 export async function files(
   req: express.Request,
   res: express.Response
@@ -76,11 +73,14 @@ export async function files(
   }
 }
 
+/**
+ * A public endpoint: receives file.
+ */
 export async function upload(
   req: express.Request,
   res: express.Response
 ): Promise<void> {
-  const uploadRequest: UploadRequest = req.body
+  const uploadRequest: RequestData = req.body
 
   try {
     const fileObj = getFileObject(req)
@@ -112,6 +112,9 @@ export async function upload(
   }
 }
 
+/**
+ * A public endpoint: creates auth token for file uploads.
+ */
 export async function authToken(
   req: express.Request,
   res: express.Response
@@ -141,6 +144,13 @@ export async function authToken(
   }
 }
 
+/**
+ * Returns Multer.File object from the request.
+ *
+ * @remarks
+ * This is a helper function. It parses the request object for a variable and
+ * throws an error on failier.
+ */
 function getFileObject(req: express.Request): Express.Multer.File {
   if (req.file) {
     return req.file
@@ -154,6 +164,13 @@ function getFileObject(req: express.Request): Express.Multer.File {
   throw new Error('No file uploaded')
 }
 
+/**
+ * Returns worker ID from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
 function getWorkerId(res: express.Response): number {
   if (res.locals.workerId || res.locals.workerId === 0) {
     return res.locals.workerId
@@ -162,6 +179,13 @@ function getWorkerId(res: express.Response): number {
   throw new Error('No Joystream worker ID loaded.')
 }
 
+/**
+ * Returns a directory for file uploading from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
 function getUploadsDir(res: express.Response): string {
   if (res.locals.uploadsDir) {
     return res.locals.uploadsDir
@@ -170,6 +194,13 @@ function getUploadsDir(res: express.Response): string {
   throw new Error('No upload directory path loaded.')
 }
 
+/**
+ * Returns a KeyPair instance from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
 function getAccount(res: express.Response): KeyringPair {
   if (res.locals.storageProviderAccount) {
     return res.locals.storageProviderAccount
@@ -178,6 +209,13 @@ function getAccount(res: express.Response): KeyringPair {
   throw new Error('No Joystream account loaded.')
 }
 
+/**
+ * Returns API promise from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
 function getApi(res: express.Response): ApiPromise {
   if (res.locals.api) {
     return res.locals.api
@@ -186,6 +224,13 @@ function getApi(res: express.Response): ApiPromise {
   throw new Error('No Joystream API loaded.')
 }
 
+/**
+ * Returns Content ID from the request.
+ *
+ * @remarks
+ * This is a helper function. It parses the request object for a variable and
+ * throws an error on failier.
+ */
 function getCid(req: express.Request): string {
   const cid = req.params.cid || ''
   if (cid.length > 0) {
@@ -195,6 +240,13 @@ function getCid(req: express.Request): string {
   throw new Error('No CID provided.')
 }
 
+/**
+ * Returns UploadTokenRequest object from the request.
+ *
+ * @remarks
+ * This is a helper function. It parses the request object for a variable and
+ * throws an error on failier.
+ */
 function getTokenRequest(req: express.Request): UploadTokenRequest {
   const tokenRequest = req.body as UploadTokenRequest
   if (tokenRequest) {
@@ -204,6 +256,14 @@ function getTokenRequest(req: express.Request): UploadTokenRequest {
   throw new Error('No token request provided.')
 }
 
+/**
+ * Validates token request. It verifies token signature and compares the
+ * member ID and account ID from the runtime with token data.
+ *
+ * @param api - runtime API promise
+ * @param tokenRequest - UploadTokenRequest instance
+ * @returns void promise.
+ */
 async function validateTokenRequest(
   api: ApiPromise,
   tokenRequest: UploadTokenRequest
@@ -224,33 +284,3 @@ async function validateTokenRequest(
     throw new Error(`Provided controller account and member id don't match.`)
   }
 }
-
-function getTokenExpirationTime(): number {
-  return Date.now() + TokenExpirationPeriod
-}
-
-type FileInfo = {
-  mimeType: string
-  ext: string
-}
-
-const MINIMUM_FILE_CHUNK = 4100
-async function getFileInfo(fullPath: string): Promise<FileInfo> {
-  // Default file info if nothing could be detected.
-  const DEFAULT_FILE_INFO = {
-    mimeType: 'application/octet-stream',
-    ext: 'bin',
-  }
-
-  const buffer = readChunk.sync(fullPath, 0, MINIMUM_FILE_CHUNK)
-  const fileType = await FileType.fromBuffer(buffer)
-
-  if (fileType === undefined) {
-    return DEFAULT_FILE_INFO
-  }
-
-  return {
-    mimeType: fileType.mime.toString(),
-    ext: fileType.ext.toString(),
-  }
-}