Skip to content

Instantly share code, notes, and snippets.

@JSRossiter
Last active June 11, 2021 19:09
Show Gist options
  • Save JSRossiter/a42ef5bfebf2e50b0bb30959a2536fd8 to your computer and use it in GitHub Desktop.
Save JSRossiter/a42ef5bfebf2e50b0bb30959a2536fd8 to your computer and use it in GitHub Desktop.
import axios from 'axios';
const SUBGRAPH_URL =
'https://api.thegraph.com/subgraphs/name/tokenunion/polymarket-matic';
export interface Condition {
id: string;
payouts: string[];
resolutionTimestamp: number;
}
export interface FixedProductMarketMaker {
id: string;
outcomeTokenAmounts: string[];
outcomeTokenPrices: string[];
scaledCollateralVolume: string;
scaledLiquidityParameter: string;
collateralVolume: string;
liquidityParameter: string;
outcomeSlotCount: string;
totalSupply: string;
conditions: Condition[];
}
export const getFixedProductMarketMaker = async (
id: string
): Promise<{ fixedProductMarketMaker: FixedProductMarketMaker }> => {
const query = `#graphql
{
fixedProductMarketMaker(id: "${id}") {
id
outcomeTokenAmounts
outcomeTokenPrices
scaledCollateralVolume
scaledLiquidityParameter
collateralVolume
liquidityParameter
outcomeSlotCount
totalSupply
conditions {
payouts
resolutionTimestamp
}
}
}
`;
return graphQuery(query);
};
interface FpmmPoolMembership {
amount: string;
funder: {
id: string;
};
}
export const getFpmmPoolMemberships = ({
market,
}: {
market: string;
}): Promise<{
fpmmPoolMemberships: FpmmPoolMembership[];
}> => {
const query = `#graphql
{
fpmmPoolMemberships(where: {pool: "${market}", amount_gt: 0}, orderBy: amount, orderDirection: desc) {
amount
funder {
id
}
}
}
`;
return graphQuery(query);
};
const graphQuery = async <R>(
query: string,
variables?: Record<string, unknown>,
url: string = SUBGRAPH_URL
): Promise<R> => {
const response = await axios.post<{
data: R;
error?: unknown;
errors?: unknown[];
}>(url, { query, variables }, { timeout: 20000 });
if (!response.data.data) {
throw new Error(
JSON.stringify(response.data.error || response.data.errors)
);
}
return response.data.data;
};
interface LpsData {
lpTokens: number;
share: number;
account: string;
shares: number[];
values: number[];
}
export async function getLpsData(
marketMakerAddress: string
): Promise<LpsData[]> {
const [
fpmmResponse,
fpmmPoolMemberships,
// collectedFees,
] = await Promise.all([
getFixedProductMarketMaker(marketMakerAddress),
getFpmmPoolMemberships({
market: marketMakerAddress,
}),
// getCollectedFees(market),
]);
const fpmm = fpmmResponse.fixedProductMarketMaker;
return fpmmPoolMemberships.fpmmPoolMemberships.map((lp) => {
const share = Number(lp.amount) / Number(fpmm.totalSupply);
const shares = fpmm.outcomeTokenAmounts.map(
(amount) => (share * Number(amount)) / 1e6
);
const values = fpmm.outcomeTokenPrices.map(
(price, i) => shares[i] * Number(price)
);
return {
lpTokens: Number(lp.amount) / 1e6,
share,
account: lp.funder.id,
shares,
values,
};
});
}
import Web3 from 'web3';
import { AbiItem } from 'web3-utils';
import fpmmContract from '../contracts/FixedProductMarketMaker.json';
import logger from './logger';
import { sleep } from './sleep';
function getContract(abi: AbiItem[], address: string): Contract {
const web3 = newWeb3();
return new web3.eth.Contract(abi, address);
}
export function newWeb3(): Web3 {
const web3 = new Web3(process.env.MATIC_PROVIDER_URL);
return web3;
}
export function getFpmmContract(marketId: string): FpmmContract {
return getContract(fpmmContract.abi as AbiItem[], marketId);
}
export function getWithdrawableFeesBatch(
markets: string[],
accounts: string[],
): Promise<{ market: string; fee: string; account: string }[]> {
return new Promise((resolve, reject) => {
const web3 = newWeb3();
const request = new web3.BatchRequest();
let count = 0;
const results: { market: string; fee: string; account: string }[] = [];
markets.map((market) => {
const fpmm = getFpmmContract(market);
accounts.map((account) => {
count++;
const callback = (err: Error, result: string) => {
count--;
if (err) {
const message = `${market} feesWithdrawableBy(${account}) returned error ${String(
err,
)}`;
logger.error(message);
} else {
results.push({ fee: result, market, account });
}
if (count === 0) {
resolve(results);
}
};
request.add(
// @ts-expect-error untyped
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
fpmm.methods.feesWithdrawableBy(account).call.request({}, callback),
);
});
});
if (count) {
request.execute();
void sleep(5000).then(() =>
reject(new Error('Timeout fetching withdrawableFees')),
);
} else {
resolve(results);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment