Change repository name and cretae error foulder (#819)
* Change repository name and cretae error foulder * Rename SolanaFailure file * Rename SolanaFailure file --------- Co-authored-by: Julian Merlo <julianmerlo@MacBook-Pro-de-Julian.local>
This commit is contained in:
parent
f29443d8b6
commit
1109c5d135
|
@ -2,39 +2,3 @@ export * from "./evm";
|
||||||
export * from "./events";
|
export * from "./events";
|
||||||
export * from "./jobs";
|
export * from "./jobs";
|
||||||
export * as solana from "./solana";
|
export * as solana from "./solana";
|
||||||
|
|
||||||
export class Fallible<R, E> {
|
|
||||||
private error?: E;
|
|
||||||
private value?: R;
|
|
||||||
|
|
||||||
constructor(value?: R, error?: E) {
|
|
||||||
this.value = value;
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getValue(): R {
|
|
||||||
if (!this.value) {
|
|
||||||
throw this.error ? this.error : new Error("No value and no error present");
|
|
||||||
}
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getError(): E {
|
|
||||||
if (!this.error) {
|
|
||||||
throw new Error("No error present");
|
|
||||||
}
|
|
||||||
return this.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isOk(): boolean {
|
|
||||||
return !this.error && this.value !== undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ok<R, E>(value: R): Fallible<R, E> {
|
|
||||||
return new Fallible<R, E>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static error<R, E>(error: E): Fallible<R, E> {
|
|
||||||
return new Fallible<R, E>(undefined, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -59,28 +59,3 @@ export enum ErrorType {
|
||||||
SkippedSlot,
|
SkippedSlot,
|
||||||
NoBlockOrBlockTime,
|
NoBlockOrBlockTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Failure extends Error {
|
|
||||||
readonly code?: number | unknown;
|
|
||||||
readonly type?: ErrorType;
|
|
||||||
constructor(code: number | unknown, message: string, type?: ErrorType) {
|
|
||||||
super(message);
|
|
||||||
this.code = code;
|
|
||||||
|
|
||||||
if (this.code === -32007 || this.code === -32009) {
|
|
||||||
this.type = ErrorType.SkippedSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public skippedSlot(): boolean {
|
|
||||||
return this.type === ErrorType.SkippedSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public noBlockOrBlockTime(): boolean {
|
|
||||||
return this.type === ErrorType.NoBlockOrBlockTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
export class Fallible<R, E> {
|
||||||
|
private value?: R;
|
||||||
|
private error?: E;
|
||||||
|
|
||||||
|
constructor(value?: R, error?: E) {
|
||||||
|
this.value = value;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getValue(): R {
|
||||||
|
if (!this.value) {
|
||||||
|
throw this.error ? this.error : new Error("No value and no error present");
|
||||||
|
}
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getError(): E {
|
||||||
|
if (!this.error) {
|
||||||
|
throw new Error("No error present");
|
||||||
|
}
|
||||||
|
return this.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOk(): boolean {
|
||||||
|
return !this.error && this.value !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ok<R, E>(value: R): Fallible<R, E> {
|
||||||
|
return new Fallible<R, E>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static error<R, E>(error: E): Fallible<R, E> {
|
||||||
|
return new Fallible<R, E>(undefined, error);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
export enum ErrorType {
|
||||||
|
SkippedSlot,
|
||||||
|
NoBlockOrBlockTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SolanaFailure extends Error {
|
||||||
|
readonly code?: number | unknown;
|
||||||
|
readonly type?: ErrorType;
|
||||||
|
|
||||||
|
constructor(code: number | unknown, message: string, type?: ErrorType) {
|
||||||
|
super(message);
|
||||||
|
this.code = code;
|
||||||
|
|
||||||
|
if (this.code === -32007 || this.code === -32009) {
|
||||||
|
this.type = ErrorType.SkippedSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public skippedSlot(): boolean {
|
||||||
|
return this.type === ErrorType.SkippedSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public noBlockOrBlockTime(): boolean {
|
||||||
|
return this.type === ErrorType.NoBlockOrBlockTime;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./SolanaFailure";
|
||||||
|
export * from "./Fallible";
|
|
@ -1,14 +1,7 @@
|
||||||
import { RunPollingJob } from "./actions/RunPollingJob";
|
import { RunPollingJob } from "./actions/RunPollingJob";
|
||||||
import {
|
import { EvmBlock, EvmLog, EvmLogFilter, Handler, JobDefinition, solana } from "./entities";
|
||||||
EvmBlock,
|
|
||||||
EvmLog,
|
|
||||||
EvmLogFilter,
|
|
||||||
Fallible,
|
|
||||||
Handler,
|
|
||||||
JobDefinition,
|
|
||||||
solana,
|
|
||||||
} from "./entities";
|
|
||||||
import { ConfirmedSignatureInfo } from "./entities/solana";
|
import { ConfirmedSignatureInfo } from "./entities/solana";
|
||||||
|
import { Fallible, SolanaFailure } from "./errors";
|
||||||
|
|
||||||
export interface EvmBlockRepository {
|
export interface EvmBlockRepository {
|
||||||
getBlockHeight(finality: string): Promise<bigint>;
|
getBlockHeight(finality: string): Promise<bigint>;
|
||||||
|
@ -18,7 +11,7 @@ export interface EvmBlockRepository {
|
||||||
|
|
||||||
export interface SolanaSlotRepository {
|
export interface SolanaSlotRepository {
|
||||||
getLatestSlot(commitment: string): Promise<number>;
|
getLatestSlot(commitment: string): Promise<number>;
|
||||||
getBlock(slot: number, finality?: string): Promise<Fallible<solana.Block, solana.Failure>>;
|
getBlock(slot: number, finality?: string): Promise<Fallible<solana.Block, SolanaFailure>>;
|
||||||
getSignaturesForAddress(
|
getSignaturesForAddress(
|
||||||
address: string,
|
address: string,
|
||||||
beforeSig: string,
|
beforeSig: string,
|
||||||
|
|
|
@ -5,13 +5,13 @@ import {
|
||||||
SnsEventRepository,
|
SnsEventRepository,
|
||||||
EvmJsonRPCBlockRepository,
|
EvmJsonRPCBlockRepository,
|
||||||
EvmJsonRPCBlockRepositoryCfg,
|
EvmJsonRPCBlockRepositoryCfg,
|
||||||
FileMetadataRepo,
|
FileMetadataRepository,
|
||||||
PromStatRepository,
|
PromStatRepository,
|
||||||
StaticJobRepository,
|
StaticJobRepository,
|
||||||
Web3SolanaSlotRepository,
|
Web3SolanaSlotRepository,
|
||||||
} from "./repositories";
|
} from "./repositories";
|
||||||
|
|
||||||
import { HttpClient } from "./repositories/HttpClient";
|
import { HttpClient } from "./http/HttpClient";
|
||||||
import { JobRepository } from "../domain/repositories";
|
import { JobRepository } from "../domain/repositories";
|
||||||
|
|
||||||
export class RepositoriesBuilder {
|
export class RepositoriesBuilder {
|
||||||
|
@ -31,7 +31,7 @@ export class RepositoriesBuilder {
|
||||||
this.repositories.set("metrics", new PromStatRepository());
|
this.repositories.set("metrics", new PromStatRepository());
|
||||||
|
|
||||||
this.cfg.metadata?.dir &&
|
this.cfg.metadata?.dir &&
|
||||||
this.repositories.set("metadata", new FileMetadataRepo(this.cfg.metadata.dir));
|
this.repositories.set("metadata", new FileMetadataRepository(this.cfg.metadata.dir));
|
||||||
|
|
||||||
this.cfg.supportedChains.forEach((chain) => {
|
this.cfg.supportedChains.forEach((chain) => {
|
||||||
if (!this.cfg.platforms[chain]) throw new Error(`No config for chain ${chain}`);
|
if (!this.cfg.platforms[chain]) throw new Error(`No config for chain ${chain}`);
|
||||||
|
@ -80,7 +80,7 @@ export class RepositoriesBuilder {
|
||||||
return this.getRepo("sns");
|
return this.getRepo("sns");
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMetadataRepository(): FileMetadataRepo {
|
public getMetadataRepository(): FileMetadataRepository {
|
||||||
return this.getRepo("metadata");
|
return this.getRepo("metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { EvmBlock, EvmLogFilter, EvmLog, EvmTag } from "../../domain/entities";
|
||||||
import { EvmBlockRepository } from "../../domain/repositories";
|
import { EvmBlockRepository } from "../../domain/repositories";
|
||||||
import { AxiosInstance } from "axios";
|
import { AxiosInstance } from "axios";
|
||||||
import winston from "../log";
|
import winston from "../log";
|
||||||
import { HttpClient, HttpClientError } from "./HttpClient";
|
import { HttpClient, HttpClientError } from "../http/HttpClient";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EvmJsonRPCBlockRepository is a repository that uses a JSON RPC endpoint to fetch blocks.
|
* EvmJsonRPCBlockRepository is a repository that uses a JSON RPC endpoint to fetch blocks.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { MetadataRepository } from "../../domain/repositories";
|
import { MetadataRepository } from "../../domain/repositories";
|
||||||
|
|
||||||
export class FileMetadataRepo implements MetadataRepository<any> {
|
export class FileMetadataRepository implements MetadataRepository<any> {
|
||||||
private readonly dirPath: string;
|
private readonly dirPath: string;
|
||||||
|
|
||||||
constructor(dirPath: string) {
|
constructor(dirPath: string) {
|
|
@ -15,13 +15,13 @@ import {
|
||||||
SolanaSlotRepository,
|
SolanaSlotRepository,
|
||||||
StatRepository,
|
StatRepository,
|
||||||
} from "../../domain/repositories";
|
} from "../../domain/repositories";
|
||||||
import { FileMetadataRepo, SnsEventRepository } from "./index";
|
import { FileMetadataRepository, SnsEventRepository } from "./index";
|
||||||
import { HandleSolanaTransactions } from "../../domain/actions/solana/HandleSolanaTransactions";
|
import { HandleSolanaTransactions } from "../../domain/actions/solana/HandleSolanaTransactions";
|
||||||
import { solanaLogMessagePublishedMapper, evmLogMessagePublishedMapper } from "../mappers";
|
import { solanaLogMessagePublishedMapper, evmLogMessagePublishedMapper } from "../mappers";
|
||||||
import log from "../log";
|
import log from "../log";
|
||||||
|
|
||||||
export class StaticJobRepository implements JobRepository {
|
export class StaticJobRepository implements JobRepository {
|
||||||
private fileRepo: FileMetadataRepo;
|
private fileRepo: FileMetadataRepository;
|
||||||
private dryRun: boolean = false;
|
private dryRun: boolean = false;
|
||||||
private sources: Map<string, (def: JobDefinition) => RunPollingJob> = new Map();
|
private sources: Map<string, (def: JobDefinition) => RunPollingJob> = new Map();
|
||||||
private handlers: Map<string, (cfg: any, target: string, mapper: any) => Promise<Handler>> =
|
private handlers: Map<string, (cfg: any, target: string, mapper: any) => Promise<Handler>> =
|
||||||
|
@ -45,7 +45,7 @@ export class StaticJobRepository implements JobRepository {
|
||||||
solanaSlotRepo: SolanaSlotRepository;
|
solanaSlotRepo: SolanaSlotRepository;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
this.fileRepo = new FileMetadataRepo(path);
|
this.fileRepo = new FileMetadataRepository(path);
|
||||||
this.blockRepoProvider = blockRepoProvider;
|
this.blockRepoProvider = blockRepoProvider;
|
||||||
this.metadataRepo = repos.metadataRepo;
|
this.metadataRepo = repos.metadataRepo;
|
||||||
this.statsRepo = repos.statsRepo;
|
this.statsRepo = repos.statsRepo;
|
||||||
|
|
|
@ -4,11 +4,11 @@ import {
|
||||||
PublicKey,
|
PublicKey,
|
||||||
VersionedTransactionResponse,
|
VersionedTransactionResponse,
|
||||||
SolanaJSONRPCError,
|
SolanaJSONRPCError,
|
||||||
Finality,
|
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
|
|
||||||
import { Fallible, solana } from "../../domain/entities";
|
import { solana } from "../../domain/entities";
|
||||||
import { SolanaSlotRepository } from "../../domain/repositories";
|
import { SolanaSlotRepository } from "../../domain/repositories";
|
||||||
|
import { Fallible, SolanaFailure } from "../../domain/errors";
|
||||||
|
|
||||||
export class Web3SolanaSlotRepository implements SolanaSlotRepository {
|
export class Web3SolanaSlotRepository implements SolanaSlotRepository {
|
||||||
connection: Connection;
|
connection: Connection;
|
||||||
|
@ -21,7 +21,7 @@ export class Web3SolanaSlotRepository implements SolanaSlotRepository {
|
||||||
return this.connection.getSlot(commitment as Commitment);
|
return this.connection.getSlot(commitment as Commitment);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBlock(slot: number, finality?: string): Promise<Fallible<solana.Block, solana.Failure>> {
|
getBlock(slot: number, finality?: string): Promise<Fallible<solana.Block, SolanaFailure>> {
|
||||||
return this.connection
|
return this.connection
|
||||||
.getBlock(slot, {
|
.getBlock(slot, {
|
||||||
maxSupportedTransactionVersion: 0,
|
maxSupportedTransactionVersion: 0,
|
||||||
|
@ -29,21 +29,21 @@ export class Web3SolanaSlotRepository implements SolanaSlotRepository {
|
||||||
})
|
})
|
||||||
.then((block) => {
|
.then((block) => {
|
||||||
if (block === null) {
|
if (block === null) {
|
||||||
return Fallible.error<solana.Block, solana.Failure>(
|
return Fallible.error<solana.Block, SolanaFailure>(
|
||||||
new solana.Failure(0, "Block not found")
|
new SolanaFailure(0, "Block not found")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Fallible.ok<solana.Block, solana.Failure>({
|
return Fallible.ok<solana.Block, SolanaFailure>({
|
||||||
...block,
|
...block,
|
||||||
transactions: block.transactions.map((tx) => this.mapTx(tx, slot)),
|
transactions: block.transactions.map((tx) => this.mapTx(tx, slot)),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err instanceof SolanaJSONRPCError) {
|
if (err instanceof SolanaJSONRPCError) {
|
||||||
return Fallible.error(new solana.Failure(err.code, err.message));
|
return Fallible.error(new SolanaFailure(err.code, err.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Fallible.error(new solana.Failure(0, err.message));
|
return Fallible.error(new SolanaFailure(0, err.message));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ if (!("toJSON" in BigInt.prototype)) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from "./FileMetadataRepo";
|
export * from "./FileMetadataRepository";
|
||||||
export * from "./SnsEventRepository";
|
export * from "./SnsEventRepository";
|
||||||
export * from "./EvmJsonRPCBlockRepository";
|
export * from "./EvmJsonRPCBlockRepository";
|
||||||
export * from "./PromStatRepository";
|
export * from "./PromStatRepository";
|
||||||
|
|
|
@ -10,7 +10,8 @@ import {
|
||||||
StatRepository,
|
StatRepository,
|
||||||
} from "../../../../src/domain/repositories";
|
} from "../../../../src/domain/repositories";
|
||||||
import { thenWaitForAssertion } from "../../../wait-assertion";
|
import { thenWaitForAssertion } from "../../../wait-assertion";
|
||||||
import { Fallible, solana } from "../../../../src/domain/entities";
|
import { solana } from "../../../../src/domain/entities";
|
||||||
|
import { Fallible } from "../../../../src/domain/errors";
|
||||||
|
|
||||||
let pollSolanaTransactions: PollSolanaTransactions;
|
let pollSolanaTransactions: PollSolanaTransactions;
|
||||||
let cfg: PollSolanaTransactionsConfig;
|
let cfg: PollSolanaTransactionsConfig;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { EvmJsonRPCBlockRepository } from "../../../src/infrastructure/repositor
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import nock from "nock";
|
import nock from "nock";
|
||||||
import { EvmLogFilter, EvmTag } from "../../../src/domain/entities";
|
import { EvmLogFilter, EvmTag } from "../../../src/domain/entities";
|
||||||
import { HttpClient } from "../../../src/infrastructure/repositories/HttpClient";
|
import { HttpClient } from "../../../src/infrastructure/http/HttpClient";
|
||||||
|
|
||||||
axios.defaults.adapter = "http"; // needed by nock
|
axios.defaults.adapter = "http"; // needed by nock
|
||||||
const rpc = "http://localhost";
|
const rpc = "http://localhost";
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { describe, expect, it, beforeEach, afterEach } from "@jest/globals";
|
import { describe, expect, it, beforeEach, afterEach } from "@jest/globals";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { FileMetadataRepo } from "../../../src/infrastructure/repositories";
|
import { FileMetadataRepository } from "../../../src/infrastructure/repositories";
|
||||||
|
|
||||||
describe("FileMetadataRepo", () => {
|
describe("FileMetadataRepository", () => {
|
||||||
const dirPath = "./metadata-repo";
|
const dirPath = "./metadata-repo";
|
||||||
const repo = new FileMetadataRepo(dirPath);
|
const repo = new FileMetadataRepository(dirPath);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
if (!fs.existsSync(dirPath)) {
|
if (!fs.existsSync(dirPath)) {
|
||||||
|
|
Loading…
Reference in New Issue