mirror of
https://github.com/AtHeartEngineering/bandada.git
synced 2026-01-09 20:58:08 -05:00
Merge pull request #441 from bandada-infra/refactor/criterias
Make criterias from credentials validators context parameters
This commit is contained in:
@@ -22,8 +22,7 @@ export class CredentialsController {
|
||||
dto.oAuthState,
|
||||
dto.oAuthCode,
|
||||
dto.address,
|
||||
dto.network,
|
||||
dto.blockNumber
|
||||
dto.network
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,8 +329,7 @@ describe("CredentialsService", () => {
|
||||
_stateId,
|
||||
undefined,
|
||||
"0x1",
|
||||
"sepolia",
|
||||
"1234"
|
||||
"sepolia"
|
||||
)
|
||||
|
||||
expect(clientRedirectUri).toBeUndefined()
|
||||
|
||||
@@ -86,8 +86,7 @@ export class CredentialsService {
|
||||
oAuthState: string,
|
||||
oAuthCode?: string,
|
||||
address?: string,
|
||||
network?: string,
|
||||
blockNumber?: string
|
||||
network?: string
|
||||
): Promise<string> {
|
||||
if (!this.oAuthState.has(oAuthState)) {
|
||||
throw new BadRequestException(`OAuth state does not exist`)
|
||||
@@ -118,14 +117,9 @@ export class CredentialsService {
|
||||
provider as BlockchainProvider
|
||||
).getJsonRpcProvider(web3providerRpcURL)
|
||||
|
||||
const BlockNumberNumber = blockNumber
|
||||
? Number(blockNumber)
|
||||
: undefined
|
||||
|
||||
context = {
|
||||
address,
|
||||
jsonRpcProvider,
|
||||
blockNumber: BlockNumberNumber
|
||||
jsonRpcProvider
|
||||
}
|
||||
|
||||
// Check if the same account has already joined the group.
|
||||
|
||||
@@ -2,6 +2,7 @@ import { validators } from "@bandada/credentials"
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
HStack,
|
||||
Icon,
|
||||
Input,
|
||||
@@ -157,15 +158,21 @@ export default function AccessModeStep({
|
||||
{_credentials &&
|
||||
_credentials.criteria &&
|
||||
Object.entries(validators[_validator].criteriaABI).map(
|
||||
(parameter) => (
|
||||
(parameter: any) => (
|
||||
<VStack
|
||||
align="left"
|
||||
pt="20px"
|
||||
key={parameter[0]}
|
||||
>
|
||||
<Text>{capitalize(parameter[0])}</Text>
|
||||
<Text>
|
||||
{capitalize(
|
||||
`${parameter[0]}${
|
||||
parameter[1].optional ? "" : "*"
|
||||
}`
|
||||
)}
|
||||
</Text>
|
||||
|
||||
{parameter[1] === "number" ? (
|
||||
{parameter[1].type === "number" && (
|
||||
<NumberInput
|
||||
size="lg"
|
||||
value={
|
||||
@@ -190,7 +197,8 @@ export default function AccessModeStep({
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
) : (
|
||||
)}
|
||||
{parameter[1].type === "string" && (
|
||||
<Input
|
||||
size="lg"
|
||||
value={
|
||||
@@ -215,6 +223,25 @@ export default function AccessModeStep({
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{parameter[1].type === "boolean" && (
|
||||
<Checkbox
|
||||
isChecked={
|
||||
_credentials.criteria[
|
||||
parameter[0]
|
||||
]
|
||||
}
|
||||
onChange={(e) =>
|
||||
setCredentials({
|
||||
..._credentials,
|
||||
criteria: {
|
||||
..._credentials.criteria,
|
||||
[parameter[0]]:
|
||||
e.target.checked
|
||||
}
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</VStack>
|
||||
)
|
||||
)}
|
||||
@@ -244,12 +271,14 @@ export default function AccessModeStep({
|
||||
(_accessMode === "credentials" &&
|
||||
(!_credentials ||
|
||||
!_credentials.criteria ||
|
||||
Object.keys(_credentials.criteria).length !==
|
||||
Object.keys(
|
||||
validators[_validator].criteriaABI
|
||||
).length ||
|
||||
Object.values(_credentials.criteria).some(
|
||||
(c) => c === undefined
|
||||
Object.entries(
|
||||
validators[_validator].criteriaABI
|
||||
).some(
|
||||
([key, { optional }]: any) =>
|
||||
!optional &&
|
||||
(_credentials.criteria[key] ===
|
||||
undefined ||
|
||||
!_credentials.criteria[key])
|
||||
)))
|
||||
}
|
||||
variant="solid"
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
export default function checkCriteria(criteria: any, criteriaABI: any) {
|
||||
for (const parameter in criteriaABI) {
|
||||
if (Object.prototype.hasOwnProperty.call(criteriaABI, parameter)) {
|
||||
if (criteria[parameter] === undefined) {
|
||||
const isOptional = criteriaABI[parameter].optional
|
||||
|
||||
if (!isOptional && criteria[parameter] === undefined) {
|
||||
throw Error(`Parameter '${parameter}' has not been defined`)
|
||||
}
|
||||
}
|
||||
@@ -28,10 +30,10 @@ export default function checkCriteria(criteria: any, criteriaABI: any) {
|
||||
value !== null &&
|
||||
!Array.isArray(value)
|
||||
) {
|
||||
checkCriteria(value, criteriaABI[parameter])
|
||||
} else if (typeof value !== criteriaABI[parameter]) {
|
||||
checkCriteria(value, criteriaABI[parameter].type)
|
||||
} else if (typeof value !== criteriaABI[parameter].type) {
|
||||
throw TypeError(
|
||||
`Parameter '${parameter}' is not a ${criteriaABI[parameter]}`
|
||||
`Parameter '${parameter}' is not a ${criteriaABI[parameter].type}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,10 @@ export type Web2Context = {
|
||||
export type BlockchainContext = {
|
||||
address: BigNumberish
|
||||
jsonRpcProvider: any
|
||||
blockNumber?: number
|
||||
}
|
||||
|
||||
export type EASContext = {
|
||||
recipient: BigNumberish
|
||||
queryGraph: (query: string) => Promise<any>
|
||||
attester?: BigNumberish
|
||||
schemaId?: BigNumberish
|
||||
revocable?: boolean
|
||||
revoked?: boolean
|
||||
isOffchain?: boolean
|
||||
}
|
||||
|
||||
export type Context = Web2Context | BlockchainContext | EASContext
|
||||
|
||||
@@ -33,13 +33,13 @@ describe("BlockchainBalance", () => {
|
||||
{
|
||||
id: blockchainBalance.id,
|
||||
criteria: {
|
||||
minBalance: "10"
|
||||
minBalance: "10",
|
||||
blockNumber: 4749638
|
||||
}
|
||||
},
|
||||
{
|
||||
address: "0x",
|
||||
jsonRpcProvider: jsonRpcProviderMocked,
|
||||
blockNumber: 4749638
|
||||
jsonRpcProvider: jsonRpcProviderMocked
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -3,13 +3,21 @@ import { BlockchainContext, Validator } from "../.."
|
||||
|
||||
export type Criteria = {
|
||||
minBalance: string
|
||||
blockNumber?: number
|
||||
}
|
||||
|
||||
const validator: Validator = {
|
||||
id: "BLOCKCHAIN_BALANCE",
|
||||
|
||||
criteriaABI: {
|
||||
minBalance: "string"
|
||||
minBalance: {
|
||||
type: "string",
|
||||
optional: false
|
||||
},
|
||||
blockNumber: {
|
||||
type: "number",
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -20,11 +28,16 @@ const validator: Validator = {
|
||||
*/
|
||||
async validate(criteria: Criteria, context) {
|
||||
if ("address" in context) {
|
||||
const blockNumber =
|
||||
criteria.blockNumber !== undefined
|
||||
? criteria.blockNumber
|
||||
: undefined
|
||||
|
||||
const balance = await (
|
||||
context as BlockchainContext
|
||||
).jsonRpcProvider.getBalance(
|
||||
(context as BlockchainContext).address,
|
||||
(context as BlockchainContext).blockNumber
|
||||
blockNumber
|
||||
)
|
||||
return balance >= BigNumber.from(criteria.minBalance)
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ describe("BlockchainTransactions", () => {
|
||||
{
|
||||
id: blockchainTransactions.id,
|
||||
criteria: {
|
||||
minTransactions: 10
|
||||
minTransactions: 10,
|
||||
blockNumber: 4749638
|
||||
}
|
||||
},
|
||||
{
|
||||
address: "0x",
|
||||
jsonRpcProvider: jsonRpcProviderMocked,
|
||||
blockNumber: 4749638
|
||||
jsonRpcProvider: jsonRpcProviderMocked
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -2,13 +2,21 @@ import { BlockchainContext, Validator } from "../.."
|
||||
|
||||
export type Criteria = {
|
||||
minTransactions: number
|
||||
blockNumber?: number
|
||||
}
|
||||
|
||||
const validator: Validator = {
|
||||
id: "BLOCKCHAIN_TRANSACTIONS",
|
||||
|
||||
criteriaABI: {
|
||||
minTransactions: "number"
|
||||
minTransactions: {
|
||||
type: "number",
|
||||
optional: false
|
||||
},
|
||||
blockNumber: {
|
||||
type: "number",
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -19,11 +27,16 @@ const validator: Validator = {
|
||||
*/
|
||||
async validate(criteria: Criteria, context) {
|
||||
if ("address" in context) {
|
||||
const blockNumber =
|
||||
criteria.blockNumber !== undefined
|
||||
? criteria.blockNumber
|
||||
: undefined
|
||||
|
||||
const transactionCount = await (
|
||||
context as BlockchainContext
|
||||
).jsonRpcProvider.getTransactionCount(
|
||||
(context as BlockchainContext).address,
|
||||
(context as BlockchainContext).blockNumber
|
||||
blockNumber
|
||||
)
|
||||
return transactionCount >= criteria.minTransactions
|
||||
}
|
||||
|
||||
@@ -54,11 +54,11 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 3
|
||||
minAttestations: 3,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8"
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
@@ -71,18 +71,18 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph,
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -94,18 +94,18 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d4",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph,
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d4",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -117,18 +117,18 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5d",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph,
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5d",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -140,18 +140,18 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: false,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph,
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: false,
|
||||
revoked: false,
|
||||
isOffchain: false
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -163,18 +163,18 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: true,
|
||||
isOffchain: false
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph,
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: true,
|
||||
isOffchain: false
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -186,18 +186,18 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: true
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae8",
|
||||
queryGraph: queryGraphMocked.queryGraph,
|
||||
attester: "0x63A35A52c0ac206108EBbf559E4C7109dAd281d3",
|
||||
schemaId:
|
||||
"0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
|
||||
revocable: true,
|
||||
revoked: false,
|
||||
isOffchain: true
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -209,11 +209,11 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 3
|
||||
minAttestations: 3,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9"
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9",
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
@@ -221,7 +221,7 @@ describe("EASAttestations", () => {
|
||||
expect(result).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should throw an error if a criteria parameter is missing", async () => {
|
||||
it("Should throw an error if a mandatory criteria parameter is missing", async () => {
|
||||
const fun = () =>
|
||||
validateCredentials(
|
||||
{
|
||||
@@ -229,7 +229,6 @@ describe("EASAttestations", () => {
|
||||
criteria: {}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9",
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
@@ -246,11 +245,11 @@ describe("EASAttestations", () => {
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: 1,
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9",
|
||||
test: 123
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9",
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
@@ -266,11 +265,11 @@ describe("EASAttestations", () => {
|
||||
{
|
||||
id: easAttestations.id,
|
||||
criteria: {
|
||||
minAttestations: "1"
|
||||
minAttestations: "1",
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9"
|
||||
}
|
||||
},
|
||||
{
|
||||
recipient: "0x9aB3971e1b065701C72C5f3cAFbF33118dC51ae9",
|
||||
queryGraph: queryGraphMocked.queryGraph
|
||||
}
|
||||
)
|
||||
|
||||
@@ -2,13 +2,46 @@ import { Context, EASContext, Validator } from "../.."
|
||||
|
||||
export type Criteria = {
|
||||
minAttestations: number
|
||||
recipient: string
|
||||
attester?: string
|
||||
schemaId?: string
|
||||
revocable?: boolean
|
||||
revoked?: boolean
|
||||
isOffchain?: boolean
|
||||
}
|
||||
|
||||
const validator: Validator = {
|
||||
id: "EAS_ATTESTATIONS",
|
||||
|
||||
criteriaABI: {
|
||||
minAttestations: "number"
|
||||
minAttestations: {
|
||||
type: "number",
|
||||
optional: false
|
||||
},
|
||||
recipient: {
|
||||
type: "string",
|
||||
optional: false
|
||||
},
|
||||
attester: {
|
||||
type: "string",
|
||||
optional: true
|
||||
},
|
||||
schemaId: {
|
||||
type: "string",
|
||||
optional: true
|
||||
},
|
||||
revocable: {
|
||||
type: "boolean",
|
||||
optional: true
|
||||
},
|
||||
revoked: {
|
||||
type: "boolean",
|
||||
optional: true
|
||||
},
|
||||
isOffchain: {
|
||||
type: "boolean",
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -18,7 +51,9 @@ const validator: Validator = {
|
||||
* @returns True if the user meets the criteria.
|
||||
*/
|
||||
async validate(criteria: Criteria, context: Context) {
|
||||
if ("recipient" in context) {
|
||||
if ("queryGraph" in context) {
|
||||
const getAttestations = (context as EASContext).queryGraph
|
||||
|
||||
const {
|
||||
recipient,
|
||||
attester,
|
||||
@@ -26,8 +61,7 @@ const validator: Validator = {
|
||||
revocable,
|
||||
revoked,
|
||||
isOffchain
|
||||
} = context as EASContext
|
||||
const getAttestations = (context as EASContext).queryGraph
|
||||
} = criteria
|
||||
|
||||
const attestations = await getAttestations(`
|
||||
query {
|
||||
@@ -44,10 +78,9 @@ const validator: Validator = {
|
||||
|
||||
const filteredAttestations = attestations.filter(
|
||||
(attestation: any) => {
|
||||
// Mandatory recipient check.
|
||||
// Criteria checks.
|
||||
if (attestation.recipient !== recipient) return false
|
||||
|
||||
// Optional criteria checks.
|
||||
if (
|
||||
attester !== undefined &&
|
||||
attestation.attester !== attester
|
||||
|
||||
@@ -8,7 +8,10 @@ const validator: Validator = {
|
||||
id: "GITHUB_FOLLOWERS",
|
||||
|
||||
criteriaABI: {
|
||||
minFollowers: "number"
|
||||
minFollowers: {
|
||||
type: "number",
|
||||
optional: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,10 @@ const validator: Validator = {
|
||||
id: "GITHUB_PERSONAL_STARS",
|
||||
|
||||
criteriaABI: {
|
||||
minStars: "number"
|
||||
minStars: {
|
||||
type: "number",
|
||||
optional: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,8 +9,14 @@ const validator: Validator = {
|
||||
id: "GITHUB_REPOSITORY_COMMITS",
|
||||
|
||||
criteriaABI: {
|
||||
repository: "string",
|
||||
minCommits: "number"
|
||||
minCommits: {
|
||||
type: "number",
|
||||
optional: false
|
||||
},
|
||||
repository: {
|
||||
type: "string",
|
||||
optional: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,10 @@ const validator: Validator = {
|
||||
id: "TWITTER_FOLLOWERS",
|
||||
|
||||
criteriaABI: {
|
||||
minFollowers: "number"
|
||||
minFollowers: {
|
||||
type: "number",
|
||||
optional: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,10 @@ const validator: Validator = {
|
||||
id: "TWITTER_FOLLOWING_USER",
|
||||
|
||||
criteriaABI: {
|
||||
username: "string"
|
||||
username: {
|
||||
type: "string",
|
||||
optional: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user