Skip to content

Commit

Permalink
Added more test cases, GitHub aciton, intermediate checks
Browse files Browse the repository at this point in the history
  • Loading branch information
OxideDall committed Jan 30, 2025
1 parent 7fa0808 commit 00e4644
Show file tree
Hide file tree
Showing 14 changed files with 830 additions and 546 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ WSS_URL=wss://rpc.superposition.so
INFRA_MARKET_ADDRESS=
BATCH_SWEEPER_ADDRESS=
ACTOR_PRIVATE_KEY=

GAS_RATIO=
CONFIRMATIONS=
RETRY_INTERVAL=
19 changes: 5 additions & 14 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,12 @@ jobs:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
- name: Install dependencies
run: |
forge --version
npm install
id: install

- name: Run Forge fmt
- name: Run integration tests
run: |
forge fmt --check
id: fmt

- name: Run Forge build
run: |
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test -vvv
sh tests.sh
id: test
6 changes: 6 additions & 0 deletions contracts/IInfraMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ interface IInfraMarket {
uint256 bal
);

event Declared(
address indexed trading,
bytes8 indexed winningOutcome,
address indexed feeRecipient
);

/// @notice CampaignEscaped, because a campaign is in an
/// indeterminate state! The DAO may be needed to step in.
event CampaignEscaped(address indexed tradingAddr);
Expand Down
6 changes: 6 additions & 0 deletions contracts/MockInfraMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "../contracts/IInfraMarket.sol";
import "forge-std/console.sol";

contract MockInfraMarket is IInfraMarket {
event MockSweeped(address tradingAddr, uint256 epochNo, address victim);

struct EpochDetails {
uint64 campaign_when_whinged;
bytes8 campaign_whinger_preferred_winner;
Expand Down Expand Up @@ -228,6 +230,8 @@ contract MockInfraMarket is IInfraMarket {
e.redeemable_pot_existing = 1000e18; // Mock value for tests
}

emit MockSweeped(tradingAddr, epochNo, victim);

return fee;
}

Expand Down Expand Up @@ -297,6 +301,8 @@ contract MockInfraMarket is IInfraMarket {
dao_money -= incentives;
}

emit Declared(tradingAddr, finalWinner, msg.sender);

return incentives;
}

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"main": "index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"test": "mocha -r tsx test/market.test.ts --timeout 0"
"start": "node dist/index.js"
},
"keywords": [],
"author": "",
Expand Down
1 change: 0 additions & 1 deletion service/const.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export const INFRA_MARKET_BIRTHBLOCK_TESTNET = 31563;
export const INFRA_MARKET_BIRTHBLOCK_MAINNET = 98847;
export const SET_TIMEOUT_THRESHOLD = 2000;
export const POOLING_INTERVAL = 1000;
118 changes: 62 additions & 56 deletions service/infra-market-handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ethers, Log } from "ethers";
import { BatchSweeper } from "../types/contracts/BatchSweeper";
import { IInfraMarket } from "../types/contracts/IInfraMarket";
import { DeclaredEvent, IInfraMarket } from "../types/contracts/IInfraMarket";
import {
ActiveMarkets,
ActiveLUT,
Expand All @@ -21,7 +21,7 @@ import { TxQueue } from "./tx-queue";
import { Logger } from "./logger";
import { sleep } from "./utils";
import { Config } from "../types/config";
import { POOLING_INTERVAL, SET_TIMEOUT_THRESHOLD } from "./const";
import { SET_TIMEOUT_THRESHOLD } from "./const";

export class InfraMarketHandler extends Logger {
#activeMarkets: ActiveMarkets = {};
Expand Down Expand Up @@ -133,34 +133,6 @@ export class InfraMarketHandler extends Logger {
log
)! as TypedLogDescription<TypedContractEvent>;

#onCreate = async (log: Log) => {
const createdEvt: MarketCreated2Event.LogDescription = this.parseLog(log);

const status = await this.#marketStatus(createdEvt.args.tradingAddr);

if (status) {
this.#scheduleEscape(createdEvt.args.tradingAddr, status.remaining);
}
};

#onCall = (log: Log) => {
const callEvt: CallMadeEvent.LogDescription = this.parseLog(log);

this.#scheduleClose(callEvt.args.tradingAddr);
};

#onRemove = (log: Log) => {
const removeEvt: InfraMarketClosedEvent.LogDescription = this.parseLog(log);
delete this.#activeMarkets[removeEvt.args.tradingAddr];
};

#onReveal = (log: Log) => {
const revealEvt: CommitmentRevealedEvent.LogDescription =
this.parseLog(log);

this.#scheduleDeclare(revealEvt.args.trading);
};

#declare = async (tradingAddr: string) => {
const outcomes = await this.infraMarket
.queryFilter(this.infraMarket.filters.CommitmentRevealed(tradingAddr))
Expand All @@ -172,16 +144,20 @@ export class InfraMarketHandler extends Logger {
outcomes,
this.txQueue.actor.address
);

this.#scheduleSweep(tradingAddr);
};

#close = (tradingAddr: string) => {
this.txQueue.push(
this.infraMarket.close,
tradingAddr,
this.txQueue.actor.address
);
#close = async (tradingAddr: string) => {
const s = await this.#marketStatus(tradingAddr);
if (s?.state === InfraMarketState.Closable) {
this.txQueue.push(
this.infraMarket.close,
tradingAddr,
this.txQueue.actor.address
);
return;
}

