Skip to content

Commit

Permalink
search for validators via withdrawal credential or address
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelsc committed Oct 25, 2023
1 parent a7b38b4 commit 38eafe9
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 25 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ android {
namespace "in.beaconcha.mobile"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 103
versionName "4.4.0"
versionCode 105
versionName "4.5.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
19 changes: 16 additions & 3 deletions src/app/requests/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ export interface CoinbaseExchangeResponse {

export interface ETH1ValidatorResponse {
publickey: string
valid_signature: boolean
validatorindex: number
}

Expand Down Expand Up @@ -354,18 +353,32 @@ export class ValidatorRequest extends APIRequest<ValidatorResponse> {
}
}

export class ValidatorETH1Request extends APIRequest<ETH1ValidatorResponse> {
export class ValidatorViaDepositAddress extends APIRequest<ETH1ValidatorResponse> {
resource = 'validator/eth1/'
method = Method.GET

/**
* @param validator Index or PubKey
* @param ethAddress Address
*/
constructor(ethAddress: string) {
super()
this.resource += ethAddress.replace(/\s/g, '')
}
}

export class ValidatorViaWithdrawalAddress extends APIRequest<ETH1ValidatorResponse> {
resource = 'validator/withdrawalCredentials/'
method = Method.GET

/**
* @param ethAddress Address or Withdrawal Credential
*/
constructor(ethAddress: string) {
super()
this.resource += ethAddress.replace(/\s/g, '')
}
}

export class BlockProducedByRequest extends APIRequest<BlockResponse> {
resource = 'execution/'
method = Method.GET
Expand Down
11 changes: 8 additions & 3 deletions src/app/tab-validators/tab-validators.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
(search)="searchEvent($event)"
(ionClear)="cancelSearch()"
(ionCancel)="cancelSearch()"
placeholder="Public Key / Index / ETH Address"
placeholder="Public Key / Index / Address"
animated>
</ion-searchbar>

Expand Down Expand Up @@ -102,13 +102,18 @@
<div class="nothingfound" *ngIf="dataSource && !dataSource.hasItems() && searchResultMode && !loading">
<ion-icon name="telescope-outline"></ion-icon>
<h2>Nothing found</h2>
<ion-label>We couldn't find the validators you are looking for. Try searching by Index, Public Key or ETH address.</ion-label>
<ion-label
>We couldn't find the validators you are looking for. Try searching by index, public key, deposit / withdrawal address or withdrawal
credential.</ion-label
>
</div>

<div class="nothingfound" *ngIf="dataSource && !dataSource.hasItems() && !searchResultMode && !loading && initialized">
<ion-icon name="arrow-up-circle-outline"></ion-icon>
<h2>Add Validators</h2>
<ion-label> You can add your validators by searching for a public key, validator index or your ETH address. </ion-label>
<ion-label>
You can add your validators by searching for a public key, validator index, your deposit / withdrawal address or withdrawal credential.
</ion-label>
</div>

<div id="container" *ngIf="loading" class="fadein fadeout">
Expand Down
7 changes: 4 additions & 3 deletions src/app/tab-validators/tab-validators.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ export class Tab2Page {
this.searchResultMode = true
this.loading = true
const isETH1Address = searchString.startsWith('0x') && searchString.length == 42
const isWithdrawalCredential = searchString.startsWith('0x') && searchString.length == 66

if (isETH1Address) await this.searchETH1(searchString)
if (isETH1Address || isWithdrawalCredential) await this.searchETH1(searchString)
else await this.searchByPubKeyOrIndex(searchString)

// this.loading = false would be preferable here but somehow the first time it is called the promises resolve instantly without waiting
Expand All @@ -284,12 +285,12 @@ export class Tab2Page {
private async searchETH1(target) {
this.dataSource.setLoadFrom(() => {
return this.validatorUtils
.searchValidatorsViaETH1(target)
.searchValidatorsViaETHAddress(target)
.catch(async (error) => {
if (error && error.message && error.message.indexOf('only a maximum of') > 0) {
console.log('SET reachedMaxValidators to true')
this.reachedMaxValidators = true
return this.validatorUtils.searchValidatorsViaETH1(target, this.currentPackageMaxValidators - 1)
return this.validatorUtils.searchValidatorsViaETHAddress(target, this.currentPackageMaxValidators - 1)
}
return []
})
Expand Down
46 changes: 32 additions & 14 deletions src/app/utils/ValidatorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
AttestationPerformanceResponse,
ValidatorRequest,
ValidatorResponse,
ValidatorETH1Request,
GetMyValidatorsRequest,
MyValidatorResponse,
DashboardRequest,
Expand All @@ -38,6 +37,8 @@ import {
ETH1ValidatorResponse,
SyncCommitteesStatisticsResponse,
ProposalLuckResponse,
ValidatorViaDepositAddress,
ValidatorViaWithdrawalAddress,
} from '../requests/requests'
import { MerchantUtils } from './MerchantUtils'
import BigNumber from 'bignumber.js'
Expand Down Expand Up @@ -492,20 +493,37 @@ export class ValidatorUtils {
}
}

async getRemoteValidatorViaETH1(arg: string, enforceMax = -1): Promise<Validator[]> {
async getRemoteValidatorViaETHAddress(arg: string, enforceMax = -1): Promise<Validator[]> {
if (!arg) return []
const request = new ValidatorETH1Request(arg)
const response = await this.api.execute(request)

if (request.wasSuccessful(response)) {
const eth1ValidatorList = request.parse(response)
const queryString = getValidatorQueryString(eth1ValidatorList, 2000, enforceMax)

return await this.getDashboardDataValidators(MEMORY, queryString)
} else {
return this.apiStatusHandler(response)
const viaDeposit = new ValidatorViaDepositAddress(arg)
const viaDepositPromise = this.api.execute(viaDeposit)

const viaWithdrawal = new ValidatorViaWithdrawalAddress(arg)
const viaWithdrawalPromise = this.api.execute(viaWithdrawal)

const response = await Promise.all([viaDepositPromise, viaWithdrawalPromise])
let result: ETH1ValidatorResponse[] = []

for (const resp of response) {
if (viaDeposit.wasSuccessful(resp)) {
// since both results are identical we can use any of the requests for parsing
const temp = viaDeposit.parse(resp)
if (temp) {
if (result.length > 0) {
result = Array.from(new Map([...result, ...temp].map((item) => [item.validatorindex, item])).values())
} else {
result = temp
}
}
} else {
return this.apiStatusHandler(response)
}
}

const queryString = getValidatorQueryString(result, 2000, enforceMax)
return await this.getDashboardDataValidators(MEMORY, queryString)
}

private async apiStatusHandler(response) {
if (response && response.data && response.data.status) {
return Promise.reject(new Error(response.data.status))
Expand Down Expand Up @@ -564,8 +582,8 @@ export class ValidatorUtils {
return result
}

async searchValidatorsViaETH1(search: string, enforceMax = -1): Promise<Validator[]> {
const result = await this.getRemoteValidatorViaETH1(search, enforceMax)
async searchValidatorsViaETHAddress(search: string, enforceMax = -1): Promise<Validator[]> {
const result = await this.getRemoteValidatorViaETHAddress(search, enforceMax)
if (result == null) return []
return result
}
Expand Down

0 comments on commit 38eafe9

Please sign in to comment.