Created
February 13, 2023 03:46
-
-
Save antonpaquin/94ff400be72374334956b1af2e3c151f 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 argparse | |
import json | |
import requests | |
api_key = '********-****-****-****-************' | |
stake_id = 'PU6qkjczILwnKHfMV2Yy' | |
def fetch(endpoint, params=None): | |
r = requests.get( | |
url=f'https://manifold.markets/api{endpoint}', | |
params=params, | |
headers={ | |
'Authorization': f'Key {api_key}' | |
} | |
) | |
r.raise_for_status() | |
return json.loads(r.content) | |
def get_market_id(url): | |
slug = url.split('/')[-1] | |
resp = fetch(f'/v0/slug/{slug}') | |
return resp['id'] | |
def get_comments(market_id): | |
resp = fetch('/v0/comments', {'contractId': market_id}) | |
return resp | |
def get_comment_text(c): | |
if 'type' not in c: | |
return get_comment_text(c['content']) | |
elif c['type'] in {'doc', 'paragraph'}: | |
return '\n'.join([get_comment_text(x) for x in c.get('content', [])]) | |
elif c['type'] == 'text': | |
return c['text'] | |
elif c['type'] == 'hardBreak': | |
return '\n' | |
elif c['type'] == 'mention': | |
return '@' + c['attrs']['id'] | |
else: | |
return str(c) | |
def extract_vote(txt): | |
key = '!vote' | |
pos = txt.lower().find(key) | |
if pos == -1: | |
raise ValueError() | |
pos += 1 + len(key) | |
end = pos | |
while end < len(txt) and txt[end] not in {' ', '\n'}: | |
end += 1 | |
return txt[pos:end] | |
def get_votes(policy_id): | |
policy_comments = sorted(get_comments(policy_id), key=lambda x: x['createdTime']) | |
votes = {} | |
for comment in policy_comments: | |
user = comment['userId'] | |
txt = get_comment_text(comment) | |
if '!vote' in txt.lower(): | |
vote = extract_vote(txt) | |
if vote.lower() == 'null': | |
if user in votes: | |
votes.pop(user) | |
else: | |
votes[user] = vote | |
return votes | |
def get_weight(user_id): | |
resp = fetch(f'/v0/bets', {'contractId': stake_id, 'userId': user_id}) | |
shares = [] | |
for bet in resp: | |
mul = 1 | |
if bet['outcome'] == 'NO': | |
mul = -1 | |
if 'fills' in bet: | |
for fill in bet['fills']: | |
shares.append(mul * fill['shares']) | |
else: | |
shares.append(mul * bet['shares']) | |
shares.sort(key=abs) | |
return int(sum(shares)) | |
def get_weights(user_ids): | |
res = {} | |
for user_id in user_ids: | |
w = get_weight(user_id) | |
if w > 0: | |
res[user_id] = w | |
return res | |
def get_username(user_id): | |
return fetch(f'/v0/user/by-id/{user_id}')['username'] | |
def agg_weights(votes, weights): | |
vote_weights = {} | |
for user_id, vote in votes.items(): | |
if user_id in weights: | |
if vote not in vote_weights: | |
vote_weights[vote] = 0 | |
vote_weights[vote] += weights[user_id] | |
return vote_weights | |
def rand_dist(vote_weights): | |
x0 = 0 | |
res = [] | |
for vote, weight in vote_weights.items(): | |
res.append((vote, f'{x0+1}-{x0+weight}')) | |
x0 += weight | |
return res | |
def fmt_resp(votes, weights, names, vote_weights, vote_rand_dist): | |
res = [] | |
for user_id, vote in votes.items(): | |
if user_id in weights: | |
name = names[user_id] | |
weight = weights[user_id] | |
res.append(f'@{name} voted {vote} (weight {weight})') | |
res.append('') | |
res.append('Totals: ') | |
for vote, weight in vote_weights.items(): | |
res.append(f'{vote}: {weight}') | |
res.append('') | |
rand_max = sum(vote_weights.values()) | |
res.append(f'To be chosen from a random draw 1-{rand_max}') | |
for vote, rand_range in vote_rand_dist: | |
res.append(f'{rand_range} = {vote}') | |
return '\n'.join(res) | |
def main(url): | |
policy_id = get_market_id(url) | |
votes = get_votes(policy_id) | |
user_ids = list(votes.keys()) | |
weights = get_weights(user_ids) | |
names = {user_id: get_username(user_id) for user_id in user_ids} | |
vote_weights = agg_weights(votes, weights) | |
vote_rand_dist = rand_dist(vote_weights) | |
print(fmt_resp(votes, weights, names, vote_weights, vote_rand_dist)) | |
def cli_args(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('url') | |
return parser.parse_args() | |
if __name__ == '__main__': | |
_args = cli_args() | |
main(_args.url) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment