@akashnetwork/chain-sdk 1.0.0-alpha.4 → 1.0.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/cjs/sdk/chain/createChainNodeSDK.cjs.map +1 -1
  2. package/dist/cjs/sdk/client/createClientFactory.cjs.map +2 -2
  3. package/dist/cjs/sdk/client/createServiceClient.cjs.map +1 -1
  4. package/dist/cjs/sdk/provider/auth/jwt/base64.cjs +6 -2
  5. package/dist/cjs/sdk/provider/auth/jwt/base64.cjs.map +2 -2
  6. package/dist/cjs/sdk/provider/auth/jwt/jwt-token.cjs +2 -2
  7. package/dist/cjs/sdk/provider/auth/jwt/jwt-token.cjs.map +2 -2
  8. package/dist/cjs/sdk/provider/auth/jwt/jwt-token.spec.cjs +4 -2
  9. package/dist/cjs/sdk/provider/auth/jwt/jwt-token.spec.cjs.map +2 -2
  10. package/dist/cjs/sdk/provider/auth/jwt/test/test-utils.cjs.map +2 -2
  11. package/dist/cjs/sdk/provider/auth/jwt/validate-payload.cjs +66 -11
  12. package/dist/cjs/sdk/provider/auth/jwt/validate-payload.cjs.map +2 -2
  13. package/dist/cjs/sdk/provider/auth/jwt/wallet-utils.cjs +1 -7
  14. package/dist/cjs/sdk/provider/auth/jwt/wallet-utils.cjs.map +2 -2
  15. package/dist/cjs/sdk/transport/tx/createStargateClient/createStargateClient.cjs.map +2 -2
  16. package/dist/cjs/sdk/transport/tx/createTxTransport.cjs +8 -1
  17. package/dist/cjs/sdk/transport/tx/createTxTransport.cjs.map +2 -2
  18. package/dist/cjs/sdk/transport/tx/createTxTransport.spec.cjs +20 -0
  19. package/dist/cjs/sdk/transport/tx/createTxTransport.spec.cjs.map +2 -2
  20. package/dist/cjs/sdk/transport/types.cjs.map +1 -1
  21. package/dist/esm/{chunk-ICOYRYBC.js → chunk-6Y3WTRIG.js} +82 -22
  22. package/dist/esm/chunk-6Y3WTRIG.js.map +7 -0
  23. package/dist/esm/index.js +1 -1
  24. package/dist/esm/index.js.map +2 -2
  25. package/dist/esm/index.web.js +1 -1
  26. package/dist/tsconfig.build.tsbuildinfo +1 -1
  27. package/dist/types/sdk/chain/createChainNodeSDK.d.ts +3 -0
  28. package/dist/types/sdk/client/createClientFactory.d.ts +2 -1
  29. package/dist/types/sdk/client/createServiceClient.d.ts +1 -1
  30. package/dist/types/sdk/provider/auth/jwt/base64.d.ts +4 -0
  31. package/dist/types/sdk/provider/auth/jwt/test/test-utils.d.ts +9 -2
  32. package/dist/types/sdk/provider/auth/jwt/validate-payload.d.ts +19 -1
  33. package/dist/types/sdk/provider/auth/jwt/wallet-utils.d.ts +0 -1
  34. package/dist/types/sdk/transport/tx/createStargateClient/createStargateClient.d.ts +8 -0
  35. package/dist/types/sdk/transport/types.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/dist/esm/chunk-ICOYRYBC.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/sdk/chain/createChainNodeSDK.ts"],
