# 4. Build a persistent store for artifact downloads

The RAILGUN proof generation system uses large artifact files. Because of the size and number of these files, which cover a variety of use cases, we recommend against packaging them directly into your application. This would increase the application size by 50MB+.

Instead, Wallet SDK will automatically download these artifact files when required and persist them for further use. The ArtifactStore module manages downloads and persistence of these assets.

As a dApp developer, you only need to provide a file storage mechanism that the ArtifactStore will use to 1) check file existence, 2) store assets, 3) retrieve assets.

````typescript
import { ArtifactStore } from "@railgun-community/wallet";
import fs from "fs";

/**
 * Creates a path for a download directory by joining a documents directory path
 * with a specified path.
 *
 * @param documentsDir - The base directory path for documents.
 * @param path - The specific path to append to the documents directory.
 * @returns A string representing the combined path.
 *
 * @example
 * ```typescript
 * const downloadDirPath = createDownloadDirPath('/path/to/documents', 'downloads');
 * console.log(downloadDirPath); // Output: '/path/to/documents/downloads'
 * ```
 */
const createDownloadDirPath = (documentsDir: string, path: string) => {
  return `${documentsDir}/${path}`;
};

/**
 * Creates an artifact store for managing file operations in a specified directory.
 *
 * @param documentsDir - The base directory path where artifacts will be stored
 * @returns An ArtifactStore instance with methods for file operations:
 *   - getFile: Reads a file from the artifact store
 *   - storeFile: Writes data to a file in the artifact store, creating directories as needed
 *   - fileExists: Checks if a file exists in the artifact store
 *
 * @example
 * ```typescript
 * const artifactStore = createArtifactStore('/path/to/documents');
 * const fileData = await artifactStore.getFile('path/to/file');
 * await artifactStore.storeFile('dir/name', 'dir/name/file.txt', 'file content');
 * const exists = await artifactStore.fileExists('path/to/file');
 * ```
 */
export const createArtifactStore = (documentsDir: string): ArtifactStore => {
  const getFile = async (path: string) => {
    return fs.promises.readFile(createDownloadDirPath(documentsDir, path));
  };

  const storeFile = async (
    dir: string,
    path: string,
    item: string | Uint8Array<ArrayBufferLike>
  ) => {
    await fs.promises.mkdir(createDownloadDirPath(documentsDir, dir), {
      recursive: true,
    });
    await fs.promises.writeFile(
      createDownloadDirPath(documentsDir, path),
      item
    );
  };

  const fileExists = (path: string): Promise<boolean> => {
    return new Promise((resolve) => {
      fs.promises
        .access(createDownloadDirPath(documentsDir, path))
        .then(() => resolve(true))
        .catch(() => resolve(false));
    });
  };

  return new ArtifactStore(getFile, storeFile, fileExists);
};
````

Use `createArtifactStore` when calling `startRailgunEngine` from Step 1.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.railgun.org/developer-guide/wallet/getting-started/4.-build-a-persistent-store-for-artifact-downloads.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
