mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-04-02 19:17:47 +03:00
Merge remote-tracking branch 'origin/main' into op-4438/pf-cex-prices
This commit is contained in:
@@ -8,7 +8,7 @@ import errorSchema from './schemas/errorSchema.js';
|
||||
import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema.js';
|
||||
import { AggregatorWS } from './ws/index.js';
|
||||
import { atomicSwapHistorySchema } from './schemas/atomicSwapHistorySchema.js';
|
||||
import type { BasicAuthCredentials, SignedCancelOrderRequest, SignedOrder } from '../../types.js';
|
||||
import type { BasicAuthCredentials, OrderSource, SignedCancelOrderRequest, SignedOrder } from '../../types.js';
|
||||
import {
|
||||
pairConfigSchema, aggregatedOrderbookSchema,
|
||||
exchangeOrderbookSchema, poolReservesSchema,
|
||||
@@ -74,13 +74,13 @@ class Aggregator {
|
||||
}
|
||||
|
||||
getOrder = (orderId: string, owner?: string) => {
|
||||
if (!ethers.utils.isHexString(orderId)) {
|
||||
if (!ethers.isHexString(orderId)) {
|
||||
throw new Error(`Invalid order id: ${orderId}. Must be a hex string`);
|
||||
}
|
||||
const url = new URL(`${this.apiUrl}/api/v1/order`);
|
||||
url.searchParams.append('orderId', orderId);
|
||||
if (owner !== undefined) {
|
||||
if (!ethers.utils.isAddress(owner)) {
|
||||
if (!ethers.isAddress(owner)) {
|
||||
throw new Error(`Invalid owner address: ${owner}`);
|
||||
}
|
||||
url.searchParams.append('owner', owner);
|
||||
@@ -196,7 +196,8 @@ class Aggregator {
|
||||
isCreateInternalOrder: boolean,
|
||||
isReversedOrder?: boolean,
|
||||
partnerId?: string,
|
||||
fromWidget?: boolean,
|
||||
source?: OrderSource,
|
||||
rawExchangeRestrictions?: string | undefined,
|
||||
) => {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -205,7 +206,7 @@ class Aggregator {
|
||||
'X-Reverse-Order': isReversedOrder ? 'true' : 'false',
|
||||
},
|
||||
...(partnerId !== undefined) && { 'X-Partner-Id': partnerId },
|
||||
...(fromWidget !== undefined) && { 'X-From-Widget': fromWidget ? 'true' : 'false' },
|
||||
...(source !== undefined) && { 'X-Source': source },
|
||||
...this.basicAuthHeaders,
|
||||
};
|
||||
|
||||
@@ -226,7 +227,7 @@ class Aggregator {
|
||||
{
|
||||
headers,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(signedOrder),
|
||||
body: JSON.stringify({ ...signedOrder, rawExchangeRestrictions }),
|
||||
},
|
||||
errorSchema,
|
||||
);
|
||||
|
||||
@@ -3,22 +3,22 @@ import { z } from 'zod';
|
||||
import { exchanges, orderStatuses, subOrderStatuses } from '../../../constants/index.js';
|
||||
|
||||
const blockchainOrderSchema = z.object({
|
||||
id: z.string().refine(ethers.utils.isHexString, (value) => ({
|
||||
id: z.string().refine(ethers.isHexString, (value) => ({
|
||||
message: `blockchainOrder.id must be a hex string, got ${value}`,
|
||||
})),
|
||||
senderAddress: z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
senderAddress: z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `blockchainOrder.senderAddress must be an address, got ${value}`,
|
||||
})),
|
||||
matcherAddress: z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
matcherAddress: z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `blockchainOrder.matcherAddress must be an address, got ${value}`,
|
||||
})),
|
||||
baseAsset: z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
baseAsset: z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `blockchainOrder.baseAsset must be an address, got ${value}`,
|
||||
})),
|
||||
quoteAsset: z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
quoteAsset: z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `blockchainOrder.quoteAsset must be an address, got ${value}`,
|
||||
})),
|
||||
matcherFeeAsset: z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
matcherFeeAsset: z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `blockchainOrder.matcherFeeAsset must be an address, got ${value}`,
|
||||
})),
|
||||
amount: z.number().int().nonnegative(),
|
||||
@@ -27,7 +27,7 @@ const blockchainOrderSchema = z.object({
|
||||
nonce: z.number(),
|
||||
expiration: z.number(),
|
||||
buySide: z.union([z.literal(1), z.literal(0)]),
|
||||
signature: z.string().refine(ethers.utils.isHexString, (value) => ({
|
||||
signature: z.string().refine(ethers.isHexString, (value) => ({
|
||||
message: `blockchainOrder.signature must be a hex string, got ${value}`,
|
||||
})).nullable(),
|
||||
isPersonalSign: z.boolean(),
|
||||
@@ -43,8 +43,6 @@ const tradeInfoSchema = z.object({
|
||||
updateTime: z.number(),
|
||||
matchedBlockchainOrder: blockchainOrderSchema.optional(),
|
||||
matchedSubOrderId: z.number().int().nonnegative().optional(),
|
||||
exchangeTradeInfo: z.boolean(),
|
||||
poolTradeInfo: z.boolean(),
|
||||
});
|
||||
|
||||
const baseOrderSchema = z.object({
|
||||
@@ -53,7 +51,7 @@ const baseOrderSchema = z.object({
|
||||
amount: z.number().nonnegative(),
|
||||
remainingAmount: z.number().nonnegative(),
|
||||
price: z.number().nonnegative(),
|
||||
sender: z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
sender: z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `order.sender must be an address, got ${value}`,
|
||||
})),
|
||||
filledAmount: z.number().nonnegative(),
|
||||
@@ -77,16 +75,17 @@ const brokerAddressSchema = z.enum([
|
||||
'SELF_BROKER'
|
||||
])
|
||||
.or(selfBrokerSchema)
|
||||
.or(z.string().refine(ethers.utils.isAddress, (value) => ({
|
||||
.or(z.string().refine(ethers.isAddress, (value) => ({
|
||||
message: `subOrder.subOrders.[n].brokerAddress must be an address, got ${value}`,
|
||||
})));
|
||||
const subOrderSchema = baseOrderSchema.extend({
|
||||
price: z.number(),
|
||||
id: z.number(),
|
||||
parentOrderId: z.string().refine(ethers.utils.isHexString, (value) => ({
|
||||
parentOrderId: z.string().refine(ethers.isHexString, (value) => ({
|
||||
message: `subOrder.parentOrderId must be a hex string, got ${value}`,
|
||||
})),
|
||||
exchange: z.string(),
|
||||
exchanges: z.string().array().optional(),
|
||||
brokerAddress: brokerAddressSchema,
|
||||
tradesInfo: z.record(
|
||||
z.string().uuid(),
|
||||
@@ -97,11 +96,11 @@ const subOrderSchema = baseOrderSchema.extend({
|
||||
});
|
||||
|
||||
const orderSchema = z.object({
|
||||
orderId: z.string().refine(ethers.utils.isHexString, (value) => ({
|
||||
orderId: z.string().refine(ethers.isHexString, (value) => ({
|
||||
message: `orderId must be a hex string, got ${value}`,
|
||||
})),
|
||||
order: baseOrderSchema.extend({
|
||||
id: z.string().refine(ethers.utils.isHexString, (value) => ({
|
||||
id: z.string().refine(ethers.isHexString, (value) => ({
|
||||
message: `order.id must be a hex string, got ${value}`,
|
||||
})),
|
||||
fee: z.number().nonnegative(),
|
||||
|
||||
@@ -7,6 +7,13 @@ const orderInfoSchema = z.object({
|
||||
safePrice: z.number(),
|
||||
}).nullable();
|
||||
|
||||
const exchangeContractStep = z.object({
|
||||
pool: z.string(),
|
||||
assetIn: z.string(),
|
||||
assetOut: z.string(),
|
||||
factory: z.string(),
|
||||
});
|
||||
|
||||
const swapInfoBase = z.object({
|
||||
id: z.string(),
|
||||
amountIn: z.number(),
|
||||
@@ -22,12 +29,7 @@ const swapInfoBase = z.object({
|
||||
minAmountOut: z.number(),
|
||||
minAmountIn: z.number(),
|
||||
marketPrice: z.number().nullable(), // spending asset market price
|
||||
exchangeContractPath: z.array(z.object({
|
||||
pool: z.string(),
|
||||
assetIn: z.string(),
|
||||
assetOut: z.string(),
|
||||
factory: z.string(),
|
||||
})),
|
||||
exchangeContractPath: z.array(exchangeContractStep),
|
||||
alternatives: z.object({ // execution alternatives
|
||||
exchanges: z.array(z.string()),
|
||||
path: z.array(z.string()),
|
||||
@@ -40,6 +42,13 @@ const swapInfoBase = z.object({
|
||||
isThroughPoolOrCurve: z.boolean(),
|
||||
}).array(),
|
||||
assetNameMapping: z.record(z.string()).optional(), // address to ERC20 names
|
||||
usd: z.object({ // USD info of this swap, nullable
|
||||
aa: z.number().optional(), // available amount in, USD
|
||||
aao: z.number().optional(), // available amount out, USD
|
||||
mo: z.number().optional(), // market amount out, USD
|
||||
mi: z.number().optional(), // market amount in, USD
|
||||
d: z.string().optional(), // difference in available amount in/out (USD) and market amount out/in (USD) in percentage
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
const swapInfoByAmountIn = swapInfoBase.extend({
|
||||
|
||||
@@ -17,8 +17,6 @@ import unsubscriptionDoneSchema from './schemas/unsubscriptionDoneSchema.js';
|
||||
import assetPairConfigSchema from './schemas/assetPairConfigSchema.js';
|
||||
import type { fullOrderSchema, orderUpdateSchema } from './schemas/addressUpdateSchema.js';
|
||||
import { objectKeys } from '../../../utils/objectKeys.js';
|
||||
// import assertError from '../../../utils/assertError.js';
|
||||
// import errorSchema from './schemas/errorSchema';
|
||||
|
||||
const UNSUBSCRIBE = 'u';
|
||||
const SERVER_PING_INTERVAL = 30000;
|
||||
@@ -42,7 +40,7 @@ type SwapInfoSubscriptionPayload = {
|
||||
i: string // asset in
|
||||
o: string // asset out
|
||||
a: number // amount IN/OUT
|
||||
es?: string[] | 'cex' | 'pools' // exchange list of all cex or all pools (ORION_POOL, UNISWAP, PANCAKESWAP etc)
|
||||
es?: string // exchange list of all cex or all pools (ORION_POOL, UNISWAP, PANCAKESWAP etc)
|
||||
e?: boolean // is amount IN? Value `false` means a = amount OUT, `true` if omitted
|
||||
is?: boolean // instant settlement
|
||||
}
|
||||
@@ -528,6 +526,13 @@ class AggregatorWS {
|
||||
availableAmountOut: item.aao,
|
||||
})),
|
||||
assetsNameMapping: json.anm,
|
||||
usdInfo: json.usd && {
|
||||
availableAmountIn: json.usd.aa,
|
||||
availableAmountOut: json.usd.aao,
|
||||
marketAmountOut: json.usd.mo,
|
||||
marketAmountIn: json.usd.mi,
|
||||
difference: json.usd.d,
|
||||
},
|
||||
};
|
||||
|
||||
switch (json.k) { // kind
|
||||
|
||||
@@ -23,6 +23,7 @@ const subOrderSchema = z.object({
|
||||
A: z.number(), // settled amount
|
||||
p: z.number(), // avg weighed settlement price
|
||||
e: z.string(), // exchange
|
||||
es: z.string().array().optional(), // exchanges
|
||||
b: z.string(), // broker address
|
||||
S: z.enum(subOrderStatuses), // status
|
||||
o: z.boolean(), // internal only
|
||||
@@ -52,6 +53,7 @@ export const orderUpdateSchema = z.object({
|
||||
subOrders: o.c.map((so) => ({
|
||||
pair: so.P,
|
||||
exchange: so.e,
|
||||
exchanges: so.es,
|
||||
id: so.i,
|
||||
amount: so.a,
|
||||
settledAmount: so.A,
|
||||
@@ -106,6 +108,7 @@ export const fullOrderSchema = z.object({
|
||||
subOrders: o.c.map((so) => ({
|
||||
pair: so.P,
|
||||
exchange: so.e,
|
||||
exchanges: so.es,
|
||||
id: so.i,
|
||||
amount: so.a,
|
||||
settledAmount: so.A,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType.js';
|
||||
import baseMessageSchema from './baseMessageSchema.js';
|
||||
import factories from '../../../../constants/factories.js';
|
||||
|
||||
const alternativeSchema = z.object({ // execution alternatives
|
||||
e: z.string().array(), // exchanges
|
||||
@@ -11,6 +12,7 @@ const alternativeSchema = z.object({ // execution alternatives
|
||||
aa: z.number().optional(), // available amount in
|
||||
aao: z.number().optional(), // available amount out
|
||||
});
|
||||
const factorySchema = z.enum(factories);
|
||||
const swapInfoSchemaBase = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.SWAP_INFO),
|
||||
S: z.string(), // swap request id
|
||||
@@ -37,8 +39,15 @@ const swapInfoSchemaBase = baseMessageSchema.extend({
|
||||
p: z.string(), // pool address
|
||||
ai: z.string().toUpperCase(), // asset in
|
||||
ao: z.string().toUpperCase(), // asset out
|
||||
f: z.string().toUpperCase(), // factory
|
||||
}))
|
||||
f: factorySchema, // factory
|
||||
})),
|
||||
usd: z.object({ // USD info of this swap, nullable
|
||||
aa: z.number().optional(), // available amount in, USD
|
||||
aao: z.number().optional(), // available amount out, USD
|
||||
mo: z.number().optional(), // market amount out, USD
|
||||
mi: z.number().optional(), // market amount in, USD
|
||||
d: z.string().optional(), // difference in available amount in/out (USD) and market amount out/in (USD) in percentage
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
const swapInfoSchemaByAmountIn = swapInfoSchemaBase.extend({
|
||||
|
||||
@@ -10,15 +10,12 @@ import {
|
||||
userEarnedSchema,
|
||||
type PairStatusEnum,
|
||||
pairStatusSchema,
|
||||
governanceContractsSchema,
|
||||
governancePoolsSchema,
|
||||
governancePoolSchema,
|
||||
governanceChainsInfoSchema,
|
||||
pricesWithQuoteAssetSchema,
|
||||
referralDataSchema,
|
||||
} from './schemas/index.js';
|
||||
import type redeemOrderSchema from '../Aggregator/schemas/redeemOrderSchema.js';
|
||||
import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/atomicHistorySchema.js';
|
||||
import { makePartial } from '../../utils/index.js';
|
||||
import { makePartial } from '../../utils';
|
||||
import type { networkCodes } from '../../constants/index.js';
|
||||
import { fetchWithValidation } from 'simple-typed-fetch';
|
||||
import type { BasicAuthCredentials } from '../../types.js';
|
||||
@@ -59,6 +56,14 @@ type AtomicSwapHistoryTargetQuery = AtomicSwapHistoryBaseQuery & {
|
||||
expiredRedeem?: 0 | 1
|
||||
state?: 'REDEEMED' | 'BEFORE-REDEEM'
|
||||
}
|
||||
|
||||
type PlatformFees = {
|
||||
assetIn: string
|
||||
assetOut: string
|
||||
walletAddress?: string | undefined
|
||||
fromWidget?: string | undefined
|
||||
}
|
||||
|
||||
class BlockchainService {
|
||||
private readonly apiUrl: string;
|
||||
|
||||
@@ -106,10 +111,7 @@ class BlockchainService {
|
||||
this.getBlockNumber = this.getBlockNumber.bind(this);
|
||||
this.getRedeemOrderBySecretHash = this.getRedeemOrderBySecretHash.bind(this);
|
||||
this.claimOrder = this.claimOrder.bind(this);
|
||||
this.getGovernanceContracts = this.getGovernanceContracts.bind(this);
|
||||
this.getGovernancePools = this.getGovernancePools.bind(this);
|
||||
this.getGovernancePool = this.getGovernancePool.bind(this);
|
||||
this.getGovernanceChainsInfo = this.getGovernanceChainsInfo.bind(this);
|
||||
this.getGasLimits = this.getGasLimits.bind(this);
|
||||
}
|
||||
|
||||
get basicAuthHeaders() {
|
||||
@@ -223,31 +225,25 @@ class BlockchainService {
|
||||
);
|
||||
|
||||
/**
|
||||
* @deprecated In favor of getPlatformFees
|
||||
*/
|
||||
* @deprecated In favor of getPlatformFees
|
||||
*/
|
||||
getTokensFee = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/tokensFee`,
|
||||
z.record(z.string()).transform(makePartial),
|
||||
{ headers: this.basicAuthHeaders }
|
||||
);
|
||||
|
||||
getPlatformFees = (
|
||||
{ assetIn, assetOut, walletAddress, fromWidget }: {
|
||||
assetIn?: string | undefined,
|
||||
assetOut?: string | undefined,
|
||||
walletAddress?: string | undefined,
|
||||
fromWidget?: string | undefined
|
||||
}
|
||||
getPlatformFees = ({
|
||||
assetIn,
|
||||
assetOut,
|
||||
walletAddress,
|
||||
fromWidget
|
||||
}: PlatformFees
|
||||
) => {
|
||||
const url = new URL(`${this.apiUrl}/api/platform-fees`);
|
||||
|
||||
if (assetIn !== undefined) {
|
||||
url.searchParams.append('assetIn', assetIn);
|
||||
}
|
||||
|
||||
if (assetOut !== undefined) {
|
||||
url.searchParams.append('assetOut', assetOut);
|
||||
}
|
||||
url.searchParams.append('assetIn', assetIn);
|
||||
url.searchParams.append('assetOut', assetOut);
|
||||
|
||||
if (walletAddress !== undefined) {
|
||||
url.searchParams.append('walletAddress', walletAddress);
|
||||
@@ -264,6 +260,12 @@ class BlockchainService {
|
||||
)
|
||||
};
|
||||
|
||||
getReferralData = (walletAddress: string) => fetchWithValidation(
|
||||
`${this.apiUrl}/api/referral-data/${walletAddress}`,
|
||||
referralDataSchema,
|
||||
{ headers: this.basicAuthHeaders }
|
||||
);
|
||||
|
||||
getGasPriceWei = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/gasPrice`,
|
||||
z.string(),
|
||||
@@ -427,9 +429,9 @@ class BlockchainService {
|
||||
);
|
||||
|
||||
/**
|
||||
* Sender is user address in source BlockchainService instance \
|
||||
* Receiver is user address in target BlockchainService instance
|
||||
*/
|
||||
* Sender is user address in source BlockchainService instance \
|
||||
* Receiver is user address in target BlockchainService instance
|
||||
*/
|
||||
getAtomicSwapHistory = (query: AtomicSwapHistorySourceQuery | AtomicSwapHistoryTargetQuery) => {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
@@ -484,28 +486,10 @@ class BlockchainService {
|
||||
},
|
||||
);
|
||||
|
||||
getGovernanceContracts = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/governance/info`,
|
||||
governanceContractsSchema,
|
||||
{ headers: this.basicAuthHeaders },
|
||||
);
|
||||
|
||||
getGovernancePools = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/governance/pools`,
|
||||
governancePoolsSchema,
|
||||
{ headers: this.basicAuthHeaders },
|
||||
);
|
||||
|
||||
getGovernancePool = (address: string) => fetchWithValidation(
|
||||
`${this.apiUrl}/api/governance/pools/${address}`,
|
||||
governancePoolSchema,
|
||||
{ headers: this.basicAuthHeaders },
|
||||
);
|
||||
|
||||
getGovernanceChainsInfo = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/governance/chains-info`,
|
||||
governanceChainsInfoSchema,
|
||||
{ headers: this.basicAuthHeaders },
|
||||
getGasLimits = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/baseLimits`,
|
||||
z.record(z.number()),
|
||||
{ headers: this.basicAuthHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ const baseAtomicHistoryItem = z.object({
|
||||
_id: z.string(),
|
||||
__v: z.number(),
|
||||
asset: z.string(),
|
||||
sender: z.string().refine(ethers.utils.isAddress),
|
||||
secretHash: z.string().refine(ethers.utils.isHexString),
|
||||
receiver: z.string().refine(ethers.utils.isAddress).optional(),
|
||||
sender: z.string().refine(ethers.isAddress),
|
||||
secretHash: z.string().refine(ethers.isHexString),
|
||||
receiver: z.string().refine(ethers.isAddress).optional(),
|
||||
secret: z.string().optional(),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const governanceChainsInfoSchema = z.object({
|
||||
isChainSupported: z.boolean(),
|
||||
});
|
||||
|
||||
export default governanceChainsInfoSchema;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const governanceContractsSchema = z.object({
|
||||
controllerAddress: z.string(),
|
||||
veTOKENAddress: z.string(),
|
||||
veTOKENYieldDistributorV4Address: z.string(),
|
||||
time_total: z.string(),
|
||||
absolute_ve_token_in_voting: z.string(),
|
||||
info: z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
gaugeAddress: z.string(),
|
||||
gaugeType: z.number(),
|
||||
gaugeName: z.string(),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
export default governanceContractsSchema;
|
||||
@@ -1,18 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const governancePoolSchema = z.object({
|
||||
min_apr: z.string(),
|
||||
max_apr: z.string(),
|
||||
tvl: z.string(),
|
||||
lp_supply: z.string(),
|
||||
lp_staked: z.string(),
|
||||
lp_staked_with_boost: z.string(),
|
||||
lp_price_in_usd: z.string(),
|
||||
reward_per_period: z.string(),
|
||||
lock_time_for_max_multiplier: z.string(),
|
||||
lock_max_multiplier: z.string(),
|
||||
veorn_max_multiplier: z.string(),
|
||||
veorn_boost_scale_factor: z.string(),
|
||||
});
|
||||
|
||||
export default governancePoolSchema;
|
||||
@@ -1,28 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const governancePoolsSchema = z.array(
|
||||
z.object({
|
||||
slug: z.string(),
|
||||
identifier: z.string(),
|
||||
chain: z.string(),
|
||||
platform: z.string(),
|
||||
logo: z.string(),
|
||||
pair: z.string(),
|
||||
lp_address: z.string(),
|
||||
lp_staked: z.string(),
|
||||
lp_staked_with_boost: z.string(),
|
||||
lp_supply: z.string(),
|
||||
lp_price_in_usd: z.string(),
|
||||
farm_address: z.string(),
|
||||
pool_tokens: z.tuple([z.string(), z.string()]),
|
||||
pool_rewards: z.array(z.string()),
|
||||
tvl: z.string(),
|
||||
min_apr: z.string(),
|
||||
max_apr: z.string(),
|
||||
reward_per_period: z.array(z.string()),
|
||||
weight: z.string(),
|
||||
liquidity: z.string(),
|
||||
})
|
||||
);
|
||||
|
||||
export default governancePoolsSchema;
|
||||
@@ -12,9 +12,6 @@ export { default as atomicSummarySchema } from './atomicSummarySchema.js';
|
||||
export { default as poolsLpAndStakedSchema } from './poolsLpAndStakedSchema.js';
|
||||
export { default as userVotesSchema } from './userVotesSchema.js';
|
||||
export { default as userEarnedSchema } from './userEarnedSchema.js';
|
||||
export { default as governanceContractsSchema } from './governanceContractsSchema.js';
|
||||
export { default as governancePoolsSchema } from './governancePoolsSchema.js';
|
||||
export { default as governancePoolSchema } from './governancePoolSchema.js';
|
||||
export { default as governanceChainsInfoSchema } from './governanceChainsInfoSchema.js';
|
||||
export { default as poolsV3InfoSchema } from './poolsV3InfoSchema.js';
|
||||
export { pricesWithQuoteAssetSchema } from './pricesWithQuoteAssetSchema.js';
|
||||
export { referralDataSchema } from './referralDataSchema.js';
|
||||
@@ -11,7 +11,7 @@ const infoSchema = z.object({
|
||||
chainId: z.number(),
|
||||
chainName: z.string(),
|
||||
exchangeContractAddress: z.string(),
|
||||
swapExecutorContractAddress: z.string().optional(),
|
||||
swapExecutorContractAddress: z.string(),
|
||||
oracleContractAddress: z.string(),
|
||||
matcherAddress: z.string(),
|
||||
orderFeePercent: z.number(),
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const referralDataSchema = z.object({
|
||||
referer: z.string().nullable(),
|
||||
isReferral: z.boolean(),
|
||||
});
|
||||
1
src/services/Indexer/constants.ts
Normal file
1
src/services/Indexer/constants.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const LOCK_START_TIME = 1690848000;// Aug 01 2023 00:00:00 UTC
|
||||
266
src/services/Indexer/index.ts
Normal file
266
src/services/Indexer/index.ts
Normal file
@@ -0,0 +1,266 @@
|
||||
import {
|
||||
environmentResponseSchema,
|
||||
getPoolResponseSchema,
|
||||
listAmountResponseSchema,
|
||||
listNFTOrderResponseSchema,
|
||||
listPoolResponseSchema,
|
||||
listPoolV2ResponseSchema,
|
||||
listPoolV3ResponseSchema,
|
||||
PoolV2InfoResponseSchema,
|
||||
testIncrementorSchema,
|
||||
veORNInfoResponseSchema,
|
||||
votingInfoResponseSchema
|
||||
} from './schemas';
|
||||
import { fetchWithValidation } from 'simple-typed-fetch';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { WEEK_DAYS, YEAR } from '../../constants';
|
||||
import { LOCK_START_TIME } from './constants';
|
||||
|
||||
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' | 'OrionV2Factory'
|
||||
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 IndexerService {
|
||||
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.getListPool = this.getListPool.bind(this);
|
||||
this.listPoolV2 = this.listPoolV2.bind(this);
|
||||
this.poolV2Info = this.poolV2Info.bind(this);
|
||||
this.listPoolV3 = this.listPoolV3.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 getAmountByORN = (amountToken: string, lockingDays: number) => {
|
||||
const alpha = 730 / (30 - Math.sqrt(730 / 7)) ** (1 / 3);
|
||||
|
||||
const deltaDaysBN = BigNumber(lockingDays);
|
||||
|
||||
if (deltaDaysBN.lte(0)) return BigNumber(0);
|
||||
|
||||
const multSQRT = deltaDaysBN.dividedBy(WEEK_DAYS).sqrt();
|
||||
const multCUBE = deltaDaysBN.dividedBy(alpha).pow(3);
|
||||
|
||||
return BigNumber(amountToken)
|
||||
.multipliedBy(multSQRT.plus(multCUBE));
|
||||
};
|
||||
|
||||
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 getListPool = (userAddress?: string) => {
|
||||
return fetchWithValidation(this.apiUrl, listPoolResponseSchema, {
|
||||
method: 'POST',
|
||||
body: this.makeRPCPayload({
|
||||
model: 'OrionVoting',
|
||||
method: 'listPool',
|
||||
params: [userAddress],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
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 listPoolV2 = (address?: string) => {
|
||||
return fetchWithValidation(this.apiUrl, listPoolV2ResponseSchema, {
|
||||
method: 'POST',
|
||||
body: this.makeRPCPayload({
|
||||
model: 'OrionFarmV2',
|
||||
method: 'listPool',
|
||||
params: [address],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
readonly poolV2Info = (token0: string, token1: string, address: string | undefined) => {
|
||||
return fetchWithValidation(this.apiUrl, PoolV2InfoResponseSchema, {
|
||||
method: 'POST',
|
||||
body: this.makeRPCPayload({
|
||||
model: 'OrionV2Factory',
|
||||
method: 'getPoolInfo',
|
||||
params: [token0, token1, address],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
readonly listPoolV3 = (address?: string) => {
|
||||
return fetchWithValidation(this.apiUrl, listPoolV3ResponseSchema, {
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
export * as schemas from './schemas/index.js';
|
||||
export { IndexerService };
|
||||
26
src/services/Indexer/schemas/basic-pool-info-schema.ts
Normal file
26
src/services/Indexer/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;
|
||||
23
src/services/Indexer/schemas/environment-response-schema.ts
Normal file
23
src/services/Indexer/schemas/environment-response-schema.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
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(),
|
||||
ORN: evmAddressSchema,
|
||||
WETH9: evmAddressSchema,
|
||||
OrionV3Factory: evmAddressSchema.optional(),
|
||||
OrionV2Factory: evmAddressSchema.optional(),
|
||||
OrionV3NFTManager: evmAddressSchema.optional(),
|
||||
SwapRouterV3: evmAddressSchema.optional(),
|
||||
OrionFarmV3: evmAddressSchema.optional(),
|
||||
OrionFarmV2: evmAddressSchema.optional(),
|
||||
OrionVoting: evmAddressSchema.optional(),
|
||||
veORN: evmAddressSchema.optional(),
|
||||
}),
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default environmentResponseSchema;
|
||||
20
src/services/Indexer/schemas/get-pool-response-schema.ts
Normal file
20
src/services/Indexer/schemas/get-pool-response-schema.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
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 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.number(), basicPoolInfo.nullable()),
|
||||
}),
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default getPoolResponseSchema;
|
||||
11
src/services/Indexer/schemas/index.ts
Normal file
11
src/services/Indexer/schemas/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export { default as environmentResponseSchema } from './environment-response-schema';
|
||||
export { default as listNFTOrderResponseSchema } from './list-nft-order-response-schema';
|
||||
export { default as getPoolResponseSchema } from './get-pool-response-schema';
|
||||
export { default as listPoolResponseSchema } from './list-pool-schema';
|
||||
export { default as listPoolV2ResponseSchema } from './list-pool-v2-response-schema';
|
||||
export { default as PoolV2InfoResponseSchema } from './pool-v2-info-schema';
|
||||
export { default as listPoolV3ResponseSchema } from './list-pool-v3-response-schema';
|
||||
export { default as veORNInfoResponseSchema } from './veORN-info-schema';
|
||||
export { default as listAmountResponseSchema } from './list-amount-schema';
|
||||
export { default as votingInfoResponseSchema } from './voting-info-schema';
|
||||
export { default as testIncrementorSchema } from './test-incrementor-schema';
|
||||
14
src/services/Indexer/schemas/info-schema.ts
Normal file
14
src/services/Indexer/schemas/info-schema.ts
Normal 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.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;
|
||||
9
src/services/Indexer/schemas/list-amount-schema.ts
Normal file
9
src/services/Indexer/schemas/list-amount-schema.ts
Normal 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;
|
||||
@@ -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;
|
||||
11
src/services/Indexer/schemas/list-pool-schema.ts
Normal file
11
src/services/Indexer/schemas/list-pool-schema.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
import infoSchema from './info-schema';
|
||||
import { listPoolV2Schema } from './list-pool-v2-response-schema';
|
||||
import { listPoolV3Schema } from './list-pool-v3-response-schema';
|
||||
|
||||
const listPoolResponseSchema = z.object({
|
||||
result: z.array(listPoolV2Schema.or(listPoolV3Schema)),
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default listPoolResponseSchema;
|
||||
62
src/services/Indexer/schemas/list-pool-v2-response-schema.ts
Normal file
62
src/services/Indexer/schemas/list-pool-v2-response-schema.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { z } from 'zod';
|
||||
import { evmAddressSchema } from './util-schemas.js';
|
||||
import basicPoolInfo from './basic-pool-info-schema.js';
|
||||
import infoSchema from './info-schema.js';
|
||||
|
||||
export const listPoolV2Schema = z.object({
|
||||
pair: z.string(),
|
||||
token0: z.string().nonempty(),
|
||||
token1: z.string().nonempty(),
|
||||
name: z.string(),
|
||||
name0: z.string(),
|
||||
name1: z.string(),
|
||||
token0Address: evmAddressSchema,
|
||||
token1Address: evmAddressSchema,
|
||||
token0Decimals: z.number().int().nonnegative().max(18),
|
||||
token1Decimals: z.number().int().nonnegative().max(18),
|
||||
WETH9: evmAddressSchema,
|
||||
farmAddress: z.string().optional(),
|
||||
weight: z.number(),
|
||||
liquidity0: z.number(),
|
||||
liquidity1: z.number(),
|
||||
token0Price: z.number(),
|
||||
token1Price: z.number(),
|
||||
totalLPSupply: z.number(),
|
||||
totalLPStake: z.number(),
|
||||
totalLPStakeInUSD: z.number(),
|
||||
userLPStaked: z.number(),
|
||||
userLPStakedInUSD: z.number(),
|
||||
lpPriceInUSD: z.number(),
|
||||
lpPriceInORN: z.number(),
|
||||
userReward: z.number(),
|
||||
weeklyReward: z.number(),
|
||||
userAPR: z.number(),
|
||||
lockMaxMultiplier: z.number(),
|
||||
veornMaxMultiplier: z.number(),
|
||||
veornBoostScaleFactor: z.number(),
|
||||
lockTimeForMaxMultiplier: z.number(),
|
||||
userBoost: z.number(),
|
||||
userTimeDeposit: z.number(),
|
||||
userLockTimeStart: z.number(),
|
||||
userLockTimePeriod: z.number(),
|
||||
userVeORN: z.number(),
|
||||
userORN: z.number(),
|
||||
userRewardToPool: z.number(),
|
||||
boostTotalVeORN: z.number(),
|
||||
boostCurrentPoolReward: z.number(),
|
||||
boostTotalLiquidity: z.number(),
|
||||
boostCurrentLiquidity: z.number(),
|
||||
boostCurrentVeORN: z.number(),
|
||||
boostTotalReward: z.number(),
|
||||
|
||||
...basicPoolInfo.shape,
|
||||
|
||||
type: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const listPoolV2ResponseSchema = z.object({
|
||||
result: z.array(listPoolV2Schema),
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default listPoolV2ResponseSchema;
|
||||
32
src/services/Indexer/schemas/list-pool-v3-response-schema.ts
Normal file
32
src/services/Indexer/schemas/list-pool-v3-response-schema.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { z } from 'zod';
|
||||
import { evmAddressSchema } from './util-schemas.js';
|
||||
import basicPoolInfo from './basic-pool-info-schema.js';
|
||||
import infoSchema from './info-schema.js';
|
||||
|
||||
export const listPoolV3Schema = z.object({
|
||||
token0: z.string().nonempty(),
|
||||
token1: z.string().nonempty(),
|
||||
name: z.string(),
|
||||
name0: z.string(),
|
||||
name1: z.string(),
|
||||
token0Address: evmAddressSchema,
|
||||
token1Address: evmAddressSchema,
|
||||
token0Decimals: z.number().int().nonnegative().max(18),
|
||||
token1Decimals: z.number().int().nonnegative().max(18),
|
||||
WETH9: evmAddressSchema,
|
||||
poolFee: z.number(),
|
||||
weeklyReward: z.number(),
|
||||
weight: z.number(),
|
||||
totalLPStakeInUSD: z.number(),
|
||||
|
||||
...basicPoolInfo.shape,
|
||||
|
||||
type: z.literal('v3'),
|
||||
});
|
||||
|
||||
const listPoolV3ResponseSchema = z.object({
|
||||
result: z.array(listPoolV3Schema),
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default listPoolV3ResponseSchema;
|
||||
33
src/services/Indexer/schemas/pool-schema.ts
Normal file
33
src/services/Indexer/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;
|
||||
64
src/services/Indexer/schemas/pool-v2-info-schema.ts
Normal file
64
src/services/Indexer/schemas/pool-v2-info-schema.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { z } from 'zod';
|
||||
import { evmAddressSchema } from './util-schemas.js';
|
||||
import basicPoolInfo from './basic-pool-info-schema';
|
||||
import infoSchema from './info-schema.js';
|
||||
|
||||
const poolInfoSchema = z.object({
|
||||
pair: z.string(),
|
||||
name: z.string(),
|
||||
token0: z.string(),
|
||||
token1: z.string(),
|
||||
name0: z.string(),
|
||||
name1: z.string(),
|
||||
token0Address: evmAddressSchema,
|
||||
token1Address: evmAddressSchema,
|
||||
token0Decimals: z.number().int().nonnegative().max(18),
|
||||
token1Decimals: z.number().int().nonnegative().max(18),
|
||||
WETH9: z.string(),
|
||||
farmAddress: z.string().optional(),
|
||||
weight: z.number(),
|
||||
liquidity0: z.number(),
|
||||
liquidity1: z.number(),
|
||||
token0Price: z.number(),
|
||||
token1Price: z.number(),
|
||||
userLPBalance: z.number(),
|
||||
userLPBalanceStr: z.string(),
|
||||
totalLPSupply: z.number(),
|
||||
totalLPStake: z.number(),
|
||||
totalLPStakeInUSD: z.number(),
|
||||
userLPStaked: z.number(),
|
||||
userLPStakedInUSD: z.number(),
|
||||
lpPriceInUSD: z.number(),
|
||||
lpPriceInORN: z.number(),
|
||||
userReward: z.number(),
|
||||
userWeeklyReward: z.number(),
|
||||
userRewardToPool: z.number(),
|
||||
weeklyReward: z.number(),
|
||||
userAPR: z.number(),
|
||||
lockMaxMultiplier: z.number(),
|
||||
veornMaxMultiplier: z.number(),
|
||||
veornBoostScaleFactor: z.number(),
|
||||
lockTimeForMaxMultiplier: z.number(),
|
||||
userBoost: z.number(),
|
||||
userTimeDeposit: z.number(),
|
||||
userLockTimeStart: z.number(),
|
||||
userLockTimePeriod: z.number(),
|
||||
userVeORN: z.number(),
|
||||
userORN: z.number(),
|
||||
boostTotalVeORN: z.number(),
|
||||
boostCurrentPoolReward: z.number(),
|
||||
boostTotalLiquidity: z.number(),
|
||||
boostCurrentLiquidity: z.number(),
|
||||
boostCurrentVeORN: z.number(),
|
||||
boostTotalReward: z.number(),
|
||||
type: z.literal('v2'),
|
||||
|
||||
...basicPoolInfo.shape,
|
||||
});
|
||||
|
||||
const PoolV2InfoResponseSchema = z.object({
|
||||
result: poolInfoSchema,
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default PoolV2InfoResponseSchema;
|
||||
9
src/services/Indexer/schemas/test-incrementor-schema.ts
Normal file
9
src/services/Indexer/schemas/test-incrementor-schema.ts
Normal 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;
|
||||
14
src/services/Indexer/schemas/util-schemas.ts
Normal file
14
src/services/Indexer/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.isAddress, (v) => ({
|
||||
message: `${v} is not a valid address`,
|
||||
}));
|
||||
|
||||
export const hexStringSchema = z
|
||||
.string()
|
||||
.refine(ethers.isHexString, (v) => ({
|
||||
message: `${v} is not a valid hex string`,
|
||||
}));
|
||||
27
src/services/Indexer/schemas/veORN-info-schema.ts
Normal file
27
src/services/Indexer/schemas/veORN-info-schema.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
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(),
|
||||
userMinLockPeriod: z.number(),
|
||||
});
|
||||
|
||||
const veORNInfoSchema = z.object({
|
||||
result: veORNResultSchema,
|
||||
info: infoSchema,
|
||||
});
|
||||
|
||||
export default veORNInfoSchema;
|
||||
34
src/services/Indexer/schemas/voting-info-schema.ts
Normal file
34
src/services/Indexer/schemas/voting-info-schema.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
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(),
|
||||
token0: z.string(), // deprecated
|
||||
token1: z.string(), // deprecated
|
||||
name0: z.string(),
|
||||
name1: z.string(),
|
||||
poolFee: z.number(),
|
||||
userWeight: z.number(),
|
||||
weight: 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;
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
aggregatedHistorySchema,
|
||||
inviteCodeLinkSchema,
|
||||
contractsAddressesSchema,
|
||||
allTimeLeadersSchema,
|
||||
} from './schemas/index.js';
|
||||
import type { SupportedChainId } from '../../types.js';
|
||||
|
||||
@@ -69,8 +70,9 @@ class ReferralSystem {
|
||||
this.getMiniStats = this.getMiniStats.bind(this);
|
||||
this.getRewardsMapping = this.getRewardsMapping.bind(this);
|
||||
this.claimRewards = this.claimRewards.bind(this);
|
||||
this.getRating = this.getRating.bind(this);
|
||||
this.getRating = this.getRating.bind(this);
|
||||
this.getLeaderboard = this.getLeaderboard.bind(this);
|
||||
this.getLeaderboardSingleChain = this.getLeaderboardSingleChain.bind(this);
|
||||
this.getAllTimeLeaders = this.getAllTimeLeaders.bind(this);
|
||||
this.getContractsAddresses = this.getContractsAddresses.bind(this);
|
||||
this.getClaimInfo = this.getClaimInfo.bind(this);
|
||||
this.getAggregatedHistory = this.getAggregatedHistory.bind(this);
|
||||
@@ -205,7 +207,20 @@ class ReferralSystem {
|
||||
errorSchema
|
||||
);
|
||||
|
||||
getRating = (refererAddress: string | undefined, chainId: SupportedChainId) =>
|
||||
getLeaderboard = (refererAddress: string | undefined) =>
|
||||
fetchWithValidation(
|
||||
`${this.apiUrl}/referer/ve/rating-table-leaderboard?tag=aggregated`,
|
||||
ratingSchema,
|
||||
{
|
||||
headers:
|
||||
refererAddress !== undefined
|
||||
? { 'referer-address': refererAddress }
|
||||
: {},
|
||||
},
|
||||
errorSchema
|
||||
);
|
||||
|
||||
getLeaderboardSingleChain = (refererAddress: string | undefined, chainId: SupportedChainId) =>
|
||||
fetchWithValidation(
|
||||
`${this.apiUrl}/referer/ve/rating-table-leaderboard?chain_id=${chainId}`,
|
||||
ratingSchema,
|
||||
@@ -218,6 +233,19 @@ class ReferralSystem {
|
||||
errorSchema
|
||||
);
|
||||
|
||||
getAllTimeLeaders = (refererAddress: string | undefined) =>
|
||||
fetchWithValidation(
|
||||
`${this.apiUrl}/referer/ve/leaderboard-lifetime`,
|
||||
allTimeLeadersSchema,
|
||||
{
|
||||
headers:
|
||||
refererAddress !== undefined
|
||||
? { 'referer-address': refererAddress }
|
||||
: {},
|
||||
},
|
||||
errorSchema
|
||||
);
|
||||
|
||||
getContractsAddresses = () =>
|
||||
fetchWithValidation(
|
||||
`${this.apiUrl}/referer/view/contracts`,
|
||||
|
||||
11
src/services/ReferralSystem/schemas/allTimeLeadersSchema.ts
Normal file
11
src/services/ReferralSystem/schemas/allTimeLeadersSchema.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const allTimeLeadersSchema = z.array(z.object({
|
||||
wallet: z.string(),
|
||||
total_earnings_fmt: z.number(),
|
||||
referrals_count_fmt: z.number(),
|
||||
total_trades_fmt: z.number(),
|
||||
weekly_earnings_fmt: z.number(),
|
||||
}));
|
||||
|
||||
export default allTimeLeadersSchema;
|
||||
@@ -1,10 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
import { SupportedChainId } from '../../../types.js';
|
||||
import { isAddress } from 'ethers/lib/utils.js';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const contractsAddressesSchema = z.record(
|
||||
z.nativeEnum(SupportedChainId),
|
||||
z.string().refine(isAddress)
|
||||
z.string().refine(ethers.isAddress)
|
||||
);
|
||||
|
||||
export default contractsAddressesSchema;
|
||||
|
||||
@@ -15,8 +15,16 @@ const distinctAnalyticsSchema = z.object({
|
||||
latest_block: z.number(),
|
||||
}),
|
||||
),
|
||||
total_earned: z.number(),
|
||||
total_sent_to_governance: z.number(),
|
||||
total_earned: z.number(),
|
||||
total_volume: z.number(),
|
||||
total_trades: z.number(),
|
||||
all_time_earnings_boost_only: z.number(),
|
||||
all_time_earnings_boost_only_usd: z.number(),
|
||||
all_time_earnings: z.number(),
|
||||
all_time_earnings_usd: z.number(),
|
||||
all_weekly_earnings: z.number(),
|
||||
all_weekly_earnings_usd: z.number(),
|
||||
});
|
||||
|
||||
export default distinctAnalyticsSchema;
|
||||
|
||||
@@ -10,3 +10,4 @@ export { default as claimInfoSchema } from './claimInfoSchema.js';
|
||||
export { default as aggregatedHistorySchema } from './aggregatedHistorySchema.js';
|
||||
export { default as contractsAddressesSchema } from './contractsAddressesSchema.js';
|
||||
export { default as inviteCodeLinkSchema } from './inviteCodeLinkSchema.js';
|
||||
export { default as allTimeLeadersSchema } from './allTimeLeadersSchema.js';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const linkSchema = z.object({
|
||||
status: z.string(),
|
||||
referer: z.string(),
|
||||
ref_link: z.string(),
|
||||
});
|
||||
|
||||
export default linkSchema;
|
||||
|
||||
@@ -4,6 +4,9 @@ const ratingSchema = z.object({
|
||||
info: z.object({
|
||||
weekly_boost_budget: z.string(),
|
||||
weekly_boost_budget_fmt: z.number(),
|
||||
monthly_boost_budget: z.string(),
|
||||
monthly_boost_budget_fmt: z.number(),
|
||||
displayed_boost_budget_fmt: z.number(),
|
||||
time_left_for_the_reward: z.number(),
|
||||
time_left_for_the_reward_local: z.string(),
|
||||
time_left_for_the_reward_utc: z.string(),
|
||||
@@ -33,6 +36,11 @@ const ratingSchema = z.object({
|
||||
weighted_volume_fmt: z.number(),
|
||||
total_weight: z.string(),
|
||||
total_weight_fmt: z.number(),
|
||||
total_volume_fmt: z.number(),
|
||||
weekly_earnings_fmt: z.number(),
|
||||
total_earnings_fmt: z.number(),
|
||||
referrals_count_fmt: z.number(),
|
||||
total_trades_fmt: z.number(),
|
||||
reward: z.string(),
|
||||
reward_fmt: z.number()
|
||||
})),
|
||||
|
||||
@@ -2,3 +2,4 @@ export * as aggregator from './Aggregator/index.js';
|
||||
export * as blockchainService from './BlockchainService/index.js';
|
||||
export * as priceFeed from './PriceFeed/index.js';
|
||||
export * as referralSystem from './ReferralSystem/index.js';
|
||||
export * as indexer from './Indexer/index.js';
|
||||
|
||||
Reference in New Issue
Block a user