113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import yargs from "yargs";
|
|
import { hideBin } from "yargs/helpers";
|
|
import { checkHex, Client } from "../index";
|
|
import { privateKeyToAccount } from "viem/accounts";
|
|
import { isHex } from "viem";
|
|
import { BidStatusUpdate, Opportunity } from "../types";
|
|
|
|
const DAY_IN_SECONDS = 60 * 60 * 24;
|
|
|
|
class SimpleSearcher {
|
|
private client: Client;
|
|
constructor(
|
|
public endpoint: string,
|
|
public chainId: string,
|
|
public privateKey: string
|
|
) {
|
|
this.client = new Client(
|
|
{ baseUrl: endpoint },
|
|
undefined,
|
|
this.opportunityHandler.bind(this),
|
|
this.bidStatusHandler.bind(this)
|
|
);
|
|
}
|
|
|
|
async bidStatusHandler(bidStatus: BidStatusUpdate) {
|
|
console.log(
|
|
`Bid status for bid ${bidStatus.id}: ${bidStatus.status} ${
|
|
bidStatus.status == "submitted" ? bidStatus.result : ""
|
|
}`
|
|
);
|
|
}
|
|
|
|
async opportunityHandler(opportunity: Opportunity) {
|
|
const bid = BigInt(argv.bid);
|
|
// Bid info should be generated by evaluating the opportunity
|
|
// here for simplicity we are using a constant bid and 24 hours of validity
|
|
const bidParams = {
|
|
amount: bid,
|
|
validUntil: BigInt(Math.round(Date.now() / 1000 + DAY_IN_SECONDS)),
|
|
};
|
|
const opportunityBid = await this.client.signOpportunityBid(
|
|
opportunity,
|
|
bidParams,
|
|
checkHex(argv.privateKey)
|
|
);
|
|
try {
|
|
const bidId = await this.client.submitOpportunityBid(opportunityBid);
|
|
console.log(
|
|
`Successful bid. Opportunity id ${opportunityBid.opportunityId} Bid id ${bidId}`
|
|
);
|
|
} catch (error) {
|
|
console.error(
|
|
`Failed to bid on opportunity ${opportunity.opportunityId}: ${error}`
|
|
);
|
|
}
|
|
}
|
|
|
|
async start() {
|
|
try {
|
|
await this.client.subscribeChains([argv.chainId]);
|
|
console.log(
|
|
`Subscribed to chain ${argv.chainId}. Waiting for opportunities...`
|
|
);
|
|
} catch (error) {
|
|
console.error(error);
|
|
this.client.websocket?.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
const argv = yargs(hideBin(process.argv))
|
|
.option("endpoint", {
|
|
description:
|
|
"Express relay endpoint. e.g: https://per-staging.dourolabs.app/",
|
|
type: "string",
|
|
demandOption: true,
|
|
})
|
|
.option("chain-id", {
|
|
description: "Chain id to fetch opportunities for. e.g: sepolia",
|
|
type: "string",
|
|
demandOption: true,
|
|
})
|
|
.option("bid", {
|
|
description: "Bid amount in wei",
|
|
type: "string",
|
|
default: "100",
|
|
})
|
|
.option("private-key", {
|
|
description:
|
|
"Private key to sign the bid with in hex format with 0x prefix. e.g: 0xdeadbeef...",
|
|
type: "string",
|
|
demandOption: true,
|
|
})
|
|
.help()
|
|
.alias("help", "h")
|
|
.parseSync();
|
|
async function run() {
|
|
if (isHex(argv.privateKey)) {
|
|
const account = privateKeyToAccount(argv.privateKey);
|
|
console.log(`Using account: ${account.address}`);
|
|
} else {
|
|
throw new Error(`Invalid private key: ${argv.privateKey}`);
|
|
}
|
|
const searcher = new SimpleSearcher(
|
|
argv.endpoint,
|
|
argv.chainId,
|
|
argv.privateKey
|
|
);
|
|
await searcher.start();
|
|
}
|
|
|
|
run();
|