Merge pull request #185 from orionprotocol/integrator_service

Integrator service
This commit is contained in:
Dmitry
2023-10-04 09:10:22 +02:00
committed by GitHub
26 changed files with 624 additions and 358 deletions

340
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@orionprotocol/sdk",
"version": "0.19.92-rc2",
"version": "0.20.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@orionprotocol/sdk",
"version": "0.19.92-rc2",
"version": "0.20.2",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
@@ -622,54 +622,6 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
"integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
"integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
"integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
@@ -686,294 +638,6 @@
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
"integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
"integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
"integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
"integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
"integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
"integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
"integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
"integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
"integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
"integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
"integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
"integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
"integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
"integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
"integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
"integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
"integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
"integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "@orionprotocol/sdk",
"version": "0.20.1",
"version": "0.20.2",
"description": "Orion Protocol SDK",
"main": "./lib/index.cjs",
"module": "./lib/index.js",

View File

@@ -58,6 +58,9 @@ export default class Orion {
priceFeed: {
api: networkConfig.api + networkConfig.services.priceFeed.all,
},
integrator: {
api: networkConfig.api + networkConfig.services.integrator.http,
}
},
};
})

View File

@@ -1,21 +1,25 @@
import { ethers } from 'ethers';
import { JsonRpcProvider } from 'ethers';
import { Aggregator } from '../services/Aggregator/index.js';
import { BlockchainService } from '../services/BlockchainService/index.js';
import { PriceFeed } from '../services/PriceFeed/index.js';
import type { KnownEnv, SupportedChainId, VerboseUnitConfig } from '../types.js';
import type {
KnownEnv,
SupportedChainId,
VerboseUnitConfig,
} from '../types.js';
import Exchange from './Exchange/index.js';
import FarmingManager from './FarmingManager/index.js';
import { chains, envs } from '../config/index.js';
import type { networkCodes } from '../constants/index.js';
import type { JsonRpcProvider } from 'ethers';
import { IntegratorService } from '../services/Integrator/index.js';
type KnownConfig = {
env: KnownEnv
chainId: SupportedChainId
}
};
export default class Unit {
public readonly networkCode: typeof networkCodes[number];
public readonly networkCode: (typeof networkCodes)[number];
public readonly chainId: SupportedChainId;
@@ -23,6 +27,8 @@ export default class Unit {
public readonly blockchainService: BlockchainService;
public readonly integrator: IntegratorService;
public readonly aggregator: Aggregator;
public readonly priceFeed: PriceFeed;
@@ -38,13 +44,33 @@ export default class Unit {
constructor(config: KnownConfig | VerboseUnitConfig) {
if ('env' in config) {
const staticConfig = envs[config.env];
if (!staticConfig) throw new Error(`Invalid environment: ${config.env}. Available environments: ${Object.keys(envs).join(', ')}`);
if (!staticConfig) {
throw new Error(
`Invalid environment: ${
config.env
}. Available environments: ${Object.keys(envs).join(', ')}`
);
}
const chainConfig = chains[config.chainId];
if (!chainConfig) throw new Error(`Invalid chainId: ${config.chainId}. Available chainIds: ${Object.keys(chains).join(', ')}`);
if (!chainConfig) {
throw new Error(
`Invalid chainId: ${
config.chainId
}. Available chainIds: ${Object.keys(chains).join(', ')}`
);
}
const networkConfig = staticConfig.networks[config.chainId];
if (!networkConfig) throw new Error(`Invalid chainId: ${config.chainId}. Available chainIds: ${Object.keys(staticConfig.networks).join(', ')}`);
if (!networkConfig) {
throw new Error(
`Invalid chainId: ${
config.chainId
}. Available chainIds: ${Object.keys(staticConfig.networks).join(
', '
)}`
);
}
this.config = {
chainId: config.chainId,
nodeJsonRpc: networkConfig.rpc ?? chainConfig.rpc,
@@ -59,8 +85,11 @@ export default class Unit {
priceFeed: {
api: networkConfig.api + networkConfig.services.priceFeed.all,
},
integrator: {
api: networkConfig.api + networkConfig.services.integrator.http,
},
},
}
};
} else {
this.config = config;
}
@@ -68,19 +97,31 @@ export default class Unit {
if (!chainInfo) throw new Error('Chain info is required');
this.chainId = config.chainId;
this.networkCode = chainInfo.code;
this.contracts = chainInfo.contracts
this.contracts = chainInfo.contracts;
const intNetwork = parseInt(this.chainId, 10);
if (Number.isNaN(intNetwork)) throw new Error('Invalid chainId (not a number)' + this.chainId);
this.provider = new ethers.JsonRpcProvider(this.config.nodeJsonRpc, intNetwork);
if (Number.isNaN(intNetwork)) {
throw new Error('Invalid chainId (not a number)' + this.chainId);
}
this.provider = new JsonRpcProvider(this.config.nodeJsonRpc, intNetwork);
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.config.services.aggregator.http,
this.config.services.aggregator.ws,
this.config.basicAuth,
this.config.basicAuth
);
this.priceFeed = new PriceFeed(
this.config.services.priceFeed.api,
this.config.basicAuth
);
this.priceFeed = new PriceFeed(this.config.services.priceFeed.api, this.config.basicAuth);
this.exchange = new Exchange(this);
this.farmingManager = new FarmingManager(this);
}

View File

@@ -177,6 +177,9 @@ describe('Orion', () => {
priceFeed: {
api: orionPriceFeedAPI + '/price-feed',
},
integrator: {
api: '',
}
},
}
}

View File

@@ -15,6 +15,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
},
"liquidityMigratorAddress": "0x23a1820a47BcD022E29f6058a5FD224242F50D1A"
@@ -31,6 +34,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -46,6 +52,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -61,6 +70,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -76,6 +88,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
}
@@ -97,6 +112,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
},
"liquidityMigratorAddress": "0x01b10dds12478C88A5E18e2707E729906bC25CfF6"
@@ -113,6 +131,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -128,6 +149,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -143,6 +167,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -158,6 +185,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -173,6 +203,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
}
@@ -194,6 +227,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -209,6 +245,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -224,6 +263,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -239,6 +281,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -254,6 +299,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
}
@@ -275,6 +323,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -290,6 +341,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
}
@@ -311,6 +365,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
},
"liquidityMigratorAddress": "0x23a1820a47BcD022E29f6058a5FD224242F50D1A"
@@ -327,6 +384,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -342,6 +402,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -357,6 +420,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
},
@@ -372,6 +438,9 @@
},
"priceFeed": {
"all": "/price-feed"
},
"integrator": {
"http": "/orion-integrator/"
}
}
}

