Skip to content

Commit

Permalink
Use NodeFileSystem for AssetVerifier (#4833)
Browse files Browse the repository at this point in the history
  • Loading branch information
danield9tqh authored Mar 12, 2024
1 parent 8f3e40c commit 663d640
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 28 deletions.
20 changes: 17 additions & 3 deletions ironfish/src/assets/assetsVerificationApi.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import fs from 'fs'
import nock from 'nock'
import { NodeFileProvider } from '../fileSystems'
import { AssetsVerificationApi } from './assetsVerificationApi'

describe('Assets Verification API Client', () => {
const files = new NodeFileProvider()

beforeAll(async () => {
await files.init()
})

beforeEach(() => {
nock.cleanAll()
})
Expand All @@ -24,6 +30,7 @@ describe('Assets Verification API Client', () => {
})

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
})
const verifiedAssets = await api.getVerifiedAssets()
Expand All @@ -47,6 +54,7 @@ describe('Assets Verification API Client', () => {
})

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
})
const verifiedAssets = await api.getVerifiedAssets()
Expand All @@ -66,6 +74,7 @@ describe('Assets Verification API Client', () => {
})

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
})
const verifiedAssets = await api.getVerifiedAssets()
Expand Down Expand Up @@ -96,6 +105,7 @@ describe('Assets Verification API Client', () => {
.reply(304)

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
})
const verifiedAssets = await api.getVerifiedAssets()
Expand All @@ -111,6 +121,7 @@ describe('Assets Verification API Client', () => {
nock('https://test').get('/assets/verified').reply(500)

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
})
await expect(api.getVerifiedAssets()).rejects.toThrow(
Expand All @@ -127,6 +138,7 @@ describe('Assets Verification API Client', () => {
})

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
timeout: 1000,
})
Expand All @@ -142,6 +154,7 @@ describe('Assets Verification API Client', () => {
})

