-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
423 additions
and
85 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import environments from "@constants/environments"; | ||
|
||
//@ts-ignore | ||
const blockfrostApiUrl = 'https://cardano-'+(environments.networkId == 0? 'preview':'mainnet')+'.blockfrost.io/api/v0/txs/'; | ||
const blockfrostApiKey = environments.blockfrostApiKey; | ||
|
||
async function fetchVoteMetadata (txHash:string): Promise<any> { | ||
const url = `${blockfrostApiUrl}${txHash}/metadata` | ||
console.log("Fetching:",url) | ||
const response = await fetch(url, { | ||
method: 'GET', | ||
headers: { | ||
'project_id': blockfrostApiKey, | ||
}, | ||
}); | ||
const txData: any[] = await response.json(); | ||
const label27=txData.filter(x=>x.label==='27')[0].json_metadata | ||
return label27; | ||
}; | ||
|
||
export async function fetchPollSummaryMetadata(txHash: string):Promise<string[]>{ | ||
return await fetchVoteMetadata(txHash) | ||
} | ||
interface OnChainVoteData { | ||
[delegate: string]: string[]; | ||
} | ||
|
||
export type Vote = VotePayload & { | ||
voterName: string | ||
cosesign1: string | ||
cosekey: string | ||
} | ||
|
||
export interface VotePayload{ | ||
pollName: string, | ||
constutionHash: string, | ||
constutionLink: string, | ||
voterStake: string, | ||
vote: 'yes'| 'no' | 'abstain' | ||
challenge: string | ||
} | ||
export async function fetchVoteTxMetadata(txHash: string):Promise<Vote[]>{ | ||
const voteData: OnChainVoteData[] = await fetchVoteMetadata(txHash) | ||
return voteData.map(v=>{ | ||
const voterName=Object.keys(v) | ||
const voteData =v[voterName[0]] | ||
const voteStr=voteData.join('') | ||
const result =extractVoteData(voteStr) | ||
result.voterName=voterName[0] | ||
return result | ||
|
||
}) | ||
} | ||
|
||
function extractVoteData(data:string): Vote { | ||
// Regular Expressions for matching different parts | ||
const pollNameRegex = /Poll: ([^,]+)/; | ||
const constitutionHashRegex = /Hashed Constitution Text: ([^,]+)/; | ||
const constitutionLinkRegex = /Link to Constitution Text: ([^,]+)/; | ||
const voteRegex = /Vote: (\w+)/; | ||
const walletRegex = /Wallet: ([^,]+)/; | ||
const cosign1Regex = /Signature: ([^,]+)/; | ||
const cosekeyRegex = /Public Key: ([^,]+)/; | ||
const challengeRegex = /Challenge: ([^,]+)/; | ||
// Match each one | ||
const pollNameMatch = data.match(pollNameRegex); | ||
const constitutionHashMatch = data.match(constitutionHashRegex); | ||
const constitutionLinkMatch = data.match(constitutionLinkRegex); | ||
const voteMatch = data.match(voteRegex); | ||
const walletMatch = data.match(walletRegex); | ||
const cosign1Match = data.match(cosign1Regex); | ||
const cosekeyMatch = data.match(cosekeyRegex); | ||
const challengeMatch = data.match(challengeRegex) | ||
|
||
const validateVote = (vote:string): 'yes'|'no'|'abstain' => { | ||
const validVotes = ['yes', 'no', 'abstain']; | ||
return validVotes.includes(vote) ? vote as any : 'abstain'; | ||
}; | ||
|
||
return { | ||
pollName: pollNameMatch ? pollNameMatch[1] : '', | ||
voterName: walletMatch ? walletMatch[1] : '', | ||
constutionHash: constitutionHashMatch ? constitutionHashMatch[1] : '', | ||
constutionLink: constitutionLinkMatch ? constitutionLinkMatch[1] : '', | ||
voterStake: walletMatch ? walletMatch[1] : '', | ||
challenge: challengeMatch? challengeMatch[1]: '', | ||
vote: voteMatch ? validateVote(voteMatch[1]) : 'abstain', | ||
cosesign1: cosign1Match ? cosign1Match[1] : '', | ||
cosekey: cosekeyMatch ? cosekeyMatch[1] : '' | ||
}; | ||
} | ||
|
||
///Wallet: stake_test1uqp28kgg6cafhzuf74eyh8trpa4fh5w50776wk5xh5npv8gx0zh92, | ||
//Poll: Rustic Plastic Chips, Hashed Constitution Text: 16885f03dd0368dbcaaf80ea0ebc5c2e81b46dd082ec628662d69968af096f8d, | ||
// Link to Constitution Text: https://proud-publication.info/, Vote: no, | ||
// Timestamp: 12/2/2024, 11:14:32 PM, Challenge: fa2c6340ddfbb809735bd51217f0cbcbd3bd2b487654549f054e74ac5e8c9d87 | ||
export function decodeOnChainPayload(data: string): VotePayload { | ||
// Regular Expressions for matching different parts of the data | ||
const pollNameRegex = /Poll: ([^,]+)/; | ||
const constitutionHashRegex = /Hashed Constitution Text: ([^,]+)/; | ||
const constitutionLinkRegex = /Link to Constitution Text: ([^,]+)/; | ||
const voteRegex = /Vote: (\w+)/; | ||
const walletRegex = /Wallet: ([^,]+)/; | ||
const challengeRegex = /Challenge: ([^,]+)/; | ||
|
||
// Match each part of the data | ||
const pollNameMatch = data.match(pollNameRegex); | ||
const constitutionHashMatch = data.match(constitutionHashRegex); | ||
const constitutionLinkMatch = data.match(constitutionLinkRegex); | ||
const voteMatch = data.match(voteRegex); | ||
const walletMatch = data.match(walletRegex); | ||
const challengeMatch = data.match(challengeRegex); | ||
|
||
// Validate the vote (same as the one in the extractVoteData function) | ||
const validateVote = (vote: string): 'yes' | 'no' | 'abstain' => { | ||
const validVotes = ['yes', 'no', 'abstain']; | ||
return validVotes.includes(vote) ? vote as any : 'abstain'; | ||
}; | ||
|
||
// Return the parsed data in a structured format | ||
return { | ||
pollName: pollNameMatch ? pollNameMatch[1] : '', | ||
constutionHash: constitutionHashMatch ? constitutionHashMatch[1] : '', | ||
constutionLink: constitutionLinkMatch ? constitutionLinkMatch[1] : '', | ||
voterStake: walletMatch ? walletMatch[1] : '', // In this case, it seems to be the wallet address again | ||
challenge: challengeMatch ? challengeMatch[1] : '', | ||
vote: voteMatch ? validateVote(voteMatch[1]) : 'abstain', | ||
}; | ||
} | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { alternateWallets, delegateWallets, organizerWallets } from "@constants/staticWallets"; | ||
import { pageWithInjectedWallet } from "@fixtures/importWallet"; | ||
import HomePage from "@pages/homePage"; | ||
import { StaticWallet } from "@types"; | ||
import { nAtaTime, sleep } from "./txUtil"; | ||
import PollPage from "@pages/pollPage"; | ||
import Logger from "./logger"; | ||
import { Browser, expect, Page } from "@playwright/test"; | ||
export type VotedPoll = { | ||
pollId: number, | ||
votes: Record<string,'yes'| 'no'|'abstain'> | ||
} | ||
export async function createFullyVotedPoll (browser: Browser,voteCount?:number) : Promise<VotedPoll&{organizerPollPage:Page}> { | ||
const getPage=async (w:StaticWallet)=>await pageWithInjectedWallet(browser,w) | ||
|
||
|
||
const organizerPages=await Promise.all([organizerWallets[0]].map(getPage)); | ||
|
||
const organizerHomePage = new HomePage(organizerPages[0]); | ||
const deleted = await organizerHomePage.deleteOpenPollCards(); | ||
if(deleted){ | ||
await organizerHomePage.goto() | ||
} | ||
const pollId = await organizerHomePage.createPoll() | ||
await organizerHomePage.beginVoteBtn.click(); | ||
|
||
const voteButtons = [ | ||
'vote-yes-button', | ||
'vote-no-button', | ||
'vote-abstain-button', | ||
]; | ||
const votes=['yes','no','abstain'] | ||
const castedVotes={} | ||
|
||
|
||
await nAtaTime(voteCount? delegateWallets.slice(0,voteCount):delegateWallets,async (wallet,index)=>{ | ||
const context = await browser.newContext() | ||
|
||
let page = await pageWithInjectedWallet(context,wallet) | ||
|
||
let pollPage=new PollPage(page) | ||
await pollPage.goto(pollId) | ||
|
||
const isActive = await pollPage.voteYesBtn.waitFor({state: "visible",timeout: 30000}).then(()=>true).catch(()=>false) | ||
|
||
if(!isActive){ | ||
Logger.info("User is not active voter: "+wallet.stakeAddress) | ||
await page.close() | ||
wallet=alternateWallets[index] | ||
page = await pageWithInjectedWallet(context,alternateWallets[index]) | ||
pollPage=new PollPage(page) | ||
await pollPage.goto(pollId) | ||
} | ||
|
||
const randomVote = Math.floor(Math.random() * 3); | ||
await page.getByTestId(voteButtons[randomVote]).click(); | ||
castedVotes[wallet.stakeAddress] = votes[randomVote]; | ||
await expect(page.getByText('Vote recorded!'),"Expected Vote to be recorded for user: "+wallet.stakeAddress).toBeVisible({timeout:20000}) | ||
await page.close() | ||
await context.close() | ||
},6); | ||
|
||
const organizerPollPage=new PollPage(organizerPages[0]) | ||
await organizerPollPage.endVoting() | ||
await sleep(2000) | ||
return {pollId,votes:castedVotes,organizerPollPage:organizerPages[0]} | ||
|
||
} |
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
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
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
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
Oops, something went wrong.