View File

@@ -14,6 +14,9 @@ export const pureEnvNetworksSchema = z.object({
priceFeed: z.object({
all: z.string(),
}),
integrator: z.object({
http: z.string(),
}),
}),
rpc: z.string().optional(),
liquidityMigratorAddress: z.string().optional(),

View File

@@ -9,5 +9,6 @@ export { default as exchangesMap } from './exchangesMap.js';
export * from './chains.js';
export * from './precisions.js';
export * from './gasLimits.js';
export * from './timings.js';
export const SERVICE_TOKEN = 'ORN';

3
src/constants/timings.ts Normal file
View File

@@ -0,0 +1,3 @@
export const DAY = 86400
export const WEEK_DAYS = 7;
export const YEAR = 365 * DAY

View File

@@ -61,8 +61,8 @@ type AtomicSwapHistoryTargetQuery = AtomicSwapHistoryBaseQuery & {
}
type PlatformFees = {
assetIn: string
assetOut: string
assetIn?: string // TODO: return types from main branch
assetOut?: string
walletAddress?: string | undefined
fromWidget?: string | undefined
}
@@ -247,8 +247,13 @@ class BlockchainService {
) => {
const url = new URL(`${this.apiUrl}/api/platform-fees`);
url.searchParams.append('assetIn', assetIn);
url.searchParams.append('assetOut', assetOut);
if (assetIn !== undefined) { // TODO: make same as in main branch
url.searchParams.append('assetIn', assetIn);
}
if (assetOut !== undefined) {
url.searchParams.append('assetOut', assetOut);
}
if (walletAddress !== undefined) {
url.searchParams.append('walletAddress', walletAddress);

View File

@@ -0,0 +1,3 @@
export const AVAILABLE_POOL_FEE = ['0.01', '0.05', '0.3', '1'] as const;
export const INITIAL_VEORN_ADJUSTMENT_FACTOR = 5;
export const LOCK_START_TIME = 1690848000;// Aug 01 2023 00:00:00 UTC

View File

@@ -0,0 +1,223 @@
import {
environmentResponseSchema,
getPoolResponseSchema,
listAmountResponseSchema,
listNFTOrderResponseSchema,
listPoolResponseSchema,
testIncrementorSchema,
veORNInfoResponseSchema,
votingInfoResponseSchema
} from './schemas/index.js';
import { fetchWithValidation } from 'simple-typed-fetch';
import { BigNumber } from 'bignumber.js';
import { DAY, WEEK_DAYS, YEAR } from '../../constants/index.js';
import { LOCK_START_TIME } from './constants.js';
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 VeORNInfoPayload = BasePayload & {
model: 'veORN'
method: 'info'
params: [string]
}
type ListAmountPayload = BasePayload & {
model: string
method: 'listAmount'
params: []
}
type GetAmountByORNPayload = BasePayload & {
amountToken: number
timeLock: number
}
type Payload =
| GetEnvironmentPayload
| ListNFTOrderPayload
| GetPoolInfoPayload
| ListPoolPayload
| VeORNInfoPayload
| ListAmountPayload
| GetAmountByORNPayload;
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);
this.veORNInfo = this.veORNInfo.bind(this);
this.listAmount = this.listAmount.bind(this);
this.getAmountByORN = this.getAmountByORN.bind(this);
this.getAmountAtCurrent = this.getAmountAtCurrent.bind(this);
this.getVotingInfo = this.getVotingInfo.bind(this);
}
readonly makeRPCPayload = (payload: Omit<Payload, 'chainId' | 'jsonrpc'>) => {
return JSON.stringify({
...payload,
chainId: this.chainId,
jsonrpc: '1.0',
});
};
readonly veORNInfo = (address: string) => {
return fetchWithValidation(this.apiUrl, veORNInfoResponseSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: 'veORN',
method: 'info',
params: [address]
})
})
}
readonly getAmountAtCurrent = (amount: number): BigNumber => {
const timestamp = Date.now() / 1000;
// sqrt
return BigNumber(amount).dividedBy(this.getK(timestamp));
}
readonly getVotingInfo = (userAddress: string) => {
return fetchWithValidation(this.apiUrl, votingInfoResponseSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: 'OrionVoting',
method: 'info',
params: [userAddress],
}),
});
}
readonly getEnvironment = () => {
return fetchWithValidation(this.apiUrl, environmentResponseSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: 'Environment',
method: 'getEnvironment',
params: [],
}),
});
};
readonly listNFTOrder = (address: string) => {
return fetchWithValidation(this.apiUrl, listNFTOrderResponseSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: 'OrionV3NFTManager',
method: 'listNFTOrder',
params: [address],
}),
});
};
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],
}),
});
}
readonly listPool = (address: string) => {
return fetchWithValidation(this.apiUrl, listPoolResponseSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: 'OrionFarmV3',
method: 'listPool',
params: [address],
}),
});
}
readonly listAmount = (poolKey: string) => {
return fetchWithValidation(this.apiUrl, listAmountResponseSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: poolKey,
method: 'listAmount',
params: [],
}),
});
}
readonly testRetrieve = () => {
return fetchWithValidation(this.apiUrl, testIncrementorSchema, {
method: 'POST',
body: this.makeRPCPayload({
model: 'Incrementer',
method: 'retrieve',
params: [],
}),
});
}
private readonly getK = (time: number) => {
const currentTime = time < LOCK_START_TIME ? LOCK_START_TIME : time;
const deltaYears = BigNumber(currentTime).minus(LOCK_START_TIME).dividedBy(YEAR);
return 2 ** BigNumber(deltaYears).multipliedBy(2).toNumber();
}
private readonly getAmountByORN = (amountToken: number, timeLock: number) => {
const timestamp = Date.now() / 1000;
const deltaDays = BigNumber(timeLock).minus(timestamp).dividedBy(DAY);
if (deltaDays.lt(0)) {
return 0;
}
// sqrt
return BigNumber(amountToken).multipliedBy(BigNumber(deltaDays).sqrt()).dividedBy(BigNumber(WEEK_DAYS).sqrt());
}
}
export * as schemas from './schemas/index.js';
export { IntegratorService };

