From 503c35b9a782af58bb9cbc9f165e1697241c1002 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 15:21:30 -0400 Subject: [PATCH 1/9] test: add v1 contract fixture and test case --- .../tests/unit/data-contract.spec.mjs | 27 +- ... => data-contract-v0-crypto-card-game.mjs} | 0 ...ta-contract-v1-with-docs-tokens-groups.mjs | 283 ++++++++++++++++++ 3 files changed, 304 insertions(+), 6 deletions(-) rename packages/wasm-sdk/tests/unit/fixtures/{data-contract-crypto-card-game.mjs => data-contract-v0-crypto-card-game.mjs} (100%) create mode 100644 packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index e04eb4f21c4..ba64df6294a 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -1,22 +1,37 @@ import init, * as sdk from '../../dist/sdk.compressed.js'; -import contractFixture from './fixtures/data-contract-crypto-card-game.mjs'; +import contractFixtureV0 from './fixtures/data-contract-v0-crypto-card-game.mjs'; +import contractFixtureV1 from './fixtures/data-contract-v1-with-docs-tokens-groups.mjs'; -const PLATFORM_VERSION = 1; +const PLATFORM_VERSION_CONTRACT_V0 = 1; +const PLATFORM_VERSION_CONTRACT_V1 = 9; // V1 contracts introduced in Platform v9 describe('DataContract', () => { before(async () => { await init(); }); - it('should create a contract from JSON and expose identifiers', async () => { - const contract = sdk.DataContract.fromJSON(contractFixture, PLATFORM_VERSION); + it('should create a V0 contract from JSON and expose identifiers', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); expect(contract).to.be.ok(); - expect(contract.id()).to.equal(contractFixture.id); + expect(contract.id()).to.equal(contractFixtureV0.id); const roundTripped = contract.toJSON(); expect(roundTripped).to.be.an('object'); - expect(roundTripped.id).to.equal(contractFixture.id); + expect(roundTripped.id).to.equal(contractFixtureV0.id); + + contract.free(); + }); + + it('should create a V1 contract from JSON and expose identifiers', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); + + expect(contract).to.be.ok(); + expect(contract.id()).to.equal(contractFixtureV1.id); + + const roundTripped = contract.toJSON(); + expect(roundTripped).to.be.an('object'); + expect(roundTripped.id).to.equal(contractFixtureV1.id); contract.free(); }); diff --git a/packages/wasm-sdk/tests/unit/fixtures/data-contract-crypto-card-game.mjs b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v0-crypto-card-game.mjs similarity index 100% rename from packages/wasm-sdk/tests/unit/fixtures/data-contract-crypto-card-game.mjs rename to packages/wasm-sdk/tests/unit/fixtures/data-contract-v0-crypto-card-game.mjs diff --git a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs new file mode 100644 index 00000000000..91d2f308242 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs @@ -0,0 +1,283 @@ +const contract = { + $format_version: '1', + id: 'Afk9QSj9UDE14K1y9y3iSx6kUSm5LLmhbdAvPvWL4P2i', + config: { + $format_version: '1', + canBeDeleted: false, + readonly: false, + keepsHistory: false, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + documentsCanBeDeletedContractDefault: true, + requiresIdentityEncryptionBoundedKey: null, + requiresIdentityDecryptionBoundedKey: null, + sizedIntegerTypes: true + }, + version: 1, + ownerId: '7XcruVSsGQVSgTcmPewaE4tXLutnW1F6PXxwMbo8GYQC', + schemaDefs: null, + documentSchemas: { + card: { + type: 'object', + documentsMutable: false, + canBeDeleted: true, + transferable: 1, + tradeMode: 1, + creationRestrictionMode: 1, + properties: { + name: { + type: 'string', + description: 'Name of the card', + minLength: 0, + maxLength: 63, + position: 0 + }, + description: { + type: 'string', + description: 'Description of the card', + minLength: 0, + maxLength: 256, + position: 1 + }, + attack: { + type: 'integer', + description: 'Attack power of the card', + position: 2 + }, + defense: { + type: 'integer', + description: 'Defense level of the card', + position: 3 + } + }, + indices: [ + { + name: 'owner', + properties: [ + { + $ownerId: 'asc' + } + ] + }, + { + name: 'attack', + properties: [ + { + attack: 'asc' + } + ] + }, + { + name: 'defense', + properties: [ + { + defense: 'asc' + } + ] + } + ], + required: [ + 'name', + 'attack', + 'defense' + ], + additionalProperties: false + } + }, + createdAt: 1756237255149, + updatedAt: null, + createdAtBlockHeight: 174305, + updatedAtBlockHeight: null, + createdAtEpoch: 9690, + updatedAtEpoch: null, + groups: { + '0': { + $format_version: '0', + members: { + '7XcruVSsGQVSgTcmPewaE4tXLutnW1F6PXxwMbo8GYQC': 1, + 'HJDxtN6FJF3U3T9TMLWCqudfJ5VRkaUrxTsRp36djXAG': 1 + }, + required_power: 2 + } + }, + tokens: { + '0': { + $format_version: '0', + conventions: { + $format_version: '0', + localizations: { + en: { + $format_version: '0', + shouldCapitalize: true, + singularForm: 'stt-99', + pluralForm: 'stt-99s' + } + }, + decimals: 0 + }, + conventionsChangeRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + baseSupply: 100, + maxSupply: null, + keepsHistory: { + $format_version: '0', + keepsTransferHistory: true, + keepsFreezingHistory: true, + keepsMintingHistory: true, + keepsBurningHistory: true, + keepsDirectPricingHistory: true, + keepsDirectPurchaseHistory: true + }, + startAsPaused: false, + allowTransferToFrozenBalance: true, + maxSupplyChangeRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + distributionRules: { + $format_version: '0', + perpetualDistribution: { + $format_version: '0', + distributionType: { + BlockBasedDistribution: { + interval: 100, + function: { + FixedAmount: { + amount: 1 + } + } + } + }, + distributionRecipient: 'ContractOwner' + }, + perpetualDistributionRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + preProgrammedDistribution: null, + newTokensDestinationIdentity: '7XcruVSsGQVSgTcmPewaE4tXLutnW1F6PXxwMbo8GYQC', + newTokensDestinationIdentityRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + mintingAllowChoosingDestination: false, + mintingAllowChoosingDestinationRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + changeDirectPurchasePricingRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + } + }, + marketplaceRules: { + $format_version: '0', + tradeMode: 'NotTradeable', + tradeModeChangeRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + } + }, + manualMintingRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + manualBurningRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + freezeRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + unfreezeRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + destroyFrozenFundsRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + emergencyActionRules: { + V0: { + authorized_to_make_change: 'ContractOwner', + admin_action_takers: 'ContractOwner', + changing_authorized_action_takers_to_no_one_allowed: true, + changing_admin_action_takers_to_no_one_allowed: true, + self_changing_admin_action_takers_allowed: true + } + }, + mainControlGroup: 0, + mainControlGroupCanBeModified: 'ContractOwner', + description: null + } + }, + keywords: [ + 'stt-99' + ], + description: null +} + +export default contract; \ No newline at end of file From 957e312c001b9770908cab3292947ed590c2c608 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 15:38:53 -0400 Subject: [PATCH 2/9] test: improve data contract test coverage and assertions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add comprehensive property validation for V0 and V1 contracts - Test document schemas, config, and metadata fields - Add memory management tests with multiple contract instances - Include JSON round-trip preservation tests - Add defensive assertions for V1-specific features - Comment out problematic assertions for WASM layer investigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../tests/unit/data-contract.spec.mjs | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index ba64df6294a..fc650471ffc 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -10,7 +10,7 @@ describe('DataContract', () => { await init(); }); - it('should create a V0 contract from JSON and expose identifiers', async () => { + it('should create a V0 contract from JSON and expose all properties', async () => { const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); expect(contract).to.be.ok(); @@ -19,11 +19,23 @@ describe('DataContract', () => { const roundTripped = contract.toJSON(); expect(roundTripped).to.be.an('object'); expect(roundTripped.id).to.equal(contractFixtureV0.id); + expect(roundTripped.ownerId).to.equal(contractFixtureV0.ownerId); + expect(roundTripped.version).to.equal(contractFixtureV0.version); + expect(roundTripped.$format_version).to.equal(contractFixtureV0.$format_version); + expect(roundTripped.config).to.deep.equal(contractFixtureV0.config); + expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV0.documentSchemas); + + // Verify document schema structure + expect(roundTripped.documentSchemas.card).to.exist; + expect(roundTripped.documentSchemas.card.properties.name).to.exist; + expect(roundTripped.documentSchemas.card.properties.rarity.enum).to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); + expect(roundTripped.documentSchemas.card.indices).to.have.length(2); contract.free(); }); - it('should create a V1 contract from JSON and expose identifiers', async () => { + // TODO: Re-enable following once PR 2794 or similar fixes underlying issue + it.skip('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); expect(contract).to.be.ok(); @@ -32,7 +44,69 @@ describe('DataContract', () => { const roundTripped = contract.toJSON(); expect(roundTripped).to.be.an('object'); expect(roundTripped.id).to.equal(contractFixtureV1.id); + expect(roundTripped.ownerId).to.equal(contractFixtureV1.ownerId); + expect(roundTripped.version).to.equal(contractFixtureV1.version); + expect(roundTripped.$format_version).to.equal(contractFixtureV1.$format_version); + expect(roundTripped.config.sizedIntegerTypes).to.be.true; + expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV1.documentSchemas); + + // Verify V1-specific features + expect(roundTripped.tokens).to.exist; + expect(roundTripped.tokens['0']).to.exist; + expect(roundTripped.tokens['0'].baseSupply).to.equal(100); + expect(roundTripped.tokens['0'].conventions.decimals).to.equal(0); + + expect(roundTripped.groups).to.exist; + expect(roundTripped.groups['0']).to.exist; + expect(roundTripped.groups['0'].required_power).to.equal(2); + + expect(roundTripped.keywords).to.deep.equal(contractFixtureV1.keywords); contract.free(); }); + + it('should fail to create a V1 contract with V0 platform version', async () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(/dpp unknown version.*known versions.*\[0\].*received.*1/); + }); + + it('should handle memory management properly with multiple contracts', async () => { + const contract1 = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + const contract2 = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); + + expect(contract1.id()).to.equal(contractFixtureV0.id); + expect(contract2.id()).to.equal(contractFixtureV1.id); + + contract1.free(); + contract2.free(); + }); + + it('should preserve all data through JSON round-trip for V0 contract', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + const roundTripped = contract.toJSON(); + + // Create a new contract from the round-tripped JSON + const contract2 = sdk.DataContract.fromJSON(roundTripped, PLATFORM_VERSION_CONTRACT_V0); + const roundTripped2 = contract2.toJSON(); + + expect(roundTripped2).to.deep.equal(roundTripped); + + contract.free(); + contract2.free(); + }); + + it('should preserve all data through JSON round-trip for V1 contract', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); + const roundTripped = contract.toJSON(); + + // Create a new contract from the round-tripped JSON + const contract2 = sdk.DataContract.fromJSON(roundTripped, PLATFORM_VERSION_CONTRACT_V1); + const roundTripped2 = contract2.toJSON(); + + expect(roundTripped2).to.deep.equal(roundTripped); + + contract.free(); + contract2.free(); + }); }); From 310623ecf0c050762362dba41ce3c036714f9228 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 15:57:59 -0400 Subject: [PATCH 3/9] test:add some error and validation cases --- .../tests/unit/data-contract.spec.mjs | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index fc650471ffc..56f5ad5e770 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -108,5 +108,86 @@ describe('DataContract', () => { contract.free(); contract2.free(); - }); + }); + + it('should handle invalid JSON input gracefully', () => { + expect(() => { + sdk.DataContract.fromJSON(null, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + expect(() => { + sdk.DataContract.fromJSON({}, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + expect(() => { + sdk.DataContract.fromJSON({ id: 'invalid' }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should require at least one document type or token', () => { + const contractWithEmptySchemas = { + $format_version: '0', + id: contractFixtureV0.id, + ownerId: contractFixtureV0.ownerId, + version: 1, + config: contractFixtureV0.config, + documentSchemas: {} + }; + + expect(() => { + sdk.DataContract.fromJSON(contractWithEmptySchemas, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(/must have at least one document type or token defined/); + }); + + it('should create a contract with only document schemas (no tokens)', () => { + // V0 fixture already has only documents + const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + const roundTripped = contract.toJSON(); + + expect(roundTripped.documentSchemas.card).to.exist; + expect(roundTripped.tokens).to.be.undefined; + + contract.free(); + }); + + it('should create a contract with only tokens (no documents)', () => { + // Use V1 fixture but remove documentSchemas + const contractWithOnlyTokens = { + ...contractFixtureV1, + documentSchemas: {} + }; + + const contract = sdk.DataContract.fromJSON(contractWithOnlyTokens, PLATFORM_VERSION_CONTRACT_V1); + const roundTripped = contract.toJSON(); + + expect(roundTripped.documentSchemas).to.deep.equal({}); + + contract.free(); + }); + + it('should reject contracts with invalid property values', () => { + // Test invalid Base58 ID + expect(() => { + sdk.DataContract.fromJSON({ + ...contractFixtureV0, + id: 'invalid-not-base58!' + }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + // Test negative version number + expect(() => { + sdk.DataContract.fromJSON({ + ...contractFixtureV0, + version: -1 + }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + // Test invalid ownerId + expect(() => { + sdk.DataContract.fromJSON({ + ...contractFixtureV0, + ownerId: 'not-a-valid-id' + }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); }); From 18e8e609d4f26128c22324c5ae9738c2bb4ac5ce Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 16:04:17 -0400 Subject: [PATCH 4/9] test: organize tests --- .../tests/unit/data-contract.spec.mjs | 334 +++++++++--------- 1 file changed, 172 insertions(+), 162 deletions(-) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index 56f5ad5e770..c58e3e6201a 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -10,184 +10,194 @@ describe('DataContract', () => { await init(); }); - it('should create a V0 contract from JSON and expose all properties', async () => { - const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); - - expect(contract).to.be.ok(); - expect(contract.id()).to.equal(contractFixtureV0.id); - - const roundTripped = contract.toJSON(); - expect(roundTripped).to.be.an('object'); - expect(roundTripped.id).to.equal(contractFixtureV0.id); - expect(roundTripped.ownerId).to.equal(contractFixtureV0.ownerId); - expect(roundTripped.version).to.equal(contractFixtureV0.version); - expect(roundTripped.$format_version).to.equal(contractFixtureV0.$format_version); - expect(roundTripped.config).to.deep.equal(contractFixtureV0.config); - expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV0.documentSchemas); - - // Verify document schema structure - expect(roundTripped.documentSchemas.card).to.exist; - expect(roundTripped.documentSchemas.card.properties.name).to.exist; - expect(roundTripped.documentSchemas.card.properties.rarity.enum).to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); - expect(roundTripped.documentSchemas.card.indices).to.have.length(2); - - contract.free(); + describe('Contract Creation', () => { + it('should create a V0 contract from JSON and expose all properties', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + + expect(contract).to.be.ok(); + expect(contract.id()).to.equal(contractFixtureV0.id); + + const roundTripped = contract.toJSON(); + expect(roundTripped).to.be.an('object'); + expect(roundTripped.id).to.equal(contractFixtureV0.id); + expect(roundTripped.ownerId).to.equal(contractFixtureV0.ownerId); + expect(roundTripped.version).to.equal(contractFixtureV0.version); + expect(roundTripped.$format_version).to.equal(contractFixtureV0.$format_version); + expect(roundTripped.config).to.deep.equal(contractFixtureV0.config); + expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV0.documentSchemas); + + // Verify document schema structure + expect(roundTripped.documentSchemas.card).to.exist; + expect(roundTripped.documentSchemas.card.properties.name).to.exist; + expect(roundTripped.documentSchemas.card.properties.rarity.enum).to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); + expect(roundTripped.documentSchemas.card.indices).to.have.length(2); + + contract.free(); + }); + + // TODO: Re-enable following once PR 2794 or similar fixes underlying issue + it.skip('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); + + expect(contract).to.be.ok(); + expect(contract.id()).to.equal(contractFixtureV1.id); + + const roundTripped = contract.toJSON(); + expect(roundTripped).to.be.an('object'); + expect(roundTripped.id).to.equal(contractFixtureV1.id); + expect(roundTripped.ownerId).to.equal(contractFixtureV1.ownerId); + expect(roundTripped.version).to.equal(contractFixtureV1.version); + expect(roundTripped.$format_version).to.equal(contractFixtureV1.$format_version); + expect(roundTripped.config.sizedIntegerTypes).to.be.true; + expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV1.documentSchemas); + + // Verify V1-specific features + expect(roundTripped.tokens).to.exist; + expect(roundTripped.tokens['0']).to.exist; + expect(roundTripped.tokens['0'].baseSupply).to.equal(100); + expect(roundTripped.tokens['0'].conventions.decimals).to.equal(0); + + expect(roundTripped.groups).to.exist; + expect(roundTripped.groups['0']).to.exist; + expect(roundTripped.groups['0'].required_power).to.equal(2); + + expect(roundTripped.keywords).to.deep.equal(contractFixtureV1.keywords); + + contract.free(); + }); + + it('should create a contract with only document schemas (no tokens)', () => { + // V0 fixture already has only documents, no tokens - verify it works + const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + const roundTripped = contract.toJSON(); + + expect(roundTripped.documentSchemas.card).to.exist; + expect(roundTripped.tokens).to.be.undefined; + + contract.free(); + }); + + it('should create a contract with only tokens (no documents)', () => { + // Use V1 fixture but remove documentSchemas + const contractWithOnlyTokens = { + ...contractFixtureV1, + documentSchemas: {} + }; + + const contract = sdk.DataContract.fromJSON(contractWithOnlyTokens, PLATFORM_VERSION_CONTRACT_V1); + const roundTripped = contract.toJSON(); + + expect(roundTripped.documentSchemas).to.deep.equal({}); + + contract.free(); + }); }); - // TODO: Re-enable following once PR 2794 or similar fixes underlying issue - it.skip('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { - const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); - - expect(contract).to.be.ok(); - expect(contract.id()).to.equal(contractFixtureV1.id); - - const roundTripped = contract.toJSON(); - expect(roundTripped).to.be.an('object'); - expect(roundTripped.id).to.equal(contractFixtureV1.id); - expect(roundTripped.ownerId).to.equal(contractFixtureV1.ownerId); - expect(roundTripped.version).to.equal(contractFixtureV1.version); - expect(roundTripped.$format_version).to.equal(contractFixtureV1.$format_version); - expect(roundTripped.config.sizedIntegerTypes).to.be.true; - expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV1.documentSchemas); - - // Verify V1-specific features - expect(roundTripped.tokens).to.exist; - expect(roundTripped.tokens['0']).to.exist; - expect(roundTripped.tokens['0'].baseSupply).to.equal(100); - expect(roundTripped.tokens['0'].conventions.decimals).to.equal(0); - - expect(roundTripped.groups).to.exist; - expect(roundTripped.groups['0']).to.exist; - expect(roundTripped.groups['0'].required_power).to.equal(2); - - expect(roundTripped.keywords).to.deep.equal(contractFixtureV1.keywords); - - contract.free(); - }); - - it('should fail to create a V1 contract with V0 platform version', async () => { - expect(() => { - sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(/dpp unknown version.*known versions.*\[0\].*received.*1/); - }); - - it('should handle memory management properly with multiple contracts', async () => { - const contract1 = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); - const contract2 = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); - - expect(contract1.id()).to.equal(contractFixtureV0.id); - expect(contract2.id()).to.equal(contractFixtureV1.id); - - contract1.free(); - contract2.free(); + describe('Version Compatibility', () => { + it('should fail to create a V1 contract with V0 platform version', async () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(/dpp unknown version.*known versions.*\[0\].*received.*1/); + }); }); - it('should preserve all data through JSON round-trip for V0 contract', async () => { - const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); - const roundTripped = contract.toJSON(); - - // Create a new contract from the round-tripped JSON - const contract2 = sdk.DataContract.fromJSON(roundTripped, PLATFORM_VERSION_CONTRACT_V0); - const roundTripped2 = contract2.toJSON(); - - expect(roundTripped2).to.deep.equal(roundTripped); - - contract.free(); - contract2.free(); + describe('Validation', () => { + it('should handle invalid JSON input gracefully', () => { + expect(() => { + sdk.DataContract.fromJSON(null, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + expect(() => { + sdk.DataContract.fromJSON({}, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + expect(() => { + sdk.DataContract.fromJSON({ id: 'invalid' }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should reject contracts with invalid property values', () => { + // Test invalid Base58 ID + expect(() => { + sdk.DataContract.fromJSON({ + ...contractFixtureV0, + id: 'invalid-not-base58!' + }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + // Test negative version number + expect(() => { + sdk.DataContract.fromJSON({ + ...contractFixtureV0, + version: -1 + }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + + // Test invalid ownerId + expect(() => { + sdk.DataContract.fromJSON({ + ...contractFixtureV0, + ownerId: 'not-a-valid-id' + }, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should require at least one document type or token', () => { + const contractWithEmptySchemas = { + $format_version: '0', + id: contractFixtureV0.id, + ownerId: contractFixtureV0.ownerId, + version: 1, + config: contractFixtureV0.config, + documentSchemas: {} + }; + + expect(() => { + sdk.DataContract.fromJSON(contractWithEmptySchemas, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(/must have at least one document type or token defined/); + }); }); - it('should preserve all data through JSON round-trip for V1 contract', async () => { - const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); - const roundTripped = contract.toJSON(); - - // Create a new contract from the round-tripped JSON - const contract2 = sdk.DataContract.fromJSON(roundTripped, PLATFORM_VERSION_CONTRACT_V1); - const roundTripped2 = contract2.toJSON(); - - expect(roundTripped2).to.deep.equal(roundTripped); - - contract.free(); - contract2.free(); - }); + describe('Data Preservation', () => { + it('should preserve all data through JSON round-trip for V0 contract', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + const roundTripped = contract.toJSON(); - it('should handle invalid JSON input gracefully', () => { - expect(() => { - sdk.DataContract.fromJSON(null, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); + // Create a new contract from the round-tripped JSON + const contract2 = sdk.DataContract.fromJSON(roundTripped, PLATFORM_VERSION_CONTRACT_V0); + const roundTripped2 = contract2.toJSON(); - expect(() => { - sdk.DataContract.fromJSON({}, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); + expect(roundTripped2).to.deep.equal(roundTripped); - expect(() => { - sdk.DataContract.fromJSON({ id: 'invalid' }, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - }); + contract.free(); + contract2.free(); + }); - it('should require at least one document type or token', () => { - const contractWithEmptySchemas = { - $format_version: '0', - id: contractFixtureV0.id, - ownerId: contractFixtureV0.ownerId, - version: 1, - config: contractFixtureV0.config, - documentSchemas: {} - }; - - expect(() => { - sdk.DataContract.fromJSON(contractWithEmptySchemas, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(/must have at least one document type or token defined/); - }); + it('should preserve all data through JSON round-trip for V1 contract', async () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); + const roundTripped = contract.toJSON(); - it('should create a contract with only document schemas (no tokens)', () => { - // V0 fixture already has only documents - const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); - const roundTripped = contract.toJSON(); + // Create a new contract from the round-tripped JSON + const contract2 = sdk.DataContract.fromJSON(roundTripped, PLATFORM_VERSION_CONTRACT_V1); + const roundTripped2 = contract2.toJSON(); - expect(roundTripped.documentSchemas.card).to.exist; - expect(roundTripped.tokens).to.be.undefined; + expect(roundTripped2).to.deep.equal(roundTripped); - contract.free(); + contract.free(); + contract2.free(); + }); }); - it('should create a contract with only tokens (no documents)', () => { - // Use V1 fixture but remove documentSchemas - const contractWithOnlyTokens = { - ...contractFixtureV1, - documentSchemas: {} - }; + describe('Memory Management', () => { + it('should handle memory management properly with multiple contracts', async () => { + const contract1 = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); + const contract2 = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); - const contract = sdk.DataContract.fromJSON(contractWithOnlyTokens, PLATFORM_VERSION_CONTRACT_V1); - const roundTripped = contract.toJSON(); - - expect(roundTripped.documentSchemas).to.deep.equal({}); - - contract.free(); - }); + expect(contract1.id()).to.equal(contractFixtureV0.id); + expect(contract2.id()).to.equal(contractFixtureV1.id); - it('should reject contracts with invalid property values', () => { - // Test invalid Base58 ID - expect(() => { - sdk.DataContract.fromJSON({ - ...contractFixtureV0, - id: 'invalid-not-base58!' - }, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - - // Test negative version number - expect(() => { - sdk.DataContract.fromJSON({ - ...contractFixtureV0, - version: -1 - }, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - - // Test invalid ownerId - expect(() => { - sdk.DataContract.fromJSON({ - ...contractFixtureV0, - ownerId: 'not-a-valid-id' - }, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); + contract1.free(); + contract2.free(); + }); }); }); From 61cd5212e06c380ae6680e064e6915b7ba25ca94 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 16:14:40 -0400 Subject: [PATCH 5/9] test: add platform version compatibility matrix and eliminate magic values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add comprehensive platform version compatibility testing for V0/V1 contracts - Test V0 contracts across all platform versions (1-10) - Test V1 contracts work on v9+ and fail on v1-8 - Add edge case testing for invalid version numbers - Replace magic values with dynamic version detection - Use LATEST_KNOWN_VERSION for future-proof invalid version testing - Reorganize tests into logical categories with nested describe blocks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../tests/unit/data-contract.spec.mjs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index c58e3e6201a..c714e5f9b34 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -2,9 +2,40 @@ import init, * as sdk from '../../dist/sdk.compressed.js'; import contractFixtureV0 from './fixtures/data-contract-v0-crypto-card-game.mjs'; import contractFixtureV1 from './fixtures/data-contract-v1-with-docs-tokens-groups.mjs'; +// Platform version constants const PLATFORM_VERSION_CONTRACT_V0 = 1; const PLATFORM_VERSION_CONTRACT_V1 = 9; // V1 contracts introduced in Platform v9 +// Platform version compatibility ranges +const V0_COMPATIBLE_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // V0 works across all versions +const V1_COMPATIBLE_VERSIONS = [9, 10]; // V1 only works from version 9+ +const V0_ONLY_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8]; // Versions that only support V0 +const LATEST_KNOWN_VERSION = Math.max(...V0_COMPATIBLE_VERSIONS); // Dynamically determine latest version + +// Helper function for testing contract compatibility across versions +const testContractAcrossVersions = (contractFixture, contractName, compatibleVersions, incompatibleVersions = []) => { + compatibleVersions.forEach(version => { + it(`should work with platform version ${version}`, () => { + const contract = sdk.DataContract.fromJSON(contractFixture, version); + expect(contract).to.be.ok(); + expect(contract.id()).to.equal(contractFixture.id); + + const roundTripped = contract.toJSON(); + expect(roundTripped.id).to.equal(contractFixture.id); + + contract.free(); + }); + }); + + incompatibleVersions.forEach(version => { + it(`should fail with platform version ${version}`, () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixture, version); + }).to.throw(/unknown version|dpp unknown version/); + }); + }); +}; + describe('DataContract', () => { before(async () => { await init(); @@ -200,4 +231,48 @@ describe('DataContract', () => { contract2.free(); }); }); + + describe('Platform Version Compatibility Matrix', () => { + describe('V0 Contract Compatibility', () => { + testContractAcrossVersions(contractFixtureV0, 'V0', V0_COMPATIBLE_VERSIONS); + }); + + describe('V1 Contract Compatibility', () => { + testContractAcrossVersions(contractFixtureV1, 'V1', V1_COMPATIBLE_VERSIONS, V0_ONLY_VERSIONS); + }); + + describe('Edge Cases', () => { + it('should fail with invalid version numbers', () => { + const invalidVersions = [ + 0, // Zero version + -1, // Negative version + LATEST_KNOWN_VERSION + 1, // One beyond latest known + LATEST_KNOWN_VERSION * 10 // Far beyond reasonable range + ]; + + invalidVersions.forEach(version => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV0, version); + }).to.throw(/unknown version/); + }); + }); + + it('should handle version boundary correctly at V9 transition', () => { + // V0 contract should work in V9 (backward compatibility) + const contract = sdk.DataContract.fromJSON(contractFixtureV0, 9); + expect(contract.id()).to.equal(contractFixtureV0.id); + contract.free(); + + // V1 contract should work in V9 (first supported version) + const contractV1 = sdk.DataContract.fromJSON(contractFixtureV1, 9); + expect(contractV1.id()).to.equal(contractFixtureV1.id); + contractV1.free(); + + // V1 contract should fail in V8 (last unsupported version) + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV1, 8); + }).to.throw(/dpp unknown version/); + }); + }); + }); }); From 39f2f7ae3455a6cfbb809508fe0aac77c590ef84 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 16:39:25 -0400 Subject: [PATCH 6/9] test: re-enable failing test Should pass once the 2794 is merged --- packages/wasm-sdk/tests/unit/data-contract.spec.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index c714e5f9b34..6bd35ab7eb1 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -66,8 +66,7 @@ describe('DataContract', () => { contract.free(); }); - // TODO: Re-enable following once PR 2794 or similar fixes underlying issue - it.skip('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { + it('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); expect(contract).to.be.ok(); From 021862ecb0a8055a54e3e490fe3e595658586c6b Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 16:44:38 -0400 Subject: [PATCH 7/9] chore: eof fix --- .../unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs index 91d2f308242..07925c18a63 100644 --- a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs +++ b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs @@ -280,4 +280,4 @@ const contract = { description: null } -export default contract; \ No newline at end of file +export default contract; From 430be3c47d528cce7dfc20851af526558c5a0349 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 7 Oct 2025 17:13:16 -0400 Subject: [PATCH 8/9] chore: lint fixes --- .../tests/unit/data-contract.spec.mjs | 59 ++++---- ...ta-contract-v1-with-docs-tokens-groups.mjs | 132 +++++++++--------- 2 files changed, 100 insertions(+), 91 deletions(-) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index 6bd35ab7eb1..763cf4f810f 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -10,11 +10,16 @@ const PLATFORM_VERSION_CONTRACT_V1 = 9; // V1 contracts introduced in Platform v const V0_COMPATIBLE_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // V0 works across all versions const V1_COMPATIBLE_VERSIONS = [9, 10]; // V1 only works from version 9+ const V0_ONLY_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8]; // Versions that only support V0 -const LATEST_KNOWN_VERSION = Math.max(...V0_COMPATIBLE_VERSIONS); // Dynamically determine latest version +const LATEST_KNOWN_VERSION = Math.max(...V0_COMPATIBLE_VERSIONS); // Helper function for testing contract compatibility across versions -const testContractAcrossVersions = (contractFixture, contractName, compatibleVersions, incompatibleVersions = []) => { - compatibleVersions.forEach(version => { +const testContractAcrossVersions = ( + contractFixture, + contractName, + compatibleVersions, + incompatibleVersions = [], +) => { + compatibleVersions.forEach((version) => { it(`should work with platform version ${version}`, () => { const contract = sdk.DataContract.fromJSON(contractFixture, version); expect(contract).to.be.ok(); @@ -27,7 +32,7 @@ const testContractAcrossVersions = (contractFixture, contractName, compatibleVer }); }); - incompatibleVersions.forEach(version => { + incompatibleVersions.forEach((version) => { it(`should fail with platform version ${version}`, () => { expect(() => { sdk.DataContract.fromJSON(contractFixture, version); @@ -58,9 +63,10 @@ describe('DataContract', () => { expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV0.documentSchemas); // Verify document schema structure - expect(roundTripped.documentSchemas.card).to.exist; - expect(roundTripped.documentSchemas.card.properties.name).to.exist; - expect(roundTripped.documentSchemas.card.properties.rarity.enum).to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); + expect(roundTripped.documentSchemas.card).to.exist(); + expect(roundTripped.documentSchemas.card.properties.name).to.exist(); + expect(roundTripped.documentSchemas.card.properties.rarity.enum) + .to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); expect(roundTripped.documentSchemas.card.indices).to.have.length(2); contract.free(); @@ -78,17 +84,17 @@ describe('DataContract', () => { expect(roundTripped.ownerId).to.equal(contractFixtureV1.ownerId); expect(roundTripped.version).to.equal(contractFixtureV1.version); expect(roundTripped.$format_version).to.equal(contractFixtureV1.$format_version); - expect(roundTripped.config.sizedIntegerTypes).to.be.true; + expect(roundTripped.config.sizedIntegerTypes).to.be.true(); expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV1.documentSchemas); // Verify V1-specific features - expect(roundTripped.tokens).to.exist; - expect(roundTripped.tokens['0']).to.exist; + expect(roundTripped.tokens).to.exist(); + expect(roundTripped.tokens['0']).to.exist(); expect(roundTripped.tokens['0'].baseSupply).to.equal(100); expect(roundTripped.tokens['0'].conventions.decimals).to.equal(0); - expect(roundTripped.groups).to.exist; - expect(roundTripped.groups['0']).to.exist; + expect(roundTripped.groups).to.exist(); + expect(roundTripped.groups['0']).to.exist(); expect(roundTripped.groups['0'].required_power).to.equal(2); expect(roundTripped.keywords).to.deep.equal(contractFixtureV1.keywords); @@ -101,8 +107,8 @@ describe('DataContract', () => { const contract = sdk.DataContract.fromJSON(contractFixtureV0, PLATFORM_VERSION_CONTRACT_V0); const roundTripped = contract.toJSON(); - expect(roundTripped.documentSchemas.card).to.exist; - expect(roundTripped.tokens).to.be.undefined; + expect(roundTripped.documentSchemas.card).to.exist(); + expect(roundTripped.tokens).to.equal(undefined); contract.free(); }); @@ -111,10 +117,13 @@ describe('DataContract', () => { // Use V1 fixture but remove documentSchemas const contractWithOnlyTokens = { ...contractFixtureV1, - documentSchemas: {} + documentSchemas: {}, }; - const contract = sdk.DataContract.fromJSON(contractWithOnlyTokens, PLATFORM_VERSION_CONTRACT_V1); + const contract = sdk.DataContract.fromJSON( + contractWithOnlyTokens, + PLATFORM_VERSION_CONTRACT_V1, + ); const roundTripped = contract.toJSON(); expect(roundTripped.documentSchemas).to.deep.equal({}); @@ -151,7 +160,7 @@ describe('DataContract', () => { expect(() => { sdk.DataContract.fromJSON({ ...contractFixtureV0, - id: 'invalid-not-base58!' + id: 'invalid-not-base58!', }, PLATFORM_VERSION_CONTRACT_V0); }).to.throw(); @@ -159,7 +168,7 @@ describe('DataContract', () => { expect(() => { sdk.DataContract.fromJSON({ ...contractFixtureV0, - version: -1 + version: -1, }, PLATFORM_VERSION_CONTRACT_V0); }).to.throw(); @@ -167,7 +176,7 @@ describe('DataContract', () => { expect(() => { sdk.DataContract.fromJSON({ ...contractFixtureV0, - ownerId: 'not-a-valid-id' + ownerId: 'not-a-valid-id', }, PLATFORM_VERSION_CONTRACT_V0); }).to.throw(); }); @@ -179,7 +188,7 @@ describe('DataContract', () => { ownerId: contractFixtureV0.ownerId, version: 1, config: contractFixtureV0.config, - documentSchemas: {} + documentSchemas: {}, }; expect(() => { @@ -243,13 +252,13 @@ describe('DataContract', () => { describe('Edge Cases', () => { it('should fail with invalid version numbers', () => { const invalidVersions = [ - 0, // Zero version - -1, // Negative version - LATEST_KNOWN_VERSION + 1, // One beyond latest known - LATEST_KNOWN_VERSION * 10 // Far beyond reasonable range + 0, // Zero version + -1, // Negative version + LATEST_KNOWN_VERSION + 1, // One beyond latest known + LATEST_KNOWN_VERSION * 10, // Far beyond reasonable range ]; - invalidVersions.forEach(version => { + invalidVersions.forEach((version) => { expect(() => { sdk.DataContract.fromJSON(contractFixtureV0, version); }).to.throw(/unknown version/); diff --git a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs index 07925c18a63..11d1ae2f6df 100644 --- a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs +++ b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs @@ -11,7 +11,7 @@ const contract = { documentsCanBeDeletedContractDefault: true, requiresIdentityEncryptionBoundedKey: null, requiresIdentityDecryptionBoundedKey: null, - sizedIntegerTypes: true + sizedIntegerTypes: true, }, version: 1, ownerId: '7XcruVSsGQVSgTcmPewaE4tXLutnW1F6PXxwMbo8GYQC', @@ -30,59 +30,59 @@ const contract = { description: 'Name of the card', minLength: 0, maxLength: 63, - position: 0 + position: 0, }, description: { type: 'string', description: 'Description of the card', minLength: 0, maxLength: 256, - position: 1 + position: 1, }, attack: { type: 'integer', description: 'Attack power of the card', - position: 2 + position: 2, }, defense: { type: 'integer', description: 'Defense level of the card', - position: 3 - } + position: 3, + }, }, indices: [ { name: 'owner', properties: [ { - $ownerId: 'asc' - } - ] + $ownerId: 'asc', + }, + ], }, { name: 'attack', properties: [ { - attack: 'asc' - } - ] + attack: 'asc', + }, + ], }, { name: 'defense', properties: [ { - defense: 'asc' - } - ] - } + defense: 'asc', + }, + ], + }, ], required: [ 'name', 'attack', - 'defense' + 'defense', ], - additionalProperties: false - } + additionalProperties: false, + }, }, createdAt: 1756237255149, updatedAt: null, @@ -91,17 +91,17 @@ const contract = { createdAtEpoch: 9690, updatedAtEpoch: null, groups: { - '0': { + 0: { $format_version: '0', members: { '7XcruVSsGQVSgTcmPewaE4tXLutnW1F6PXxwMbo8GYQC': 1, - 'HJDxtN6FJF3U3T9TMLWCqudfJ5VRkaUrxTsRp36djXAG': 1 + HJDxtN6FJF3U3T9TMLWCqudfJ5VRkaUrxTsRp36djXAG: 1, }, - required_power: 2 - } + required_power: 2, + }, }, tokens: { - '0': { + 0: { $format_version: '0', conventions: { $format_version: '0', @@ -110,10 +110,10 @@ const contract = { $format_version: '0', shouldCapitalize: true, singularForm: 'stt-99', - pluralForm: 'stt-99s' - } + pluralForm: 'stt-99s', + }, }, - decimals: 0 + decimals: 0, }, conventionsChangeRules: { V0: { @@ -121,8 +121,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, baseSupply: 100, maxSupply: null, @@ -133,7 +133,7 @@ const contract = { keepsMintingHistory: true, keepsBurningHistory: true, keepsDirectPricingHistory: true, - keepsDirectPurchaseHistory: true + keepsDirectPurchaseHistory: true, }, startAsPaused: false, allowTransferToFrozenBalance: true, @@ -143,8 +143,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, distributionRules: { $format_version: '0', @@ -155,12 +155,12 @@ const contract = { interval: 100, function: { FixedAmount: { - amount: 1 - } - } - } + amount: 1, + }, + }, + }, }, - distributionRecipient: 'ContractOwner' + distributionRecipient: 'ContractOwner', }, perpetualDistributionRules: { V0: { @@ -168,8 +168,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, preProgrammedDistribution: null, newTokensDestinationIdentity: '7XcruVSsGQVSgTcmPewaE4tXLutnW1F6PXxwMbo8GYQC', @@ -179,8 +179,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, mintingAllowChoosingDestination: false, mintingAllowChoosingDestinationRules: { @@ -189,8 +189,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, changeDirectPurchasePricingRules: { V0: { @@ -198,9 +198,9 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } - } + self_changing_admin_action_takers_allowed: true, + }, + }, }, marketplaceRules: { $format_version: '0', @@ -211,9 +211,9 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } - } + self_changing_admin_action_takers_allowed: true, + }, + }, }, manualMintingRules: { V0: { @@ -221,8 +221,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, manualBurningRules: { V0: { @@ -230,8 +230,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, freezeRules: { V0: { @@ -239,8 +239,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, unfreezeRules: { V0: { @@ -248,8 +248,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, destroyFrozenFundsRules: { V0: { @@ -257,8 +257,8 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, emergencyActionRules: { V0: { @@ -266,18 +266,18 @@ const contract = { admin_action_takers: 'ContractOwner', changing_authorized_action_takers_to_no_one_allowed: true, changing_admin_action_takers_to_no_one_allowed: true, - self_changing_admin_action_takers_allowed: true - } + self_changing_admin_action_takers_allowed: true, + }, }, mainControlGroup: 0, mainControlGroupCanBeModified: 'ContractOwner', - description: null - } + description: null, + }, }, keywords: [ - 'stt-99' + 'stt-99', ], - description: null -} + description: null, +}; export default contract; From 83b0785de1db2c8d52ea6002f3e7a4524b469c40 Mon Sep 17 00:00:00 2001 From: thephez Date: Wed, 15 Oct 2025 10:05:29 -0400 Subject: [PATCH 9/9] test: skip test that requires sdk fix for now Once the SDK is fixed, test can be enabled. --- packages/wasm-sdk/tests/unit/data-contract.spec.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs index 763cf4f810f..9f6df0fa5d5 100644 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs @@ -72,7 +72,8 @@ describe('DataContract', () => { contract.free(); }); - it('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { + // TODO: enable test once an SDK fix to support this is merged + it.skip('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { const contract = sdk.DataContract.fromJSON(contractFixtureV1, PLATFORM_VERSION_CONTRACT_V1); expect(contract).to.be.ok();