From fd2d80e9ce6f9ef249b7c12ddbfef2cdb339030e Mon Sep 17 00:00:00 2001 From: PedroAraoz Date: Wed, 27 May 2026 16:26:14 -0300 Subject: [PATCH 1/5] cli: simple refactor --- packages/cli/src/lib/InputsInterfaceGenerator.ts | 11 ++--------- packages/cli/src/lib/ManifestHandler.ts | 10 ++++------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/cli/src/lib/InputsInterfaceGenerator.ts b/packages/cli/src/lib/InputsInterfaceGenerator.ts index 10b18b7d..1c963838 100644 --- a/packages/cli/src/lib/InputsInterfaceGenerator.ts +++ b/packages/cli/src/lib/InputsInterfaceGenerator.ts @@ -44,17 +44,10 @@ function generateImports(inputs: Record): string { } function generateInputsMapping(inputs: Record, originalInputs: ManifestInputs): string { + const variableTypes = new Set(['string', 'Address', 'Bytes', 'BigInt', 'BlockchainToken', 'TokenAmount']) return Object.entries(inputs) .map(([name, type]) => { - const declaration = - type === 'string' || - type === 'Address' || - type === 'Bytes' || - type === 'BigInt' || - type === 'BlockchainToken' || - type === 'TokenAmount' - ? `var ${name}: string | null` - : `const ${name}: ${type}` + const declaration = variableTypes.has(type) ? `var ${name}: string | null` : `const ${name}: ${type}` const originalInput = originalInputs[name] const hasDescription = typeof originalInput === 'object' && !!originalInput.description diff --git a/packages/cli/src/lib/ManifestHandler.ts b/packages/cli/src/lib/ManifestHandler.ts index 297d7308..85851ca3 100644 --- a/packages/cli/src/lib/ManifestHandler.ts +++ b/packages/cli/src/lib/ManifestHandler.ts @@ -4,7 +4,7 @@ import * as fs from 'fs' import { load } from 'js-yaml' import { ZodError } from 'zod' -import { DuplicateEntryError, EmptyManifestError, MoreThanOneEntryError } from '../errors' +import { DuplicateEntryError, EmptyManifestError, GENERIC_SUGGESTION, MoreThanOneEntryError } from '../errors' import { Manifest } from '../types' import { ManifestValidator } from '../validators' @@ -41,9 +41,9 @@ export default { }, } -function mergeIfUnique(list: Record[]) { +function mergeIfUnique(list: Record[] = []) { const merged: Record = {} - for (const obj of list || []) { + for (const obj of list) { const entries = Object.entries(obj) if (entries.length !== 1) throw new MoreThanOneEntryError(entries) const [key, val] = entries[0] @@ -72,9 +72,7 @@ function handleValidationError(command: Command, err: unknown): never { suggestions = err.errors.map((e) => `Fix Field "${e.path.join('.')}" -- ${e.message}`) } else { ;[message, code] = [`Unkown Error: ${err}`, 'UnknownError'] - suggestions = [ - 'Contact the Mimic team for further assistance at our website https://www.mimic.fi/ or discord https://discord.com/invite/cpcyV9EsEg', - ] + suggestions = GENERIC_SUGGESTION } command.error(message, { code, suggestions }) From a1e84c02e345a4f48bcf860146fed81673ac0cb4 Mon Sep 17 00:00:00 2001 From: PedroAraoz Date: Wed, 27 May 2026 16:26:36 -0300 Subject: [PATCH 2/5] lib: add api query --- packages/lib-ts/index.ts | 1 + packages/lib-ts/src/environment.ts | 24 ++++++++++ packages/lib-ts/src/queries/ApiQuery.ts | 62 +++++++++++++++++++++++++ packages/lib-ts/src/queries/index.ts | 1 + 4 files changed, 88 insertions(+) create mode 100644 packages/lib-ts/src/queries/ApiQuery.ts diff --git a/packages/lib-ts/index.ts b/packages/lib-ts/index.ts index 3f018da1..60b9f32e 100644 --- a/packages/lib-ts/index.ts +++ b/packages/lib-ts/index.ts @@ -4,6 +4,7 @@ export * from './src/evm' export * from './src/helpers' export * from './src/intents' export * from './src/log' +export * from './src/queries' export * from './src/storage' export * from './src/svm' export * from './src/tokens' diff --git a/packages/lib-ts/src/environment.ts b/packages/lib-ts/src/environment.ts index 12b93bd4..7e0006de 100644 --- a/packages/lib-ts/src/environment.ts +++ b/packages/lib-ts/src/environment.ts @@ -5,8 +5,11 @@ import { evm } from './evm' import { Consensus, ListType, MIMIC_HELPER_ADDRESS } from './helpers' import { Intent } from './intents' import { + ApiQuery, + ApiQueryResponse, EvmCallQuery, EvmCallQueryResponse, + MethodType, RelevantTokensQuery, RelevantTokensQueryResponse, SubgraphQuery, @@ -38,6 +41,9 @@ export namespace environment { @external('environment', '_subgraphQuery') declare function _subgraphQuery(params: string): string + @external('environment', '_apiQuery') + declare function _apiQuery(params: string): string + @external('environment', '_svmAccountsInfoQuery') declare function _svmAccountsInfoQuery(params: string): string @@ -162,6 +168,24 @@ export namespace environment { return SvmAccountsInfoQueryResponse.fromJson(responseStr).toResult() } + /** + * Executes an HTTP API call and returns the raw (stringified) response body. + * @param url - The endpoint URL to call + * @param method - The HTTP method to use (GET, POST or PUT) + * @param data - Optional. The request payload as a stringified JSON + * @param timestamp - Optional. Cache/snapshot timestamp used to fetch a previously cached response at the given point in time + * @returns A `Result` containing either the response body as a string or an error string + */ + export function apiQuery( + url: string, + method: MethodType, + data: string | null = null, + timestamp: Date | null = null + ): Result { + const responseStr = _apiQuery(JSON.stringify(ApiQuery.from(url, method, data, timestamp))) + return ApiQueryResponse.fromJson(responseStr).toResult() + } + /** * Returns the current execution context containing environment information. * @returns The Context object containing: user, settler, timestamp, consensusThreshold and triggerPayload diff --git a/packages/lib-ts/src/queries/ApiQuery.ts b/packages/lib-ts/src/queries/ApiQuery.ts new file mode 100644 index 00000000..ff628e39 --- /dev/null +++ b/packages/lib-ts/src/queries/ApiQuery.ts @@ -0,0 +1,62 @@ +import { Result } from '../types' + +import { QueryResponseBase } from './QueryResponse' + +export enum MethodType { + GET, + POST, + PUT, +} + +export function methodTypeToString(method: MethodType): string { + switch (method) { + case MethodType.GET: + return 'GET' + case MethodType.POST: + return 'POST' + case MethodType.PUT: + return 'PUT' + default: + throw new Error('Invalid MethodType') + } +} + +@json +class ApiQueryBase { + constructor( + public readonly url: string, + public readonly method: string, + public readonly data: string + ) {} +} + +@json +export class ApiQuery extends ApiQueryBase { + public readonly timestamp: i64 + + constructor(url: string, method: MethodType, data: string, timestamp: i64) { + super(url, methodTypeToString(method), data) + this.timestamp = timestamp + } + + static from(url: string, method: MethodType, data: string | null, timestamp: Date | null): ApiQueryBase { + if (!data) data = '{}' + return timestamp + ? new ApiQuery(url, method, data, changetype(timestamp).getTime()) + : new ApiQueryBase(url, methodTypeToString(method), data) + } +} + +@json +export class ApiQueryResponse extends QueryResponseBase { + public data: string + + constructor(success: string, data: string, error: string) { + super(success, error) + this.data = data + } + + toResult(): Result { + return this.buildResult(this.data, 'Unknown error getting api call') + } +} diff --git a/packages/lib-ts/src/queries/index.ts b/packages/lib-ts/src/queries/index.ts index c59a2729..f302bf0b 100644 --- a/packages/lib-ts/src/queries/index.ts +++ b/packages/lib-ts/src/queries/index.ts @@ -1,3 +1,4 @@ +export * from './ApiQuery' export * from './EvmCallQuery' export * from './QueryResponse' export * from './RelevantTokensQuery' From b8f6df84acbd87d46a74546a6ef204255f7ee367 Mon Sep 17 00:00:00 2001 From: PedroAraoz Date: Wed, 27 May 2026 16:27:45 -0300 Subject: [PATCH 3/5] add changeset --- .changeset/little-sloths-cry.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/little-sloths-cry.md diff --git a/.changeset/little-sloths-cry.md b/.changeset/little-sloths-cry.md new file mode 100644 index 00000000..a372f80c --- /dev/null +++ b/.changeset/little-sloths-cry.md @@ -0,0 +1,7 @@ +--- +"@mimicprotocol/lib-ts": patch +"@mimicprotocol/cli": patch +"@mimicprotocol/test-ts": patch +--- + +add api query From a044a4fe659f785440ba01fe913d3fa3d3c48c8f Mon Sep 17 00:00:00 2001 From: PedroAraoz Date: Thu, 28 May 2026 12:34:59 -0300 Subject: [PATCH 4/5] review changes --- .changeset/little-sloths-cry.md | 2 +- packages/lib-ts/src/environment.ts | 9 ++----- packages/lib-ts/src/queries/ApiQuery.ts | 36 ++++--------------------- 3 files changed, 8 insertions(+), 39 deletions(-) diff --git a/.changeset/little-sloths-cry.md b/.changeset/little-sloths-cry.md index a372f80c..02d9c156 100644 --- a/.changeset/little-sloths-cry.md +++ b/.changeset/little-sloths-cry.md @@ -4,4 +4,4 @@ "@mimicprotocol/test-ts": patch --- -add api query +Add api query diff --git a/packages/lib-ts/src/environment.ts b/packages/lib-ts/src/environment.ts index 7e0006de..4ef61a5d 100644 --- a/packages/lib-ts/src/environment.ts +++ b/packages/lib-ts/src/environment.ts @@ -9,7 +9,6 @@ import { ApiQueryResponse, EvmCallQuery, EvmCallQueryResponse, - MethodType, RelevantTokensQuery, RelevantTokensQueryResponse, SubgraphQuery, @@ -169,20 +168,16 @@ export namespace environment { } /** - * Executes an HTTP API call and returns the raw (stringified) response body. + * Executes an HTTP API GET call and returns the raw (stringified) response body. * @param url - The endpoint URL to call - * @param method - The HTTP method to use (GET, POST or PUT) - * @param data - Optional. The request payload as a stringified JSON * @param timestamp - Optional. Cache/snapshot timestamp used to fetch a previously cached response at the given point in time * @returns A `Result` containing either the response body as a string or an error string */ export function apiQuery( url: string, - method: MethodType, - data: string | null = null, timestamp: Date | null = null ): Result { - const responseStr = _apiQuery(JSON.stringify(ApiQuery.from(url, method, data, timestamp))) + const responseStr = _apiQuery(JSON.stringify(ApiQuery.from(url, timestamp))) return ApiQueryResponse.fromJson(responseStr).toResult() } diff --git a/packages/lib-ts/src/queries/ApiQuery.ts b/packages/lib-ts/src/queries/ApiQuery.ts index ff628e39..ce91db03 100644 --- a/packages/lib-ts/src/queries/ApiQuery.ts +++ b/packages/lib-ts/src/queries/ApiQuery.ts @@ -2,48 +2,22 @@ import { Result } from '../types' import { QueryResponseBase } from './QueryResponse' -export enum MethodType { - GET, - POST, - PUT, -} - -export function methodTypeToString(method: MethodType): string { - switch (method) { - case MethodType.GET: - return 'GET' - case MethodType.POST: - return 'POST' - case MethodType.PUT: - return 'PUT' - default: - throw new Error('Invalid MethodType') - } -} - @json class ApiQueryBase { - constructor( - public readonly url: string, - public readonly method: string, - public readonly data: string - ) {} + constructor(public readonly url: string) {} } @json export class ApiQuery extends ApiQueryBase { public readonly timestamp: i64 - constructor(url: string, method: MethodType, data: string, timestamp: i64) { - super(url, methodTypeToString(method), data) + constructor(url: string, timestamp: i64) { + super(url) this.timestamp = timestamp } - static from(url: string, method: MethodType, data: string | null, timestamp: Date | null): ApiQueryBase { - if (!data) data = '{}' - return timestamp - ? new ApiQuery(url, method, data, changetype(timestamp).getTime()) - : new ApiQueryBase(url, methodTypeToString(method), data) + static from(url: string, timestamp: Date | null): ApiQueryBase { + return timestamp ? new ApiQuery(url, changetype(timestamp).getTime()) : new ApiQueryBase(url) } } From ec7e80b36c5172b0f0f02847cd52b6dde373fe23 Mon Sep 17 00:00:00 2001 From: PedroAraoz Date: Thu, 28 May 2026 15:35:00 -0300 Subject: [PATCH 5/5] add missing test --- packages/lib-ts/src/queries/ApiQuery.ts | 2 +- .../lib-ts/tests/queries/ApiQuery.spec.ts | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 packages/lib-ts/tests/queries/ApiQuery.spec.ts diff --git a/packages/lib-ts/src/queries/ApiQuery.ts b/packages/lib-ts/src/queries/ApiQuery.ts index ce91db03..4971fbc8 100644 --- a/packages/lib-ts/src/queries/ApiQuery.ts +++ b/packages/lib-ts/src/queries/ApiQuery.ts @@ -31,6 +31,6 @@ export class ApiQueryResponse extends QueryResponseBase { } toResult(): Result { - return this.buildResult(this.data, 'Unknown error getting api call') + return this.buildResult(this.data, 'Unknown error getting API response') } } diff --git a/packages/lib-ts/tests/queries/ApiQuery.spec.ts b/packages/lib-ts/tests/queries/ApiQuery.spec.ts new file mode 100644 index 00000000..495aee85 --- /dev/null +++ b/packages/lib-ts/tests/queries/ApiQuery.spec.ts @@ -0,0 +1,53 @@ +import { ApiQueryResponse } from '../../src/queries' + +describe('ApiQueryResponse', () => { + describe('toResult', () => { + describe('when response is successful', () => { + describe('when data is provided', () => { + it('should return result with data', () => { + const responseData = '{"test": true}' + const response = new ApiQueryResponse('true', responseData, '') + const result = response.toResult() + + expect(result.isOk).toBe(true) + const data = result.unwrap() + expect(data).toBe(responseData) + }) + }) + + describe('when data is empty', () => { + it('should return empty string', () => { + const response = new ApiQueryResponse('true', '', '') + const result = response.toResult() + + expect(result.isOk).toBe(true) + const data = result.unwrap() + expect(data).toBe('') + }) + }) + }) + + describe('when response is not successful', () => { + describe('when error message is provided', () => { + it('should return error with provided message', () => { + const errorMessage = 'Something went wrong' + const response = new ApiQueryResponse('false', '', errorMessage) + const result = response.toResult() + + expect(result.isError).toBe(true) + expect(result.error).toBe(errorMessage) + }) + }) + + describe('when error message is not provided', () => { + it('should return default error message', () => { + const response = new ApiQueryResponse('false', '', '') + const result = response.toResult() + + expect(result.isError).toBe(true) + expect(result.error).toBe('Unknown error getting API response') + }) + }) + }) + }) +})