View 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;

View File

@@ -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;

View 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;

View File

@@ -0,0 +1,8 @@
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';
export { default as veORNInfoResponseSchema } from './veORN-info-schema.js';
export { default as listAmountResponseSchema } from './list-amount-schema.js';
export { default as votingInfoResponseSchema } from './voting-info-schema.js';
export { default as testIncrementorSchema } from './test-incrementor-schema.js';

View File

@@ -0,0 +1,14 @@
import { z } from 'zod';
import { ethers } from 'ethers';
const infoSchema = z.object({
blockNumber: z.number().int().nonnegative(),
blockHash: z.string().refine((v) => v.length === 0 || ethers.utils.isHexString(v), {
message: 'blockHash must be a valid hex string or empty',
}),
timeRequest: z.number().int().nonnegative(),
timeAnswer: z.number().int().nonnegative(),
changes: z.number().int().nonnegative(),
});
export default infoSchema;

View File

@@ -0,0 +1,9 @@
import { z } from 'zod';
import infoSchema from './info-schema.js';
const listAmountSchema = z.object({
result: z.record(z.number()),
info: infoSchema,
});
export default listAmountSchema;

View File

@@ -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;

View 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;

View 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;

View File

@@ -0,0 +1,9 @@
import { z } from 'zod';
import infoSchema from './info-schema.js';
const testIncrementorSchema = z.object({
result: z.number().int(),
info: infoSchema,
});
export default testIncrementorSchema;

