Skip to content

Commit

Permalink
Merge branch 'main' into feat/OP-5062-new-referral-system
Browse files Browse the repository at this point in the history
# Conflicts:
#	package-lock.json
#	package.json
  • Loading branch information
TheJuze committed Feb 23, 2024
2 parents ef7cbf4 + 5613f8c commit c871587
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 29 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package",
"name": "@electra.finance/sdk",
"version": "0.2.7-rc7",
"version": "0.2.7",
"description": "Electra finance SDK",
"main": "./lib/index.cjs",
"module": "./lib/index.js",
Expand Down
8 changes: 6 additions & 2 deletions src/constants/positionStatuses.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const positionStatuses = [
'SHORT',
export const positionSides = [
'LONG',
'SHORT'
] as const

const positionStatuses = [
...positionSides,
'CLOSING',
'LIQUIDATION',
'ZERO',
Expand Down
7 changes: 1 addition & 6 deletions src/crypt/signCancelOrder.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import { ethers } from 'ethers';
import CANCEL_ORDER_TYPES from '../constants/cancelOrderTypes.js';
import type { CancelOrderRequest, SignedCancelOrderRequest, SupportedChainId } from '../types.js';
import getDomainData from './getDomainData.js';
import signCancelOrderPersonal from './signCancelOrderPersonal.js';

type SignerWithTypedDataSign = ethers.Signer & TypedDataSigner;

const signCancelOrder = async (
senderAddress: string,
id: string,
Expand All @@ -21,13 +18,11 @@ const signCancelOrder = async (
isPersonalSign: usePersonalSign,
isFromDelegate,
};
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const typedDataSigner = signer as SignerWithTypedDataSign;

const signature = usePersonalSign
? await signCancelOrderPersonal(cancelOrderRequest, signer)
// https://docs.ethers.io/v5/api/signer/#Signer-signTypedData
: await typedDataSigner.signTypedData(
: await signer.signTypedData(
getDomainData(chainId),
CANCEL_ORDER_TYPES,
cancelOrderRequest,
Expand Down
13 changes: 6 additions & 7 deletions src/crypt/signCrossMarginCFDOrder.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { DEFAULT_EXPIRATION, INTERNAL_PROTOCOL_PRECISION } from '../constants/index.js';
import { DEFAULT_EXPIRATION, INTERNAL_PROTOCOL_PRECISION } from '../constants';
import type { CrossMarginCFDOrder, SignedCrossMarginCFDOrder, SupportedChainId } from '../types.js';
import normalizeNumber from '../utils/normalizeNumber.js';
import getDomainData from './getDomainData.js';
import { CROSS_MARGIN_CFD_ORDER_TYPES } from '../constants/cfdOrderTypes.js';
import signCrossMarginCFDOrderPersonal from './signCrossMarginCFDOrderPersonal.js';
import hashCrossMarginCFDOrder from './hashCrossMarginCFDOrder.js';

type SignerWithTypedDataSign = ethers.Signer & TypedDataSigner;

export const signCrossMarginCFDOrder = async (
instrumentIndex: number,
side: 'BUY' | 'SELL',
Expand All @@ -23,6 +20,7 @@ export const signCrossMarginCFDOrder = async (
signer: ethers.Signer,
chainId: SupportedChainId,
stopPrice: BigNumber.Value | undefined,
leverage: string | undefined,
isFromDelegate?: boolean,
) => {
const nonce = Date.now();
Expand Down Expand Up @@ -52,15 +50,16 @@ export const signCrossMarginCFDOrder = async (
stopPrice: stopPrice !== undefined
? new BigNumber(stopPrice).toNumber()
: undefined,
leverage: leverage !== undefined
? leverage
: undefined,
isPersonalSign: usePersonalSign,
isFromDelegate,
};

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const typedDataSigner = signer as SignerWithTypedDataSign;
const signature = usePersonalSign
? await signCrossMarginCFDOrderPersonal(order, signer)
: await typedDataSigner.signTypedData(
: await signer.signTypedData(
getDomainData(chainId),
CROSS_MARGIN_CFD_ORDER_TYPES,
order,
Expand Down
7 changes: 1 addition & 6 deletions src/crypt/signIsolatedMarginCFDOrder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { DEFAULT_EXPIRATION, INTERNAL_PROTOCOL_PRECISION } from '../constants/index.js';
Expand All @@ -13,8 +12,6 @@ import signIsolatedMarginCFDOrderPersonal from './signIsolatedMarginCFDOrderPers
import hashIsolatedMarginCFDOrder from './hashIsolatedMarginCFDOrder.js';
import { ISOLATED_MARGIN_CFD_ORDER_TYPES } from '../constants/cfdOrderTypes.js';

type SignerWithTypedDataSign = ethers.Signer & TypedDataSigner;

export const signIsolatedMarginCFDOrder = async (
instrumentAddress: string,
side: 'BUY' | 'SELL',
Expand Down Expand Up @@ -61,11 +58,9 @@ export const signIsolatedMarginCFDOrder = async (
isFromDelegate,
};

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const typedDataSigner = signer as SignerWithTypedDataSign;
const signature = usePersonalSign
? await signIsolatedMarginCFDOrderPersonal(order, signer)
: await typedDataSigner.signTypedData(
: await signer.signTypedData(
getDomainData(chainId),
ISOLATED_MARGIN_CFD_ORDER_TYPES,
order,
Expand Down
3 changes: 2 additions & 1 deletion src/services/Aggregator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { z } from 'zod';
import exchangeInfoSchema from './schemas/exchangeInfoSchema.js';
import cancelOrderSchema from './schemas/cancelOrderSchema.js';
import errorSchema from './schemas/errorSchema.js';
import { AggregatorWS } from './ws/index.js';
import { AggregatorWS } from './ws';
import type {
BasicAuthCredentials, IsolatedCFDOrder, SignedCancelOrderRequest, SignedCrossMarginCFDOrder, SignedOrder
} from '../../types.js';
Expand Down Expand Up @@ -272,6 +272,7 @@ class Aggregator {
);
};
}

export * as schemas from './schemas/index.js';
export * as ws from './ws/index.js';
export { Aggregator };
1 change: 1 addition & 0 deletions src/services/Aggregator/ws/MessageType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const MessageType = {
CFD_ADDRESS_UPDATE: 'auf',
ISOLATED_CFD_ADDRESS_UPDATE: 'iauf',
FUTURES_TRADE_INFO_UPDATE: 'fti',
FUTURES_TRADES_STREAM_UPDATE: 'ftsu',
UNSUBSCRIPTION_DONE: 'ud',
} as const;

Expand Down
1 change: 1 addition & 0 deletions src/services/Aggregator/ws/SubscriptionType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const SubscriptionType = {
CFD_ADDRESS_UPDATES_SUBSCRIBE: 'ausf',
ISOLATED_CFD_ADDRESS_UPDATES_SUBSCRIBE: 'iausf',
FUTURES_TRADE_INFO_SUBSCRIBE: 'fts',
FUTURES_TRADES_STREAM_SUBSCRIBE: 'ftss'
} as const;

export default SubscriptionType;
1 change: 1 addition & 0 deletions src/services/Aggregator/ws/UnsubscriptionType.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const UnsubscriptionType = {
ASSET_PAIRS_CONFIG_UPDATES_UNSUBSCRIBE: 'apcu',
FUTURES_TRADES_STREAM_UNSUBSCRIBE: 'ftsu'
} as const;
export default UnsubscriptionType;
32 changes: 29 additions & 3 deletions src/services/Aggregator/ws/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import {
pingPongMessageSchema, initMessageSchema,
errorSchema, orderBookSchema,
assetPairsConfigSchema, addressUpdateSchema,
isolatedAddressUpdateSchema
isolatedAddressUpdateSchema, futuresTradesStreamSchema
} from './schemas/index.js';
import UnsubscriptionType from './UnsubscriptionType.js';
import type {
AssetPairUpdate, OrderbookItem, Balance, CFDBalance,
FuturesTradeInfo, Json, BasicAuthCredentials, IsolatedCFDBalance,
FuturesTradeInfo, Json, BasicAuthCredentials, IsolatedCFDBalance, FuturesTradesStream,
} from '../../../types.js';
import unsubscriptionDoneSchema from './schemas/unsubscriptionDoneSchema.js';
import assetPairConfigSchema from './schemas/assetPairConfigSchema.js';
Expand Down Expand Up @@ -42,6 +42,7 @@ const messageSchema = z.union([
assetPairConfigSchema,
orderBookSchema,
futuresTradeInfoSchema,
futuresTradesStreamSchema,
errorSchema,
unsubscriptionDoneSchema,
]);
Expand Down Expand Up @@ -88,6 +89,10 @@ type FuturesTradeInfoSubscription = {
errorCb?: (message: string) => void
}

type FuturesTradesStreamSubscription = {
callback: (futuresTrades: FuturesTradesStream) => void
}

type IsolatedAddressUpdateUpdate = {
kind: 'update'
balances: Partial<
Expand Down Expand Up @@ -187,6 +192,7 @@ type Subscription = {
[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]: PairsConfigSubscription
[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]: PairConfigSubscription
[SubscriptionType.FUTURES_TRADE_INFO_SUBSCRIBE]: FuturesTradeInfoSubscription
[SubscriptionType.FUTURES_TRADES_STREAM_SUBSCRIBE]: FuturesTradesStreamSubscription
}

const exclusiveSubscriptions = [
Expand Down Expand Up @@ -280,6 +286,7 @@ class AggregatorWS {
}

private hearbeatIntervalId: NodeJS.Timer | undefined;

private setupHeartbeat() {
const heartbeat = () => {
if (this.isAlive) {
Expand Down Expand Up @@ -318,7 +325,7 @@ class AggregatorWS {
if ('payload' in subscription) {
if (typeof subscription.payload === 'string') {
subRequest['S'] = subscription.payload;
} else { // SwapInfoSubscriptionPayload | FuturesTradeInfoPayload
} else { // SwapInfoSubscriptionPayload | FuturesTradeInfoPayload | FuturesTradesStreamSubscription
subRequest['S'] = {
d: id,
...subscription.payload,
Expand Down Expand Up @@ -428,6 +435,7 @@ class AggregatorWS {
// is swap info subscription (contains hyphen)
delete this.subscriptions[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]?.[newestSubId];
delete this.subscriptions[SubscriptionType.FUTURES_TRADE_INFO_SUBSCRIBE]?.[newestSubId];
delete this.subscriptions[SubscriptionType.FUTURES_TRADES_STREAM_SUBSCRIBE]?.[newestSubId];
// !!! swap info subscription is uuid that contains hyphen
} else if (isOrderBooksSubscription(newestSubId)) { // is pair name(AGGREGATED_ORDER_BOOK_UPDATE)
const aobSubscriptions = this.subscriptions[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE];
Expand Down Expand Up @@ -578,6 +586,24 @@ class AggregatorWS {
minAmount: json.ma,
});
break;
case MessageType.FUTURES_TRADES_STREAM_UPDATE:
this.subscriptions[SubscriptionType.FUTURES_TRADES_STREAM_SUBSCRIBE]?.[json.id]?.callback(
{
timestamp: json._,
sender: json.S,
id: json.id,
instrument: json.i,
side: json.s,
amount: json.a,
leverage: json.l,
price: json.p,
txHash: json.h,
network: json.n,
realizedPnL: json.rpnl,
roi: json.r,
}
);
break;
case MessageType.INITIALIZATION:
this.onInit?.();
break;
Expand Down
8 changes: 8 additions & 0 deletions src/services/Aggregator/ws/schemas/addressUpdateSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export const orderUpdateSchema = z.object({
t: z.number(), // update time
E: z.enum(executionTypes).optional(), // execution type
C: z.string().optional(), // trigger condition
lv: z.number().optional(), // leverage
roi: z.number().optional(), // ROI%
rpnl: z.number().optional(), // realized PnL
sltp: z.enum(['STOP_LOSS', 'TAKE_PROFIT']).optional(), // side
c: subOrderSchema.array(), // sub orders (content)
Expand All @@ -67,6 +69,8 @@ export const orderUpdateSchema = z.object({
liquidated: o.l,
executionType: o.E,
triggerCondition: o.C,
leverage: o.lv,
roi: o.roi,
realizedPnL: o.rpnl,
sltp: o.sltp,
subOrders: getTransformedSubOrders(o.c),
Expand All @@ -90,6 +94,8 @@ export const fullOrderSchema = z.object({
ro: z.boolean().optional(), // reversed order
T: z.number(), // creation time / unix timestamp
t: z.number(), // update time
lv: z.number().optional(), // leverage
roi: z.number().optional(), // ROI%
c: subOrderSchema.array(), // sub orders (content)

// CFD only
Expand Down Expand Up @@ -120,6 +126,8 @@ export const fullOrderSchema = z.object({
stopPrice: o.L,
liquidated: o.l,
realizedPnL: o.rpnl,
leverage: o.lv,
roi: o.roi,
subOrders: getTransformedSubOrders(o.c),
}));

Expand Down
21 changes: 21 additions & 0 deletions src/services/Aggregator/ws/schemas/futuresTradesStreamSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { z } from 'zod';
import MessageType from '../MessageType.js';
import { positionSides } from '../../../../constants/positionStatuses';
import { networkCodes } from '../../../../constants';
// import addressSchema from '../../../../addressSchema';

export const futuresTradesStreamSchema = z.object({
T: z.literal(MessageType.FUTURES_TRADES_STREAM_UPDATE), // futures trades stream update
_: z.number(), // timestamp
S: z.string(), // sender // TODO: change to addressSchema
id: z.string(), // request id
i: z.string(), // instrument
s: z.enum(positionSides), // trade side (LONG/SHORT)
a: z.string(), // trade amount
l: z.string(), // leverage
p: z.string(), // price
h: z.string(), // transaction hash
n: z.enum(networkCodes), // network
rpnl: z.string().optional(), // realized PnL, optional
r: z.string().optional(), // ROI in %, optional
});
1 change: 1 addition & 0 deletions src/services/Aggregator/ws/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export { default as pingPongMessageSchema } from './pingPongMessageSchema.js';
export { default as balancesSchema } from './balancesSchema.js';
export { default as cfdBalancesSchema } from './cfdBalancesSchema.js';
export { default as isolatedCFDBalancesSchema } from './isolatedCFDBalancesSchema.js';
export { futuresTradesStreamSchema } from './futuresTradesStreamSchema';

export * from './orderBookSchema.js';
23 changes: 22 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import type { BigNumber } from 'bignumber.js';
import type subOrderStatuses from './constants/subOrderStatuses.js';
import type positionStatuses from './constants/positionStatuses.js';
import type { knownEnvs } from './config/schemas/index.js';
import type { positionSides } from './constants/positionStatuses.js';
import type { knownEnvs } from './config/schemas';
import type { networkCodes } from './constants';

export type DeepPartial<T> = T extends object ? {
[P in keyof T]?: DeepPartial<T[P]>;
Expand Down Expand Up @@ -32,6 +34,7 @@ export type Balance = {
allowance: string
}

export type PositionSide = typeof positionSides[number];
export type PositionStatus = typeof positionStatuses[number];

type StatesByInstrument = {
Expand Down Expand Up @@ -118,6 +121,7 @@ type BaseFuturesOrder = {
expiration: number // uint64
buySide: 0 | 1 // uint8, 1=buy, 0=sell
stopPrice?: number | undefined // uint64
leverage?: string | undefined // string
isPersonalSign: boolean // bool
isFromDelegate?: boolean | undefined // bool
}
Expand Down Expand Up @@ -186,6 +190,8 @@ export enum SupportedChainId {
// BROKEN = '0',
}

export type NetworkShortName = typeof networkCodes[number];

const balanceTypes = ['exchange', 'wallet'] as const;

export type Source = typeof balanceTypes[number];
Expand Down Expand Up @@ -249,6 +255,21 @@ export type FuturesTradeInfo = {
minAmount: number
}

export type FuturesTradesStream = {
timestamp: number
sender: string
id: string
instrument: string
side: PositionSide
amount: string
leverage: string
price: string
txHash: string
network: NetworkShortName
realizedPnL: string | undefined
roi: string | undefined
}

export enum HistoryTransactionStatus {
PENDING = 'Pending',
DONE = 'Done',
Expand Down

0 comments on commit c871587

Please sign in to comment.