Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import { eq, asc, and, gt, sql, inArray, not } from 'drizzle-orm'
import * as schema from './schema'
import { env } from '../env'
import { HLMigration, MigrationRegisteredEvent, MigrationStatus } from '../interfaces'
import { DatabaseError } from '../errors'
import { DatabaseError, DatabaseInitError } from '../errors'

let db: PostgresJsDatabase<typeof schema> | null = null

export async function initializeDatabaseConnection(): Promise<PostgresJsDatabase<typeof schema>> {
if (db) {
return db
}
try {
if (db) {
return db
}
let connection: postgres.Sql<{}> | null = null
if (env.NODE_ENV === 'local') {
//local defaults for a local db instance
Expand All @@ -34,6 +35,9 @@ export async function initializeDatabaseConnection(): Promise<PostgresJsDatabase
db = drizzle(connection, { schema })
console.log('database connection initialized')
return db
} catch (error) {
throw new DatabaseInitError('Error initializing database connection: ' + error)
}
}

export async function filterAndaddNewFractalityTokenMigrations(
Expand Down
56 changes: 54 additions & 2 deletions errors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
import { HLMigration } from "./interfaces";


export class PrivateKeyManagerInitError extends Error {
constructor(message: string) {
super(message);
this.name = "PrivateKeyManagerError";
}
}

export class DatabaseInitError extends Error {
constructor(message: string) {
super(message);
this.name = "DatabaseInitError";
}
}

export class HyperliquidInitError extends Error {
constructor(message: string) {
super(message);
this.name = "HyperliquidInitError";
}
}

export class RedisInitError extends Error {
constructor(message: string) {
super(message);
this.name = "RedisInitError";
}
}

export class BlockchainConnectionInitError extends Error {
constructor(message: string) {
super(message);
this.name = "BlockchainConnectionInitError";
}
}



export class FatalFinalizationError extends Error {
failedMigrations: HLMigration[];
constructor(message: string, failedMigrations: HLMigration[]) {
Expand Down Expand Up @@ -38,10 +76,24 @@ export class DecimalConversionError extends Error {
}
}

export class BlockchainConnectionError extends Error {
export class HyperLiquidInsufficientHlTokenError extends Error {
constructor(message: string) {
super(message);
this.name = "HyperLiquidInsufficientHlTokenError";
}
}

export class HyperLiquidInsufficientGasTokenError extends Error {
constructor(message: string) {
super(message);
this.name = "HyperLiquidInsufficientGasTokenError";
}
}

export class BlockchainGetCurrentBlockError extends Error {
constructor(message: string) {
super(message);
this.name = "BlockchainConnectionError";
this.name = "BlockchainGetCurrentBlockError";
}
}

Expand Down
16 changes: 10 additions & 6 deletions libs/BlockchainConnectionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { arbitrum, arbitrumSepolia } from 'viem/chains'
import { env } from '../env'
import abi from '../contracts/FractalityTokenMigration.sol.json'
import { MigrationRegisteredEvent } from '../interfaces'
import { AlchemyScanError, BlockchainConnectionError } from '../errors'
import { AlchemyScanError, BlockchainConnectionInitError, BlockchainGetCurrentBlockError } from '../errors'
interface BlockchainConnectionProviderOptions {
providerUrl: string
y2kTokenMigrationAddress: Address
Expand Down Expand Up @@ -57,10 +57,14 @@ export class BlockchainConnectionProvider {
public _viemClient: ReturnType<typeof createPublicClient>

constructor(opts: BlockchainConnectionProviderOptions) {
this.y2kTokenMigrationAddress = opts.y2kTokenMigrationAddress
this.frctRTokenMigrationAddress = opts.frctRTokenMigrationAddress
this._viemClient = this._init(opts)
console.log('Connected to blockchain', this._viemClient.chain!.name)
try {
this.y2kTokenMigrationAddress = opts.y2kTokenMigrationAddress
this.frctRTokenMigrationAddress = opts.frctRTokenMigrationAddress
this._viemClient = this._init(opts)
console.log('Connected to blockchain', this._viemClient.chain!.name)
} catch (error) {
throw new BlockchainConnectionInitError('Error initializing blockchain connection provider: ' + error)
}
}

private _init = (opts: BlockchainConnectionProviderOptions) => {
Expand All @@ -74,7 +78,7 @@ export class BlockchainConnectionProvider {
try {
return this._viemClient.getBlockNumber()
} catch (error) {
throw new BlockchainConnectionError('Error getting current block number: ' + error)
throw new BlockchainGetCurrentBlockError('Error getting current block number: ' + error)
}
}

Expand Down
31 changes: 22 additions & 9 deletions libs/HyperliquidManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { Hyperliquid } = require('hyperliquid')
import { setHLMigrationStatus } from '../database'
import { env } from '../env'
import { HyperliquidError } from '../errors'
import { HyperliquidError, HyperliquidInitError, HyperLiquidInsufficientGasTokenError, HyperLiquidInsufficientHlTokenError } from '../errors'
import { HLMigration, MigrationStatus } from '../interfaces'
import { DecimalConversion } from './DecimalConversion'

Expand All @@ -22,15 +22,19 @@ export class HyperliquidManager {
}

async init(arbitrumTokenDecimals: bigint) {
await this.hlSdk.connect()
this.tokenInfo = await this.getTokenInfo(env.TOKEN_ADDRESS)
console.info(
try {
await this.hlSdk.connect()
this.tokenInfo = await this.getTokenInfo(env.TOKEN_ADDRESS)
console.info(
`Using HL token with name ${this.tokenInfo.name} wei decimals ${this.tokenInfo.weiDecimals}`
)
this.decimalConversion = new DecimalConversion(
this.tokenInfo.weiDecimals,
arbitrumTokenDecimals
)
this.decimalConversion = new DecimalConversion(
this.tokenInfo.weiDecimals,
arbitrumTokenDecimals
)
} catch (error) {
throw new HyperliquidInitError('Error initializing hyperliquid manager: ' + error)
}
}

async getUserTokenBalances(userAddress: string) {
Expand Down Expand Up @@ -66,7 +70,16 @@ export class HyperliquidManager {
console.info('Transfer successful')
} else {
console.info('Transfer failed', result.response)
throw new HyperliquidError('Transfer failed: ' + result.response)

if(result.response.toLowerCase().includes('insufficient balance for token transfer')) {
throw new HyperLiquidInsufficientHlTokenError('NEED TO TOP UP HL TOKEN BALANCE - ' + result.response)
}

if(result.response.toLowerCase().includes('Insufficient USDC balance for token transfer gas')) {
throw new HyperLiquidInsufficientGasTokenError('NEED TO TOP UP USDC GAS TOKEN BALANCE - ' + result.response)
}

throw new HyperliquidError('Transfer failed for a reason not related to hl or gas balance - ' + result.response)
}
}
//4000 migrations will take aroud 1000$ USDC!
Expand Down
15 changes: 10 additions & 5 deletions libs/PrivateKeyManager.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import getSecret from "./SecretManager";
import { env } from "../env";
import { PrivateKeyManagerInitError } from "../errors";

export class PrivateKeyManager {
private privateKey: string | null = null;
async init() {
const secret = await getSecret();
if (secret) {
this.privateKey = JSON.parse(secret).HL_PRIVATE_KEY;
try {
const secret = await getSecret();
if (secret) {
this.privateKey = JSON.parse(secret).HL_PRIVATE_KEY;
console.log("private key set from secret manager");
} else if (env.PRIVATE_KEY) {
this.privateKey = env.PRIVATE_KEY;
console.log("private key set from env var");
this.privateKey = env.PRIVATE_KEY;
console.log("private key set from env var");
}
} catch (error) {
throw new PrivateKeyManagerInitError("Error initializing private key manager: " + error);
}
}
getPrivateKey() {
Expand Down
21 changes: 16 additions & 5 deletions migrationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,39 @@ export async function main(runWithCron: boolean) {
Slack.initialize(env.SLACK_TOKEN!, env.SLACK_CHANNEL_ID!)
}

let blockManager: PreviousBlockManager | null = null
let blockchainConnectionProvider: BlockchainConnectionProvider | null = null
let hlManager: HyperliquidManager | null = null
let redisOperations: RedisOperations | null = null
try{

await privateKeyManager.init()
await initializeDatabaseConnection()

const redisOperations = new RedisOperations()
redisOperations = new RedisOperations()
await redisOperations.initialize()

const hlManager = new HyperliquidManager(true, true, privateKeyManager.getPrivateKey())
hlManager = new HyperliquidManager(true, true, privateKeyManager.getPrivateKey())

const blockchainConnectionProvider = new BlockchainConnectionProvider({
blockchainConnectionProvider = new BlockchainConnectionProvider({
providerUrl: env.PROVIDER_URL,
y2kTokenMigrationAddress: env.Y2K_TOKEN_MIGRATION_ADDRESS as Address,
frctRTokenMigrationAddress: env.FRCT_R_MIGRATION_ADDRESS as Address
})

await hlManager.init(await blockchainConnectionProvider.getArbitrumTokenDecimals())

const blockManager = new PreviousBlockManager(
blockManager = new PreviousBlockManager(
redisOperations,
BigInt(env.SAFETY_CUSHION_NUMBER_OF_BLOCKS),
() => blockchainConnectionProvider.getCurrentBlockNumber()
() => blockchainConnectionProvider!.getCurrentBlockNumber()
)

} catch (error) {
console.error("Error initializing migration service due to the following error, skipping this run", error);
throw error;
}

if (runWithCron) {
console.info('starting cron job for migrations, running every 5 minutes')
const scheduledTask = cron.schedule('* * * * *', async () => {
Expand Down
Loading