Backend
Details how to fetch trade data from off-chain services
Backend services, for the purpose of managing trades, do not provide anything that can't be fetched or listened to directly on-chain.
It is recommended to use gTrade backends when possible however to improve resilience against RPC issues - service is optimized for uptime.
DNS
Common DNS syntax - backend-<network>.gains.trade
Arbitrum: https://backend-arbitrum.gains.trade
Polygon: https://backend-polygon.gains.trade
Apechain: https://backend-apechain.gains.trade
Sepolia: https://backend-sepolia.gains.trade
Arbitrum WS:
wss://backend-arbitrum.gains.trade
Base WS:
wss://backend-base.gains.trade
Polygon WS:
wss://backend-polygon.gains.trade
Apechain WS:
wss://backend-apechain.gains.trade
Sepolia WS:
wss://backend-sepolia.gains.trade
NOTE: No auth is required for accessing REST GET endpoints and the WebSocket event stream. However, rate limiting is in place, so please fetch data only as necessary and rely on the event stream to keep your data updated.
Backend types
You can find backend return types HERE
Normalizing backend values
Keep in mind that for SDK usage, you need to normalize selected string values. Example: FeeBackend should be normalized to meet Fee frontend interface following way (js implementation):
const convertFee = (fee: FeeBackend): Fee => ({
totalPositionSizeFeeP: parseFloat(fee.totalPositionSizeFeeP) / 1e12,
totalLiqCollateralFeeP: parseFloat(fee.totalLiqCollateralFeeP) / 1e12,
oraclePositionSizeFeeP: parseFloat(fee.oraclePositionSizeFeeP) / 1e12,
minPositionSizeUsd: parseFloat(fee.minPositionSizeUsd) / 1e3,
});
Common Endpoints
Trading Variables
Provides main data necessary for opening, closing, and managing trades. Payload also contains all active trades (allTrades
).
Request:
GET /trading-variables
Response:
{
lastRefreshed: "2024-05-20T21:07:02.133Z", // string, timestamp
refreshId: 6180, // number, unique identifier
tradingState: 0, // ITradingStorage.TradingActivated, 0: Activated, 1: CloseOnly, 2: Paused
maxGainP: 1000000, // deprecated; Maximum PNL % is no longer enforced
marketOrdersTimeoutBlocks: 200, // number of blocks after which an unsuccessful order's collateral can be reclaimed
globalTradeFeeParams: { // object<string, string>, breakdown of how `fees[feeIndex].totalPositionSizeFeeP` is split per category in 1e3 precision (%)
referralFeeP: "5000",
govFeeP: "24500",
triggerOrderFeeP: "4000",
gnsOtcFeeP: "56500",
gTokenFeeP: "15000"
},
pairs : [ // array, containing objects for each trading pair
{
from: "ETH",
to: "USD",
spreadP: "400000000",
groupIndex: "0",
feeIndex: "0"
},
// Other trading pairs...
],
groups: [ // array, containing objects for each trading group
{
name: "crypto",
minLeverage: "2",
maxLeverage: "150"
},
// Other trading groups...
],
fees: [ // array, containing objects for each fee category
{
totalPositionSizeFeeP: "600000000", // % in 1e10 precision
totalLiqCollateralFeeP: "100000000000", // % in 1e10 precision
oraclePositionSizeFeeP: "20000000", // % in 1e10 precision
minPositionSizeUsd: "1250000" // USD in 1e3 precision
},
// Other fee categories...
],
pairInfos: {
maxLeverages: [], // array, leverage overrides for each pair index for risk management
pairDepths: [] // array, 1% depth (in USD) for current price per each pair index
pairFactors: [] // array, protection close & cumulative factors for each pair index
},
collaterals: [ // array, containing objects for each supported collateral
{
collateralIndex: 1,
collateral: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", // string, collateral token address e.g., WETH, USDC, DAI
symbol: "DAI",
isActive: true,
prices: {}, // object, collateral / GNS USD prices
collateralConfig: {}, // object, collateral precision and decimals
gToken: {}, // object, address and market cap of gToken e.g., gWETH, gUSDC, gDAI
borrowingFees: {} // object, fees for every group and pair index
},
// Other collaterals...
],
sssTokenBalance: "23314652901338666091114242", // string, amount of $GNS staked in single-side staking
sssLegacyTokenBalance: "112675327174399043872284", // string, legacy single-side staking balance
sssRewardTokens: ["0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", ...], // array, addresses of tokens (collaterals) distributed as rewards
vaultClosingFeeP: "50", // number, vault closing fee percentage
maxNegativePnlOnOpenP: 400000000000, // number, maximum negative PnL threshold upon trade opening
blockConfirmations: 1, // number, required block confirmations
oiWindowsSettings: { // object, settings for cumulative volume windows
startTs: 1704401556,
windowsDuration: 150,
windowsCount: 4
},
oiWindows: [ // array, cumulative volume window objects for each trading pair
{
"1645": {
oiLongUsd: "8484501256212500000000", // open longs + close shorts
oiShortUsd: "17262712465625000000000" // close longs + open shorts
},
// Other windows...
},
// Other trading pairs...
],
feeTiers: { // object, gCredit system fee tiers
tiers: [ // array, all possible point tiers/thresholds
{
feeMultiplier: "975",
pointsThreshold: "6000000"
},
// Other tiers...
],
multipliers: [ // array, point multipliers for each trading group (by index)
"8000",
// Other multipliers...
]
},
allTrades: [ // array, objects representing each active trade/order
{
trade: {
user: "0x7152BC14A1eFBfD553D1Cbc7D4E49e63Dae5A669",
index: "0", // user's trade index
pairIndex: "19",
leverage: "150000", // number, leverage supports up to 3 decimals
long: true,
isOpen: true,
collateralIndex: "1",
tradeType: "2", // number, 0 - MARKET, 1 - LIMIT, 2 - STOP
collateralAmount: "550000000000000000000",
openPrice: "7700000000",
tp: "8162000000",
sl: "0"
},
tradeInfo: {
createdBlock: "192695790",
tpLastUpdatedBlock: "192695790",
slLastUpdatedBlock: "192695790",
maxSlippageP: "1000",
lastOiUpdateTs: 0,
collateralPriceUsd: "0"
},
initialAccFees: {
accPairFee: "0",
accGroupFee: "0",
block: "0"
}
},
// Other trades...
],
currentBlock: 213452457,
currentL1Block: 19916646,
isForexOpen: true,
isStocksOpen: false,
isIndicesOpen: false,
isCommoditiesOpen: true,
}
User Trading Variables
Provides useful trader specific data, such as pending order IDs and fee tiers.
Request:
GET /user-trading-variables/<address>
Response:
{
pendingMarketOrdersIds: [],
pendingMarketOrders: [], // array, user's market orders that are currently being processed
feeTiers: { // object, gCredit system details
traderInfo: {
lastDayUpdated: 19864, // number, last recorded day on-chain
trailingPoints: "199553481323944469547134920" // string, cumulative user's gCredit points
},
lastDayUpdatedPoints: "5397470676054960000000000", // string, user's on-chain points as of the last update
inboundPoints: "5397470676054960000000000", // string, points expected to be added the next day
outboundPoints: "0", // string, points expected to expire the next day
expiredPoints: [] // array of strings, points for each expired day not yet recorded on-chain
},
collaterals: [ // array, user holdings and allowances for each collateral
{
balance: "5000086815959570800000", // string, user's collateral balance
allowance: "5000086815959570800000", // string, user's collateral allowance
decimals: 18 // number, number of decimal places for the collateral
},
// Other collaterals...
]
}
Historical Trades
Provides all historical trades (open & closed) for a given address
Request:
GET /personal-trading-history-table/<address>
Provides all open & closed trades in last 24hrs
GET /trading-history-24h
Response (same for both historical endpoints):
[
{
date: "2024-05-21T12:04:44.000Z", // string, timestamp
pair: "W/USD",
address: "0x1454A3be2322B60B813713E11af36bbAF4CfeeA7",
action: "TradeOpenedMarket", // string, type of trade action (see TradeAction type below)
price: 0.5697297128,
collateralPriceUsd: 1.0003745,
long: 1, // number, position direction (1 for long, 0 for short)
size: 3160.946482, // number, trade collateral
leverage: 7,
pnl_net: 0, // number, net profit and loss after fees
tx: "0x7e71dd845bb791803c16b13e4e5fe6c1a764dec4aef8205dd1f7ab8c91309aff",
collateralIndex: 1,
collateralDelta: 5, // number if collateral updated through partials
leverageDelta: 20, // number if leverage updated through partials
marketPrice: 0.5837195234 // number, market price during position size update through partials
},
// Other trades...
]
// Possible values for TradeAction
type TradeAction = [
'TradeOpenedMarket',
'TradeClosedMarket',
'TradeOpenedLimit',
'TradeClosedTP',
'TradeClosedSL',
'TradeClosedLIQ'
'TradeLeverageUpdate',
'TradePosSizeIncrease',
'TradePosSizeDecrease'
];
Event Stream
As mentioned in Events, backend event streams can serve as proxies for on-chain trade events. The stream will publish both unconfirmed and confirmed events. Unconfirmed events are published until the risk a block is reorged is negligible, at which point a confirmed event is sent. For most integrations, only confirmed events (liveEvent
) need to be listened to.
Backends also publish structured, post-processed events based on what on-chain event has just taken place. For example, registerTrade
provides a full trade struct following the raw event MarketOrderExecuted
. This is to limit how much clients need to fetch additional data.
Structure:
{
name: <event name>,
value: { <payload> },
}
Common event names:
liveEvents
- raw on-chain events. Payload is identical to on-chain event.registerTrade
- trade has been registeredunregisterTrade
- trade has been closedupdateTrade
- trade SL/TP has been updatedupdateLeverage
- trade leverage updated (collateral removed or added)updatePositionSize
- trade position size updated (adding to position or partial close)tradingVariables
- updated/trading-variables
payloadcurrentBlock
- L2 block number for networkcurrentL1Block
- L1 block number for networkdeepReorg
- Reorg has been detected - refresh datanew-trade-history
- New trade history document
Last updated
Was this helpful?