Skip to content

Commit

Permalink
Merge pull request #1070 from TempleDAO/1069-fix-tlc-batch-liquidate-…
Browse files Browse the repository at this point in the history
…subgraph

fix: tlc liquidations subgraph url
  • Loading branch information
frost-ostrich authored Aug 10, 2024
2 parents 11226d4 + ccefd48 commit e67f1c3
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 170 deletions.
2 changes: 1 addition & 1 deletion apps/automation-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"local-fork:mainnet-test:tlc": "(cd ../../protocol && forge script --fork-url http://127.0.0.1:8545 scripts/deploys/localhost/v2/999-localhost-tlc-mainnet-test.s.sol)"
},
"dependencies": {
"@mountainpath9/overlord": "^0.8.1",
"@mountainpath9/overlord": "0.13.1",
"axios": "^1.5.1",
"date-fns": "^2.30.0",
"discord.js": "^14.13.0",
Expand Down
13 changes: 10 additions & 3 deletions apps/automation-v2/src/common/discord.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Logger, TaskContext, TaskException } from '@mountainpath9/overlord';
import { ERROR_INTERFACES } from '@/utils/ethers-exceptions';
import { Logger, TaskContext, TaskException, logTaskException, mapParsedEthersException } from '@mountainpath9/overlord';
import { WebhookClient, MessageCreateOptions } from 'discord.js';

interface DiscordChannel {
Expand Down Expand Up @@ -32,12 +33,18 @@ export function decodeWebhookUrl(url: string): { id: string; token: string } {
return { id: m[1], token: m[2] };
}

export async function discordNotifyTaskException(ctx: TaskContext, te: TaskException) {
export async function discordNotifyTaskException(ctx: TaskContext, te0: TaskException) {
// Map custom errors for our contracts to be human readable
const te = { ...te0, exception: mapParsedEthersException(te0.exception, ERROR_INTERFACES) };

// Log failure to overlord
await logTaskException(ctx, te);

const content = [
`**TEMPLE Task Failed**`,
`task label: ${te.label}`,
`task id: ${te.taskId}`,
`task phase: ${te.phase}`,
`task exception: ${te.exception}`,
];

if (te.exception instanceof Error) {
Expand Down
4 changes: 2 additions & 2 deletions apps/automation-v2/src/config/prodnets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const TLC_BATCH_LIQUIDATE_CONFIG: TlcBatchLiquidateConfig = {
ACC_LIQ_MAX_CHUNK_NO: 100,
MIN_ETH_BALANCE_WARNING: parseEther('0.1'),
GAS_LIMIT: 1_000_000n,
SUBGRAPH_URL: 'https://api.thegraph.com/subgraphs/name/templedao/templedao-tlc-liquidations',
SUBGRAPH_ALCHEMY_URL: 'https://subgraph.satsuma-prod.com/a912521dd162/templedao/tlc-liquidations-mainnet/api',
SUBGRAPH_URL:
'https://subgraph.satsuma-prod.com/a912521dd162/templedao/tlc-liquidations-mainnet/api',
SUBGRAPH_RETRY_LIMIT: 3,
};

Expand Down
1 change: 0 additions & 1 deletion apps/automation-v2/src/config/testnets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const TLC_BATCH_LIQUIDATE_CONFIG: TlcBatchLiquidateConfig = {
MIN_ETH_BALANCE_WARNING: parseEther('0.1'),
GAS_LIMIT: 1_000_000n,
SUBGRAPH_URL: 'https://thegraph.com/hosted-service/subgraph/medariox/tlc-liquidations-sepolia',
SUBGRAPH_ALCHEMY_URL: '',
SUBGRAPH_RETRY_LIMIT: 3,
};

Expand Down
25 changes: 6 additions & 19 deletions apps/automation-v2/src/tlc/batch-liquidate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { subgraphRequest } from '@/subgraph/subgraph-request';
import { GetUserResponse } from '@/subgraph/types';
import { matchAndDecodeEvent } from '@/common/filters';
import { backOff } from 'exponential-backoff';
import { AxiosResponse } from 'axios';

export interface TlcBatchLiquidateConfig {
CHAIN: Chain;
Expand All @@ -29,7 +28,6 @@ export interface TlcBatchLiquidateConfig {
MIN_ETH_BALANCE_WARNING: bigint;
GAS_LIMIT: bigint;
SUBGRAPH_URL: string;
SUBGRAPH_ALCHEMY_URL: string;
SUBGRAPH_RETRY_LIMIT: number;
}

Expand Down Expand Up @@ -64,23 +62,12 @@ export async function batchLiquidate(
return chunk;
};

let res: AxiosResponse<GetUserResponse> | undefined = undefined;
const randomUrlFirstAlchemyApi = Math.random() < 0.5;
try {
// try first random subgraph api endpoint
res = await getTlcUsers(
ctx,
randomUrlFirstAlchemyApi ? config.SUBGRAPH_ALCHEMY_URL : config.SUBGRAPH_URL,
config.SUBGRAPH_RETRY_LIMIT
);
} catch (e) {
// if first fails, try the second endpoint option
res = await getTlcUsers(
ctx,
randomUrlFirstAlchemyApi ? config.SUBGRAPH_URL : config.SUBGRAPH_ALCHEMY_URL,
config.SUBGRAPH_RETRY_LIMIT
);
}
// try first random subgraph api endpoint
const res = await getTlcUsers(
ctx,
config.SUBGRAPH_URL,
config.SUBGRAPH_RETRY_LIMIT
);

const tlcUsers = res.data.data?.tlcUsers;
ctx.logger.info(`tlcUsers to check: ${JSON.stringify(tlcUsers)}`);
Expand Down
42 changes: 42 additions & 0 deletions apps/automation-v2/src/utils/ethers-exceptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { CallExceptionError, EthersError, Interface } from "ethers";
import { ITempleLineOfCredit__factory } from "../typechain";

/// Given evm custom errors as per the specified interfaces, attempt to parse
/// an ethers CallException, if successful throw a new error that decodes the custom
/// error.
///
/// Otherwise, just rethrow the original exception
///
/// TODO: once stablised, bake this into the overlord TransactionManager

export async function throwParsedEthersError(e: unknown, errorInterfaces: Interface[]): Promise<never> {
throw mapParsedEthersException(e, errorInterfaces);
}

export function mapParsedEthersException(e: unknown, errorInterfaces: Interface[]): unknown {
if ((e as EthersError).code !== "CALL_EXCEPTION") {
// Rethrow anything that is not an ethers call exception
return e;
}
const callExceptionError = e as CallExceptionError;
const data = callExceptionError.data;
if (data === null || data.length === 0 || data === '0x') {
return e;
}

for (const ei of errorInterfaces) {
const err = ei.parseError(data);
if (err) {
const args = err.args.toArray().map(v => v.toString());
return new Error(`CALL_EXCEPTION: ${err.signature} ${args}\nCause: ${e}`);
}
}
return e;
}


export const ERROR_INTERFACES: Interface[] = [
ITempleLineOfCredit__factory.createInterface(),
];


3 changes: 2 additions & 1 deletion apps/automation-v2/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"forceConsistentCasingInFileNames": true,
"paths": {
"@/*": ["./src/*"]
}
},
"skipLibCheck": true,
},
"include": ["./src"]
}
Loading

0 comments on commit e67f1c3

Please sign in to comment.