From 4d47568bad00e8ae18ad4240a19f1b62b95da192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Libert?= Date: Thu, 23 May 2024 15:08:25 +0200 Subject: [PATCH 1/4] Update as-types to dev version --- package-lock.json | 80 ++++++++++++++++------------------------------- package.json | 2 +- 2 files changed, 28 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index 716d6f4f..2b441398 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "devDependencies": { "@as-pect/cli": "^8.1.0", "@massalabs/as-transformer": "^0.3.2", - "@massalabs/as-types": "^2.0.0", + "@massalabs/as-types": "^2.0.1-dev.20240521132240", "@massalabs/eslint-config": "^0.0.8", "@massalabs/prettier-config-as": "^0.0.2", "as-bignum": "^0.2.40", @@ -68,29 +68,6 @@ "visitor-as": "^0.11.4" } }, - "node_modules/@as-covers/transform/node_modules/assemblyscript": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.25.2.tgz", - "integrity": "sha512-67TQOMvKo23htvSK6lhOzsoQjnplNKkdwgq925uBvQZLDbg9pHfAWhg/R8i8tqKrtk6GH8haOJbQY4oNSQqehA==", - "dev": true, - "peer": true, - "dependencies": { - "binaryen": "110.0.0-nightly.20221105", - "long": "^5.2.0" - }, - "bin": { - "asc": "bin/asc.js", - "asinit": "bin/asinit.js" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/assemblyscript" - } - }, "node_modules/@as-covers/transform/node_modules/visitor-as": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/visitor-as/-/visitor-as-0.11.4.tgz", @@ -763,15 +740,21 @@ } }, "node_modules/@massalabs/as-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@massalabs/as-types/-/as-types-2.0.0.tgz", - "integrity": "sha512-e5vr6nxOmXLjgaFeRdML+DHf5/rIPWiASWJUPAZCdUU7gHhJm6InsZo4+jQVmfzrPzahBZoKAq8j7Hfv9K6Faw==", + "version": "2.0.1-dev.20240521132240", + "resolved": "https://registry.npmjs.org/@massalabs/as-types/-/as-types-2.0.1-dev.20240521132240.tgz", + "integrity": "sha512-K5UwZrGfIpX7ryCaEEMEtmoFsqwb/eyq0AAyc2Dv/pmoHTrO2I+V3oi6Mz10JVUF8Vh4wC8ZOP5noyy+xdl9vg==", "dev": true, "dependencies": { - "as-bignum": "^0.2.31", - "assemblyscript": "^0.27.9" + "as-bignum": "^0.3.0", + "assemblyscript": "^0.27.18" } }, + "node_modules/@massalabs/as-types/node_modules/as-bignum": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/as-bignum/-/as-bignum-0.3.1.tgz", + "integrity": "sha512-/RS4NbSPYUCRTsGNeCNA8aLjiyYlsEYaevY4Jwzj/QlzVk82t4gXdaWb8R3hnqo96g0MSIbhdaq18UcpeyW7gA==", + "dev": true + }, "node_modules/@massalabs/as-types/node_modules/assemblyscript": { "version": "0.27.22", "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.27.22.tgz", @@ -9518,17 +9501,6 @@ "visitor-as": "^0.11.4" }, "dependencies": { - "assemblyscript": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.25.2.tgz", - "integrity": "sha512-67TQOMvKo23htvSK6lhOzsoQjnplNKkdwgq925uBvQZLDbg9pHfAWhg/R8i8tqKrtk6GH8haOJbQY4oNSQqehA==", - "dev": true, - "peer": true, - "requires": { - "binaryen": "110.0.0-nightly.20221105", - "long": "^5.2.0" - } - }, "visitor-as": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/visitor-as/-/visitor-as-0.11.4.tgz", @@ -10058,15 +10030,21 @@ } }, "@massalabs/as-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@massalabs/as-types/-/as-types-2.0.0.tgz", - "integrity": "sha512-e5vr6nxOmXLjgaFeRdML+DHf5/rIPWiASWJUPAZCdUU7gHhJm6InsZo4+jQVmfzrPzahBZoKAq8j7Hfv9K6Faw==", + "version": "2.0.1-dev.20240521132240", + "resolved": "https://registry.npmjs.org/@massalabs/as-types/-/as-types-2.0.1-dev.20240521132240.tgz", + "integrity": "sha512-K5UwZrGfIpX7ryCaEEMEtmoFsqwb/eyq0AAyc2Dv/pmoHTrO2I+V3oi6Mz10JVUF8Vh4wC8ZOP5noyy+xdl9vg==", "dev": true, "requires": { - "as-bignum": "^0.2.31", - "assemblyscript": "^0.27.9" + "as-bignum": "^0.3.0", + "assemblyscript": "^0.27.18" }, "dependencies": { + "as-bignum": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/as-bignum/-/as-bignum-0.3.1.tgz", + "integrity": "sha512-/RS4NbSPYUCRTsGNeCNA8aLjiyYlsEYaevY4Jwzj/QlzVk82t4gXdaWb8R3hnqo96g0MSIbhdaq18UcpeyW7gA==", + "dev": true + }, "assemblyscript": { "version": "0.27.22", "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.27.22.tgz", @@ -10409,8 +10387,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "aes-js": { "version": "4.0.0-beta.5", @@ -10909,15 +10886,13 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-config-prettier": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-jsdoc": { "version": "39.9.1", @@ -16552,8 +16527,7 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" }, "yallist": { "version": "4.0.0", diff --git a/package.json b/package.json index ca644127..7d5567da 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "devDependencies": { "@as-pect/cli": "^8.1.0", "@massalabs/as-transformer": "^0.3.2", - "@massalabs/as-types": "^2.0.0", + "@massalabs/as-types": "^2.0.1-dev.20240521132240", "@massalabs/eslint-config": "^0.0.8", "@massalabs/prettier-config-as": "^0.0.2", "as-bignum": "^0.2.40", From 41af5361ff4afe5283d7eb5bc370c99d037f440e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Libert?= Date: Thu, 23 May 2024 15:09:11 +0200 Subject: [PATCH 2/4] Add constantKeyManager and keyIncrementer --- .../__tests__/constantKeyManager.spec.ts | 54 +++++++++++++++++++ .../helpers/__tests__/keyIncrementer.spec.ts | 20 +++++++ assembly/helpers/constantKeyManager.ts | 54 +++++++++++++++++++ assembly/helpers/keyIncrementer.ts | 31 +++++++++++ 4 files changed, 159 insertions(+) create mode 100644 assembly/helpers/__tests__/constantKeyManager.spec.ts create mode 100644 assembly/helpers/__tests__/keyIncrementer.spec.ts create mode 100644 assembly/helpers/constantKeyManager.ts create mode 100644 assembly/helpers/keyIncrementer.ts diff --git a/assembly/helpers/__tests__/constantKeyManager.spec.ts b/assembly/helpers/__tests__/constantKeyManager.spec.ts new file mode 100644 index 00000000..2eed5540 --- /dev/null +++ b/assembly/helpers/__tests__/constantKeyManager.spec.ts @@ -0,0 +1,54 @@ +import { Address } from '../../std'; +import { resetStorage } from '../../vm-mock'; +import { u256 } from 'as-bignum/assembly'; +import { ConstantManager } from '../constantKeyManager'; +import { KeyIncrementer } from '../keyIncrementer'; + +beforeEach(() => { + resetStorage(); +}); + +describe('ConstantManager - use cases', () => { + test('executes a basic scenario - one key', () => { + const bins = new ConstantManager>(); + + bins.set([1, 2, 3, 4, 5]); + + expect(bins.mustValue()).toStrictEqual([1, 2, 3, 4, 5]); + }); + + test('executes a basic scenario - multiple keys', () => { + // a key manager instance is needed to generate unique keys + const keyManager = new KeyIncrementer(); + const owner = new ConstantManager
(keyManager); + const fee = new ConstantManager(keyManager); + const usdc = new ConstantManager(keyManager); + + owner.set( + new Address('AU12UBnqTHDQALpocVBnkPNy7y5CndUJQTLutaVDDFgMJcq5kQiKq'), + ); + fee.set(100); + usdc.set(u256.fromU64(1000000)); + + expect(owner.mustValue().toString()).toBe( + 'AU12UBnqTHDQALpocVBnkPNy7y5CndUJQTLutaVDDFgMJcq5kQiKq', + ); + expect(fee.mustValue()).toBe(100); + expect(usdc.mustValue().toString()).toBe('1000000'); + }); +}); + +describe('ConstantManager - unit tests', () => { + test('mustValue - key not found', () => { + expect(() => { + const cst = new ConstantManager(); + cst.mustValue(); + }).toThrow('Key not found'); + }); + + test('tryValue - key not found', () => { + const cst = new ConstantManager>(); + expect(cst.tryValue().isErr()).toBe(true); + expect(cst.tryValue().error).toBe('Key not found'); + }); +}); diff --git a/assembly/helpers/__tests__/keyIncrementer.spec.ts b/assembly/helpers/__tests__/keyIncrementer.spec.ts new file mode 100644 index 00000000..8505e798 --- /dev/null +++ b/assembly/helpers/__tests__/keyIncrementer.spec.ts @@ -0,0 +1,20 @@ +import { KeyIncrementer } from '../keyIncrementer'; +import { resetStorage } from '../../vm-mock'; + +beforeEach(() => { + resetStorage(); +}); + +describe('KeyIncrementer - unit tests', () => { + test('nextKey - u8', () => { + const keyInc = new KeyIncrementer(); + expect(keyInc.nextKey()).toStrictEqual([0]); + expect(keyInc.nextKey()).toStrictEqual([1]); + }); + + test('nextKey - u64', () => { + const keyInc = new KeyIncrementer(); + expect(keyInc.nextKey()).toStrictEqual([0, 0, 0, 0, 0, 0, 0, 0]); + expect(keyInc.nextKey()).toStrictEqual([1, 0, 0, 0, 0, 0, 0, 0]); + }); +}); diff --git a/assembly/helpers/constantKeyManager.ts b/assembly/helpers/constantKeyManager.ts new file mode 100644 index 00000000..9e4989d4 --- /dev/null +++ b/assembly/helpers/constantKeyManager.ts @@ -0,0 +1,54 @@ +import { Args, Result } from '@massalabs/as-types'; +import { KeyIncrementer, KeySequenceManager } from './keyIncrementer'; +import { Storage } from '../std'; + +/** + * Manages a constant value in storage. + * + * @typeParam TValue - The type of the value stored. + * @typeParam TKey - The type of the key used to store the value. + * @typeParam TArray - When value is an array of serializable, the underlying serializable type. + */ +export class ConstantManager { + public key: StaticArray; + + constructor(manager: KeySequenceManager = new KeyIncrementer(0)) { + this.key = manager.nextKey(); + } + + /** + * Retrieves the value from storage and panics in case of failure. + * + * @returns the value stored. + * @throws if the key is not found in storage. + * @throws if the value is not found in storage. + */ + public mustValue(): TValue { + return new Args(Storage.get(this.key)).next().unwrap(); + } + + /** + * Retrieves the value from storage and returns a result. + * + * @returns the value stored wrapped in a result. + */ + public tryValue(): Result { + if (!Storage.has(this.key)) { + if (isManaged()) { + return new Result(instantiate(), 'Key not found'); + } + return new Result(0, 'Key not found'); + } + + return new Args(Storage.get(this.key)).next(); + } + + /** + * Sets the value in storage. + * + * @param value - The value to store. Must be an A + */ + public set(value: TValue): void { + Storage.set(this.key, new Args().add(value).serialize()); + } +} diff --git a/assembly/helpers/keyIncrementer.ts b/assembly/helpers/keyIncrementer.ts new file mode 100644 index 00000000..1830f9dc --- /dev/null +++ b/assembly/helpers/keyIncrementer.ts @@ -0,0 +1,31 @@ +import { Args } from '@massalabs/as-types'; +/** + * Manages key sequences for storage. + */ +export interface KeySequenceManager { + nextKey(): StaticArray; +} + +/** + * A key sequence manager that simply increments a counter each time a key is requested. + * + * @typeParam T - The type of the counter, defaults to `u8`. + */ +export class KeyIncrementer implements KeySequenceManager { + constructor(public counter: T = 0) {} + + /** + * Generates the next key in the sequence. + * + * @remarks + * The `Args` class is used to serialize the counter into a key. Ideally, this serialization should + * be done outside of the `Args` object as we are allocating an object simply to get a proper serialization + * of the counter. + * + * @returns A unique storage key. + */ + @inline + public nextKey(): StaticArray { + return new Args().add(this.counter++).serialize(); + } +} From bc93f1f2b743507894d596047a104b93ac38d29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Libert?= Date: Thu, 23 May 2024 15:10:46 +0200 Subject: [PATCH 3/4] Export helpers --- assembly/helpers/index.ts | 2 ++ assembly/index.ts | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 assembly/helpers/index.ts diff --git a/assembly/helpers/index.ts b/assembly/helpers/index.ts new file mode 100644 index 00000000..bfba27c6 --- /dev/null +++ b/assembly/helpers/index.ts @@ -0,0 +1,2 @@ +export * from './constantKeyManager'; +export * from './keyIncrementer'; diff --git a/assembly/index.ts b/assembly/index.ts index 681e2a3f..3e183629 100644 --- a/assembly/index.ts +++ b/assembly/index.ts @@ -11,6 +11,8 @@ export { env }; import * as security from './security/index'; export { security }; +export * from './helpers/index'; + // massa std functionalities export * from './std'; From aa5d2256a52ca23fcd2b4da11d8f24c9bd5c8010 Mon Sep 17 00:00:00 2001 From: BenRey Date: Thu, 23 May 2024 15:58:25 +0200 Subject: [PATCH 4/4] Update package lock --- package-lock.json | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2b441398..3e94aa20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,6 +68,29 @@ "visitor-as": "^0.11.4" } }, + "node_modules/@as-covers/transform/node_modules/assemblyscript": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.25.2.tgz", + "integrity": "sha512-67TQOMvKo23htvSK6lhOzsoQjnplNKkdwgq925uBvQZLDbg9pHfAWhg/R8i8tqKrtk6GH8haOJbQY4oNSQqehA==", + "dev": true, + "peer": true, + "dependencies": { + "binaryen": "110.0.0-nightly.20221105", + "long": "^5.2.0" + }, + "bin": { + "asc": "bin/asc.js", + "asinit": "bin/asinit.js" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/assemblyscript" + } + }, "node_modules/@as-covers/transform/node_modules/visitor-as": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/visitor-as/-/visitor-as-0.11.4.tgz", @@ -9501,6 +9524,17 @@ "visitor-as": "^0.11.4" }, "dependencies": { + "assemblyscript": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.25.2.tgz", + "integrity": "sha512-67TQOMvKo23htvSK6lhOzsoQjnplNKkdwgq925uBvQZLDbg9pHfAWhg/R8i8tqKrtk6GH8haOJbQY4oNSQqehA==", + "dev": true, + "peer": true, + "requires": { + "binaryen": "110.0.0-nightly.20221105", + "long": "^5.2.0" + } + }, "visitor-as": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/visitor-as/-/visitor-as-0.11.4.tgz", @@ -10387,7 +10421,8 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "aes-js": { "version": "4.0.0-beta.5", @@ -10886,13 +10921,15 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-config-prettier": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", - "dev": true + "dev": true, + "requires": {} }, "eslint-plugin-jsdoc": { "version": "39.9.1", @@ -16527,7 +16564,8 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} }, "yallist": { "version": "4.0.0",