4
- "sourcesContent": ["import type { GeneratedType } from \"@cosmjs/proto-signing\";\n\nimport { createSDK as createCosmosSDK, serviceLoader as cosmosServiceLoader } from \"../../generated/createCosmosSDK.ts\";\nimport { createSDK as createNodeSDK, serviceLoader as nodeServiceLoader } from \"../../generated/createNodeSDK.ts\";\nimport { patches as cosmosPatches } from \"../../generated/patches/cosmosCustomTypePatches.ts\";\nimport { patches as nodePatches } from \"../../generated/patches/nodeCustomTypePatches.ts\";\nimport { TxRaw } from \"../../generated/protos/cosmos/tx/v1beta1/tx.ts\";\nimport { createMessageType } from \"../client/createServiceLoader.ts\";\nimport type { MessageDesc } from \"../client/types.ts\";\nimport { createNoopTransport } from \"../transport/createNoopTransport.ts\";\nimport { createGrpcTransport } from \"../transport/grpc/createGrpcTransport.ts\";\nimport type { StargateClientOptions } from \"../transport/tx/createStargateClient/createStargateClient.ts\";\nimport { createStargateClient } from \"../transport/tx/createStargateClient/createStargateClient.ts\";\nimport { createTxTransport } from \"../transport/tx/createTxTransport.ts\";\nimport type { Transport, TxCallOptions } from \"../transport/types.ts\";\n\nexport type { PayloadOf, ResponseOf } from \"../types.ts\";\n\nexport function createChainNodeSDK(options: ChainNodeSDKOptions) {\n const queryTransport = createGrpcTransport({\n baseUrl: options.query.baseUrl,\n });\n let txTransport: Transport<TxCallOptions>;\n\n if (options.tx) {\n const { builtInTypes, ...txOptions } = options.tx;\n const defaultRegistryTypes = [\n createMessageType(TxRaw),\n ...(builtInTypes ?? []).map(createMessageType),\n ].reduce<Record<string, GeneratedType>>((acc, type) => {\n acc[type.typeUrl] = type;\n return acc;\n }, {});\n const getMessageType: StargateClientOptions[\"getMessageType\"] = (typeUrl) => nodeServiceLoader.getLoadedType(typeUrl) || cosmosServiceLoader.getLoadedType(typeUrl) || defaultRegistryTypes[typeUrl];\n txTransport = createTxTransport({\n getMessageType,\n client: createStargateClient({\n ...txOptions,\n getMessageType,\n }),\n });\n } else {\n txTransport = createNoopTransport({\n unaryErrorMessage: `Unable to sign transaction. \"tx\" option is not provided during chain SDK creation`,\n });\n }\n const nodeSDK = createNodeSDK(queryTransport, txTransport, {\n clientOptions: { typePatches: { ...cosmosPatches, ...nodePatches } },\n });\n const cosmosSDK = createCosmosSDK(queryTransport, txTransport, {\n clientOptions: { typePatches: cosmosPatches },\n });\n return { ...nodeSDK, ...cosmosSDK };\n}\n\nexport interface ChainNodeSDKOptions {\n query: {\n /**\n * Blockchain gRPC endpoint\n */\n baseUrl: string;\n };\n tx?: Omit<StargateClientOptions, \"getMessageType\" | \"builtInTypes\"> & {\n builtInTypes?: MessageDesc[];\n };\n}\n"],
4
+ "sourcesContent": ["import type { GeneratedType } from \"@cosmjs/proto-signing\";\n\nimport { createSDK as createCosmosSDK, serviceLoader as cosmosServiceLoader } from \"../../generated/createCosmosSDK.ts\";\nimport { createSDK as createNodeSDK, serviceLoader as nodeServiceLoader } from \"../../generated/createNodeSDK.ts\";\nimport { patches as cosmosPatches } from \"../../generated/patches/cosmosCustomTypePatches.ts\";\nimport { patches as nodePatches } from \"../../generated/patches/nodeCustomTypePatches.ts\";\nimport { TxRaw } from \"../../generated/protos/cosmos/tx/v1beta1/tx.ts\";\nimport { createMessageType } from \"../client/createServiceLoader.ts\";\nimport type { MessageDesc } from \"../client/types.ts\";\nimport { createNoopTransport } from \"../transport/createNoopTransport.ts\";\nimport { createGrpcTransport } from \"../transport/grpc/createGrpcTransport.ts\";\nimport type { StargateClientOptions } from \"../transport/tx/createStargateClient/createStargateClient.ts\";\nimport { createStargateClient } from \"../transport/tx/createStargateClient/createStargateClient.ts\";\nimport { createTxTransport } from \"../transport/tx/createTxTransport.ts\";\nimport type { Transport, TxCallOptions } from \"../transport/types.ts\";\n\nexport type { PayloadOf, ResponseOf } from \"../types.ts\";\n\nexport function createChainNodeSDK(options: ChainNodeSDKOptions) {\n const queryTransport = createGrpcTransport({\n baseUrl: options.query.baseUrl,\n });\n let txTransport: Transport<TxCallOptions>;\n\n if (options.tx) {\n const { builtInTypes, ...txOptions } = options.tx;\n const defaultRegistryTypes = [\n createMessageType(TxRaw),\n ...(builtInTypes ?? []).map(createMessageType),\n ].reduce<Record<string, GeneratedType>>((acc, type) => {\n acc[type.typeUrl] = type;\n return acc;\n }, {});\n const getMessageType: StargateClientOptions[\"getMessageType\"] = (typeUrl) => nodeServiceLoader.getLoadedType(typeUrl) || cosmosServiceLoader.getLoadedType(typeUrl) || defaultRegistryTypes[typeUrl];\n txTransport = createTxTransport({\n getMessageType,\n client: createStargateClient({\n ...txOptions,\n getMessageType,\n }),\n });\n } else {\n txTransport = createNoopTransport({\n unaryErrorMessage: `Unable to sign transaction. \"tx\" option is not provided during chain SDK creation`,\n });\n }\n const nodeSDK = createNodeSDK(queryTransport, txTransport, {\n clientOptions: { typePatches: { ...cosmosPatches, ...nodePatches } },\n });\n const cosmosSDK = createCosmosSDK(queryTransport, txTransport, {\n clientOptions: { typePatches: cosmosPatches },\n });\n return { ...nodeSDK, ...cosmosSDK };\n}\n\nexport interface ChainNodeSDKOptions {\n query: {\n /**\n * Blockchain gRPC endpoint\n */\n baseUrl: string;\n };\n tx?: Omit<StargateClientOptions, \"getMessageType\" | \"builtInTypes\"> & {\n /**\n * Additional protobuf message types to register with the transaction transport\n */\n builtInTypes?: MessageDesc[];\n };\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,6BAAmF;AACnF,2BAA+E;AAC/E,qCAAyC;AACzC,mCAAuC;AACvC,gBAAsB;AACtB,iCAAkC;AAElC,iCAAoC;AACpC,iCAAoC;AAEpC,kCAAqC;AACrC,+BAAkC;AAK3B,SAAS,mBAAmB,SAA8B;AAC/D,QAAM,qBAAiB,gDAAoB;AAAA,IACzC,SAAS,QAAQ,MAAM;AAAA,EACzB,CAAC;AACD,MAAI;AAEJ,MAAI,QAAQ,IAAI;AACd,UAAM,EAAE,cAAc,GAAG,UAAU,IAAI,QAAQ;AAC/C,UAAM,uBAAuB;AAAA,UAC3B,8CAAkB,eAAK;AAAA,MACvB,IAAI,gBAAgB,CAAC,GAAG,IAAI,4CAAiB;AAAA,IAC/C,EAAE,OAAsC,CAAC,KAAK,SAAS;AACrD,UAAI,KAAK,OAAO,IAAI;AACpB,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AACL,UAAM,iBAA0D,CAAC,YAAY,qBAAAA,cAAkB,cAAc,OAAO,KAAK,uBAAAC,cAAoB,cAAc,OAAO,KAAK,qBAAqB,OAAO;AACnM,sBAAc,4CAAkB;AAAA,MAC9B;AAAA,MACA,YAAQ,kDAAqB;AAAA,QAC3B,GAAG;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,OAAO;AACL,sBAAc,gDAAoB;AAAA,MAChC,mBAAmB;AAAA,IACrB,CAAC;AAAA,EACH;AACA,QAAM,cAAU,qBAAAC,WAAc,gBAAgB,aAAa;AAAA,IACzD,eAAe,EAAE,aAAa,EAAE,GAAG,+BAAAC,SAAe,GAAG,6BAAAC,QAAY,EAAE;AAAA,EACrE,CAAC;AACD,QAAM,gBAAY,uBAAAC,WAAgB,gBAAgB,aAAa;AAAA,IAC7D,eAAe,EAAE,aAAa,+BAAAF,QAAc;AAAA,EAC9C,CAAC;AACD,SAAO,EAAE,GAAG,SAAS,GAAG,UAAU;AACpC;",
6
6
  "names": ["nodeServiceLoader", "cosmosServiceLoader", "createNodeSDK", "cosmosPatches", "nodePatches", "createCosmosSDK"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/sdk/client/createClientFactory.ts"],
4
- "sourcesContent": ["import type { Transport } from \"../transport/types.ts\";\nimport type { Client, ServiceClientOptions } from \"./createServiceClient.ts\";\nimport { createServiceClient } from \"./createServiceClient.ts\";\nimport type { ServiceDesc } from \"./types.ts\";\n\nexport function createClientFactory<TCallOptions>(transport: Transport, options?: ServiceClientOptions) {\n const services: Record<string, Client<ServiceDesc, TCallOptions>> = Object.create(null);\n\n return function getClient<T extends ServiceDesc>(service: T): Client<T, TCallOptions> {\n if (!services[service.typeName]) {\n services[service.typeName] = createServiceClient<T, TCallOptions>(service, transport, options);\n }\n return services[service.typeName] as Client<T, TCallOptions>;\n };\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iCAAoC;AAG7B,SAAS,oBAAkC,WAAsB,SAAgC;AACtG,QAAM,WAA8D,uBAAO,OAAO,IAAI;AAEtF,SAAO,SAAS,UAAiC,SAAqC;AACpF,QAAI,CAAC,SAAS,QAAQ,QAAQ,GAAG;AAC/B,eAAS,QAAQ,QAAQ,QAAI,gDAAqC,SAAS,WAAW,OAAO;AAAA,IAC/F;AACA,WAAO,SAAS,QAAQ,QAAQ;AAAA,EAClC;AACF;",
4
+ "sourcesContent": ["import type { Transport } from \"../transport/types.ts\";\nimport type { Client, ServiceClientOptions } from \"./createServiceClient.ts\";\nimport { createServiceClient } from \"./createServiceClient.ts\";\nimport type { ServiceDesc } from \"./types.ts\";\n\nexport function createClientFactory<TCallOptions>(transport: Transport<TCallOptions>, options?: ServiceClientOptions): ClientFactory<TCallOptions> {\n const services: Record<string, Client<ServiceDesc, TCallOptions>> = Object.create(null);\n\n return function getClient<T extends ServiceDesc>(service: T): Client<T, TCallOptions> {\n if (!services[service.typeName]) {\n services[service.typeName] = createServiceClient<T, TCallOptions>(service, transport, options);\n }\n return services[service.typeName] as Client<T, TCallOptions>;\n };\n}\n\nexport type ClientFactory<TCallOptions> = <T extends ServiceDesc>(service: T) => Client<T, TCallOptions>;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iCAAoC;AAG7B,SAAS,oBAAkC,WAAoC,SAA6D;AACjJ,QAAM,WAA8D,uBAAO,OAAO,IAAI;AAEtF,SAAO,SAAS,UAAiC,SAAqC;AACpF,QAAI,CAAC,SAAS,QAAQ,QAAQ,GAAG;AAC/B,eAAS,QAAQ,QAAQ,QAAI,gDAAqC,SAAS,WAAW,OAAO;AAAA,IAC/F;AACA,WAAO,SAAS,QAAQ,QAAQ;AAAA,EAClC;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/sdk/client/createServiceClient.ts"],
4
- "sourcesContent": ["import type { CallOptions, Transport } from \"../transport/types.ts\";\nimport type { TypePatches } from \"./applyPatches.ts\";\nimport { applyPatches } from \"./applyPatches.ts\";\nimport { createAsyncIterable, handleStreamResponse, mapStream } from \"./stream.ts\";\nimport type { MessageDesc, MessageInitShape, MessageShape, MethodDesc, ServiceDesc } from \"./types.ts\";\n\nexport type Client<Desc extends ServiceDesc, TCallOptions> = {\n [P in keyof Desc[\"methods\"]]:\n Desc[\"methods\"][P] extends MethodDesc<\"server_streaming\"> ? (input: MessageInitShape<Desc[\"methods\"][P][\"input\"]>, options?: TCallOptions) => AsyncIterable<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : Desc[\"methods\"][P] extends MethodDesc<\"client_streaming\"> ? (input: AsyncIterable<MessageInitShape<Desc[\"methods\"][P][\"input\"]>>, options?: TCallOptions) => Promise<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : Desc[\"methods\"][P] extends MethodDesc<\"bidi_streaming\"> ? (input: AsyncIterable<MessageInitShape<Desc[\"methods\"][P][\"input\"]>>, options?: TCallOptions) => AsyncIterable<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : Desc[\"methods\"][P] extends MethodDesc<\"unary\"> | Omit<MethodDesc<\"unary\">, \"kind\"> ? (input: MessageInitShape<Desc[\"methods\"][P][\"input\"]>, options?: TCallOptions) => Promise<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : never;\n};\n\nconst defaultEncoder: MethodOptions = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n encode: (type: MessageDesc<unknown>, value: unknown) => type.fromPartial(value as any),\n decode: (_: MessageDesc<unknown>, value: unknown) => value,\n};\n\nexport function createServiceClient<TSchema extends ServiceDesc, TCallOptions>(\n service: TSchema,\n transport: Transport,\n options?: ServiceClientOptions,\n): Client<TSchema, TCallOptions> {\n const methodOptions: MethodOptions = options?.typePatches\n ? { encode: createEncodeWithPatches(options.typePatches), decode: createDecodeWithPatches(options.typePatches) }\n : defaultEncoder;\n const client: Record<string, ReturnType<typeof createMethod>> = {};\n const methodNames = Object.keys(service.methods);\n for (let i = 0; i < methodNames.length; i++) {\n const methodDesc = service.methods[methodNames[i]];\n client[methodNames[i]] = createMethod(methodDesc as MethodDesc, transport, methodOptions);\n }\n\n return client as Client<TSchema, TCallOptions>;\n}\n\nexport interface ServiceClientOptions {\n typePatches?: TypePatches;\n}\n\nfunction createMethod(methodDesc: MethodDesc, transport: Transport, options: MethodOptions) {\n switch (methodDesc.kind) {\n case \"server_streaming\":\n return createServerStreamingFn(transport, methodDesc as MethodDesc<\"server_streaming\", MessageDesc, MessageDesc>, options);\n case \"client_streaming\":\n return createClientStreamingFn(transport, methodDesc as MethodDesc<\"client_streaming\", MessageDesc, MessageDesc>, options);\n case \"bidi_streaming\":\n return createBiDiStreamingFn(transport, methodDesc as MethodDesc<\"bidi_streaming\", MessageDesc, MessageDesc>, options);\n default:\n return createUnaryFn(transport, methodDesc as MethodDesc<\"unary\", MessageDesc, MessageDesc>, options);\n }\n}\n\ninterface MethodOptions {\n encode(schema: MessageDesc<unknown>, value: unknown): unknown;\n decode(schema: MessageDesc<unknown>, value: unknown): unknown;\n}\n\ntype UnaryFn<I extends MessageDesc<unknown>, O extends MessageDesc<unknown>> = (\n input: MessageInitShape<I>,\n options?: CallOptions,\n) => Promise<MessageShape<O>>;\n\nfunction createUnaryFn<I extends MessageDesc<unknown>, O extends MessageDesc<unknown>>(\n transport: Transport,\n method: MethodDesc<\"unary\", I, O>,\n methodOptions: MethodOptions,\n): UnaryFn<I, O> {\n return async (input, options) => {\n const response = await transport.unary(\n method,\n methodOptions.encode(method.input, input) as MessageInitShape<I>,\n options,\n );\n options?.onHeader?.(response.header);\n options?.onTrailer?.(response.trailer);\n\n return methodOptions.decode(method.output, response.message) as MessageShape<O>;\n };\n}\n\ntype ServerStreamingFn<I extends MessageDesc, O extends MessageDesc> = (\n input: MessageInitShape<I>,\n options?: CallOptions,\n) => AsyncIterable<MessageShape<O>>;\n\nfunction createServerStreamingFn<\n I extends MessageDesc,\n O extends MessageDesc,\n>(\n transport: Transport,\n method: MethodDesc<\"server_streaming\", I, O>,\n methodOptions: MethodOptions,\n): ServerStreamingFn<I, O> {\n return (input, options) => {\n return handleStreamResponse(\n method,\n transport.stream(\n method,\n createAsyncIterable([methodOptions.encode(method.input, input) as MessageInitShape<I>]),\n options,\n ),\n options,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n methodOptions.decode as any,\n );\n };\n}\n\ntype ClientStreamingFn<I extends MessageDesc, O extends MessageDesc> = (\n input: AsyncIterable<MessageInitShape<I>>,\n options?: CallOptions,\n) => Promise<MessageShape<O>>;\n\nfunction createClientStreamingFn<\n I extends MessageDesc,\n O extends MessageDesc,\n>(\n transport: Transport,\n method: MethodDesc<\"client_streaming\", I, O>,\n methodOptions: MethodOptions,\n): ClientStreamingFn<I, O> {\n return async (input, options) => {\n const response = await transport.stream(\n method,\n mapStream(input, (json) => methodOptions.encode(method.input, json) as MessageInitShape<I>),\n options,\n );\n options?.onHeader?.(response.header);\n let singleMessage: MessageShape<O> | undefined;\n let count = 0;\n for await (const message of response.message) {\n singleMessage = message;\n count++;\n }\n if (!singleMessage) {\n throw new Error(\"akash sdk protocol error: missing response message\");\n }\n if (count > 1) {\n throw new Error(\"akash sdk protocol error: received extra messages for client streaming method\");\n }\n options?.onTrailer?.(response.trailer);\n return methodOptions.decode(method.output, singleMessage) as MessageShape<O>;\n };\n}\n\ntype BiDiStreamingFn<I extends MessageDesc, O extends MessageDesc> = (\n input: AsyncIterable<MessageInitShape<I>>,\n options?: CallOptions,\n) => AsyncIterable<MessageShape<O>>;\n\nfunction createBiDiStreamingFn<\n I extends MessageDesc,\n O extends MessageDesc,\n>(\n transport: Transport,\n method: MethodDesc<\"bidi_streaming\", I, O>,\n methodOptions: MethodOptions,\n): BiDiStreamingFn<I, O> {\n return (input, options) => {\n return handleStreamResponse(\n method,\n transport.stream(\n method,\n mapStream(input, (json) => methodOptions.encode(method.input, json) as MessageInitShape<I>),\n options,\n ),\n options,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n methodOptions.decode as any,\n );\n };\n}\n\nconst PATCHED_FROM_JSON_CACHE = new Map<TypePatches, MethodOptions[\"encode\"]>();\nfunction createEncodeWithPatches(patches: TypePatches): MethodOptions[\"encode\"] {\n if (PATCHED_FROM_JSON_CACHE.has(patches)) return PATCHED_FROM_JSON_CACHE.get(patches)!;\n\n const encode: MethodOptions[\"encode\"] = (messageDesc, value) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return applyPatches(\"encode\", messageDesc, messageDesc.fromPartial(value as any), patches);\n };\n PATCHED_FROM_JSON_CACHE.set(patches, encode);\n return encode;\n}\n\nconst PATCHED_TO_JSON_CACHE = new Map<TypePatches, MethodOptions[\"decode\"]>();\nfunction createDecodeWithPatches(patches: TypePatches): MethodOptions[\"decode\"] {\n if (PATCHED_TO_JSON_CACHE.has(patches)) return PATCHED_TO_JSON_CACHE.get(patches)!;\n\n const decode: MethodOptions[\"decode\"] = (schema, message) => {\n return applyPatches(\"decode\", schema, message, patches);\n };\n PATCHED_TO_JSON_CACHE.set(patches, decode);\n return decode;\n}\n"],
4
+ "sourcesContent": ["import type { CallOptions, Transport } from \"../transport/types.ts\";\nimport type { TypePatches } from \"./applyPatches.ts\";\nimport { applyPatches } from \"./applyPatches.ts\";\nimport { createAsyncIterable, handleStreamResponse, mapStream } from \"./stream.ts\";\nimport type { MessageDesc, MessageInitShape, MessageShape, MethodDesc, ServiceDesc } from \"./types.ts\";\n\nexport type Client<Desc extends ServiceDesc, TCallOptions> = {\n [P in keyof Desc[\"methods\"]]:\n Desc[\"methods\"][P] extends MethodDesc<\"server_streaming\"> ? (input: MessageInitShape<Desc[\"methods\"][P][\"input\"]>, options?: TCallOptions) => AsyncIterable<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : Desc[\"methods\"][P] extends MethodDesc<\"client_streaming\"> ? (input: AsyncIterable<MessageInitShape<Desc[\"methods\"][P][\"input\"]>>, options?: TCallOptions) => Promise<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : Desc[\"methods\"][P] extends MethodDesc<\"bidi_streaming\"> ? (input: AsyncIterable<MessageInitShape<Desc[\"methods\"][P][\"input\"]>>, options?: TCallOptions) => AsyncIterable<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : Desc[\"methods\"][P] extends MethodDesc<\"unary\"> | Omit<MethodDesc<\"unary\">, \"kind\"> ? (input: MessageInitShape<Desc[\"methods\"][P][\"input\"]>, options?: TCallOptions) => Promise<MessageShape<Desc[\"methods\"][P][\"output\"]>>\n : never;\n};\n\nconst defaultEncoder: MethodOptions = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n encode: (type: MessageDesc<unknown>, value: unknown) => type.fromPartial(value as any),\n decode: (_: MessageDesc<unknown>, value: unknown) => value,\n};\n\nexport function createServiceClient<TSchema extends ServiceDesc, TCallOptions>(\n service: TSchema,\n transport: Transport<TCallOptions>,\n options?: ServiceClientOptions,\n): Client<TSchema, TCallOptions> {\n const methodOptions: MethodOptions = options?.typePatches\n ? { encode: createEncodeWithPatches(options.typePatches), decode: createDecodeWithPatches(options.typePatches) }\n : defaultEncoder;\n const client: Record<string, ReturnType<typeof createMethod>> = {};\n const methodNames = Object.keys(service.methods);\n for (let i = 0; i < methodNames.length; i++) {\n const methodDesc = service.methods[methodNames[i]];\n client[methodNames[i]] = createMethod(methodDesc as MethodDesc, transport, methodOptions);\n }\n\n return client as Client<TSchema, TCallOptions>;\n}\n\nexport interface ServiceClientOptions {\n typePatches?: TypePatches;\n}\n\nfunction createMethod(methodDesc: MethodDesc, transport: Transport, options: MethodOptions) {\n switch (methodDesc.kind) {\n case \"server_streaming\":\n return createServerStreamingFn(transport, methodDesc as MethodDesc<\"server_streaming\", MessageDesc, MessageDesc>, options);\n case \"client_streaming\":\n return createClientStreamingFn(transport, methodDesc as MethodDesc<\"client_streaming\", MessageDesc, MessageDesc>, options);\n case \"bidi_streaming\":\n return createBiDiStreamingFn(transport, methodDesc as MethodDesc<\"bidi_streaming\", MessageDesc, MessageDesc>, options);\n default:\n return createUnaryFn(transport, methodDesc as MethodDesc<\"unary\", MessageDesc, MessageDesc>, options);\n }\n}\n\ninterface MethodOptions {\n encode(schema: MessageDesc<unknown>, value: unknown): unknown;\n decode(schema: MessageDesc<unknown>, value: unknown): unknown;\n}\n\ntype UnaryFn<I extends MessageDesc<unknown>, O extends MessageDesc<unknown>> = (\n input: MessageInitShape<I>,\n options?: CallOptions,\n) => Promise<MessageShape<O>>;\n\nfunction createUnaryFn<I extends MessageDesc<unknown>, O extends MessageDesc<unknown>>(\n transport: Transport,\n method: MethodDesc<\"unary\", I, O>,\n methodOptions: MethodOptions,\n): UnaryFn<I, O> {\n return async (input, options) => {\n const response = await transport.unary(\n method,\n methodOptions.encode(method.input, input) as MessageInitShape<I>,\n options,\n );\n options?.onHeader?.(response.header);\n options?.onTrailer?.(response.trailer);\n\n return methodOptions.decode(method.output, response.message) as MessageShape<O>;\n };\n}\n\ntype ServerStreamingFn<I extends MessageDesc, O extends MessageDesc> = (\n input: MessageInitShape<I>,\n options?: CallOptions,\n) => AsyncIterable<MessageShape<O>>;\n\nfunction createServerStreamingFn<\n I extends MessageDesc,\n O extends MessageDesc,\n>(\n transport: Transport,\n method: MethodDesc<\"server_streaming\", I, O>,\n methodOptions: MethodOptions,\n): ServerStreamingFn<I, O> {\n return (input, options) => {\n return handleStreamResponse(\n method,\n transport.stream(\n method,\n createAsyncIterable([methodOptions.encode(method.input, input) as MessageInitShape<I>]),\n options,\n ),\n options,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n methodOptions.decode as any,\n );\n };\n}\n\ntype ClientStreamingFn<I extends MessageDesc, O extends MessageDesc> = (\n input: AsyncIterable<MessageInitShape<I>>,\n options?: CallOptions,\n) => Promise<MessageShape<O>>;\n\nfunction createClientStreamingFn<\n I extends MessageDesc,\n O extends MessageDesc,\n>(\n transport: Transport,\n method: MethodDesc<\"client_streaming\", I, O>,\n methodOptions: MethodOptions,\n): ClientStreamingFn<I, O> {\n return async (input, options) => {\n const response = await transport.stream(\n method,\n mapStream(input, (json) => methodOptions.encode(method.input, json) as MessageInitShape<I>),\n options,\n );\n options?.onHeader?.(response.header);\n let singleMessage: MessageShape<O> | undefined;\n let count = 0;\n for await (const message of response.message) {\n singleMessage = message;\n count++;\n }\n if (!singleMessage) {\n throw new Error(\"akash sdk protocol error: missing response message\");\n }\n if (count > 1) {\n throw new Error(\"akash sdk protocol error: received extra messages for client streaming method\");\n }\n options?.onTrailer?.(response.trailer);\n return methodOptions.decode(method.output, singleMessage) as MessageShape<O>;\n };\n}\n\ntype BiDiStreamingFn<I extends MessageDesc, O extends MessageDesc> = (\n input: AsyncIterable<MessageInitShape<I>>,\n options?: CallOptions,\n) => AsyncIterable<MessageShape<O>>;\n\nfunction createBiDiStreamingFn<\n I extends MessageDesc,\n O extends MessageDesc,\n>(\n transport: Transport,\n method: MethodDesc<\"bidi_streaming\", I, O>,\n methodOptions: MethodOptions,\n): BiDiStreamingFn<I, O> {\n return (input, options) => {\n return handleStreamResponse(\n method,\n transport.stream(\n method,\n mapStream(input, (json) => methodOptions.encode(method.input, json) as MessageInitShape<I>),\n options,\n ),\n options,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n methodOptions.decode as any,\n );\n };\n}\n\nconst PATCHED_FROM_JSON_CACHE = new Map<TypePatches, MethodOptions[\"encode\"]>();\nfunction createEncodeWithPatches(patches: TypePatches): MethodOptions[\"encode\"] {\n if (PATCHED_FROM_JSON_CACHE.has(patches)) return PATCHED_FROM_JSON_CACHE.get(patches)!;\n\n const encode: MethodOptions[\"encode\"] = (messageDesc, value) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return applyPatches(\"encode\", messageDesc, messageDesc.fromPartial(value as any), patches);\n };\n PATCHED_FROM_JSON_CACHE.set(patches, encode);\n return encode;\n}\n\nconst PATCHED_TO_JSON_CACHE = new Map<TypePatches, MethodOptions[\"decode\"]>();\nfunction createDecodeWithPatches(patches: TypePatches): MethodOptions[\"decode\"] {\n if (PATCHED_TO_JSON_CACHE.has(patches)) return PATCHED_TO_JSON_CACHE.get(patches)!;\n\n const decode: MethodOptions[\"decode\"] = (schema, message) => {\n return applyPatches(\"decode\", schema, message, patches);\n };\n PATCHED_TO_JSON_CACHE.set(patches, decode);\n return decode;\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,0BAA6B;AAC7B,oBAAqE;AAYrE,MAAM,iBAAgC;AAAA;AAAA,EAEpC,QAAQ,CAAC,MAA4B,UAAmB,KAAK,YAAY,KAAY;AAAA,EACrF,QAAQ,CAAC,GAAyB,UAAmB;AACvD;AAEO,SAAS,oBACd,SACA,WACA,SAC+B;AAC/B,QAAM,gBAA+B,SAAS,cAC1C,EAAE,QAAQ,wBAAwB,QAAQ,WAAW,GAAG,QAAQ,wBAAwB,QAAQ,WAAW,EAAE,IAC7G;AACJ,QAAM,SAA0D,CAAC;AACjE,QAAM,cAAc,OAAO,KAAK,QAAQ,OAAO;AAC/C,WAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAM,aAAa,QAAQ,QAAQ,YAAY,CAAC,CAAC;AACjD,WAAO,YAAY,CAAC,CAAC,IAAI,aAAa,YAA0B,WAAW,aAAa;AAAA,EAC1F;AAEA,SAAO;AACT;AAMA,SAAS,aAAa,YAAwB,WAAsB,SAAwB;AAC1F,UAAQ,WAAW,MAAM;AAAA,IACvB,KAAK;AACH,aAAO,wBAAwB,WAAW,YAAwE,OAAO;AAAA,IAC3H,KAAK;AACH,aAAO,wBAAwB,WAAW,YAAwE,OAAO;AAAA,IAC3H,KAAK;AACH,aAAO,sBAAsB,WAAW,YAAsE,OAAO;AAAA,IACvH;AACE,aAAO,cAAc,WAAW,YAA6D,OAAO;AAAA,EACxG;AACF;AAYA,SAAS,cACP,WACA,QACA,eACe;AACf,SAAO,OAAO,OAAO,YAAY;AAC/B,UAAM,WAAW,MAAM,UAAU;AAAA,MAC/B;AAAA,MACA,cAAc,OAAO,OAAO,OAAO,KAAK;AAAA,MACxC;AAAA,IACF;AACA,aAAS,WAAW,SAAS,MAAM;AACnC,aAAS,YAAY,SAAS,OAAO;AAErC,WAAO,cAAc,OAAO,OAAO,QAAQ,SAAS,OAAO;AAAA,EAC7D;AACF;AAOA,SAAS,wBAIP,WACA,QACA,eACyB;AACzB,SAAO,CAAC,OAAO,YAAY;AACzB,eAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,QACR;AAAA,YACA,mCAAoB,CAAC,cAAc,OAAO,OAAO,OAAO,KAAK,CAAwB,CAAC;AAAA,QACtF;AAAA,MACF;AAAA,MACA;AAAA;AAAA,MAEA,cAAc;AAAA,IAChB;AAAA,EACF;AACF;AAOA,SAAS,wBAIP,WACA,QACA,eACyB;AACzB,SAAO,OAAO,OAAO,YAAY;AAC/B,UAAM,WAAW,MAAM,UAAU;AAAA,MAC/B;AAAA,UACA,yBAAU,OAAO,CAAC,SAAS,cAAc,OAAO,OAAO,OAAO,IAAI,CAAwB;AAAA,MAC1F;AAAA,IACF;AACA,aAAS,WAAW,SAAS,MAAM;AACnC,QAAI;AACJ,QAAI,QAAQ;AACZ,qBAAiB,WAAW,SAAS,SAAS;AAC5C,sBAAgB;AAChB;AAAA,IACF;AACA,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,QAAI,QAAQ,GAAG;AACb,YAAM,IAAI,MAAM,+EAA+E;AAAA,IACjG;AACA,aAAS,YAAY,SAAS,OAAO;AACrC,WAAO,cAAc,OAAO,OAAO,QAAQ,aAAa;AAAA,EAC1D;AACF;AAOA,SAAS,sBAIP,WACA,QACA,eACuB;AACvB,SAAO,CAAC,OAAO,YAAY;AACzB,eAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,QACR;AAAA,YACA,yBAAU,OAAO,CAAC,SAAS,cAAc,OAAO,OAAO,OAAO,IAAI,CAAwB;AAAA,QAC1F;AAAA,MACF;AAAA,MACA;AAAA;AAAA,MAEA,cAAc;AAAA,IAChB;AAAA,EACF;AACF;AAEA,MAAM,0BAA0B,oBAAI,IAA0C;AAC9E,SAAS,wBAAwB,SAA+C;AAC9E,MAAI,wBAAwB,IAAI,OAAO,EAAG,QAAO,wBAAwB,IAAI,OAAO;AAEpF,QAAM,SAAkC,CAAC,aAAa,UAAU;AAE9D,eAAO,kCAAa,UAAU,aAAa,YAAY,YAAY,KAAY,GAAG,OAAO;AAAA,EAC3F;AACA,0BAAwB,IAAI,SAAS,MAAM;AAC3C,SAAO;AACT;AAEA,MAAM,wBAAwB,oBAAI,IAA0C;AAC5E,SAAS,wBAAwB,SAA+C;AAC9E,MAAI,sBAAsB,IAAI,OAAO,EAAG,QAAO,sBAAsB,IAAI,OAAO;AAEhF,QAAM,SAAkC,CAAC,QAAQ,YAAY;AAC3D,eAAO,kCAAa,UAAU,QAAQ,SAAS,OAAO;AAAA,EACxD;AACA,wBAAsB,IAAI,SAAS,MAAM;AACzC,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -20,13 +20,17 @@ var base64_exports = {};
20
20
  __export(base64_exports, {
21
21
  base64Decode: () => base64Decode,
22
22
  base64UrlDecode: () => base64UrlDecode,
23
- base64UrlEncode: () => base64UrlEncode
23
+ base64UrlEncode: () => base64UrlEncode,
24
+ toBase64Url: () => toBase64Url
24
25
  });
25
26
  module.exports = __toCommonJS(base64_exports);
26
27
  function base64UrlEncode(value) {
27
28
  const str = typeof value === "string" ? value : String.fromCharCode(...value);
28
29
  const base64 = btoa(str);
29
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
30
+ return toBase64Url(base64);
31
+ }
32
+ function toBase64Url(base64Encoded) {
33
+ return base64Encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
30
34
  }
31
35
  function base64UrlDecode(value) {
32
36
  let str = value;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/sdk/provider/auth/jwt/base64.ts"],
4
- "sourcesContent": ["export function base64UrlEncode(value: string | Uint8Array): string {\n const str = typeof value === \"string\" ? value : String.fromCharCode(...value);\n const base64 = btoa(str);\n return base64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nexport function base64UrlDecode(value: string): string {\n let str = value;\n // Convert from base64url \u2192 base64\n str = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n str = str.padEnd(str.length + (4 - (str.length % 4)) % 4, \"=\");\n\n return new TextDecoder().decode(Uint8Array.from(atob(str), (c) => c.charCodeAt(0)));\n}\n\n/**\n * Decode a base64 string\n * @param base64String The base64 string to decode\n * @returns The decoded object\n */\nexport function base64Decode(base64String: string): Record<string, unknown> {\n const decoded = atob(base64String);\n return JSON.parse(decoded);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,gBAAgB,OAAoC;AAClE,QAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO,aAAa,GAAG,KAAK;AAC5E,QAAM,SAAS,KAAK,GAAG;AACvB,SAAO,OAAO,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AACzE;AAEO,SAAS,gBAAgB,OAAuB;AACrD,MAAI,MAAM;AAEV,QAAM,IAAI,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC9C,QAAM,IAAI,OAAO,IAAI,UAAU,IAAK,IAAI,SAAS,KAAM,GAAG,GAAG;AAE7D,SAAO,IAAI,YAAY,EAAE,OAAO,WAAW,KAAK,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AACpF;AAOO,SAAS,aAAa,cAA+C;AAC1E,QAAM,UAAU,KAAK,YAAY;AACjC,SAAO,KAAK,MAAM,OAAO;AAC3B;",
4
+ "sourcesContent": ["export function base64UrlEncode(value: string | Uint8Array): string {\n const str = typeof value === \"string\" ? value : String.fromCharCode(...value);\n const base64 = btoa(str);\n return toBase64Url(base64);\n}\n\n/**\n * Converts a base64 encoded string to a base64url encoded string\n */\nexport function toBase64Url(base64Encoded: string): string {\n return base64Encoded.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nexport function base64UrlDecode(value: string): string {\n let str = value;\n // Convert from base64url \u2192 base64\n str = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n str = str.padEnd(str.length + (4 - (str.length % 4)) % 4, \"=\");\n\n return new TextDecoder().decode(Uint8Array.from(atob(str), (c) => c.charCodeAt(0)));\n}\n\n/**\n * Decode a base64 string\n * @param base64String The base64 string to decode\n * @returns The decoded object\n */\nexport function base64Decode(base64String: string): Record<string, unknown> {\n const decoded = atob(base64String);\n return JSON.parse(decoded);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,gBAAgB,OAAoC;AAClE,QAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO,aAAa,GAAG,KAAK;AAC5E,QAAM,SAAS,KAAK,GAAG;AACvB,SAAO,YAAY,MAAM;AAC3B;AAKO,SAAS,YAAY,eAA+B;AACzD,SAAO,cAAc,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AAChF;AAEO,SAAS,gBAAgB,OAAuB;AACrD,MAAI,MAAM;AAEV,QAAM,IAAI,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC9C,QAAM,IAAI,OAAO,IAAI,UAAU,IAAK,IAAI,SAAS,KAAM,GAAG,GAAG;AAE7D,SAAO,IAAI,YAAY,EAAE,OAAO,WAAW,KAAK,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AACpF;AAOO,SAAS,aAAa,cAA+C;AAC1E,QAAM,UAAU,KAAK,YAAY;AACjC,SAAO,KAAK,MAAM,OAAO;AAC3B;",
6
6
  "names": []
7
7
  }
@@ -79,8 +79,8 @@ class JwtTokenManager {
79
79
  const header = (0, import_base64.base64UrlEncode)(JSON.stringify({ alg: "ES256K", typ: "JWT" }));
80
80
  const stringPayload = (0, import_base64.base64UrlEncode)(JSON.stringify(inputPayload));
81
81
  const { signature } = await this.wallet.signArbitrary(this.wallet.address, `${header}.${stringPayload}`);
82
- const reorderedJWT = `${header}.${stringPayload}.${signature}`;
83
- return reorderedJWT;
82
+ const token = `${header}.${stringPayload}.${(0, import_base64.toBase64Url)(signature)}`;
83
+ return token;
84
84
  }
85
85
  /**
86
86
  * Decodes a JWT token
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/sdk/provider/auth/jwt/jwt-token.ts"],
4
- "sourcesContent": ["import { base64UrlDecode, base64UrlEncode } from \"./base64.ts\";\nimport { JwtValidator } from \"./jwt-validator.ts\";\nimport type { JwtTokenPayload } from \"./types.ts\";\nimport type { SignArbitraryAkashWallet } from \"./wallet-utils.ts\";\n\nexport class JwtTokenManager {\n private validator: JwtValidator;\n private wallet: SignArbitraryAkashWallet;\n\n constructor(wallet: SignArbitraryAkashWallet) {\n this.validator = new JwtValidator();\n this.wallet = wallet;\n }\n\n /**\n * Creates a new JWT token with ES256K signature using a custom signArbitrary method with the current wallet\n * @param options - JWT token options\n * @returns The signed JWT token\n * @example\n * const wallet = await DirectSecp256k1HdWallet.fromMnemonic(jwtMnemonic, {\n * prefix: \"akash\"\n * });\n * const akashWallet = await createSignArbitraryAkashWallet(wallet);\n * const jwtToken = new JwtToken(akashWallet);\n * // OR ON FRONTEND\n * const { getAccount, signArbitrary } = useSelectedChain();\n * const { address, pubkey } = await getAccount();\n * const jwt = new JwtToken(\n * {\n * signArbitrary,\n * address,\n * pubkey\n * }\n * );\n * const token = await jwtToken.generateToken({\n * version: \"v1\",\n * iss: \"akash...\",\n * exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now\n * iat: Math.floor(Date.now() / 1000), // current timestamp\n * });\n * console.log(token);\n */\n async generateToken(options: CreateJWTOptions): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const inputPayload: JwtTokenPayload = {\n iss: options.iss,\n exp: options.exp ? options.exp : now + 3600, // Default to 1 hour expiration\n nbf: options.nbf || now,\n iat: options.iat || now,\n version: options.version,\n leases: options.leases || { access: \"full\" },\n };\n if (options.jti) inputPayload.jti = options.jti;\n\n const validationResult = this.validatePayload(inputPayload);\n if (!validationResult.isValid) {\n throw new Error(`Invalid payload: ${validationResult.errors?.join(\", \")}`);\n }\n\n const header = base64UrlEncode(JSON.stringify({ alg: \"ES256K\", typ: \"JWT\" }));\n const stringPayload = base64UrlEncode(JSON.stringify(inputPayload));\n const { signature } = await this.wallet.signArbitrary(this.wallet.address, `${header}.${stringPayload}`);\n\n const reorderedJWT = `${header}.${stringPayload}.${signature}`;\n\n return reorderedJWT;\n }\n\n /**\n * Decodes a JWT token\n * @param token - The JWT token to decode\n * @returns The decoded JWT payload\n * @throws Error if the token is malformed\n */\n decodeToken(token: string): JwtTokenPayload {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new Error(\"Invalid JWT format\");\n }\n\n try {\n const [, payload] = parts;\n const json = base64UrlDecode(payload);\n return JSON.parse(json);\n } catch (error) {\n throw new Error(\"Failed to decode JWT token\", { cause: error });\n }\n }\n\n /**\n * Validates a JWT payload against the schema and time-based constraints\n * @param payload - The JWT payload to validate\n * @returns A boolean indicating whether the payload is valid\n */\n public validatePayload(payload: JwtTokenPayload): { isValid: boolean; errors?: string[] } {\n const result = this.validator.validateToken(payload);\n if (!result.isValid) {\n return { isValid: false, errors: result.errors };\n }\n\n const now = Math.floor(Date.now() / 1000);\n const errors: string[] = [];\n\n if (payload.exp <= now) {\n errors.push(\"Token has expired\");\n }\n\n if (payload.nbf > now) {\n errors.push(\"Token is not yet valid (nbf check failed)\");\n }\n\n return {\n isValid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n}\n\nexport interface CreateJWTOptions extends Partial<Omit<JwtTokenPayload, \"iss\" | \"version\">> {\n version: JwtTokenPayload[\"version\"];\n iss: JwtTokenPayload[\"iss\"];\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiD;AACjD,2BAA6B;AAItB,MAAM,gBAAgB;AAAA,EAI3B,YAAY,QAAkC;AAH9C,wBAAQ;AACR,wBAAQ;AAGN,SAAK,YAAY,IAAI,kCAAa;AAClC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,MAAM,cAAc,SAA4C;AAC9D,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,UAAM,eAAgC;AAAA,MACpC,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ,MAAM,QAAQ,MAAM,MAAM;AAAA;AAAA,MACvC,KAAK,QAAQ,OAAO;AAAA,MACpB,KAAK,QAAQ,OAAO;AAAA,MACpB,SAAS,QAAQ;AAAA,MACjB,QAAQ,QAAQ,UAAU,EAAE,QAAQ,OAAO;AAAA,IAC7C;AACA,QAAI,QAAQ,IAAK,cAAa,MAAM,QAAQ;AAE5C,UAAM,mBAAmB,KAAK,gBAAgB,YAAY;AAC1D,QAAI,CAAC,iBAAiB,SAAS;AAC7B,YAAM,IAAI,MAAM,oBAAoB,iBAAiB,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IAC3E;AAEA,UAAM,aAAS,+BAAgB,KAAK,UAAU,EAAE,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAC5E,UAAM,oBAAgB,+BAAgB,KAAK,UAAU,YAAY,CAAC;AAClE,UAAM,EAAE,UAAU,IAAI,MAAM,KAAK,OAAO,cAAc,KAAK,OAAO,SAAS,GAAG,MAAM,IAAI,aAAa,EAAE;AAEvG,UAAM,eAAe,GAAG,MAAM,IAAI,aAAa,IAAI,SAAS;AAE5D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,OAAgC;AAC1C,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC;AAEA,QAAI;AACF,YAAM,CAAC,EAAE,OAAO,IAAI;AACpB,YAAM,WAAO,+BAAgB,OAAO;AACpC,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,8BAA8B,EAAE,OAAO,MAAM,CAAC;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,gBAAgB,SAAmE;AACxF,UAAM,SAAS,KAAK,UAAU,cAAc,OAAO;AACnD,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,EAAE,SAAS,OAAO,QAAQ,OAAO,OAAO;AAAA,IACjD;AAEA,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,UAAM,SAAmB,CAAC;AAE1B,QAAI,QAAQ,OAAO,KAAK;AACtB,aAAO,KAAK,mBAAmB;AAAA,IACjC;AAEA,QAAI,QAAQ,MAAM,KAAK;AACrB,aAAO,KAAK,2CAA2C;AAAA,IACzD;AAEA,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B,QAAQ,OAAO,SAAS,IAAI,SAAS;AAAA,IACvC;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { base64UrlDecode, base64UrlEncode, toBase64Url } from \"./base64.ts\";\nimport { JwtValidator } from \"./jwt-validator.ts\";\nimport type { JwtTokenPayload } from \"./types.ts\";\nimport type { SignArbitraryAkashWallet } from \"./wallet-utils.ts\";\n\nexport class JwtTokenManager {\n private validator: JwtValidator;\n private wallet: SignArbitraryAkashWallet;\n\n constructor(wallet: SignArbitraryAkashWallet) {\n this.validator = new JwtValidator();\n this.wallet = wallet;\n }\n\n /**\n * Creates a new JWT token with ES256K signature using a custom signArbitrary method with the current wallet\n * @param options - JWT token options\n * @returns The signed JWT token\n * @example\n * const wallet = await DirectSecp256k1HdWallet.fromMnemonic(jwtMnemonic, {\n * prefix: \"akash\"\n * });\n * const akashWallet = await createSignArbitraryAkashWallet(wallet);\n * const jwtToken = new JwtToken(akashWallet);\n * // OR ON FRONTEND\n * const { getAccount, signArbitrary } = useSelectedChain();\n * const { address, pubkey } = await getAccount();\n * const jwt = new JwtToken(\n * {\n * signArbitrary,\n * address,\n * pubkey\n * }\n * );\n * const token = await jwtToken.generateToken({\n * version: \"v1\",\n * iss: \"akash...\",\n * exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now\n * iat: Math.floor(Date.now() / 1000), // current timestamp\n * });\n * console.log(token);\n */\n async generateToken(options: CreateJWTOptions): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const inputPayload: JwtTokenPayload = {\n iss: options.iss,\n exp: options.exp ? options.exp : now + 3600, // Default to 1 hour expiration\n nbf: options.nbf || now,\n iat: options.iat || now,\n version: options.version,\n leases: options.leases || { access: \"full\" },\n };\n if (options.jti) inputPayload.jti = options.jti;\n\n const validationResult = this.validatePayload(inputPayload);\n if (!validationResult.isValid) {\n throw new Error(`Invalid payload: ${validationResult.errors?.join(\", \")}`);\n }\n\n const header = base64UrlEncode(JSON.stringify({ alg: \"ES256K\", typ: \"JWT\" }));\n const stringPayload = base64UrlEncode(JSON.stringify(inputPayload));\n const { signature } = await this.wallet.signArbitrary(this.wallet.address, `${header}.${stringPayload}`);\n const token = `${header}.${stringPayload}.${toBase64Url(signature)}`;\n\n return token;\n }\n\n /**\n * Decodes a JWT token\n * @param token - The JWT token to decode\n * @returns The decoded JWT payload\n * @throws Error if the token is malformed\n */\n decodeToken(token: string): JwtTokenPayload {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new Error(\"Invalid JWT format\");\n }\n\n try {\n const [, payload] = parts;\n const json = base64UrlDecode(payload);\n return JSON.parse(json);\n } catch (error) {\n throw new Error(\"Failed to decode JWT token\", { cause: error });\n }\n }\n\n /**\n * Validates a JWT payload against the schema and time-based constraints\n * @param payload - The JWT payload to validate\n * @returns A boolean indicating whether the payload is valid\n */\n public validatePayload(payload: JwtTokenPayload): { isValid: boolean; errors?: string[] } {\n const result = this.validator.validateToken(payload);\n if (!result.isValid) {\n return { isValid: false, errors: result.errors };\n }\n\n const now = Math.floor(Date.now() / 1000);\n const errors: string[] = [];\n\n if (payload.exp <= now) {\n errors.push(\"Token has expired\");\n }\n\n if (payload.nbf > now) {\n errors.push(\"Token is not yet valid (nbf check failed)\");\n }\n\n return {\n isValid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n}\n\nexport interface CreateJWTOptions extends Partial<Omit<JwtTokenPayload, \"iss\" | \"version\">> {\n version: JwtTokenPayload[\"version\"];\n iss: JwtTokenPayload[\"iss\"];\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA8D;AAC9D,2BAA6B;AAItB,MAAM,gBAAgB;AAAA,EAI3B,YAAY,QAAkC;AAH9C,wBAAQ;AACR,wBAAQ;AAGN,SAAK,YAAY,IAAI,kCAAa;AAClC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,MAAM,cAAc,SAA4C;AAC9D,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,UAAM,eAAgC;AAAA,MACpC,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ,MAAM,QAAQ,MAAM,MAAM;AAAA;AAAA,MACvC,KAAK,QAAQ,OAAO;AAAA,MACpB,KAAK,QAAQ,OAAO;AAAA,MACpB,SAAS,QAAQ;AAAA,MACjB,QAAQ,QAAQ,UAAU,EAAE,QAAQ,OAAO;AAAA,IAC7C;AACA,QAAI,QAAQ,IAAK,cAAa,MAAM,QAAQ;AAE5C,UAAM,mBAAmB,KAAK,gBAAgB,YAAY;AAC1D,QAAI,CAAC,iBAAiB,SAAS;AAC7B,YAAM,IAAI,MAAM,oBAAoB,iBAAiB,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IAC3E;AAEA,UAAM,aAAS,+BAAgB,KAAK,UAAU,EAAE,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAC5E,UAAM,oBAAgB,+BAAgB,KAAK,UAAU,YAAY,CAAC;AAClE,UAAM,EAAE,UAAU,IAAI,MAAM,KAAK,OAAO,cAAc,KAAK,OAAO,SAAS,GAAG,MAAM,IAAI,aAAa,EAAE;AACvG,UAAM,QAAQ,GAAG,MAAM,IAAI,aAAa,QAAI,2BAAY,SAAS,CAAC;AAElE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,OAAgC;AAC1C,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC;AAEA,QAAI;AACF,YAAM,CAAC,EAAE,OAAO,IAAI;AACpB,YAAM,WAAO,+BAAgB,OAAO;AACpC,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,8BAA8B,EAAE,OAAO,MAAM,CAAC;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,gBAAgB,SAAmE;AACxF,UAAM,SAAS,KAAK,UAAU,cAAc,OAAO;AACnD,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,EAAE,SAAS,OAAO,QAAQ,OAAO,OAAO;AAAA,IACjD;AAEA,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,UAAM,SAAmB,CAAC;AAE1B,QAAI,QAAQ,OAAO,KAAK;AACtB,aAAO,KAAK,mBAAmB;AAAA,IACjC;AAEA,QAAI,QAAQ,MAAM,KAAK;AACrB,aAAO,KAAK,2CAA2C;AAAA,IACzD;AAEA,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B,QAAQ,OAAO,SAAS,IAAI,SAAS;AAAA,IACvC;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -25,6 +25,7 @@ var import_proto_signing = require("@cosmjs/proto-signing");
25
25
  var import_globals = require("@jest/globals");
26
26
  var import_fs = __toESM(require("fs"), 1);
27
27
  var import_path = __toESM(require("path"), 1);
28
+ var import_base64 = require("./base64.cjs");
28
29
  var import_jwt_token = require("./jwt-token.cjs");
29
30
  var import_test_utils = require("./test/test-utils.cjs");
30
31
  var import_wallet_utils = require("./wallet-utils.cjs");
@@ -67,10 +68,11 @@ var import_wallet_utils = require("./wallet-utils.cjs");
67
68
  (0, import_globals.expect)(expectedSignature).toBeDefined();
68
69
  const signingString = `${expectedHeader}.${expectedPayload}`;
69
70
  const signResponse = await akashWallet.signArbitrary(akashWallet.address, signingString);
71
+ const signature = (0, import_base64.toBase64Url)(signResponse.signature);
70
72
  if (!testCase.mustFail) {
71
- (0, import_globals.expect)(signResponse.signature).toBe(expectedSignature);
73
+ (0, import_globals.expect)(signature).toBe(expectedSignature);
72
74
  } else {
73
- (0, import_globals.expect)(signResponse.signature).not.toBe(expectedSignature);
75
+ (0, import_globals.expect)(signature).not.toBe(expectedSignature);
74
76
  }
75
77
  });
76
78
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/sdk/provider/auth/jwt/jwt-token.spec.ts"],
4
- "sourcesContent": ["import { DirectSecp256k1HdWallet } from \"@cosmjs/proto-signing\";\nimport { beforeAll, describe, expect, it } from \"@jest/globals\";\nimport fs from \"fs\";\nimport path from \"path\";\n\nimport type { CreateJWTOptions } from \"./jwt-token.ts\";\nimport { JwtTokenManager } from \"./jwt-token.ts\";\nimport type { ClaimsTestCase, SigningTestCase } from \"./test/test-utils.ts\";\nimport { replaceTemplateValues } from \"./test/test-utils.ts\";\nimport { createSignArbitraryAkashWallet, type SignArbitraryAkashWallet } from \"./wallet-utils.ts\";\n\ndescribe(\"JWT Claims Validation\", () => {\n const testdataPath = path.join(__dirname, \"../../../../../..\", \"testdata\", \"jwt\");\n const jwtMnemonic = fs.readFileSync(path.join(testdataPath, \"mnemonic\"), \"utf-8\").trim();\n const jwtSigningTestCases = JSON.parse(fs.readFileSync(path.join(testdataPath, \"cases_es256k.json\"), \"utf-8\")) as SigningTestCase[];\n const jwtClaimsTestCases = JSON.parse(fs.readFileSync(path.join(testdataPath, \"cases_jwt.json.tmpl\"), \"utf-8\")) as ClaimsTestCase[];\n\n let testWallet: DirectSecp256k1HdWallet;\n let jwtToken: JwtTokenManager;\n let akashWallet: SignArbitraryAkashWallet;\n\n beforeAll(async () => {\n testWallet = await DirectSecp256k1HdWallet.fromMnemonic(jwtMnemonic, {\n prefix: \"akash\",\n });\n akashWallet = await createSignArbitraryAkashWallet(testWallet);\n jwtToken = new JwtTokenManager(akashWallet);\n });\n\n it.each(jwtClaimsTestCases)(\"$description\", async (testCase) => {\n const { claims, tokenString } = replaceTemplateValues(testCase);\n\n // For test cases that should fail, we need to validate the payload first\n if (testCase.expected.signFail || testCase.expected.verifyFail) {\n const validationResult = jwtToken.validatePayload(claims);\n expect(validationResult.isValid).toBe(false);\n\n if (validationResult.isValid) {\n throw new Error(\"Validation should have failed\", { cause: testCase });\n }\n\n return;\n }\n\n // For test cases that should pass, create and verify the token\n const token = await jwtToken.generateToken(claims as CreateJWTOptions);\n const decoded = jwtToken.decodeToken(token);\n expect(decoded).toBeDefined();\n\n // If the test case has a token string, compare it with the generated token\n if (tokenString) {\n expect(token).toEqual(tokenString);\n }\n });\n\n it.each(jwtSigningTestCases)(\"$description\", async (testCase) => {\n const [expectedHeader, expectedPayload, expectedSignature] = testCase.tokenString.split(\".\");\n expect(expectedHeader).toBeDefined();\n expect(expectedPayload).toBeDefined();\n expect(expectedSignature).toBeDefined();\n\n const signingString = `${expectedHeader}.${expectedPayload}`;\n\n // Sign using the mock wallet's signArbitrary method\n const signResponse = await akashWallet.signArbitrary(akashWallet.address, signingString);\n\n if (!testCase.mustFail) {\n expect(signResponse.signature).toBe(expectedSignature);\n } else {\n expect(signResponse.signature).not.toBe(expectedSignature);\n }\n });\n});\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA,2BAAwC;AACxC,qBAAgD;AAChD,gBAAe;AACf,kBAAiB;AAGjB,uBAAgC;AAEhC,wBAAsC;AACtC,0BAA8E;AAAA,IAE9E,yBAAS,yBAAyB,MAAM;AACtC,QAAM,eAAe,YAAAA,QAAK,KAAK,WAAW,qBAAqB,YAAY,KAAK;AAChF,QAAM,cAAc,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,cAAc,UAAU,GAAG,OAAO,EAAE,KAAK;AACvF,QAAM,sBAAsB,KAAK,MAAM,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,cAAc,mBAAmB,GAAG,OAAO,CAAC;AAC7G,QAAM,qBAAqB,KAAK,MAAM,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,cAAc,qBAAqB,GAAG,OAAO,CAAC;AAE9G,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,gCAAU,YAAY;AACpB,iBAAa,MAAM,6CAAwB,aAAa,aAAa;AAAA,MACnE,QAAQ;AAAA,IACV,CAAC;AACD,kBAAc,UAAM,oDAA+B,UAAU;AAC7D,eAAW,IAAI,iCAAgB,WAAW;AAAA,EAC5C,CAAC;AAED,oBAAG,KAAK,kBAAkB,EAAE,gBAAgB,OAAO,aAAa;AAC9D,UAAM,EAAE,QAAQ,YAAY,QAAI,yCAAsB,QAAQ;AAG9D,QAAI,SAAS,SAAS,YAAY,SAAS,SAAS,YAAY;AAC9D,YAAM,mBAAmB,SAAS,gBAAgB,MAAM;AACxD,iCAAO,iBAAiB,OAAO,EAAE,KAAK,KAAK;AAE3C,UAAI,iBAAiB,SAAS;AAC5B,cAAM,IAAI,MAAM,iCAAiC,EAAE,OAAO,SAAS,CAAC;AAAA,MACtE;AAEA;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM,SAAS,cAAc,MAA0B;AACrE,UAAM,UAAU,SAAS,YAAY,KAAK;AAC1C,+BAAO,OAAO,EAAE,YAAY;AAG5B,QAAI,aAAa;AACf,iCAAO,KAAK,EAAE,QAAQ,WAAW;AAAA,IACnC;AAAA,EACF,CAAC;AAED,oBAAG,KAAK,mBAAmB,EAAE,gBAAgB,OAAO,aAAa;AAC/D,UAAM,CAAC,gBAAgB,iBAAiB,iBAAiB,IAAI,SAAS,YAAY,MAAM,GAAG;AAC3F,+BAAO,cAAc,EAAE,YAAY;AACnC,+BAAO,eAAe,EAAE,YAAY;AACpC,+BAAO,iBAAiB,EAAE,YAAY;AAEtC,UAAM,gBAAgB,GAAG,cAAc,IAAI,eAAe;AAG1D,UAAM,eAAe,MAAM,YAAY,cAAc,YAAY,SAAS,aAAa;AAEvF,QAAI,CAAC,SAAS,UAAU;AACtB,iCAAO,aAAa,SAAS,EAAE,KAAK,iBAAiB;AAAA,IACvD,OAAO;AACL,iCAAO,aAAa,SAAS,EAAE,IAAI,KAAK,iBAAiB;AAAA,IAC3D;AAAA,EACF,CAAC;AACH,CAAC;",
4
+ "sourcesContent": ["import { DirectSecp256k1HdWallet } from \"@cosmjs/proto-signing\";\nimport { beforeAll, describe, expect, it } from \"@jest/globals\";\nimport fs from \"fs\";\nimport path from \"path\";\n\nimport { toBase64Url } from \"./base64.ts\";\nimport type { CreateJWTOptions } from \"./jwt-token.ts\";\nimport { JwtTokenManager } from \"./jwt-token.ts\";\nimport type { ClaimsTestCase, SigningTestCase } from \"./test/test-utils.ts\";\nimport { replaceTemplateValues } from \"./test/test-utils.ts\";\nimport { createSignArbitraryAkashWallet, type SignArbitraryAkashWallet } from \"./wallet-utils.ts\";\n\ndescribe(\"JWT Claims Validation\", () => {\n const testdataPath = path.join(__dirname, \"../../../../../..\", \"testdata\", \"jwt\");\n const jwtMnemonic = fs.readFileSync(path.join(testdataPath, \"mnemonic\"), \"utf-8\").trim();\n const jwtSigningTestCases = JSON.parse(fs.readFileSync(path.join(testdataPath, \"cases_es256k.json\"), \"utf-8\")) as SigningTestCase[];\n const jwtClaimsTestCases = JSON.parse(fs.readFileSync(path.join(testdataPath, \"cases_jwt.json.tmpl\"), \"utf-8\")) as ClaimsTestCase[];\n\n let testWallet: DirectSecp256k1HdWallet;\n let jwtToken: JwtTokenManager;\n let akashWallet: SignArbitraryAkashWallet;\n\n beforeAll(async () => {\n testWallet = await DirectSecp256k1HdWallet.fromMnemonic(jwtMnemonic, {\n prefix: \"akash\",\n });\n akashWallet = await createSignArbitraryAkashWallet(testWallet);\n jwtToken = new JwtTokenManager(akashWallet);\n });\n\n it.each(jwtClaimsTestCases)(\"$description\", async (testCase) => {\n const { claims, tokenString } = replaceTemplateValues(testCase);\n\n // For test cases that should fail, we need to validate the payload first\n if (testCase.expected.signFail || testCase.expected.verifyFail) {\n const validationResult = jwtToken.validatePayload(claims);\n expect(validationResult.isValid).toBe(false);\n\n if (validationResult.isValid) {\n throw new Error(\"Validation should have failed\", { cause: testCase });\n }\n\n return;\n }\n\n // For test cases that should pass, create and verify the token\n const token = await jwtToken.generateToken(claims as CreateJWTOptions);\n const decoded = jwtToken.decodeToken(token);\n expect(decoded).toBeDefined();\n\n // If the test case has a token string, compare it with the generated token\n if (tokenString) {\n expect(token).toEqual(tokenString);\n }\n });\n\n it.each(jwtSigningTestCases)(\"$description\", async (testCase) => {\n const [expectedHeader, expectedPayload, expectedSignature] = testCase.tokenString.split(\".\");\n expect(expectedHeader).toBeDefined();\n expect(expectedPayload).toBeDefined();\n expect(expectedSignature).toBeDefined();\n\n const signingString = `${expectedHeader}.${expectedPayload}`;\n\n // Sign using the mock wallet's signArbitrary method\n const signResponse = await akashWallet.signArbitrary(akashWallet.address, signingString);\n const signature = toBase64Url(signResponse.signature);\n\n if (!testCase.mustFail) {\n expect(signature).toBe(expectedSignature);\n } else {\n expect(signature).not.toBe(expectedSignature);\n }\n });\n});\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA,2BAAwC;AACxC,qBAAgD;AAChD,gBAAe;AACf,kBAAiB;AAEjB,oBAA4B;AAE5B,uBAAgC;AAEhC,wBAAsC;AACtC,0BAA8E;AAAA,IAE9E,yBAAS,yBAAyB,MAAM;AACtC,QAAM,eAAe,YAAAA,QAAK,KAAK,WAAW,qBAAqB,YAAY,KAAK;AAChF,QAAM,cAAc,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,cAAc,UAAU,GAAG,OAAO,EAAE,KAAK;AACvF,QAAM,sBAAsB,KAAK,MAAM,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,cAAc,mBAAmB,GAAG,OAAO,CAAC;AAC7G,QAAM,qBAAqB,KAAK,MAAM,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,cAAc,qBAAqB,GAAG,OAAO,CAAC;AAE9G,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,gCAAU,YAAY;AACpB,iBAAa,MAAM,6CAAwB,aAAa,aAAa;AAAA,MACnE,QAAQ;AAAA,IACV,CAAC;AACD,kBAAc,UAAM,oDAA+B,UAAU;AAC7D,eAAW,IAAI,iCAAgB,WAAW;AAAA,EAC5C,CAAC;AAED,oBAAG,KAAK,kBAAkB,EAAE,gBAAgB,OAAO,aAAa;AAC9D,UAAM,EAAE,QAAQ,YAAY,QAAI,yCAAsB,QAAQ;AAG9D,QAAI,SAAS,SAAS,YAAY,SAAS,SAAS,YAAY;AAC9D,YAAM,mBAAmB,SAAS,gBAAgB,MAAM;AACxD,iCAAO,iBAAiB,OAAO,EAAE,KAAK,KAAK;AAE3C,UAAI,iBAAiB,SAAS;AAC5B,cAAM,IAAI,MAAM,iCAAiC,EAAE,OAAO,SAAS,CAAC;AAAA,MACtE;AAEA;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM,SAAS,cAAc,MAA0B;AACrE,UAAM,UAAU,SAAS,YAAY,KAAK;AAC1C,+BAAO,OAAO,EAAE,YAAY;AAG5B,QAAI,aAAa;AACf,iCAAO,KAAK,EAAE,QAAQ,WAAW;AAAA,IACnC;AAAA,EACF,CAAC;AAED,oBAAG,KAAK,mBAAmB,EAAE,gBAAgB,OAAO,aAAa;AAC/D,UAAM,CAAC,gBAAgB,iBAAiB,iBAAiB,IAAI,SAAS,YAAY,MAAM,GAAG;AAC3F,+BAAO,cAAc,EAAE,YAAY;AACnC,+BAAO,eAAe,EAAE,YAAY;AACpC,+BAAO,iBAAiB,EAAE,YAAY;AAEtC,UAAM,gBAAgB,GAAG,cAAc,IAAI,eAAe;AAG1D,UAAM,eAAe,MAAM,YAAY,cAAc,YAAY,SAAS,aAAa;AACvF,UAAM,gBAAY,2BAAY,aAAa,SAAS;AAEpD,QAAI,CAAC,SAAS,UAAU;AACtB,iCAAO,SAAS,EAAE,KAAK,iBAAiB;AAAA,IAC1C,OAAO;AACL,iCAAO,SAAS,EAAE,IAAI,KAAK,iBAAiB;AAAA,IAC9C;AAAA,EACF,CAAC;AACH,CAAC;",
6
6
  "names": ["path", "fs"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/sdk/provider/auth/jwt/test/test-utils.ts"],
4
- "sourcesContent": ["import type { JwtTokenPayload } from \"../types.ts\";\nimport { createAkashAddress } from \"./seeders/akash-address.seeder.ts\";\n\nconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;\nconst TWO_DAYS_IN_SECONDS = 2 * ONE_DAY_IN_SECONDS;\n\n/**\n * Replaces template values in JWT test cases with actual values\n *\n * Supports the following template patterns:\n * - {{.Issuer}} - Replaced with a generated Akash address for the issuer\n * - {{.Provider}} - Replaced with a generated Akash address for the provider\n * - {{.IatCurr}} - Replaced with the current timestamp\n * - {{.Iat24h}} - Replaced with a timestamp 24 hours in the past\n * - {{.NbfCurr}} - Replaced with the current timestamp\n * - {{.Nbf24h}} - Replaced with a timestamp 24 hours in the past\n * - {{.Exp48h}} - Replaced with a timestamp 48 hours in the future\n * @param testCase - The test case containing template values\n * @returns The test case with template values replaced\n */\nexport function replaceTemplateValues(testCase: ClaimsTestCase) {\n const now = Math.floor(Date.now() / 1000);\n const issuer = createAkashAddress();\n const provider = createAkashAddress();\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const claims = { ...testCase.claims } as unknown as Record<string, any>;\n if (claims.iss === \"{{.Issuer}}\") claims.iss = issuer;\n if (claims.iat === \"{{.IatCurr}}\") claims.iat = now;\n if (claims.iat === \"{{.Iat24h}}\") claims.iat = now + ONE_DAY_IN_SECONDS;\n if (claims.nbf === \"{{.NbfCurr}}\") claims.nbf = now;\n if (claims.nbf === \"{{.Nbf24h}}\") claims.nbf = now + ONE_DAY_IN_SECONDS;\n if (claims.exp === \"{{.Exp48h}}\") claims.exp = now + TWO_DAYS_IN_SECONDS;\n\n // Convert string timestamps to numbers\n if (typeof claims.iat === \"string\") claims.iat = parseInt(claims.iat, 10);\n if (typeof claims.exp === \"string\") claims.exp = parseInt(claims.exp, 10);\n if (typeof claims.nbf === \"string\") claims.nbf = parseInt(claims.nbf, 10);\n\n // Replace provider address in permissions if present\n if (claims.leases && Array.isArray(claims.leases.permissions) && claims.leases.permissions.length > 0) {\n claims.leases.permissions = claims.leases.permissions.map((perm: { provider: string }) => ({\n ...perm,\n provider: perm.provider === \"{{.Provider}}\" ? provider : perm.provider,\n }));\n }\n\n return { ...testCase, claims: claims as JwtTokenPayload };\n}\n\nexport interface ClaimsTestCase {\n description: string;\n tokenString: string;\n claims: JwtTokenPayload;\n expected: {\n error: string;\n signFail: boolean;\n verifyFail: boolean;\n };\n}\n\nexport interface SigningTestCase extends ClaimsTestCase {\n mustFail?: boolean;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kCAAmC;AAEnC,MAAM,qBAAqB,KAAK,KAAK;AACrC,MAAM,sBAAsB,IAAI;AAgBzB,SAAS,sBAAsB,UAA0B;AAC9D,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,aAAS,gDAAmB;AAClC,QAAM,eAAW,gDAAmB;AAGpC,QAAM,SAAS,EAAE,GAAG,SAAS,OAAO;AACpC,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM;AAC/C,MAAI,OAAO,QAAQ,eAAgB,QAAO,MAAM;AAChD,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM,MAAM;AACrD,MAAI,OAAO,QAAQ,eAAgB,QAAO,MAAM;AAChD,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM,MAAM;AACrD,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM,MAAM;AAGrD,MAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,MAAM,SAAS,OAAO,KAAK,EAAE;AACxE,MAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,MAAM,SAAS,OAAO,KAAK,EAAE;AACxE,MAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,MAAM,SAAS,OAAO,KAAK,EAAE;AAGxE,MAAI,OAAO,UAAU,MAAM,QAAQ,OAAO,OAAO,WAAW,KAAK,OAAO,OAAO,YAAY,SAAS,GAAG;AACrG,WAAO,OAAO,cAAc,OAAO,OAAO,YAAY,IAAI,CAAC,UAAgC;AAAA,MACzF,GAAG;AAAA,MACH,UAAU,KAAK,aAAa,kBAAkB,WAAW,KAAK;AAAA,IAChE,EAAE;AAAA,EACJ;AAEA,SAAO,EAAE,GAAG,UAAU,OAAkC;AAC1D;",
4
+ "sourcesContent": ["import type { CreateJWTOptions } from \"../jwt-token.ts\";\nimport type { JwtTokenPayload } from \"../types.ts\";\nimport { createAkashAddress } from \"./seeders/akash-address.seeder.ts\";\n\nconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;\nconst TWO_DAYS_IN_SECONDS = 2 * ONE_DAY_IN_SECONDS;\n\n/**\n * Replaces template values in JWT test cases with actual values\n *\n * Supports the following template patterns:\n * - {{.Issuer}} - Replaced with a generated Akash address for the issuer\n * - {{.Provider}} - Replaced with a generated Akash address for the provider\n * - {{.IatCurr}} - Replaced with the current timestamp\n * - {{.Iat24h}} - Replaced with a timestamp 24 hours in the past\n * - {{.NbfCurr}} - Replaced with the current timestamp\n * - {{.Nbf24h}} - Replaced with a timestamp 24 hours in the past\n * - {{.Exp48h}} - Replaced with a timestamp 48 hours in the future\n * @param testCase - The test case containing template values\n * @returns The test case with template values replaced\n */\nexport function replaceTemplateValues(testCase: ClaimsTestCase) {\n const now = Math.floor(Date.now() / 1000);\n const issuer = createAkashAddress();\n const provider = createAkashAddress();\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const claims = { ...testCase.claims } as unknown as Record<string, any>;\n if (claims.iss === \"{{.Issuer}}\") claims.iss = issuer;\n if (claims.iat === \"{{.IatCurr}}\") claims.iat = now;\n if (claims.iat === \"{{.Iat24h}}\") claims.iat = now + ONE_DAY_IN_SECONDS;\n if (claims.nbf === \"{{.NbfCurr}}\") claims.nbf = now;\n if (claims.nbf === \"{{.Nbf24h}}\") claims.nbf = now + ONE_DAY_IN_SECONDS;\n if (claims.exp === \"{{.Exp48h}}\") claims.exp = now + TWO_DAYS_IN_SECONDS;\n\n // Convert string timestamps to numbers\n if (typeof claims.iat === \"string\") claims.iat = parseInt(claims.iat, 10);\n if (typeof claims.exp === \"string\") claims.exp = parseInt(claims.exp, 10);\n if (typeof claims.nbf === \"string\") claims.nbf = parseInt(claims.nbf, 10);\n\n // Replace provider address in permissions if present\n if (claims.leases && Array.isArray(claims.leases.permissions) && claims.leases.permissions.length > 0) {\n claims.leases.permissions = claims.leases.permissions.map((perm: { provider: string }) => ({\n ...perm,\n provider: perm.provider === \"{{.Provider}}\" ? provider : perm.provider,\n }));\n }\n\n return { ...testCase, claims: claims as JwtTokenPayload };\n}\n\nexport interface ClaimsTestCase {\n description: string;\n tokenString: string;\n claims: JwtTokenPayload;\n expected: {\n error: string;\n signFail: boolean;\n verifyFail: boolean;\n };\n}\n\nexport interface SigningTestCase {\n description: string;\n tokenString: string;\n expected: {\n alg: string;\n claims: CreateJWTOptions;\n };\n mustFail: boolean;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kCAAmC;AAEnC,MAAM,qBAAqB,KAAK,KAAK;AACrC,MAAM,sBAAsB,IAAI;AAgBzB,SAAS,sBAAsB,UAA0B;AAC9D,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,aAAS,gDAAmB;AAClC,QAAM,eAAW,gDAAmB;AAGpC,QAAM,SAAS,EAAE,GAAG,SAAS,OAAO;AACpC,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM;AAC/C,MAAI,OAAO,QAAQ,eAAgB,QAAO,MAAM;AAChD,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM,MAAM;AACrD,MAAI,OAAO,QAAQ,eAAgB,QAAO,MAAM;AAChD,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM,MAAM;AACrD,MAAI,OAAO,QAAQ,cAAe,QAAO,MAAM,MAAM;AAGrD,MAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,MAAM,SAAS,OAAO,KAAK,EAAE;AACxE,MAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,MAAM,SAAS,OAAO,KAAK,EAAE;AACxE,MAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,MAAM,SAAS,OAAO,KAAK,EAAE;AAGxE,MAAI,OAAO,UAAU,MAAM,QAAQ,OAAO,OAAO,WAAW,KAAK,OAAO,OAAO,YAAY,SAAS,GAAG;AACrG,WAAO,OAAO,cAAc,OAAO,OAAO,YAAY,IAAI,CAAC,UAAgC;AAAA,MACzF,GAAG;AAAA,MACH,UAAU,KAAK,aAAa,kBAAkB,WAAW,KAAK;AAAA,IAChE,EAAE;AAAA,EACJ;AAEA,SAAO,EAAE,GAAG,UAAU,OAAkC;AAC1D;",
6
6
  "names": []
7
7
  }
@@ -81,9 +81,10 @@ const schema = {
81
81
  type: "string",
82
82
  enum: [
83
83
  "full",
84
- "granular"
84
+ "granular",
85
+ "scoped"
85
86
  ],
86
- description: "Access level for the lease: 'full' for unrestricted access to all actions, 'granular' for provider-specific permissions."
87
+ description: "Access level for the lease: 'full' for unrestricted access to all actions, 'scoped' for specific actions across all provider leases,'granular' for provider-specific permissions."
87
88
  },
88
89
  scope: {
89
90
  type: "array",
@@ -103,7 +104,7 @@ const schema = {
103
104
  "ip-migrate"
104
105
  ]
105
106
  },
106
- description: "Global list of permitted actions across all owned leases (no duplicates). Optional when access is 'full'."
107
+ description: "Global list of permitted actions across all owned leases (no duplicates). Required when access is 'scoped'."
107
108
  },
108
109
  permissions: {
109
110
  type: "array",
@@ -292,6 +293,27 @@ const schema = {
292
293
  },
293
294
  then: {
294
295
  properties: {
296
+ permissions: false,
297
+ scope: false
298
+ }
299
+ }
300
+ },
301
+ {
302
+ if: {
303
+ properties: {
304
+ access: {
305
+ const: "scoped"
306
+ }
307
+ }
308
+ },
309
+ then: {
310
+ required: [
311
+ "scope"
312
+ ],
313
+ properties: {
314
+ scope: {
315
+ minItems: 1
316
+ },
295
317
  permissions: false
296
318
  }
297
319
  }
@@ -569,7 +591,7 @@ const validate = function() {
569
591
  validate2.errors.push({ keywordLocation: "#/properties/leases/properties/access/type", instanceLocation: "#/leases/access" });
570
592
  errorCount++;
571
593
  } else {
572
- if (!(data.leases.access === "full" || data.leases.access === "granular")) {
594
+ if (!(data.leases.access === "full" || data.leases.access === "granular" || data.leases.access === "scoped")) {
573
595
  if (validate2.errors === null) validate2.errors = [];
574
596
  validate2.errors.push({ keywordLocation: "#/properties/leases/properties/access/enum", instanceLocation: "#/leases/access" });
575
597
  errorCount++;
@@ -974,8 +996,41 @@ const validate = function() {
974
996
  validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/0/then/properties/permissions", instanceLocation: "#/leases/permissions" });
975
997
  errorCount++;
976
998
  }
999
+ if ("scope" in data.leases && hasOwn(data.leases, "scope")) {
1000
+ if (validate2.errors === null) validate2.errors = [];
1001
+ validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/0/then/properties/scope", instanceLocation: "#/leases/scope" });
1002
+ errorCount++;
1003
+ }
977
1004
  }
978
1005
  const sub4 = (() => {
1006
+ let errorCount2 = 0;
1007
+ if ("access" in data.leases && hasOwn(data.leases, "access")) {
1008
+ if (!(data.leases.access === "scoped")) errorCount2++;
1009
+ }
1010
+ return errorCount2 === 0;
1011
+ })();
1012
+ if (sub4) {
1013
+ if (!("scope" in data.leases && hasOwn(data.leases, "scope"))) {
1014
+ if (validate2.errors === null) validate2.errors = [];
1015
+ validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/1/then/required", instanceLocation: "#/leases/scope" });
1016
+ errorCount++;
1017
+ }
1018
+ if ("scope" in data.leases && hasOwn(data.leases, "scope")) {
1019
+ if (Array.isArray(data.leases.scope)) {
1020
+ if (data.leases.scope.length < 1) {
1021
+ if (validate2.errors === null) validate2.errors = [];
1022
+ validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/1/then/properties/scope/minItems", instanceLocation: "#/leases/scope" });
1023
+ errorCount++;
1024
+ }
1025
+ }
1026
+ }
1027
+ if ("permissions" in data.leases && hasOwn(data.leases, "permissions")) {
1028
+ if (validate2.errors === null) validate2.errors = [];
1029
+ validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/1/then/properties/permissions", instanceLocation: "#/leases/permissions" });
1030
+ errorCount++;
1031
+ }
1032
+ }
1033
+ const sub5 = (() => {
979
1034
  let errorCount2 = 0;
980
1035
  if (!("access" in data.leases && hasOwn(data.leases, "access"))) errorCount2++;
981
1036
  if ("access" in data.leases && hasOwn(data.leases, "access")) {
@@ -983,15 +1038,15 @@ const validate = function() {
983
1038
  }
984
1039
  return errorCount2 === 0;
985
1040
  })();
986
- if (sub4) {
1041
+ if (sub5) {
987
1042
  if (!("permissions" in data.leases && hasOwn(data.leases, "permissions"))) {
988
1043
  if (validate2.errors === null) validate2.errors = [];
989
- validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/1/then/required", instanceLocation: "#/leases/permissions" });
1044
+ validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/2/then/required", instanceLocation: "#/leases/permissions" });
990
1045
  errorCount++;
991
1046
  }
992
1047
  if ("scope" in data.leases && hasOwn(data.leases, "scope")) {
993
1048
  if (validate2.errors === null) validate2.errors = [];
994
- validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/1/then/properties/scope", instanceLocation: "#/leases/scope" });
1049
+ validate2.errors.push({ keywordLocation: "#/properties/leases/allOf/2/then/properties/scope", instanceLocation: "#/leases/scope" });
995
1050
  errorCount++;
996
1051
  }
997
1052
  }
@@ -1004,7 +1059,7 @@ const validate = function() {
1004
1059
  errorCount++;
1005
1060
  }
1006
1061
  }
1007
- const sub5 = (() => {
1062
+ const sub6 = (() => {
1008
1063
  let errorCount2 = 0;
1009
1064
  if (!("leases" in data && hasOwn(data, "leases"))) errorCount2++;
1010
1065
  if ("leases" in data && hasOwn(data, "leases")) {
@@ -1017,7 +1072,7 @@ const validate = function() {
1017
1072
  }
1018
1073
  return errorCount2 === 0;
1019
1074
  })();
1020
- if (sub5) {
1075
+ if (sub6) {
1021
1076
  if ("leases" in data && hasOwn(data, "leases")) {
1022
1077
  if (typeof data.leases === "object" && data.leases && !Array.isArray(data.leases)) {
1023
1078
  if (!("permissions" in data.leases && hasOwn(data.leases, "permissions"))) {
@@ -1033,7 +1088,7 @@ const validate = function() {
1033
1088
  }
1034
1089
  }
1035
1090
  }
1036
- const sub6 = (() => {
1091
+ const sub7 = (() => {
1037
1092
  let errorCount2 = 0;
1038
1093
  if (!("leases" in data && hasOwn(data, "leases"))) errorCount2++;
1039
1094
  if ("leases" in data && hasOwn(data, "leases")) {
@@ -1050,7 +1105,7 @@ const validate = function() {
1050
1105
  }
1051
1106
  return errorCount2 === 0;
1052
1107
  })();
1053
- if (sub6) {
1108
+ if (sub7) {
1054
1109
  if ("leases" in data && hasOwn(data, "leases")) {
1055
1110
  if (typeof data.leases === "object" && data.leases && !Array.isArray(data.leases)) {
1056
1111
  if (!("access" in data.leases && hasOwn(data.leases, "access"))) {