diff --git a/src/core/format/KeyGenerator.ts b/src/core/format/KeyGenerator.ts new file mode 100644 index 0000000000..6bb813ec55 --- /dev/null +++ b/src/core/format/KeyGenerator.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2019 NEM + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { UInt64 } from '../../model/UInt64'; +import { sha3_256 } from 'js-sha3'; + +export class KeyGenerator { + /** + * Generate UInt64 from a string + * @param {string} input Input string + * @returns {UInt64} Deterministic uint64 value for the given string + */ + public static generateUInt64Key(input: string): UInt64 { + if (input.length === 0) { + throw Error(`Input must not be empty`); + } + const buf = sha3_256.arrayBuffer(input); + const result = new Uint32Array(buf); + return new UInt64([result[0], (result[1] | 0x80000000) >>> 0]); + } +} diff --git a/src/core/format/index.ts b/src/core/format/index.ts index 27fc8ea316..45d6ee1ca4 100644 --- a/src/core/format/index.ts +++ b/src/core/format/index.ts @@ -18,4 +18,5 @@ export * from './RawAddress'; export * from './RawArray'; export * from './Convert'; export * from './IdGenerator'; +export * from './KeyGenerator'; export * from './RawUInt64'; diff --git a/test/core/format/KeyGenerator.spec.ts b/test/core/format/KeyGenerator.spec.ts new file mode 100644 index 0000000000..23c4749eb5 --- /dev/null +++ b/test/core/format/KeyGenerator.spec.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2019 NEM + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { expect } from 'chai'; +import { UInt64 } from '../../../src/model/UInt64'; +import { KeyGenerator } from '../../../src/core/format/KeyGenerator'; + +describe('key generator', () => { + describe('generate key from string', () => { + it('throws if input is empty', () => { + expect(() => KeyGenerator.generateUInt64Key('')).to.throw(Error, 'Input must not be empty'); + }) + it('returns UInt64', () => { + expect(KeyGenerator.generateUInt64Key('a')).to.be.instanceOf(UInt64); + }) + it('generates correct keys', () => { + expect(KeyGenerator.generateUInt64Key('a').toHex()).to.equal('F524A0FBF24B0880'); + }) + it('generates keys deterministically', () => { + expect(KeyGenerator.generateUInt64Key('abc').toHex()).to.equal('B225E24FA75D983A'); + expect(KeyGenerator.generateUInt64Key('abc').toHex()).to.equal('B225E24FA75D983A'); + expect(KeyGenerator.generateUInt64Key('def').toHex()).to.equal('B0AC5222678F0D8E'); + expect(KeyGenerator.generateUInt64Key('def').toHex()).to.equal('B0AC5222678F0D8E'); + expect(KeyGenerator.generateUInt64Key('abc').toHex()).to.equal('B225E24FA75D983A'); + }) + }) +});