this.#scheduleClose(tradingAddr);
};

#sweep = async (tradingAddr: string) => {
Expand Down Expand Up @@ -213,30 +189,23 @@ export class InfraMarketHandler extends Logger {
this.txQueue.push(this.infraMarket.escape, tradingAddr);
};

#scheduleSweep = async (tradingAddr: string) => {
while (true) {
const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Sweeping) {
await this.#sweep(tradingAddr);
break;
}

await sleep(POOLING_INTERVAL);
}
};

#scheduleDeclare = async (tradingAddr: string) => {
if (!this.#activeMarkets[tradingAddr]) {
this.#activeMarkets[tradingAddr] = {};
}

if (this.#activeMarkets[tradingAddr]?.declareTimer) {
return;
}

clearTimeout(this.#activeMarkets[tradingAddr]?.closeTimer);

const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Revealing) {
clearTimeout(this.#activeMarkets[tradingAddr]?.declareTimer);
if (
s?.state === InfraMarketState.Revealing &&
!this.#activeMarkets[tradingAddr]?.declareTimer
) {
this.#activeMarkets[tradingAddr].declareTimer = setTimeout(
() => this.#declare(tradingAddr),
s.remaining * 1000 + SET_TIMEOUT_THRESHOLD
Expand All @@ -249,8 +218,6 @@ export class InfraMarketHandler extends Logger {
this.#activeMarkets[tradingAddr] = {};
}

clearTimeout(this.#activeMarkets[tradingAddr]?.escapeTimer);

const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Whinging) {
Expand All @@ -270,19 +237,58 @@ export class InfraMarketHandler extends Logger {
this.#activeMarkets[tradingAddr] = {};
}

clearTimeout(this.#activeMarkets[tradingAddr]?.escapeTimer);
if (this.#activeMarkets[tradingAddr]?.escapeTimer) {
return;
}

this.#activeMarkets[tradingAddr].escapeTimer = setTimeout(
() => this.#escape(tradingAddr),
remaining * 1000 + SET_TIMEOUT_THRESHOLD
);
};

#onCreate = async (log: Log) => {
const createdEvt: MarketCreated2Event.LogDescription = this.parseLog(log);

this.#scheduleEscape(
createdEvt.args.tradingAddr,
Number(createdEvt.args.callDeadline) - ((Date.now() / 1000) | 0)
);
};

#onCall = (log: Log) => {
const callEvt: CallMadeEvent.LogDescription = this.parseLog(log);

clearTimeout(this.#activeMarkets[callEvt.args.tradingAddr]?.escapeTimer);
delete this.#activeMarkets[callEvt.args.tradingAddr].escapeTimer;

this.#scheduleClose(callEvt.args.tradingAddr);
};

#onRemove = (log: Log) => {
const removeEvt: InfraMarketClosedEvent.LogDescription = this.parseLog(log);
delete this.#activeMarkets[removeEvt.args.tradingAddr];
};

#onReveal = (log: Log) => {
const revealEvt: CommitmentRevealedEvent.LogDescription =
this.parseLog(log);

this.#scheduleDeclare(revealEvt.args.trading);
};

#onDeclare = (log: Log) => {
const declareEvt: DeclaredEvent.LogDescription = this.parseLog(log);
this.#sweep(declareEvt.args.trading);
};

readonly #eventLUT: EventLUT = [
[this.infraMarket.filters.MarketCreated2(), this.#onCreate],
[this.infraMarket.filters.CallMade(), this.#onCall],
[this.infraMarket.filters.InfraMarketClosed(), this.#onRemove],
[this.infraMarket.filters.CampaignEscaped(), this.#onRemove],
[this.infraMarket.filters.CommitmentRevealed(), this.#onReveal],
[this.infraMarket.filters.Declared(), this.#onDeclare],
];

destroy = () => {
Expand Down
24 changes: 14 additions & 10 deletions service/tx-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ export class TxQueue extends Logger {
return;
}

// TODO: add retry logic
await thisService.#send(intent);
let cooldown = thisService.config.RETRY_INTERVAL;
for (let i = 0; i < thisService.config.MAX_RETRIES; i++) {
const success = await thisService.#send(intent);
if (success) {
break;
}
cooldown *= 2;
await sleep(cooldown);
}

setImmediate(() => sendLoop(thisService));
})(this);
Expand Down Expand Up @@ -67,26 +74,23 @@ export class TxQueue extends Logger {
const txBody = await buildResp.catch(this.error);
if (!txBody) {
this.error(`Failed to build transaction ${intent.func.name}`);
await sleep(1000);
return;
return false;
}

const tipReq = this.#estimate(txBody);

const tipped = await tipReq.catch(this.error);
if (!tipped) {
this.error(`Failed to estimate transaction ${intent.func.name}`);
await sleep(1000);
return;
return false;
}

const txReq = this.actor.sendTransaction(tipped);

const txResp = await txReq.catch(this.error);
if (!txResp) {
this.error(`Failed to send transaction ${intent.func.name}`);
await sleep(1000);
return;
return false;
}

const waitReq = await txReq
Expand All @@ -95,9 +99,9 @@ export class TxQueue extends Logger {

if (!waitReq) {
this.error(`Failed to wait for transaction ${intent.func.name}`);
await sleep(1000);
return;
return false;
}
return true;
};

flush = () => (this.queue = []);
Expand Down
Loading

0 comments on commit 00e4644

Please sign in to comment.