diff --git a/jest.config.ts b/jest.config.ts index 542e0d5b..9023ebe4 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -6,7 +6,7 @@ import type { Config } from '@jest/types' import { BeeRequestOptions } from './src' import { createPostageBatch } from './src/modules/debug/stamps' -import { DEFAULT_BATCH_AMOUNT } from './test/utils' +import { DEFAULT_BATCH_AMOUNT, DEFAULT_BATCH_DEPTH } from './test/utils' export default async (): Promise => { try { @@ -34,7 +34,7 @@ export default async (): Promise => { const stamps = await Promise.all( stampsOrder.map(async order => - createPostageBatch(order.requestOptions, DEFAULT_BATCH_AMOUNT, 20, { + createPostageBatch(order.requestOptions, DEFAULT_BATCH_AMOUNT, DEFAULT_BATCH_DEPTH, { waitForUsable: true, }), ), @@ -83,6 +83,6 @@ export default async (): Promise => { testPathIgnorePatterns: ['/node_modules/'], // Increase timeout since we have long running cryptographic functions - testTimeout: 8 * 60 * 1000, + testTimeout: 9 * 60 * 1000, } } diff --git a/package-lock.json b/package-lock.json index df37f0c0..d32b7101 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,8 @@ "version": "8.1.0", "license": "BSD-3-Clause", "dependencies": { - "@ethersphere/swarm-cid": "^0.1.0", "axios": "^0.28.1", - "cafe-utility": "^23.7.0", + "cafe-utility": "^23.10.0", "elliptic": "^6.5.4", "isomorphic-ws": "^4.0.1", "js-sha3": "^0.8.0", @@ -27,7 +26,6 @@ "@babel/preset-typescript": "^7.18.6", "@commitlint/cli": "^17.0.2", "@commitlint/config-conventional": "^17.4.2", - "@fluffy-spoon/substitute": "^1.208.0", "@jest/types": "^29.6.3", "@naholyr/cross-env": "^1.0.0", "@types/elliptic": "^6.4.14", @@ -2398,29 +2396,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ethersphere/swarm-cid": { - "version": "0.1.0", - "license": "BSD-3-Clause", - "dependencies": { - "multiformats": "^9.5.4" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@fluffy-spoon/substitute": { - "version": "1.208.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/substitute-js#section-contribute" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.2", "dev": true, @@ -4745,9 +4720,9 @@ "license": "MIT" }, "node_modules/cafe-utility": { - "version": "23.7.0", - "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-23.7.0.tgz", - "integrity": "sha512-bVMtRoECZ+hlgVc5euorOz282L8OvlcAg7ArIjovIT3X4Fcoe9lmX0y6YveFEt5AUY2GkOVxyrS/MPWsllomyg==", + "version": "23.10.0", + "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-23.10.0.tgz", + "integrity": "sha512-e+jz+KE5tndsAiG3kSMqkF3PxiWKx6rpgMfhKkHQMwAaGGf4EVSm9y9gH6dEF8UGWbNXRtmyq2bPF/PXwNTrqA==", "license": "MIT" }, "node_modules/call-bind": { @@ -10051,10 +10026,6 @@ "dev": true, "license": "MIT" }, - "node_modules/multiformats": { - "version": "9.6.5", - "license": "(Apache-2.0 AND MIT)" - }, "node_modules/multimatch": { "version": "5.0.0", "dev": true, diff --git a/package.json b/package.json index 4dbfeda2..29b94e24 100644 --- a/package.json +++ b/package.json @@ -61,9 +61,8 @@ "bee": "npx @fairdatasociety/fdp-play@3.2.0 start --detach --fresh" }, "dependencies": { - "@ethersphere/swarm-cid": "^0.1.0", "axios": "^0.28.1", - "cafe-utility": "^23.7.0", + "cafe-utility": "^23.10.0", "elliptic": "^6.5.4", "isomorphic-ws": "^4.0.1", "js-sha3": "^0.8.0", @@ -79,7 +78,6 @@ "@babel/preset-typescript": "^7.18.6", "@commitlint/cli": "^17.0.2", "@commitlint/config-conventional": "^17.4.2", - "@fluffy-spoon/substitute": "^1.208.0", "@jest/types": "^29.6.3", "@naholyr/cross-env": "^1.0.0", "@types/elliptic": "^6.4.14", diff --git a/src/bee.ts b/src/bee.ts index 5f94ac14..09ad0608 100644 --- a/src/bee.ts +++ b/src/bee.ts @@ -1,4 +1,3 @@ -import { ReferenceType } from '@ethersphere/swarm-cid' import { Objects, System } from 'cafe-utility' import { Readable } from 'stream' import { makeSigner } from './chunk/signer' @@ -435,7 +434,7 @@ export class Bee { fileName, fileOptions, ), - ReferenceType.MANIFEST, + 'manifest', ) } else if (isReadable(data) && options?.tag && !options.size) { // TODO: Needed until https://github.com/ethersphere/bee/issues/2317 is resolved @@ -448,11 +447,11 @@ export class Bee { ) await this.updateTag(options.tag, result.reference) - return addCidConversionFunction(result, ReferenceType.MANIFEST) + return addCidConversionFunction(result, 'manifest') } else { return addCidConversionFunction( await bzz.uploadFile(this.getRequestOptionsForCall(requestOptions), data, postageBatchId, name, options), - ReferenceType.MANIFEST, + 'manifest', ) } } @@ -475,7 +474,7 @@ export class Bee { options?: BeeRequestOptions, ): Promise> { assertRequestOptions(options) - reference = makeReferenceOrEns(reference, ReferenceType.MANIFEST) + reference = makeReferenceOrEns(reference, 'manifest') return bzz.downloadFile(this.getRequestOptionsForCall(options), reference, path) } @@ -498,7 +497,7 @@ export class Bee { options?: BeeRequestOptions, ): Promise>> { assertRequestOptions(options) - reference = makeReferenceOrEns(reference, ReferenceType.MANIFEST) + reference = makeReferenceOrEns(reference, 'manifest') return bzz.downloadFileReadable(this.getRequestOptionsForCall(options), reference, path) } @@ -536,7 +535,7 @@ export class Bee { return addCidConversionFunction( await bzz.uploadCollection(this.getRequestOptionsForCall(requestOptions), data, postageBatchId, options), - ReferenceType.MANIFEST, + 'manifest', ) } @@ -569,7 +568,7 @@ export class Bee { postageBatchId, options, ), - ReferenceType.MANIFEST, + 'manifest', ) } @@ -603,7 +602,7 @@ export class Bee { return addCidConversionFunction( await bzz.uploadCollection(this.getRequestOptionsForCall(requestOptions), data, postageBatchId, options), - ReferenceType.MANIFEST, + 'manifest', ) } @@ -1049,7 +1048,7 @@ export class Bee { stamp, ) - return addCidConversionFunction({ reference }, ReferenceType.FEED) + return addCidConversionFunction({ reference }, 'feed') } /** diff --git a/src/types/index.ts b/src/types/index.ts index c44236d8..b4d8acea 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -118,7 +118,6 @@ export interface UploadResultWithCid extends UploadResult { * Function that converts the reference into Swarm CIDs * * @throws TypeError if the reference is encrypted reference (eq. 128 chars long) which is not supported in CID - * @see https://github.com/ethersphere/swarm-cid-js */ cid: () => string } @@ -449,8 +448,6 @@ export interface FeedManifestResult { /** * Function that converts the reference into Swarm Feed CID. - * - * @see https://github.com/ethersphere/swarm-cid-js */ cid: () => string } diff --git a/src/utils/cid.ts b/src/utils/cid.ts new file mode 100644 index 00000000..2d8c3e96 --- /dev/null +++ b/src/utils/cid.ts @@ -0,0 +1,49 @@ +import { Binary } from 'cafe-utility' +import { Reference } from '..' + +export const SWARM_MANIFEST_CODEC = 0xfa +export const SWARM_FEED_CODEC = 0xfb + +const CODEC_TABLE: Record = { + [SWARM_MANIFEST_CODEC]: 'manifest', + [SWARM_FEED_CODEC]: 'feed', +} + +export type DecodedCID = { + type: 'feed' | 'manifest' + reference: Reference +} + +export function convertReferenceToCid(reference: Reference | string, type: 'feed' | 'manifest'): string { + if (reference.length !== 64) { + throw TypeError('Only 32-byte, non-encrypted references are supported') + } + const base32 = 'b' + const version = new Uint8Array([1]) + const codec = new Uint8Array([type === 'feed' ? SWARM_FEED_CODEC : SWARM_MANIFEST_CODEC]) + const unknown = new Uint8Array([1]) + const sha256 = new Uint8Array([27]) + const size = new Uint8Array([32]) + const header = Binary.uint8ArrayToBase32(Binary.concatBytes(version, codec, unknown, sha256, size)).replace( + /\=+$/, + '', + ) + const hash = Binary.uint8ArrayToBase32(Binary.hexToUint8Array(reference)).replace(/\=+$/, '') + + return `${base32}${header}${hash}`.toLowerCase() +} + +export function convertCidToReference(cid: string): DecodedCID { + const bytes = Binary.base32ToUint8Array(cid.toLowerCase()) + const codec = bytes[2] + + if (!CODEC_TABLE[codec]) { + throw new Error('Unknown codec') + } + const reference = bytes.slice(-32) + + return { + type: CODEC_TABLE[codec] as 'feed' | 'manifest', + reference: Binary.uint8ArrayToHex(reference) as Reference, + } +} diff --git a/src/utils/type.ts b/src/utils/type.ts index 5f694299..0ba72ff1 100644 --- a/src/utils/type.ts +++ b/src/utils/type.ts @@ -1,4 +1,3 @@ -import { decodeCid, encodeReference, ReferenceType } from '@ethersphere/swarm-cid' import { Readable } from 'stream' import { Address, @@ -28,6 +27,7 @@ import { TransactionOptions, UploadOptions, } from '../types' +import { convertCidToReference, convertReferenceToCid } from './cid' import { BeeArgumentError, BeeError } from './error' import { isFile } from './file' import { assertHexString, assertPrefixedHexString, isHexString } from './hex' @@ -158,13 +158,13 @@ export function assertReferenceOrEns(value: unknown): asserts value is Reference * @param value * @param expectedCidType */ -export function makeReferenceOrEns(value: unknown, expectedCidType: ReferenceType): ReferenceOrEns { +export function makeReferenceOrEns(value: unknown, expectedCidType: 'feed' | 'manifest'): ReferenceOrEns { if (typeof value !== 'string') { throw new TypeError('ReferenceCidOrEns has to be a string!') } try { - const result = decodeCid(value) + const result = convertCidToReference(value) if (result.type !== expectedCidType) { throw new BeeError( @@ -185,16 +185,16 @@ export function makeReferenceOrEns(value: unknown, expectedCidType: ReferenceTyp /** * Function that adds getter which converts the reference into CID base32 encoded string. * @param result - * @param cidType Type as described in the @ethersphere/swarm-cids-js -> ReferenceType + * @param cidType feed or manifest */ export function addCidConversionFunction( result: T, - cidType: ReferenceType, + cidType: 'feed' | 'manifest', ): T & { cid: () => string } { return { ...result, cid() { - return encodeReference(result.reference, cidType).toString() + return convertReferenceToCid(result.reference, cidType) }, } } diff --git a/test/unit/feed/json.spec.ts b/test/unit/feed/json.spec.ts index f96f2003..3c29cd17 100644 --- a/test/unit/feed/json.spec.ts +++ b/test/unit/feed/json.spec.ts @@ -1,5 +1,4 @@ -import { Arg, Substitute } from '@fluffy-spoon/substitute' -import { AnyJson, Bee, FeedWriter, Reference } from '../../../src' +import { AnyJson, Reference } from '../../../src' import { getJsonData, setJsonData } from '../../../src/feed/json' import { FetchFeedUpdateResponse } from '../../../src/modules/feed' import { wrapBytesWithHelpers } from '../../../src/utils/bytes' @@ -19,27 +18,19 @@ describe('JsonFeed', () => { function testSet(data: unknown, expectedBytes: Uint8Array): void { it(`should set feed for data: ${data}`, async () => { - const bee = Substitute.for() - bee.uploadData(Arg.all()).resolves({ reference: DATA_REFERENCE, tagUid: 0, historyAddress: '00'.repeat(32) }) - - const writer = Substitute.for() - writer.upload(Arg.all()).resolves({ reference: FEED_REFERENCE_HASH, historyAddress: '00'.repeat(32) }) + const bee = { + uploadData: () => ({ reference: DATA_REFERENCE, tagUid: 0, historyAddress: '00'.repeat(32) }), + } as any + const writer = { upload: () => ({ reference: FEED_REFERENCE_HASH, historyAddress: '00'.repeat(32) }) } as any expect((await setJsonData(bee, writer, testAddress, data as AnyJson)).reference).toBe(FEED_REFERENCE_HASH) - bee.received(1).uploadData(testAddress, expectedBytes) - writer.received(1).upload(testAddress, DATA_REFERENCE, { pin: undefined }) }) it(`should get feed for data: ${data}`, async () => { - const bee = Substitute.for() - bee.downloadData(Arg.all()).resolves(wrapBytesWithHelpers(expectedBytes)) - - const writer = Substitute.for() - writer.download().resolves(FEED_REFERENCE) + const bee = { downloadData: () => wrapBytesWithHelpers(expectedBytes) } as any + const writer = { download: () => FEED_REFERENCE } as any expect(await getJsonData(bee, writer)).toStrictEqual(data) - bee.received(1).downloadData(FEED_REFERENCE_HASH) - writer.received(1).download() }) } @@ -60,8 +51,8 @@ describe('JsonFeed', () => { ) it(`should fail for non-serializable data`, async () => { - const bee = Substitute.for() - const writer = Substitute.for() + const bee = {} as any + const writer = {} as any await expect(setJsonData(bee, writer, testAddress, BigInt(123) as unknown as AnyJson)).rejects.toThrow(TypeError) const circularReference: CircularReference = { otherData: 123 } diff --git a/test/utils.ts b/test/utils.ts index 693d3b21..9d72a03c 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,4 +1,3 @@ -import { System } from 'cafe-utility' import { Readable } from 'stream' import * as stamps from '../src/modules/debug/stamps' @@ -203,27 +202,8 @@ export function shorten(inputStr: unknown, len = 17): string { return `${str.slice(0, 6)}...${str.slice(-6)} (length: ${str.length})` } -async function timeout(ms: number, message = 'Execution reached timeout!'): Promise { - await System.sleepMillis(ms) - throw new Error(message) -} - -export async function waitForBatchToBeUsable(batchId: string, pollingInterval = 200): Promise { - await Promise.race([ - timeout(USABLE_TIMEOUT, 'Awaiting of usable postage batch timed out!'), - async () => { - let stamp - - do { - await System.sleepMillis(pollingInterval) - stamp = await stamps.getPostageBatch(beeKyOptions(), batchId as BatchId) - } while (!stamp.usable) - }, - ]) -} - -export const DEFAULT_BATCH_AMOUNT = '600000000' -const DEFAULT_BATCH_DEPTH = 17 +export const DEFAULT_BATCH_AMOUNT = '1200000000' +export const DEFAULT_BATCH_DEPTH = 22 /** * Returns already existing batch or will create one. @@ -247,10 +227,9 @@ export async function getOrCreatePostageBatch( beeKyOptions(), amount ?? DEFAULT_BATCH_AMOUNT, depth ?? DEFAULT_BATCH_DEPTH, + { waitForUsable: true }, ) - await waitForBatchToBeUsable(batchId) - return stamps.getPostageBatch(beeKyOptions(), batchId) } @@ -287,10 +266,9 @@ export async function getOrCreatePostageBatch( beeKyOptions(), amount ?? DEFAULT_BATCH_AMOUNT, depth ?? DEFAULT_BATCH_DEPTH, + { waitForUsable: true }, ) - await waitForBatchToBeUsable(batchId) - return stamps.getPostageBatch(beeKyOptions(), batchId) } diff --git a/tsconfig-base.json b/tsconfig-base.json index 3c1db6f5..63a4f2ba 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -7,9 +7,9 @@ "allowSyntheticDefaultImports": true, "moduleResolution": "node", "strict": true, - "skipLibCheck": true, + "skipLibCheck": false, "typeRoots": ["./src/types", "node_modules/@types"], "target": "es2020", - "rootDirs": ["src"], - }, + "rootDirs": ["src"] + } }