Skip to content

Commit

Permalink
feat: add functions to download artifacts (#45)
Browse files Browse the repository at this point in the history
* feat: add functions to download artifacts

* chore: add test step in `pr` gh workflow

* changeset

* chore: update `rollup.config.ts`

* chore: export download node module

* docs: add back tsdoc comments

* fix `tsconfig.json`

* chore: remove `@rollup/plugin-terser`

* chore: check build in pr workflow

* fix tsconfig.json

* chore: fix remaining conf issues

* chore(poseidon): add circuit npm field

---------

Co-authored-by: cedoor <[email protected]>
  • Loading branch information
sripwoud and cedoor authored May 17, 2024
1 parent f1ba2dd commit 766578d
Show file tree
Hide file tree
Showing 16 changed files with 2,252 additions and 117 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-humans-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zk-kit/artifacts": minor
---

Add `maybeGetSnarkArtifacts` function (initally from `@zk-kit/utils`)
6 changes: 6 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ jobs:

- name: Check formatting, linting and import sorting
run: pnpm check

- name: Check TS build
run: pnpm --filter @zk-kit/artifacts build

- name: Test
run: pnpm --filter @zk-kit/artifacts test
2 changes: 1 addition & 1 deletion biome.jsonc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
"files": {
"ignore": ["dist/**"]
"ignore": ["coverage/**", "dist/**"]
},
"organizeImports": {
"enabled": true
Expand Down
29 changes: 19 additions & 10 deletions packages/artifacts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "Utilities for downloading snark artifacts",
"scripts": {
"build": "npm run clean && rollup -c rollup.config.ts --configPlugin typescript",
"clean": "rimraf dist"
"clean": "rimraf dist",
"test": "jest -c test/jest.config.ts"
},
"repository": {
"type": "git",
Expand All @@ -20,24 +21,32 @@
"publishConfig": {
"access": "public"
},
"main": "./dist/index.cjs.js",
"module": "./dist/index.esm.js",
"types": "./dist/index.d.ts",
"main": "./dist/index.node.js",
"module": "./dist/index.browser.js",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"default": "./dist/index.esm.js",
"import": "./dist/index.esm.js",
"require": "./dist/index.cjs.js",
"types": "./dist/index.d.ts"
"browser": "./dist/index.browser.js",
"default": "./dist/index.browser.js",
"node": {
"default": "./dist/index.node.js",
"import": "./dist/index.node.js",
"require": "./dist/index.node.cjs"
},
"types": "./dist/types/index.d.ts"
}
},
"files": ["dist"],
"files": ["dist", "src"],
"devDependencies": {
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-alias": "^5.1.0",
"@rollup/plugin-typescript": "^11.1.6",
"@types/jest": "^29.5.12",
"@types/node": "^20.12.10",
"jest": "^29.7.0",
"rimraf": "^5.0.5",
"rollup": "^2.79.1",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"tslib": "^2.6.2",
"typescript": "^5.4.5"
}
Expand Down
51 changes: 42 additions & 9 deletions packages/artifacts/rollup.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import fs from 'node:fs'
import terser from '@rollup/plugin-terser'
import alias from '@rollup/plugin-alias'
import typescript from '@rollup/plugin-typescript'
import type { RollupOptions } from 'rollup'

const input = 'src/index.ts'
const plugins = [
typescript({
tsconfig: './tsconfig.build.json',
}),
]
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'))
const banner = `/**
* @module ${pkg.name}
Expand All @@ -12,11 +19,37 @@ const banner = `/**
* @see [Github]{@link ${pkg.homepage}}
*/`

export default {
input: 'src/index.ts',
output: [
{ file: pkg.main, format: 'cjs', banner, exports: 'auto' },
{ file: pkg.module, format: 'es', banner },
],
plugins: [typescript({ tsconfig: './tsconfig.build.json' }), terser()],
}
const config: RollupOptions[] = [
{
input,
output: [
{
file: pkg.exports['.'].node.require,
format: 'cjs',
banner,
exports: 'auto',
},
{ file: pkg.exports['.'].node.import, format: 'es', banner },
],
external: ['node:fs', 'node:fs/promises', 'node:os', 'node:path'],
plugins,
},
{
input,
output: [{ file: pkg.exports['.'].browser, format: 'es', banner }],
external: ['node:fs', 'node:fs/promises', 'node:os', 'node:path'],
plugins: [
...plugins,
alias({
entries: [
{
find: './download/download.node',
replacement: './download/download.browser',
},
],
}),
],
},
]

export default config
28 changes: 28 additions & 0 deletions packages/artifacts/src/download/download.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type Project, projects } from '../projects'
import type { SnarkArtifacts, Version } from './types'

export default async function maybeGetSnarkArtifacts(
project: Project,
options: {
parameters?: (bigint | number | string)[]
version?: Version
cdnUrl?: string
} = {},
): Promise<SnarkArtifacts> {
if (!projects.includes(project)) {
throw new Error(`Project '${project}' is not supported`)
}

options.version ??= 'latest'
options.cdnUrl ??= 'https://unpkg.com'

const BASE_URL = `${options.cdnUrl}/@zk-kit/${project}-artifacts@${options.version}`
const parameters = options.parameters
? `-${options.parameters.join('-')}`
: ''

return {
wasm: `${BASE_URL}/${project}${parameters}.wasm`,
zkey: `${BASE_URL}/${project}${parameters}.zkey`,
}
}
77 changes: 77 additions & 0 deletions packages/artifacts/src/download/download.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { createWriteStream, existsSync } from 'node:fs'
import { mkdir } from 'node:fs/promises'
import os from 'node:os'
import { dirname } from 'node:path'
import _maybeGetSnarkArtifacts from './download.browser'
import type { SnarkArtifacts } from './types'

async function download(url: string, outputPath: string) {
const response = await fetch(url)

if (!response.ok)
throw new Error(`Failed to fetch ${url}: ${response.statusText}`)
if (!response.body) throw new Error('Failed to get response body')

const dir = dirname(outputPath)
await mkdir(dir, { recursive: true })

const fileStream = createWriteStream(outputPath)
const reader = response.body.getReader()

try {
const pump = async () => {
const { done, value } = await reader.read()
if (done) {
fileStream.end()
return
}

fileStream.write(Buffer.from(value))
await pump()
}

await pump()
} catch (error) {
fileStream.close()
throw error
}
}

// https://unpkg.com/@zk-kit/poseidon-artifacts@latest/poseidon.wasm -> @zk/poseidon-artifacts@latest/poseidon.wasm
const extractEndPath = (url: string) => url.substring(url.indexOf('@zk'))

async function maybeDownload(url: string) {
const outputPath = `${os.tmpdir()}/${extractEndPath(url)}`

if (!existsSync(outputPath)) await download(url, outputPath)

return outputPath
}

/**
* Downloads SNARK artifacts (`wasm` and `zkey`) files if not already present in OS tmp folder.
* @example
* ```ts
* {
* wasm: "/tmp/@zk-kit/semaphore-artifacts@latest/semaphore-3.wasm",
* zkey: "/tmp/@zk-kit/semaphore-artifacts@latest/semaphore-3.zkey"
* }
* ```
* @returns {@link SnarkArtifacts}
*/
export default async function maybeGetSnarkArtifacts(
...pars: Parameters<typeof _maybeGetSnarkArtifacts>
): Promise<SnarkArtifacts> {
const { wasm: wasmUrl, zkey: zkeyUrl } = await _maybeGetSnarkArtifacts(
...pars,
)
const [wasm, zkey] = await Promise.all([
maybeDownload(wasmUrl),
maybeDownload(zkeyUrl),
])

return {
wasm,
zkey,
}
}
23 changes: 23 additions & 0 deletions packages/artifacts/src/download/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @prop SnarkArtifacts.wasm
* @prop SnarkArtifacts.zkey
* @interface
*/
export type SnarkArtifacts = Record<'wasm' | 'zkey', string>

type Digit = `${number}`
type PreRelease = 'alpha' | 'beta'

/**
* Semantic version.
* @example
* 1.0.0-beta
* 2.0.0
* @example
* "latest"
*/
export type Version =
| `${Digit}.${Digit}.${Digit}`
| `${Digit}.${Digit}.${Digit}-${PreRelease}`
| `${Digit}.${Digit}.${Digit}-${PreRelease}.${Digit}`
| 'latest'
8 changes: 2 additions & 6 deletions packages/artifacts/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
export enum Proof {
SEMAPHORE_IDENTITY = 'semaphore-identity',
POSEIDON = 'poseidon',
//RLN = 'rln',
SEMAPHORE = 'semaphore',
}
export * from './projects'
export * from './download/download.node'
8 changes: 8 additions & 0 deletions packages/artifacts/src/projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum Project {
SEMAPHORE_IDENTITY = 'semaphore-identity',
POSEIDON = 'poseidon',
//RLN = 'rln',
SEMAPHORE = 'semaphore',
}

export const projects = Object.values(Project)
Loading

0 comments on commit 766578d

Please sign in to comment.