View 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.isHexString, (v) => ({
message: `${v} is not a valid hex string`,
}));

View File

@@ -0,0 +1,26 @@
import { z } from 'zod';
import { evmAddressSchema } from './util-schemas.js';
import infoSchema from './info-schema.js';
const veORNResultSchema = z.object({
avgAPR: z.number(),
minAPR: z.number(),
maxAPR: z.number(),
veTokenAddress: evmAddressSchema,
totalORNLocked: z.number(),
totalVeORN: z.number(),
weeklyReward: z.number(),
userAPR: z.number(),
userVeORN: z.number(),
userORNLocked: z.number(),
userLockEndDate: z.number(),
userReward: z.number(),
userWeeklyReward: z.number()
});
const veORNInfoSchema = z.object({
result: veORNResultSchema,
info: infoSchema,
});
export default veORNInfoSchema;

View File

@@ -0,0 +1,27 @@
import { z } from 'zod';
import infoSchema from './info-schema.js';
const poolSchema = z.object({
allVote: z.number(),
name: z.string(),
poolAddress: z.string(),
type: z.string(),
userVote: z.number()
})
const votingResultSchema = z.object({
absoluteVeTokenInVoting: z.number(),
pools: z.array(poolSchema),
userVeTokenBalance: z.number(),
userVeTokenInVoting: z.number(),
veTokenAddress: z.string(),
votingAddress: z.string(),
weeklyReward: z.number()
})
const votingInfoSchema = z.object({
result: votingResultSchema,
info: infoSchema,
});
export default votingInfoSchema;

View File

@@ -252,6 +252,12 @@ export type VerboseUnitConfig = {
// http://10.23.5.11:3003/,
// https://price-feed:3003/
}
integrator: {
api: string
// For example:
// http://localhost:3004/,
// http://
}
}
basicAuth?: BasicAuthCredentials
}