mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-22 21:59:44 +03:00
feat!: added Integrator service
This commit is contained in:
@@ -58,6 +58,9 @@ export default class Orion {
|
|||||||
priceFeed: {
|
priceFeed: {
|
||||||
api: networkConfig.api + networkConfig.services.priceFeed.all,
|
api: networkConfig.api + networkConfig.services.priceFeed.all,
|
||||||
},
|
},
|
||||||
|
integrator: {
|
||||||
|
api: networkConfig.api + networkConfig.services.integrator.http,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Exchange from './Exchange/index.js';
|
|||||||
import FarmingManager from './FarmingManager/index.js';
|
import FarmingManager from './FarmingManager/index.js';
|
||||||
import { chains, envs } from '../config/index.js';
|
import { chains, envs } from '../config/index.js';
|
||||||
import type { networkCodes } from '../constants/index.js';
|
import type { networkCodes } from '../constants/index.js';
|
||||||
|
import { IntegratorService } from '../services/Integrator/index.js';
|
||||||
|
|
||||||
type KnownConfig = {
|
type KnownConfig = {
|
||||||
env: KnownEnv
|
env: KnownEnv
|
||||||
@@ -22,6 +23,8 @@ export default class Unit {
|
|||||||
|
|
||||||
public readonly blockchainService: BlockchainService;
|
public readonly blockchainService: BlockchainService;
|
||||||
|
|
||||||
|
public readonly integrator: IntegratorService;
|
||||||
|
|
||||||
public readonly aggregator: Aggregator;
|
public readonly aggregator: Aggregator;
|
||||||
|
|
||||||
public readonly priceFeed: PriceFeed;
|
public readonly priceFeed: PriceFeed;
|
||||||
@@ -58,6 +61,9 @@ export default class Unit {
|
|||||||
priceFeed: {
|
priceFeed: {
|
||||||
api: networkConfig.api + networkConfig.services.priceFeed.all,
|
api: networkConfig.api + networkConfig.services.priceFeed.all,
|
||||||
},
|
},
|
||||||
|
integrator: {
|
||||||
|
api: networkConfig.api + networkConfig.services.integrator.http,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -65,7 +71,7 @@ export default class Unit {
|
|||||||
}
|
}
|
||||||
const chainInfo = chains[config.chainId];
|
const chainInfo = chains[config.chainId];
|
||||||
if (!chainInfo) throw new Error('Chain info is required');
|
if (!chainInfo) throw new Error('Chain info is required');
|
||||||
|
|
||||||
this.chainId = config.chainId;
|
this.chainId = config.chainId;
|
||||||
this.networkCode = chainInfo.code;
|
this.networkCode = chainInfo.code;
|
||||||
this.contracts = chainInfo.contracts
|
this.contracts = chainInfo.contracts
|
||||||
@@ -75,6 +81,7 @@ export default class Unit {
|
|||||||
this.provider.pollingInterval = 1000;
|
this.provider.pollingInterval = 1000;
|
||||||
|
|
||||||
this.blockchainService = new BlockchainService(this.config.services.blockchainService.http, this.config.basicAuth);
|
this.blockchainService = new BlockchainService(this.config.services.blockchainService.http, this.config.basicAuth);
|
||||||
|
this.integrator = new IntegratorService(this.config.services.integrator.api, intNetwork);
|
||||||
this.aggregator = new Aggregator(
|
this.aggregator = new Aggregator(
|
||||||
this.config.services.aggregator.http,
|
this.config.services.aggregator.http,
|
||||||
this.config.services.aggregator.ws,
|
this.config.services.aggregator.ws,
|
||||||
|
|||||||
@@ -177,6 +177,9 @@ describe('Orion', () => {
|
|||||||
priceFeed: {
|
priceFeed: {
|
||||||
api: orionPriceFeedAPI + '/price-feed',
|
api: orionPriceFeedAPI + '/price-feed',
|
||||||
},
|
},
|
||||||
|
integrator: {
|
||||||
|
api: '',
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ export const pureEnvNetworksSchema = z.object({
|
|||||||
priceFeed: z.object({
|
priceFeed: z.object({
|
||||||
all: z.string(),
|
all: z.string(),
|
||||||
}),
|
}),
|
||||||
|
integrator: z.object({
|
||||||
|
http: z.string(),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
rpc: z.string().optional(),
|
rpc: z.string().optional(),
|
||||||
liquidityMigratorAddress: z.string().optional(),
|
liquidityMigratorAddress: z.string().optional(),
|
||||||
|
|||||||
1
src/services/Integrator/constants.ts
Normal file
1
src/services/Integrator/constants.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const AVAILABLE_POOL_FEE = ['0.01', '0.05', '0.3', '1'] as const;
|
||||||
121
src/services/Integrator/index.ts
Normal file
121
src/services/Integrator/index.ts
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import {
|
||||||
|
environmentResponseSchema,
|
||||||
|
getPoolResponseSchema,
|
||||||
|
listNFTOrderResponseSchema,
|
||||||
|
listPoolResponseSchema,
|
||||||
|
} from './schemas/index.js';
|
||||||
|
import { fetchWithValidation } from 'simple-typed-fetch';
|
||||||
|
|
||||||
|
type BasePayload = {
|
||||||
|
chainId: number
|
||||||
|
jsonrpc: '1.0'
|
||||||
|
};
|
||||||
|
|
||||||
|
type GetEnvironmentPayload = BasePayload & {
|
||||||
|
model: 'Environment'
|
||||||
|
method: 'getEnvironment'
|
||||||
|
params: []
|
||||||
|
};
|
||||||
|
|
||||||
|
type ListNFTOrderPayload = BasePayload & {
|
||||||
|
model: 'OrionV3NFTManager'
|
||||||
|
method: 'listNFTOrder'
|
||||||
|
params: [string]
|
||||||
|
};
|
||||||
|
|
||||||
|
type GetPoolInfoPayload = BasePayload & {
|
||||||
|
model: 'OrionV3Factory'
|
||||||
|
method: 'getPoolInfo'
|
||||||
|
params: [string, string, string]
|
||||||
|
};
|
||||||
|
|
||||||
|
type ListPoolPayload = BasePayload & {
|
||||||
|
model: 'OrionFarmV3'
|
||||||
|
method: 'listPool'
|
||||||
|
params: [string]
|
||||||
|
};
|
||||||
|
|
||||||
|
type Payload =
|
||||||
|
| GetEnvironmentPayload
|
||||||
|
| ListNFTOrderPayload
|
||||||
|
| GetPoolInfoPayload
|
||||||
|
| ListPoolPayload;
|
||||||
|
|
||||||
|
class IntegratorService {
|
||||||
|
private readonly apiUrl: string;
|
||||||
|
|
||||||
|
private readonly chainId: number;
|
||||||
|
|
||||||
|
get api() {
|
||||||
|
return this.apiUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(apiUrl: string, chainId: number) {
|
||||||
|
this.apiUrl = apiUrl;
|
||||||
|
this.chainId = chainId;
|
||||||
|
|
||||||
|
this.getEnvironment = this.getEnvironment.bind(this);
|
||||||
|
this.listNFTOrder = this.listNFTOrder.bind(this);
|
||||||
|
this.getPoolInfo = this.getPoolInfo.bind(this);
|
||||||
|
this.listPool = this.listPool.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRPCPayload = (payload: Omit<Payload, 'chainId' | 'jsonrpc'>) => {
|
||||||
|
return JSON.stringify({
|
||||||
|
...payload,
|
||||||
|
chainId: this.chainId,
|
||||||
|
jsonrpc: '1.0',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly getEnvironment = () => {
|
||||||
|
return fetchWithValidation(this.apiUrl, environmentResponseSchema, {
|
||||||
|
method: 'POST',
|
||||||
|
body: this.makeRPCPayload({
|
||||||
|
model: 'Environment',
|
||||||
|
method: 'getEnvironment',
|
||||||
|
params: [],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly listNFTOrder = (address: string) => {
|
||||||
|
return fetchWithValidation(this.apiUrl, listNFTOrderResponseSchema, {
|
||||||
|
method: 'POST',
|
||||||
|
body: this.makeRPCPayload({
|
||||||
|
model: 'OrionV3NFTManager',
|
||||||
|
method: 'listNFTOrder',
|
||||||
|
params: [address],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly getPoolInfo = (
|
||||||
|
token0: string,
|
||||||
|
token1: string,
|
||||||
|
poolAddress: string
|
||||||
|
) => {
|
||||||
|
return fetchWithValidation(this.apiUrl, getPoolResponseSchema, {
|
||||||
|
method: 'POST',
|
||||||
|
body: this.makeRPCPayload({
|
||||||
|
model: 'OrionV3Factory',
|
||||||
|
method: 'getPoolInfo',
|
||||||
|
params: [token0, token1, poolAddress],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly listPool = (address: string) => {
|
||||||
|
return fetchWithValidation(this.apiUrl, listPoolResponseSchema, {
|
||||||
|
method: 'POST',
|
||||||
|
body: this.makeRPCPayload({
|
||||||
|
model: 'OrionFarmV3',
|
||||||
|
method: 'listPool',
|
||||||
|
params: [address],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export * as schemas from './schemas/index.js';
|
||||||
|
export { IntegratorService };
|
||||||
26
src/services/Integrator/schemas/basic-pool-info-schema.ts
Normal file
26
src/services/Integrator/schemas/basic-pool-info-schema.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { evmAddressSchema } from './util-schemas.js';
|
||||||
|
|
||||||
|
const basicPoolInfo = z.object({
|
||||||
|
poolAddress: evmAddressSchema,
|
||||||
|
isInitialized: z.boolean(),
|
||||||
|
liquidity: z.number().nonnegative(),
|
||||||
|
liquidityInUsd: z.number().nonnegative(),
|
||||||
|
liquidityShare: z.number().nonnegative(),
|
||||||
|
isFarming: z.boolean(),
|
||||||
|
rewardsTotal: z.number().nonnegative(),
|
||||||
|
rewardsPerPeriod: z.number().nonnegative(),
|
||||||
|
rewardsShare: z.number().nonnegative(),
|
||||||
|
feePerPeriod: z.number().nonnegative(),
|
||||||
|
feeTotal: z.number().nonnegative(),
|
||||||
|
feeShare: z.number().nonnegative(),
|
||||||
|
tickMultiplier: z.number().nonnegative(),
|
||||||
|
MAX_TICK: z.number().nonnegative().int(),
|
||||||
|
minAPR: z.number().nonnegative(),
|
||||||
|
maxAPR: z.number().nonnegative(),
|
||||||
|
avgAPR: z.number().nonnegative(),
|
||||||
|
maxBoost: z.number().nonnegative().int(),
|
||||||
|
feeRate: z.array(z.number().nonnegative()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default basicPoolInfo;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { evmAddressSchema } from './util-schemas.js';
|
||||||
|
import infoSchema from './info-schema.js';
|
||||||
|
|
||||||
|
const environmentResponseSchema = z.object({
|
||||||
|
result: z.object({
|
||||||
|
chainId: z.number().int().nonnegative(),
|
||||||
|
nativeToken: z.string(),
|
||||||
|
OrionV3Factory: evmAddressSchema,
|
||||||
|
OrionV3NFTManager: evmAddressSchema,
|
||||||
|
SwapRouter: evmAddressSchema,
|
||||||
|
OrionFarmV3: evmAddressSchema,
|
||||||
|
OrionVoting: evmAddressSchema,
|
||||||
|
veORN: evmAddressSchema,
|
||||||
|
}),
|
||||||
|
info: infoSchema,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default environmentResponseSchema;
|
||||||
21
src/services/Integrator/schemas/get-pool-response-schema.ts
Normal file
21
src/services/Integrator/schemas/get-pool-response-schema.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { evmAddressSchema } from './util-schemas.js';
|
||||||
|
import { AVAILABLE_POOL_FEE } from '../constants.js';
|
||||||
|
import basicPoolInfo from './basic-pool-info-schema.js';
|
||||||
|
import infoSchema from './info-schema.js';
|
||||||
|
|
||||||
|
const getPoolResponseSchema = z.object({
|
||||||
|
result: z.object({
|
||||||
|
token0: z.string().nonempty(),
|
||||||
|
token1: z.string().nonempty(),
|
||||||
|
token0Address: evmAddressSchema,
|
||||||
|
token1Address: evmAddressSchema,
|
||||||
|
|
||||||
|
totalLiquidity: z.number().nonnegative(),
|
||||||
|
WETH9: evmAddressSchema,
|
||||||
|
pools: z.record(z.enum(AVAILABLE_POOL_FEE), basicPoolInfo.nullable()),
|
||||||
|
}),
|
||||||
|
info: infoSchema,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default getPoolResponseSchema;
|
||||||
4
src/services/Integrator/schemas/index.ts
Normal file
4
src/services/Integrator/schemas/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export { default as environmentResponseSchema } from './environment-response-schema.js';
|
||||||
|
export { default as listNFTOrderResponseSchema } from './list-nft-order-response-schema.js';
|
||||||
|
export { default as getPoolResponseSchema } from './get-pool-response-schema.js';
|
||||||
|
export { default as listPoolResponseSchema } from './list-pool-response-schema.js';
|
||||||
12
src/services/Integrator/schemas/info-schema.ts
Normal file
12
src/services/Integrator/schemas/info-schema.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { hexStringSchema } from './util-schemas.js';
|
||||||
|
|
||||||
|
const infoSchema = z.object({
|
||||||
|
blockNumber: z.number().int().nonnegative(),
|
||||||
|
blockHash: hexStringSchema,
|
||||||
|
timeRequest: z.number().int().nonnegative(),
|
||||||
|
timeAnswer: z.number().int().nonnegative(),
|
||||||
|
changes: z.number().int().nonnegative(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default infoSchema;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import poolSchema from './pool-schema.js';
|
||||||
|
import infoSchema from './info-schema.js';
|
||||||
|
|
||||||
|
const listNFTOrderResponseSchema = z.object({
|
||||||
|
result: z.array(poolSchema),
|
||||||
|
info: infoSchema,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default listNFTOrderResponseSchema;
|
||||||
26
src/services/Integrator/schemas/list-pool-response-schema.ts
Normal file
26
src/services/Integrator/schemas/list-pool-response-schema.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { evmAddressSchema } from './util-schemas.js';
|
||||||
|
import basicPoolInfo from './basic-pool-info-schema.js';
|
||||||
|
import infoSchema from './info-schema.js';
|
||||||
|
|
||||||
|
const poolOfListPoolSchema = z.object({
|
||||||
|
token0: z.string().nonempty(),
|
||||||
|
token1: z.string().nonempty(),
|
||||||
|
token0Address: evmAddressSchema,
|
||||||
|
token1Address: evmAddressSchema,
|
||||||
|
|
||||||
|
token0Decimals: z.number().int().nonnegative().max(18),
|
||||||
|
token1Decimals: z.number().int().nonnegative().max(18),
|
||||||
|
WETH9: evmAddressSchema,
|
||||||
|
|
||||||
|
...basicPoolInfo.shape,
|
||||||
|
|
||||||
|
type: z.string().nonempty(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const listPoolResponseSchema = z.object({
|
||||||
|
result: z.array(poolOfListPoolSchema),
|
||||||
|
info: infoSchema,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default listPoolResponseSchema;
|
||||||
33
src/services/Integrator/schemas/pool-schema.ts
Normal file
33
src/services/Integrator/schemas/pool-schema.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { evmAddressSchema } from './util-schemas.js';
|
||||||
|
|
||||||
|
const poolSchema = z.object({
|
||||||
|
tokenId: evmAddressSchema,
|
||||||
|
|
||||||
|
token0: z.string().nonempty(),
|
||||||
|
token1: z.string().nonempty(),
|
||||||
|
token0Address: evmAddressSchema,
|
||||||
|
token1Address: evmAddressSchema,
|
||||||
|
token0Decimals: z.number().int().nonnegative().max(18),
|
||||||
|
token1Decimals: z.number().int().nonnegative().max(18),
|
||||||
|
|
||||||
|
amount: z.number().nonnegative(),
|
||||||
|
amount0: z.number().nonnegative(),
|
||||||
|
amount1: z.number().nonnegative(),
|
||||||
|
from: z.number().nonnegative(),
|
||||||
|
to: z.number().nonnegative(),
|
||||||
|
fee: z.number().nonnegative(),
|
||||||
|
collectFee: z.number().nonnegative(),
|
||||||
|
reward: z.number().nonnegative(),
|
||||||
|
apr: z.number().nonnegative(),
|
||||||
|
boost: z.number().int().nonnegative(),
|
||||||
|
isStaked: z.boolean(),
|
||||||
|
poolFee: z.number().nonnegative(),
|
||||||
|
poolAddress: evmAddressSchema,
|
||||||
|
veOrnForMaxBoost: z.number().nonnegative(),
|
||||||
|
veOrnMaxBoost: z.number().nonnegative(),
|
||||||
|
veORNCurrent: z.number().nonnegative(),
|
||||||
|
time: z.number().int().nonnegative(), // tim
|
||||||
|
});
|
||||||
|
|
||||||
|
export default poolSchema;
|
||||||
14
src/services/Integrator/schemas/util-schemas.ts
Normal file
14
src/services/Integrator/schemas/util-schemas.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { ethers } from 'ethers';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const evmAddressSchema = z
|
||||||
|
.string()
|
||||||
|
.refine(ethers.utils.isAddress, (v) => ({
|
||||||
|
message: `${v} is not a valid address`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const hexStringSchema = z
|
||||||
|
.string()
|
||||||
|
.refine(ethers.utils.isAddress, (v) => ({
|
||||||
|
message: `${v} is not a valid hex string`,
|
||||||
|
}));
|
||||||
@@ -252,6 +252,12 @@ export type VerboseUnitConfig = {
|
|||||||
// http://10.23.5.11:3003/,
|
// http://10.23.5.11:3003/,
|
||||||
// https://price-feed:3003/
|
// https://price-feed:3003/
|
||||||
}
|
}
|
||||||
|
integrator: {
|
||||||
|
api: string
|
||||||
|
// For example:
|
||||||
|
// http://localhost:3004/,
|
||||||
|
// http://
|
||||||
|
}
|
||||||
}
|
}
|
||||||
basicAuth?: BasicAuthCredentials
|
basicAuth?: BasicAuthCredentials
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user