Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 289 additions & 0 deletions packages/jammin-sdk/config/config-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,295 @@ describe("Validate Build Config", () => {
});
});

describe("Preimage Blobs Config Validation", () => {
test("Should parse valid preimage_blobs config", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_blobs: {
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xdeadbeef",
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": "0xadadadadad",
},
},
},
},
};

const result = validateBuildConfig(config);
expect(result.deployment?.services?.["auth-service"]?.preimageBlobs).toEqual({
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xdeadbeef",
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": "0xadadadadad",
});
});

test("Should reject preimage_blobs with hash missing 0x prefix", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_blobs: {
"0000000000000000000000000000000000000000000000000000000000000001": "0x1234",
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});

test("Should reject preimage_blobs with blob missing 0x prefix", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_blobs: {
"0x0000000000000000000000000000000000000000000000000000000000000001": "deadbeef",
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});

test("Should reject preimage_blobs with blob consisting of an uneven number of characters", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_blobs: {
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xabc",
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});

test("Should reject preimage_blobs where hash is not 32 bytes long", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_blobs: {
"0x00000000000000000000000000000001": "0xdeadbeef", // 16 bytes instead of 32
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});
});

describe("Preimage Requests Config Validation", () => {
test("Should parse valid preimage_requests config", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_requests: {
"0x0000000000000000000000000000000000000000000000000000000000000001": [100, 200, 300],
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": [42],
},
},
},
},
};

const result = validateBuildConfig(config);
expect(result.deployment?.services?.["auth-service"]?.preimageRequests).toEqual({
"0x0000000000000000000000000000000000000000000000000000000000000001": [100, 200, 300],
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890": [42],
});
});

test("Should accept preimage_requests with empty array", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_requests: {
"0x0000000000000000000000000000000000000000000000000000000000000001": [],
},
},
},
},
};

const result = validateBuildConfig(config);
expect(result.deployment?.services?.["auth-service"]?.preimageRequests).toEqual({
"0x0000000000000000000000000000000000000000000000000000000000000001": [],
});
});

test("Should accept preimage_requests with 1, 2, and 3 time slots", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_requests: {
"0x0000000000000000000000000000000000000000000000000000000000000001": [1],
"0x0000000000000000000000000000000000000000000000000000000000000002": [1, 2],
"0x0000000000000000000000000000000000000000000000000000000000000003": [1, 2, 3],
},
},
},
},
};

const result = validateBuildConfig(config);
const preimageRequests = result.deployment?.services?.["auth-service"]?.preimageRequests;
expect(preimageRequests?.["0x0000000000000000000000000000000000000000000000000000000000000001"]).toEqual([1]);
expect(preimageRequests?.["0x0000000000000000000000000000000000000000000000000000000000000002"]).toEqual([1, 2]);
expect(preimageRequests?.["0x0000000000000000000000000000000000000000000000000000000000000003"]).toEqual([
1, 2, 3,
]);
});

test("Should reject preimage_requests with more than 3 time slots", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_requests: {
"0x0000000000000000000000000000000000000000000000000000000000000001": [1, 2, 3, 4],
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});

test("Should reject preimage_requests with non-integer time slot values", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_requests: {
"0x0000000000000000000000000000000000000000000000000000000000000001": [100.5, 200],
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});

test("Should reject preimage_requests with negative time slot values", () => {
const config = {
services: [
{
path: "./services/auth.ts",
name: "auth-service",
sdk: "jam-sdk-0.1.26",
},
],
deployment: {
spawn: "local",
services: {
"auth-service": {
preimage_requests: {
"0x0000000000000000000000000000000000000000000000000000000000000001": [-10, 0, 100],
},
},
},
},
};

expect(() => validateBuildConfig(config)).toThrow();
});
});

describe("Service Info Config Validation", () => {
test("Should parse valid info config with all fields", () => {
const config = {
Expand Down
86 changes: 51 additions & 35 deletions packages/jammin-sdk/config/config-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ const MAX_U64 = 18_446_744_073_709_551_615n;
const u64Schema = () =>
z.union([z.bigint().min(0n).max(MAX_U64), z.number().int().min(0)]).transform((val) => BigInt(val));
const u32Schema = () => z.number().int().min(0).max(MAX_U32);
const preimageHashSchema = () =>
z
.string()
.regex(/^0x[0-9a-fA-F]+$/)
.length(66);

// jammin.build.yml schema

Expand All @@ -30,41 +35,52 @@ const ServiceConfigSchema = z.object({
),
});

const ServiceDeploymentConfigSchema = z.object({
id: u32Schema().optional(),
storage: z.record(z.string(), z.string()).optional(),
info: z
.object({
balance: u64Schema().optional(),
accumulate_min_gas: u64Schema().optional(),
on_transfer_min_gas: u64Schema().optional(),
storage_utilisation_bytes: u64Schema().optional(),
gratis_storage: u64Schema().optional(),
storage_utilisation_count: u32Schema().optional(),
created: u32Schema().optional(),
last_accumulation: u32Schema().optional(),
parent_service: u32Schema().optional(),
})
.transform((info) => {
// snake to camel case
if (!info) {
return undefined;
}
const transformed = {
balance: info.balance,
accumulateMinGas: info.accumulate_min_gas,
onTransferMinGas: info.on_transfer_min_gas,
storageUtilisationBytes: info.storage_utilisation_bytes,
gratisStorage: info.gratis_storage,
storageUtilisationCount: info.storage_utilisation_count,
created: info.created,
lastAccumulation: info.last_accumulation,
parentService: info.parent_service,
};
return transformed;
})
.optional(),
});
const ServiceDeploymentConfigSchema = z
.object({
id: u32Schema().optional(),
storage: z.record(z.string(), z.string()).optional(),
preimage_blobs: z.record(preimageHashSchema(), z.string().regex(/^0x([0-9a-fA-F]{2})+$/)).optional(),
preimage_requests: z.record(preimageHashSchema(), z.array(u32Schema()).max(3)).optional(),
info: z
.object({
balance: u64Schema().optional(),
accumulate_min_gas: u64Schema().optional(),
on_transfer_min_gas: u64Schema().optional(),
storage_utilisation_bytes: u64Schema().optional(),
gratis_storage: u64Schema().optional(),
storage_utilisation_count: u32Schema().optional(),
created: u32Schema().optional(),
last_accumulation: u32Schema().optional(),
parent_service: u32Schema().optional(),
})
.transform((info) => {
// snake to camel case
if (!info) {
return undefined;
}
const transformed = {
balance: info.balance,
accumulateMinGas: info.accumulate_min_gas,
onTransferMinGas: info.on_transfer_min_gas,
storageUtilisationBytes: info.storage_utilisation_bytes,
gratisStorage: info.gratis_storage,
storageUtilisationCount: info.storage_utilisation_count,
created: info.created,
lastAccumulation: info.last_accumulation,
parentService: info.parent_service,
};
return transformed;
})
.optional(),
})
.transform((config) => {
const { preimage_blobs, preimage_requests, ...rest } = config;
return {
...rest,
preimageBlobs: preimage_blobs,
preimageRequests: preimage_requests,
};
});

const DeploymentConfigSchema = z.object({
spawn: z.string().min(1),
Expand Down
Loading
Loading