const api = new AssetsVerificationApi({
files,
url: 'https://test/assets/verified',
timeout: 1000,
})
Expand All @@ -152,15 +165,16 @@ describe('Assets Verification API Client', () => {
const contents = JSON.stringify({
assets: [{ identifier: '0123' }, { identifier: 'abcd' }],
})
const readFileSpy = jest.spyOn(fs.promises, 'readFile').mockResolvedValue(contents)
const readFileSpy = jest.spyOn(files, 'readFile').mockResolvedValue(contents)

const api = new AssetsVerificationApi({
files,
url: 'file:///some/where',
})
const verifiedAssets = await api.getVerifiedAssets()

expect(verifiedAssets['assetIds']).toStrictEqual(new Set(['0123', 'abcd']))
expect(readFileSpy).toHaveBeenCalledWith('/some/where', { encoding: 'utf8' })
expect(readFileSpy).toHaveBeenCalledWith('/some/where')
})
})
})
45 changes: 24 additions & 21 deletions ironfish/src/assets/assetsVerificationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import axios, { AxiosAdapter, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import { readFile } from 'node:fs/promises'
import url, { URL } from 'url'
import { FileSystem } from '../fileSystems'

type GetVerifiedAssetsResponse = {
assets: Array<{ identifier: string }>
Expand Down Expand Up @@ -62,10 +62,12 @@ export class AssetsVerificationApi {

readonly url: string

constructor(options?: { url?: string; timeout?: number }) {
constructor(options: { files: FileSystem; url?: string; timeout?: number }) {
this.url = options?.url || 'https://api.ironfish.network/assets/verified'
this.timeout = options?.timeout ?? 30 * 1000 // 30 seconds
this.adapter = isFileUrl(this.url) ? axiosFileAdapter : axios.defaults.adapter
this.adapter = isFileUrl(this.url)
? axiosFileAdapter(options.files)
: axios.defaults.adapter
}

async getVerifiedAssets(): Promise<VerifiedAssets> {
Expand Down Expand Up @@ -116,22 +118,23 @@ const isFileUrl = (url: string): boolean => {
return parsedUrl.protocol === 'file:'
}

const axiosFileAdapter = (
config: AxiosRequestConfig,
): Promise<AxiosResponse<GetVerifiedAssetsResponse>> => {
if (!config.url) {
return Promise.reject(new Error('url is undefined'))
}
const axiosFileAdapter =
(files: FileSystem) =>
(config: AxiosRequestConfig): Promise<AxiosResponse<GetVerifiedAssetsResponse>> => {
if (!config.url) {
return Promise.reject(new Error('url is undefined'))
}

const path = url.fileURLToPath(config.url)

return readFile(path, { encoding: 'utf8' })
.then(JSON.parse)
.then((data: GetVerifiedAssetsResponse) => ({
data,
status: 0,
statusText: '',
headers: {},
config: config,
}))
}
const path = url.fileURLToPath(config.url)

return files
.readFile(path)
.then(JSON.parse)
.then((data: GetVerifiedAssetsResponse) => ({
data,
status: 0,
statusText: '',
headers: {},
config: config,
}))
}
23 changes: 21 additions & 2 deletions ironfish/src/assets/assetsVerifier.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import nock from 'nock'
import { VerifiedAssetsCacheStore } from '../fileStores/verifiedAssets'
import { NodeFileProvider } from '../fileSystems'
import { AssetsVerifier } from './assetsVerifier'

/* eslint-disable jest/no-standalone-expect */
Expand All @@ -17,6 +18,12 @@ describe('AssetsVerifier', () => {
}
}

const files = new NodeFileProvider()

beforeAll(async () => {
await files.init()
})

beforeEach(() => {
nock.cleanAll()
jest.clearAllTimers()
Expand All @@ -27,7 +34,7 @@ describe('AssetsVerifier', () => {
})

it('does not refresh when not started', () => {
const assetsVerifier = new AssetsVerifier()
const assetsVerifier = new AssetsVerifier({ files })
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')

jest.runOnlyPendingTimers()
Expand All @@ -50,6 +57,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand Down Expand Up @@ -91,6 +99,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand Down Expand Up @@ -120,6 +129,7 @@ describe('AssetsVerifier', () => {
.reply(304)

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand All @@ -139,7 +149,7 @@ describe('AssetsVerifier', () => {

describe('verify', () => {
it("returns 'unknown' when not started", () => {
const assetsVerifier = new AssetsVerifier()
const assetsVerifier = new AssetsVerifier({ files })

expect(assetsVerifier.verify('0123')).toStrictEqual({ status: 'unknown' })
expect(assetsVerifier.verify('4567')).toStrictEqual({ status: 'unknown' })
Expand All @@ -149,6 +159,7 @@ describe('AssetsVerifier', () => {
nock('https://test').get('/assets/verified').reply(500)

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand All @@ -172,6 +183,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand All @@ -190,6 +202,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand All @@ -210,6 +223,7 @@ describe('AssetsVerifier', () => {
.reply(500)

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand Down Expand Up @@ -240,6 +254,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
})
const refresh = jest.spyOn(assetsVerifier as any, 'refresh')
Expand Down Expand Up @@ -276,6 +291,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
cache: cache,
})
Expand Down Expand Up @@ -307,6 +323,7 @@ describe('AssetsVerifier', () => {
})

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://bar.test/assets/verified',
cache: cache,
})
Expand Down Expand Up @@ -343,6 +360,7 @@ describe('AssetsVerifier', () => {
)

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
cache: cache,
})
Expand Down Expand Up @@ -387,6 +405,7 @@ describe('AssetsVerifier', () => {
.reply(304)

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: 'https://test/assets/verified',
cache: cache,
})
Expand Down
6 changes: 4 additions & 2 deletions ironfish/src/assets/assetsVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { VerifiedAssetsCacheStore } from '../fileStores/verifiedAssets'
import { FileSystem } from '../fileSystems'
import { createRootLogger, Logger } from '../logger'
import { ErrorUtils } from '../utils'
import { SetIntervalToken } from '../utils'
Expand All @@ -28,13 +29,14 @@ export class AssetsVerifier {
private refreshToken?: SetIntervalToken
private verifiedAssets?: VerifiedAssets

constructor(options?: {
constructor(options: {
files: FileSystem
apiUrl?: string
cache?: VerifiedAssetsCacheStore
logger?: Logger
}) {
this.logger = options?.logger ?? createRootLogger()
this.api = new AssetsVerificationApi({ url: options?.apiUrl })
this.api = new AssetsVerificationApi({ url: options?.apiUrl, files: options.files })
this.cache = options?.cache
this.started = false

Expand Down
1 change: 1 addition & 0 deletions ironfish/src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export class FullNode {
await verifiedAssetsCache.load()

const assetsVerifier = new AssetsVerifier({
files,
apiUrl: config.get('assetVerificationApi'),
cache: verifiedAssetsCache,
logger,
Expand Down

0 comments on commit 663d640

Please sign in to comment.