Skip to content

Commit

Permalink
Add conditional order id to our model (#145)
Browse files Browse the repository at this point in the history
# Description
Ths PR adds the conditional order ID to our mode.

As this is a breaking change, the PR also does some model migration
(from version 1 to version 2).

Additionally, it adds some additional logging to print the conditional
order ID which is convenient.
  • Loading branch information
anxolin authored Feb 14, 2024
1 parent d714c38 commit b1a8b5a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 20 deletions.
19 changes: 16 additions & 3 deletions src/domain/events/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import {
Proof,
Registry,
} from "../../types";
import { ConditionalOrder, ConditionalOrderParams } from "@cowprotocol/cow-sdk";

import { ChainContext } from "../../services/chain";
import { ConditionalOrderParams } from "@cowprotocol/cow-sdk";

/**
* Listens to these events on the `ComposableCoW` contract:
Expand Down Expand Up @@ -201,11 +201,13 @@ export function add(
const log = getLogger("addContract:add");
const { handler, salt, staticInput } = params;
const { network, ownerOrders } = registry;

const conditionalOrderId = ConditionalOrder.leafToId(params);
if (ownerOrders.has(owner)) {
const conditionalOrders = ownerOrders.get(owner);
log.info(
`Adding conditional order to already existing owner contract ${owner}`,
{ tx, handler, salt, staticInput }
{ conditionalOrderId, tx, handler, salt, staticInput }
);
let exists = false;
// Iterate over the conditionalOrders to make sure that the params are not already in the registry
Expand All @@ -220,6 +222,7 @@ export function add(
// If the params are not in the conditionalOrder, add them
if (!exists) {
conditionalOrders?.add({
id: conditionalOrderId,
tx,
params: { handler, salt, staticInput },
proof,
Expand All @@ -230,14 +233,24 @@ export function add(
}
} else {
log.info(`Adding conditional order to new owner contract ${owner}:`, {
conditionalOrderId,
tx,
handler,
salt,
staticInput,
});
registry.ownerOrders.set(
owner,
new Set([{ tx, params, proof, orders: new Map(), composableCow }])
new Set([
{
id: conditionalOrderId,
tx,
params,
proof,
orders: new Map(),
composableCow,
},
])
);
metrics.activeOwnersTotal.labels(network).inc();
metrics.activeOrdersTotal.labels(network).inc();
Expand Down
26 changes: 18 additions & 8 deletions src/domain/polling/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export async function checkForAndPlaceOrder(
blockNumber.toString(),
ownerRef
);
const logOrderDetails = `Processing order from TX ${conditionalOrder.tx} with params:`;
const logOrderDetails = `Processing order ${conditionalOrder.id} from TX ${conditionalOrder.tx} with params:`;

const { result: lastHint } = conditionalOrder.pollResult || {};

Expand Down Expand Up @@ -201,12 +201,15 @@ export async function checkForAndPlaceOrder(
(isError && pollResult.reason ? `. Reason: ${pollResult.reason}` : "");

log[unexpectedError ? "error" : "info"](
`Check conditional order result: ${getEmojiByPollResult(
pollResult?.result
)} ${resultDescription}`
`Check conditional order result for ${
conditionalOrder.id
}: ${getEmojiByPollResult(pollResult?.result)} ${resultDescription}`
);
if (unexpectedError) {
log.error(`UNEXPECTED_ERROR Details:`, pollResult.error);
log.error(
`UNEXPECTED_ERROR for order ${conditionalOrder.id}. Details:`,
pollResult.error
);
}

hasErrors ||= unexpectedError;
Expand All @@ -217,7 +220,9 @@ export async function checkForAndPlaceOrder(
const deleted = conditionalOrders.delete(conditionalOrder);
const action = deleted ? "Stop Watching" : "Failed to stop watching";

log.debug(`${action} conditional order from TX ${conditionalOrder.tx}`);
log.debug(
`${action} conditional order ${conditionalOrder.id} from TX ${conditionalOrder.tx}`
);
metrics.activeOrdersTotal.labels(chainId.toString()).dec();
}
}
Expand Down Expand Up @@ -259,8 +264,12 @@ async function _processConditionalOrder(
"checkForAndPlaceOrder:_processConditionalOrder",
orderRef
);
const id = ConditionalOrderSDK.leafToId(conditionalOrder.params);
const metricLabels = [chainId.toString(), handler, owner, id];
const metricLabels = [
chainId.toString(),
handler,
owner,
conditionalOrder.id,
];
try {
metrics.pollingRunsTotal.labels(...metricLabels).inc();

Expand Down Expand Up @@ -289,6 +298,7 @@ async function _processConditionalOrder(
},
};
let pollResult = await pollConditionalOrder(
conditionalOrder.id,
pollParams,
conditionalOrder.params,
orderRef
Expand Down
3 changes: 2 additions & 1 deletion src/domain/polling/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const ordersFactory = new ConditionalOrderFactory(
);

export async function pollConditionalOrder(
conditionalOrderId: string,
pollParams: PollParams,
conditionalOrderParams: ConditionalOrderParams,
orderRef: string
Expand All @@ -30,7 +31,7 @@ export async function pollConditionalOrder(
: pollParams;

log.debug(
`Polling for ${order.toString()} using block (${
`Polling id ${conditionalOrderId}. Order ${order.toString()} using block (${
actualPollParams.blockInfo === undefined
? "latest"
: actualPollParams.blockInfo.blockNumber
Expand Down
41 changes: 33 additions & 8 deletions src/types/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import type { ConditionalOrderCreatedEvent } from "./generated/ComposableCoW";
import { ConditionalOrderParams, PollResult } from "@cowprotocol/cow-sdk";
import { DBService } from "../services";
import { metrics } from "../utils";
import { ConditionalOrder as ConditionalOrderSdk } from "@cowprotocol/cow-sdk";

// Standardise the storage key
const LAST_NOTIFIED_ERROR_STORAGE_KEY = "LAST_NOTIFIED_ERROR";
const LAST_PROCESSED_BLOCK_STORAGE_KEY = "LAST_PROCESSED_BLOCK";
const CONDITIONAL_ORDER_REGISTRY_STORAGE_KEY = "CONDITIONAL_ORDER_REGISTRY";
const CONDITIONAL_ORDER_REGISTRY_VERSION_KEY =
"CONDITIONAL_ORDER_REGISTRY_VERSION";
const CONDITIONAL_ORDER_REGISTRY_VERSION = 1;
const CONDITIONAL_ORDER_REGISTRY_VERSION = 2;

export const getNetworkStorageKey = (key: string, network: string): string => {
return `${key}_${network}`;
Expand Down Expand Up @@ -49,6 +50,13 @@ export enum OrderStatus {
}

export type ConditionalOrder = {
/**
* Id of the conditional order (which also happens to be the key used for `ctx` in the ComposableCoW contract).
*
* This is a `keccak256` hash of the serialized conditional order.
*/
id: string;

/**
* The transaction hash that created the conditional order (useful for debugging purposes)
*/
Expand Down Expand Up @@ -279,15 +287,15 @@ async function loadOwnerOrders(
getNetworkStorageKey(CONDITIONAL_ORDER_REGISTRY_STORAGE_KEY, network)
);
// Get the persisted registry version
const version = await db.get(
getNetworkStorageKey(CONDITIONAL_ORDER_REGISTRY_VERSION_KEY, network)

const version = Number(
await db.get(
getNetworkStorageKey(CONDITIONAL_ORDER_REGISTRY_VERSION_KEY, network)
)
);

// Parse conditional orders registry (for the persisted version, converting it to the last version)
const ownerOrders = parseConditionalOrders(
!!str ? str : undefined,
Number(version)
);
const ownerOrders = parseConditionalOrders(!!str ? str : undefined, version);

return ownerOrders;
}
Expand All @@ -299,7 +307,24 @@ function parseConditionalOrders(
if (!serializedConditionalOrders) {
return createNewOrderMap();
}
return JSON.parse(serializedConditionalOrders, _reviver);
const ownerOrders: Map<
Owner,
Set<Omit<ConditionalOrder, "id"> & { id?: string }>
> = JSON.parse(serializedConditionalOrders, _reviver);

// The conditional order id was added in version 2
if (_version && _version < 2) {
// Migrate model: Add the missing order Id
for (const orders of ownerOrders.values()) {
for (const order of orders.values()) {
if (!order.id) {
order.id = ConditionalOrderSdk.leafToId(order.params);
}
}
}
}

return ownerOrders as Map<Owner, Set<ConditionalOrder>>;
}

function createNewOrderMap(): Map<Owner, Set<ConditionalOrder>> {
Expand Down

0 comments on commit b1a8b5a

Please sign in to comment.