Last active
June 11, 2021 19:09
-
-
Save JSRossiter/a42ef5bfebf2e50b0bb30959a2536fd8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
}; | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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