Skip to content

Add order matcher anchor service#148

Open
ezraripps wants to merge 6 commits intomainfrom
feature/add-order-matcher
Open

Add order matcher anchor service#148
ezraripps wants to merge 6 commits intomainfrom
feature/add-order-matcher

Conversation

@ezraripps
Copy link
Copy Markdown
Member

@ezraripps ezraripps commented Jan 4, 2026

This PR adds support for "order matcher" services to be in the resolver.

These services are intended to listen to the network, and once two orders that satisfy one-another are seen, it will match them against each-other and (optionally) take a fee specified by the user.

@ezraripps ezraripps self-assigned this Jan 4, 2026
@ezraripps ezraripps changed the title WIP: Add order matcher anchor service Add order matcher anchor service Jan 4, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jan 4, 2026

@rkeene rkeene modified the milestones: v0.0.46, v0.0.47, v0.0.48 Mar 16, 2026
@ezraripps ezraripps modified the milestones: v0.0.48, v0.0.47 Mar 18, 2026
@ezraripps ezraripps marked this pull request as ready for review March 20, 2026 15:40
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support for “order matcher” services to the Anchor resolver ecosystem, including an HTTP server implementation, a discovery/consumption client, shared types/validators, and tests.

Changes:

  • Introduces an Order Matcher HTTP server exposing price-info/history/depth endpoints and producing resolver metadata.
  • Adds an Order Matcher client that discovers providers via the resolver and calls the advertised endpoints with runtime response validation.
  • Extends the central resolver schema + lookup logic to support services.orderMatcher and token-pair-based filtering.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/services/order-matcher/server.ts New HTTP server for order matcher endpoints + service metadata generation
src/services/order-matcher/server.test.ts Verifies endpoints and metadata exposure
src/services/order-matcher/common.ts Shared response/metadata types and typia runtime guards
src/services/order-matcher/client.ts Provider discovery + endpoint invocation client
src/services/order-matcher/client.test.ts End-to-end resolver + client integration test
src/lib/resolver.ts Adds orderMatcher to metadata schema, search criteria, and resolver lookup
src/client/index.ts Exposes Order Matcher client through the main client entrypoint

throw(new Error('Missing grouping query parameter'));
}

const grouping = Number.parseFloat(groupingParam);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grouping is parsed with Number.parseFloat, which accepts inputs like "100abc" and will silently coerce them to 100. If the API intends to require a strictly numeric query value, use Number(groupingParam) (or validate with a numeric regex) so trailing garbage is rejected and clients get a consistent error.

Suggested change
const grouping = Number.parseFloat(groupingParam);
const grouping = Number(groupingParam);

Copilot uses AI. Check for mistakes.
Comment on lines +110 to +116
routes['GET /api/price-info/:tokens'] = async (urlParams) => {
const pair = parseTokenParameter(urlParams);
const response = await getPairInfo(pair);
return({
output: JSON.stringify(response),
contentType: 'application/json'
});
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike the other handlers, the getPairInfo route doesn’t guard against an undefined handler result. If an implementation accidentally returns undefined, JSON.stringify(undefined) yields undefined and the HTTP server response generation can break (output is expected to be a string/Buffer). Add the same response === undefined check used by the other endpoints (or enforce via a runtime assert).

Copilot uses AI. Check for mistakes.
Comment thread src/lib/resolver.ts
throw(new Error(`Expected "pairs" to be an Valuizable, got ${typeof pairsUnrealized}`));
}
// XXX:TODO: Perform deeper validation of the "pairs" structure
await pairsUnrealized('array');
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertResolverLookupOrderMatcherResult validates operations and pairs, but does not validate the required matchingAccounts field for an order matcher service. This can let malformed metadata through the resolver and later fail in order-matcher/client.ts when it calls serviceInfo.matchingAccounts('array'). Add a presence/type check for matchingAccounts similar to how other services validate required fields (and ensure it’s a Valuizable array of strings).

Suggested change
await pairsUnrealized('array');
await pairsUnrealized('array');
if (!('matchingAccounts' in input)) {
throw(new Error('Expected "matchingAccounts" key in order matcher service, but it was not found'));
}
const matchingAccountsUnrealized = input.matchingAccounts;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (!Metadata.isValuizable(matchingAccountsUnrealized)) {
throw(new Error(`Expected "matchingAccounts" to be an Valuizable, got ${typeof matchingAccountsUnrealized}`));
}
// XXX:TODO: Perform deeper validation of the "matchingAccounts" structure
await matchingAccountsUnrealized('array');

Copilot uses AI. Check for mistakes.
Comment thread src/lib/resolver.ts
Comment on lines +556 to +559
function assertValidOperationsOrderMatcher(input: unknown): asserts input is { operations: ToValuizableObject<NonNullable<ServiceMetadata['services']['orderMatcher']>[string]>['operations'] } {
/* XXX:TODO: Validate the specific operations */
assertValidOperationsBanking(input);
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertValidOperationsOrderMatcher delegates to assertValidOperationsBanking, whose error message currently says "Expected "operations" key in KYC service". With order matcher using this helper too, missing/invalid operations metadata will now report an incorrect service name. Consider making the operations validator generic (e.g., accept a serviceName parameter) or adding an order-matcher-specific wrapper that throws an order-matcher-specific message before/after calling the shared validation logic.

Copilot uses AI. Check for mistakes.
Comment on lines +265 to +278
* Fetch price depth for a given token pair
* @param pair The pair to fetch depth for
* @param grouping The grouping to fetch the depth in, as an integer representing the price in pair[0] (the base token)
* @returns The price depth buckets with volume for the pair, priced in pair[0] (the base token)
*/
async getPairDepth(pair: TokenPairInput, grouping: number): Promise<KeetaOrderMatcherPairDepthResponse> {
const operationFactory = await this.serviceInfo.operations.getPairDepth;
if (operationFactory === undefined) {
throw(new Error('Service getPairDepth does not exist'));
}

if (!Number.isFinite(grouping) || grouping <= 0) {
throw(new Error('Grouping must be a positive numeric value'));
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc says grouping is "an integer", but the implementation accepts any positive finite number (and the server parses with parseFloat). Either tighten validation to integers (e.g., Number.isInteger) or update the doc comment to reflect that non-integer groupings are allowed.

Copilot uses AI. Check for mistakes.
@ezraripps ezraripps modified the milestones: v0.0.47, v0.0.48, v0.0.49 Mar 23, 2026
@ezraripps ezraripps modified the milestones: v0.0.49, v0.0.50 Mar 31, 2026
@sephynox sephynox removed this from the v0.0.51 milestone Apr 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants