Skip to content

Commit

Permalink
Merge pull request #17 from ATOR-Development/16-hardware-serial-proof…
Browse files Browse the repository at this point in the history
…-validation

hardware serial proof validation
  • Loading branch information
jim-toth committed Jul 30, 2024
2 parents d10c703 + da2d42b commit 03c488a
Show file tree
Hide file tree
Showing 33 changed files with 1,240 additions and 207 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ lerna-debug.log*
# Warp
cache/*

version.yml
version.yml
data
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ Entity-Type: <string with the type of entities stored in the datafile>
}
```

## CLI

### Seeding Relay Sale Data

- Seed Relay Sale Data
```bash
npm run cli -- seed relay-sale-data -d <path-to-relay-sale-data.csv>
```

- Remove Relay Sale Data
```bash
npm run cli -- seed relay-sale-data -d <path-to-relay-sale-data.csv> down
```

## Development

Expand Down
19 changes: 19 additions & 0 deletions cli/cli.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Module } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { MongooseModule } from '@nestjs/mongoose'

import { SeedModule } from './commands/seed.module'

@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
MongooseModule.forRootAsync({
inject: [ConfigService<{ MONGO_URI: string }>],
useFactory: (config: ConfigService) => ({
uri: config.get<string>('MONGO_URI', { infer: true })
})
}),
SeedModule
]
})
export class CliModule {}
17 changes: 17 additions & 0 deletions cli/commands/seed-lock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
import { HydratedDocument } from 'mongoose'

@Schema()
export class SeedLock {
@Prop({ type: String, required: true })
seedName: string

@Prop({ type: Number, required: true, default: Date.now })
startedAt?: number

@Prop({ type: Number, required: false })
finishedAt?: number
}

export type SeedLockDocument = HydratedDocument<SeedLock>
export const SeedLockSchema = SchemaFactory.createForClass(SeedLock)
121 changes: 121 additions & 0 deletions cli/commands/seed-relay-sale-data.subcommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { Logger } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import fs from 'fs'
import { Model } from 'mongoose'
import { CommandRunner, Option, SubCommand } from 'nest-commander'

import { SeedLock, SeedLockDocument } from './seed-lock'
import { RelaySaleData } from '../../src/verification/schemas/relay-sale-data'


@SubCommand({ name: 'relay-sale-data' })
export class RelaySaleDataSubCommand extends CommandRunner {
private readonly seedName = 'relay-sale-data'
private readonly logger = new Logger(RelaySaleDataSubCommand.name)

constructor(
@InjectModel(SeedLock.name)
private readonly seedLockModel: Model<SeedLock>,
@InjectModel(RelaySaleData.name)
private readonly relaySaleDataModel: Model<RelaySaleData>
) {
super()
}

@Option({
flags: '-d, --data <data-path>',
description: 'Path to CSV seed data',
required: true
})
parseSeedFilePath(path: string) {
const exists = fs.existsSync(path)

if (!exists) {
this.logger.error(`File not found: ${path}`)
process.exit(1)
}

return path
}

async run(
params: string[],
options: { data: string }
): Promise<void> {
const existingLock = await this.seedLockModel.findOne({
seedName: this.seedName
})

if (params.includes('down')) {
return this.down(existingLock)
} else {
return this.up(existingLock, options.data)
}
}

private async up(
existingLock: SeedLockDocument | null,
dataFilePath: string
) {
if (existingLock) {
this.logger.log(
`Found existing seed lock for ${this.seedName}`,
existingLock.toObject()
)

return
}

const saleDataCsv = fs.readFileSync(dataFilePath).toString('utf-8')
const saleDataLines = saleDataCsv.split('\r\n')

const seedLock = await this.seedLockModel.create<SeedLock>({
seedName: this.seedName
})

const session = await this.relaySaleDataModel.startSession()
session.startTransaction()

this.logger.log(`Clearing existing ${this.seedName} data`)
await this.relaySaleDataModel.deleteMany()

this.logger.log(
`Seeding ${saleDataLines.length - 1} ${this.seedName} documents.`
)
for (let i = 1; i < saleDataLines.length; i++) {
const [ serial, unparsedNftId ] = saleDataLines[i].split(',')
const parsedNftId = Number.parseInt(unparsedNftId)
const nftId = Number.isNaN(parsedNftId) ? 0 : parsedNftId

await this.relaySaleDataModel.create<RelaySaleData>({ serial, nftId })
}

await session.commitTransaction()
await session.endSession()

seedLock.finishedAt = Date.now()
await seedLock.save()

this.logger.log(
`Done seeding ${saleDataLines.length - 1} ${this.seedName} documents.`
)
}

private async down(existingLock: SeedLockDocument | null) {
if (!existingLock) {
this.logger.log(`No seed lock found for ${this.seedName}, nothing to remove`)

return
}

this.logger.log(
`Removing existing seed lock for ${this.seedName}`,
existingLock
)
await existingLock.deleteOne()

this.logger.log(`Removing existing ${this.seedName} seed data`)
const result = await this.relaySaleDataModel.deleteMany()
this.logger.log(`Removed ${result.deletedCount}`)
}
}
21 changes: 21 additions & 0 deletions cli/commands/seed.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ConfigService } from '@nestjs/config'
import { Command, CommandRunner, Option, SubCommand } from 'nest-commander'

import { RelaySaleDataSubCommand } from './seed-relay-sale-data.subcommand'

@Command({
name: 'seed',
arguments: '<seed-category>',
subCommands: [ RelaySaleDataSubCommand ]
})
export class SeedCommand extends CommandRunner {
constructor(
private readonly config: ConfigService
) {
super()
}

async run(): Promise<void> {
throw new Error('Unknown seed')
}
}
23 changes: 23 additions & 0 deletions cli/commands/seed.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Module } from '@nestjs/common'
import { ConfigModule } from '@nestjs/config'
import { MongooseModule } from '@nestjs/mongoose'

import { SeedCommand } from './seed.command'
import { SeedLock, SeedLockSchema } from './seed-lock'
import {
RelaySaleData,
RelaySaleDataSchema
} from '../../src/verification/schemas/relay-sale-data'

@Module({
imports: [
ConfigModule,
MongooseModule.forFeature([
{ name: RelaySaleData.name, schema: RelaySaleDataSchema },
{ name: SeedLock.name, schema: SeedLockSchema }
])
],
providers: [ ...SeedCommand.registerWithSubCommands() ],
exports: [ SeedCommand ]
})
export class SeedModule {}
12 changes: 12 additions & 0 deletions cli/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CommandFactory } from 'nest-commander'

import { CliModule } from './cli.module'

const bootstrap = async () => {
await CommandFactory.run(CliModule, {
logger: ['error', 'warn', 'log', 'debug'],
// errorHandler: (error) => { console.error('Validator CLI error', error) }
})
}

bootstrap()
54 changes: 54 additions & 0 deletions operations/seed-relay-sale-data.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
job "seed-relay-sale-data" {
datacenters = ["ator-fin"]
type = "batch"

group "seed-relay-sale-data-group" {
count = 1

volume "relay-sale-data-volume" {
type = "host"
read_only = true
source = "relay-sale-data-volume"
}

network {
mode = "bridge"
port "validator" {
to = 3000
host_network = "wireguard"
}
}

vault {
// TODO
}

task "seed-relay-sale-data-task" {
driver = "docker"

volume_mount {
volume = "relay-sale-data-volume"

read_only = true
}

env {
// TODO
}

template {
// TODO
}

config {
image = "ghcr.io/ator-development/valid-ator:[[.deploy]]"
entrypoint = [ "npm" ]
args = [
"run", "cli", "--",
"seed", "relay-sale-data",
"--data", "TODO -> pathtodata" // TODO
]
}
}
}
}
Loading

0 comments on commit 03c488a

Please sign in to comment.