Skip to content

Commit

Permalink
Add poll-txs code by BBK912
Browse files Browse the repository at this point in the history
  • Loading branch information
kalvkusk committed Mar 16, 2024
1 parent 2ac683d commit f22fb4c
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 87 deletions.
52 changes: 52 additions & 0 deletions .github/workflows/build-and-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Deploy static content to Pages

on:
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: false

jobs:
build-and-deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Pages
uses: actions/configure-pages@v3

- name: Set Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 18.x

- name: Run install
uses: borales/actions-yarn@v4
with:
cmd: install # will run `yarn install` command

- name: Build production bundle
uses: borales/actions-yarn@v4
with:
cmd: build # will run `yarn build` command

- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: 'build'

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"devDependencies": {
"@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.22.6",
"@sveltejs/vite-plugin-svelte": "^2.4.5",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.48.0",
Expand All @@ -21,8 +22,7 @@
"prettier-plugin-svelte": "^3.0.3",
"svelte": "^4.2.0",
"svelte-check": "^3.5.0",
"vite": "^4.4.9",
"@sveltejs/vite-plugin-svelte": "^2.4.5"
"vite": "^4.4.9"
},
"prettier": {
"printWidth": 100,
Expand All @@ -32,6 +32,7 @@
"dependencies": {
"axios": "^1.5.0",
"moment": "^2.29.4",
"node-fetch": "^3.3.2",
"uikit": "^3.16.26",
"uikit-icons": "^0.5.0"
}
Expand Down
4 changes: 3 additions & 1 deletion src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import AccountView from '../ui/AccountView.svelte'
import BoundaryStatus from '../ui/BoundaryStatus.svelte'
// import GovEvents from '../ui/GovEvents.svelte'
import TransactionTable from '../ui/TransactionTable.svelte'
onMount(async () => {
await initApi() // ONLY DO THIS ONCE ON LOAD
Expand Down Expand Up @@ -52,5 +52,7 @@
<div class="uk-flex">
<Validators />
</div>
<div class="uk-flex">
<TransactionTable />
</div>
</main>
5 changes: 4 additions & 1 deletion src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import type {
SystemInfo,
ProofOfFee,
govEventData,
Transaction,
} from '../types'
import * as systemPayloads from '../api/payloads/system'
import * as validatorPayloads from '../api/payloads/validators'
import * as commonPayloads from '../api/payloads/common'
import { govEvents } from '../api/payloads/events'
import { fetchTransactions } from './transactions.js'

export interface User {
address: string
Expand All @@ -32,7 +34,7 @@ export const indexDataStore = writable<IndexData>()
export const valDataStore = writable<valData>()
export const selectedAccount = writable<UserAccount>({ address: '' })
export const govStore = writable<govEventData[]>()

export const transactions = writable<Transaction[]>([])
export const setAccount = (address: string) => {
selectedAccount.set({
address,
Expand Down Expand Up @@ -158,6 +160,7 @@ export const refresh = async () => {
getIndexData()
getSystemInfo()
getValidators()
fetchTransactions()
getEventList(govEvents()).then((res) => govStore.set(res))
} catch (error) {
console.error(`Failed to refresh: ${error}`)
Expand Down
86 changes: 86 additions & 0 deletions src/store/transactions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { transactions } from '.'

async function queryTransactions(offset = 0, limit = 100) {
const transactions = await fetch('https://api.0l.fyi/graphql', {
headers: {
accept: '*/*',
'accept-language': 'en,zh-CN;q=0.9,zh;q=0.8,eu;q=0.7',
'content-type': 'application/json',
'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
},
mode: 'cors',
credentials: 'omit',
body: JSON.stringify({
operationName: 'GetUserTransactions',
variables: {
limit: limit,
offset: offset,
},
query:
'query GetUserTransactions($limit: Int!, $offset: Int!) {\n userTransactions(limit: $limit, offset: $offset, order: "DESC") {\n size\n items {\n version\n sender\n moduleAddress\n moduleName\n functionName\n timestamp\n success\n __typename\n }\n __typename\n }\n}',
}),
method: 'POST',
}).then((res) => res.json())
return transactions.data.userTransactions
}

async function getTransactionDetail(version) {
const data = await fetch(`https://rpc.0l.fyi/v1/transactions/by_version/${version}`).then((res) =>
res.json(),
)
return data.payload.arguments
}
let isFetching = false;
export async function fetchTransactions() {
if (isFetching) return;
const endTime = (Date.now() - 3 * 24 * 60 * 60 * 1000) * 1_000;
const minAmount = 1_000 * 1e6;
const limit = 200
let page = 0
const { size } = await queryTransactions(0, 1)
const totalPage = Math.ceil(size / limit)
let allTransferList = []
isFetching = true;
for (page = 0; page < totalPage; page++) {
try {
const { items } = await queryTransactions(page * limit, limit)
if (items[0] && items[0].timestamp < endTime) {
break
}
let transferList = items.filter(
(item) =>
item.functionName === 'transfer' && item.success && item.timestamp >= endTime,
)

const details = await Promise.all(
transferList.map((item) => getTransactionDetail(item.version)),
)

transferList = transferList.map((item, index) => {
const [receiver, amount] = details[index]
return {
sender: item.sender.toLowerCase(),
receiver: receiver.slice(2).toLowerCase(),
amount: amount,
ledger_version: item.version,
ledger_timestamp: item.timestamp.toString(),
}
})
allTransferList = allTransferList.concat(transferList.filter(t => t.amount >= minAmount));
console.log(`${page + 1}/${totalPage}`)
} catch (error) {
console.log('Fetch error, will retry after 3s')
await new Promise((resolve) => setTimeout(resolve, 3000))
page-- // Retry the same page
}
}
transactions.set(allTransferList)
isFetching = false
}

// fetchTransactions()
10 changes: 10 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface SlowWalletBalance {
unlocked: number
total: number
}

export interface UserAccount {
address: string
in_val_set?: boolean
Expand All @@ -53,6 +54,7 @@ export interface valData {
eligible_validators: string[] // Array of addresses
current_profiles: UserAccount[]
}

export interface govEventData {
data: {
num_votes: string
Expand All @@ -62,3 +64,11 @@ export interface govEventData {
voter: string
}
}

export interface Transaction {
sender: string,
receiver: string,
amount: number,
ledger_version: number,
ledger_timestamp: number,
}
32 changes: 32 additions & 0 deletions src/ui/TransactionTable.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { scaleCoin } from '../utils/coin'
import {transactions} from '../store/index'
</script>

<main>
<table class="uk-table uk-table-responsive uk-table-divider">
<thead>
<!-- sender,receiver,amount,version,timestamp -->
<tr>
<th>Sender</th>
<th>Receiver</th>
<th>Amount</th>
<th>Version</th>
<th>Timestamp</th>
</tr>
</thead>
<tbody>
{#if $transactions.length > 0}
{#each $transactions as tx}
<tr>
<td>{tx.sender}</td>
<td>{tx.receiver}</td>
<td>{scaleCoin(tx.amount)}</td>
<td>{tx.ledger_version}</td>
<td>{new Date(Math.floor(tx.ledger_timestamp / 1_000)).toLocaleString()}</td>
</tr>
{/each}
{/if}
</tbody>
</table>
</main>
45 changes: 45 additions & 0 deletions src/ui/Transactions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script lang="ts">
import { fetchUserAccounts, systemInfo, valDataStore } from '../store'
import type { UserAccount } from '../types'
import AccountTable from './AccountTable.svelte'
import { scaleCoin } from '../utils/coin'
let profiles: UserAccount[]
valDataStore.subscribe((valState) => {
if (valState) {
fetchUserAccounts(valState.eligible_validators).then((r) => {
r.map((el) => {
el.in_val_set = valState.current_list.includes(el.address)
})
r.sort(sortVals)
profiles = r
})
}
})
function sortVals(a: UserAccount) {
if (a.in_val_set) return -1 // sort to top
else return 1
}
</script>

<main>
{#if $valDataStore && $valDataStore.current_list}
<h5>
Validator Set ({($valDataStore &&
$valDataStore.current_list &&
$valDataStore.current_list.length) ||
0}):
</h5>
{/if}

{#if $systemInfo}
Epoch Reward: {scaleCoin($systemInfo.consensus_reward)}
{/if}

{#if profiles && profiles.length > 0}
<AccountTable {profiles} />
{:else}
loading ...
{/if}
</main>
Loading

0 comments on commit f22fb4c

Please sign in to comment.