Skip to Content
Trading SDK

Morpher Trading SDK

The Morpher Trading SDK provides a comprehensive library for developers to integrate with the Morpher trading platform. It allows you to execute trades, manage orders, query market data, and check portfolio status programmatically.

Installation

npm install morpher-trading-sdk

Getting Started

First, you need to import and instantiate the MorpherTradeSDK class with the API endpoint.

import { MorpherTradeSDK } from 'morpher-trading-sdk'; const sdk = new MorpherTradeSDK('https://api.morpher.com/v2');

MorpherTradeSDK Class

constructor(endpoint: string)

Initialise the trading SDK and fetch the contract addresses and other configuration information from the backend API.

  • endpoint (string): Address of the Morpher backend API that all internal functions will connect to, usually https://api.morpher.com 

getCurrencyList({ address, publicClient, tokenAddresses })

Fetch a list of tradable currencies along with the current USD exchange rate and the current balance for each for the given ETH address.

  • address (0x${string}): The user’s Ethereum address.
  • publicClient (Viem PublicClient): A Viem PublicClient instance for interacting with the blockchain.
  • tokenAddresses (array): An array of objects containing token symbols and addresses.
    • symbol (string)
    • address (0x${string})

Returns: A promise that resolves to an object where keys are currency symbols (e.g., ‘ETH’, ‘USDC’, ‘MPH’) and values are objects with currency details.

{ [symbol: string]: { symbol: string; balance?: bigint; usd?: number; decimals?: number; usd_exchange_rate?: number; }; }

Example:

const fetchCurrencyList = async (address, publicClient) => { if (address && sdk.tokenAddress && sdk.usdcAddress) { const tokenAddresses = [ { symbol: 'MPH', address: sdk.tokenAddress }, { symbol: 'USDC', address: sdk.usdcAddress } ]; const currencyList = await sdk.getCurrencyList({ address, publicClient, tokenAddresses }); console.log(currencyList); } };

getMarketList({ type })

Fetch the market information for tradable markets from the Morpher API. This includes the market’s current status and also current OHLC pricing for the markets.

  • type (optional, TMarketType): The type of markets to fetch (e.g., 'stock', 'forex'). Defaults to 'stock'.

Returns: A promise that resolves to an object where keys are market IDs and values are market objects (TMarketData).

Example Response:

{ "STOCK_AAPL": { "market_id": "STOCK_AAPL", "name": "Apple Inc.", "symbol": "AAPL", "type": "stock" }, "CRYPTO_BTC": { "market_id": "CRYPTO_BTC", "name": "Bitcoin", "symbol": "BTC", "type": "crypto" } }

getMarketData({ eth_address, market_id })

Fetch the detailed information for a specific market and the chart data for the market. This will also include the position ID if the given ETH address has an open position in the market.

  • eth_address (0x${string}): The user’s Ethereum address.
  • market_id (string): The ID of the market (e.g., 'STOCK_AAPL').

Returns: A promise that resolves to a TMarketDetail object or undefined.

Example Response:

{ "market_id": "STOCK_AAPL", "name": "Apple Inc.", "symbol": "AAPL", "type": "stock", "close": 175.50, "change_percent": 1.2, "status": "OPEN", "position_id": "0x123abc...", "pending_order_id": "0x456def...", "data_hourly": [ [1672531200000, 174.0, 175.0, 173.5, 174.8], [1672534800000, 174.8, 176.0, 174.5, 175.9] ] }

getOrders({ eth_address, tx_hash, order_id, market_id })

Fetch a list of orders for a specific ETH address. Can also fetch a specific order by ID or tx_hash, or all orders for a specific market for a user.

  • eth_address (TAddress): The user’s Ethereum address.
  • tx_hash (optional, string): Filter by transaction hash.
  • order_id (optional, string): Filter by order ID.
  • market_id (optional, string): Filter by market ID.

Returns: A promise that resolves to an array of order objects (TORders).

Example Response:

[ { "id": "0xabc...", "position_id": "0xdef...", "eth_address": "0x123...", "market_id": "STOCK_AAPL", "direction": "long", "status": "EXECUTED", "type": "OPEN", "created_at": 1672531200, "price": "175.50", "shares": "1000000000000000000", "leverage": "100000000" } ]

Example:

const getOrderById = async (ethAddress, orderId) => { if (!ethAddress) return; const orders = await sdk.getOrders({ eth_address: ethAddress, order_id: orderId, }); if (orders && orders.length > 0) { console.log('Found order:', orders[0]); } };

getTrendingMarkets()

Fetch a list of trending markets from the Morpher API.

Returns: A promise that resolves to an array of TMarketData objects. Each object in the array represents a market, with the market ID as the key.

Example Response:

[ { "STOCK_AAPL": { "market_id": "STOCK_AAPL", "name": "Apple Inc.", "symbol": "AAPL", "type": "stock" } }, { "CRYPTO_BTC": { "market_id": "CRYPTO_BTC", "name": "Bitcoin", "symbol": "BTC", "type": "crypto" } } ]

getPortfolio({ eth_address })

Get the portfolio details for a given ETH address.

  • eth_address (TAddress): The user’s Ethereum address.

Returns: A promise that resolves to a portfolio object (TPortfolio).

Example Response:

{ "user_id": "some-uuid", "eth_address": "0x123...", "email": "user@example.com", "status": "confirmed", "chain_id": 1, "current_value": "1234500000000000000000", "cash_balance": "1000000000000000000000", "eth_balance": "500000000000000000", "tradeable_balance": "1000000000000000000000", "usdc_balance": "0", "position_count": 5 }

Example:

const fetchPortfolio = async (ethAddress) => { if (ethAddress && sdk) { try { const portfolioData = await sdk.getPortfolio({ eth_address: ethAddress }); console.log('Portfolio data:', portfolioData); } catch (err) { console.log('No portfolio found for the given address.'); } } };

getPositions({ eth_address, market_id, position_id })

Fetch all the open positions for a given ETH address.

  • eth_address (TAddress): The user’s Ethereum address.
  • market_id (optional, string): Filter by market ID.
  • position_id (optional, string): Filter by position ID.

Returns: A promise that resolves to an array of position objects (TPosition[]).

Example:

const fetchAllPositions = async (ethAddress) => { if (!ethAddress) return; const positionList = await sdk.getPositions({ eth_address: ethAddress }); console.log('All open positions:', positionList); }; const fetchSinglePosition = async (ethAddress, positionId) => { if (!ethAddress || !positionId) return; const positions = await sdk.getPositions({ eth_address: ethAddress, position_id: positionId }); if (positions && positions.length > 0) { console.log('Details for a single position:', positions[0]); } };

getReturns({ eth_address, type })

Fetch the returns breakdown for a specific user. Used for showing portfolio charts or calculating returns over a specific period.

  • eth_address (TAddress): The user’s Ethereum address.
  • type (optional, ‘d’ | ‘w’ | ‘m’ | ‘y’): The time frame for the history (‘d’ for day, ‘w’ for week, ‘m’ for month, ‘y’ for year). Defaults to 'd'.

Returns: A promise that resolves to an array of portfolio data points (TPortfolioDataPoint[]) or null.

Example:

const getDailyReturns = async (ethAddress) => { if (ethAddress && sdk) { try { // Fetch returns for the last day ('d'), week ('w'), month ('m'), or year ('y') const returnsData = await sdk.getReturns({ eth_address: ethAddress, type: 'd' }); console.log('Daily portfolio returns:', returnsData); // Example output: // [ // { timestamp: 1672531200, positions: 1050.50 }, // { timestamp: 1672617600, positions: 1055.75 }, // ... // ] } catch (err) { console.log('Error fetching returns'); } } };

getLeaderboard({ type, eth_address, app })

Fetch the leaderboard information to show where the given ETH address is on the leaderboards and the top users on each leaderboard. The leaderboards are separated by app, i.e., each app has its own leaderboards.

  • type (‘order’ | ‘returns’): The type of leaderboard to fetch.
  • eth_address (TAddress): The user’s Ethereum address.
  • app (string): The application identifier.

Returns: A promise that resolves to the leaderboard data.

getContext({ eth_address, app })

Retrieve the application-specific context for the given ETH address.

  • eth_address (TAddress): The user’s Ethereum address.
  • app (string): The application identifier.

Returns: A promise that resolves to the user’s context data.

setContext({ eth_address, id, app, user_name, display_name, profile_image })

Link application-specific context to an ETH address. This will link the local username, ID, etc., to an ETH address for display on leaderboards etc. The context does not need to be set by an application if the users should remain completely anonymous - this will only be used for social interactions.

  • eth_address (TAddress): The user’s Ethereum address.
  • id (string): The user’s unique ID within the application.
  • app (string): The application identifier.
  • user_name (optional, string): The user’s username.
  • display_name (optional, string): The user’s display name.
  • profile_image (optional, string): URL to the user’s profile image.

Returns: A promise that resolves when the context has been set.

subscribeToMarket(market_id, callback)

Subscribe to pricing updates for a specific market.

  • market_id (string): The ID of the market to subscribe to.
  • callback (function): A callback function that will be invoked with the market data on each update.

Example:

const marketId = 'STOCK_AAPL'; // Example: Apple Inc. // Define a callback to handle real-time market updates const handleMarketUpdate = (update) => { console.log('Market Update Received:', update); // Example update: { close: 175.50, ... } // Use this data to update your application's state. }; // Subscribe to the market sdk.subscribeToMarket(marketId, handleMarketUpdate); // To unsubscribe, you can subscribe to an empty market_id // sdk.subscribeToMarket("", () => {});

subscribeToOrder(eth_address, callback)

Subscribe to order execution updates for a specific ETH address. Used to see when an order executes, as this could be some time after it is initially placed.

  • eth_address (string): The user’s Ethereum address.
  • callback (function): A callback function that will be invoked with the order data on each update.

cancelOrder({ account, walletClient, publicClient, order_id, market_id, callback })

Cancel a pending order that is still awaiting execution. Pending open orders place the user’s tokens in escrow, so the order needs to be cancelled to release the tokens if the user no longer wants to execute the trade.

  • account (Viem Account): The user’s account object.
  • walletClient (Viem WalletClient): A Viem WalletClient instance for sending transactions.
  • publicClient (Viem PublicClient): A Viem PublicClient instance.
  • order_id (string): The ID of the order to cancel.
  • market_id (string): The market ID associated with the order.
  • callback (optional, function): A callback function that receives the result of the operation (TTradeCallback).

openPosition({ account, walletClient, publicClient, market_id, currency, direction, tradeAmount, leverage, callback })

Open a new position on a market or extend an existing position. If a position already exists, then you can only extend in the same direction. i.e., if you have a long position, you can’t execute a short trade on the same market. You cannot execute any trades on a market that already has a pending trade - the pending trade must be cancelled first.

  • account (Viem Account): The user’s account object.
  • walletClient (Viem WalletClient): A Viem WalletClient instance.
  • publicClient (Viem PublicClient): A Viem PublicClient instance.
  • market_id (string): The ID of the market to trade.
  • currency (TCurrency): The currency to use for the trade (‘MPH’, ‘USDC’, ‘ETH’).
  • direction (“long” | “short”): The direction of the trade.
  • tradeAmount (bigint): The amount of currency to invest.
  • leverage (number): The leverage to apply.
  • callback (optional, function): A callback function that receives the result of the operation (TTradeCallback).

Example (Opening a position):

const tradeCompleteCallback = (result) => { if (result.result === 'error') { console.error('Trade Error:', result.err || 'An unknown error occurred.'); } else { console.log('Trade successful:', result); } // Update UI state, e.g., setTradeExecuting(false) }; const openNewPosition = (marketId, amount, leverage, direction) => { // Assumes 'account', 'walletClient', and 'publicClient' are available from wagmi/viem // tradeAmount should be a bigint, e.g. parseEther('100') for 100 MPH sdk.openPosition({ account, walletClient, publicClient, market_id: marketId, currency: 'MPH', direction: direction, // "long" or "short" tradeAmount: amount, leverage: leverage, callback: tradeCompleteCallback }); };

setSLTP({ account, walletClient, publicClient, market_id, priceAbove, priceBelow, callback })

Add a Stop-Loss or Take-Profit protection order on a market where you have a current open position. You cannot add a protection order to a market that already has a pending trade (open or close) - the pending trade must be cancelled first. For a long/buy position, priceAbove is specified for a Take-Profit limit order and priceBelow is specified for a Stop-Loss limit order. Both can be specified to create both protection orders at the same time. For a short/sell position, priceBelow is specified for a Take-Profit limit order and priceAbove is specified for a Stop-Loss limit order. Both can be specified to create both protection orders at the same time.

  • account (Viem Account): The user’s account object.
  • walletClient (Viem WalletClient): A Viem WalletClient instance.
  • publicClient (Viem PublicClient): A Viem PublicClient instance.
  • market_id (string): The ID of the market.
  • priceAbove (optional, number): The upper price bound for a limit order.
  • priceBelow (optional, number): The lower price bound for a limit order.
  • callback (optional, function): A callback function that receives the result of the operation (TTradeCallback).

Example (Setting Stop-Loss and Take-Profit):

const tradeCompleteCallback = (result) => { if (result.result === 'error') { console.error('Trade Error:', result.err || 'An unknown error occurred.'); } else { console.log('Trade successful:', result); } // Update UI state, e.g., setTradeExecuting(false) }; const setProtectionForPosition = (marketId, takeProfitPrice, stopLossPrice) => { // Assumes 'account', 'walletClient', and 'publicClient' are available from wagmi/viem // For a long position, priceAbove is Take-Profit, priceBelow is Stop-Loss. // For a short position, it's the reverse. sdk.setSLTP({ account, walletClient, publicClient, market_id: marketId, priceAbove: takeProfitPrice, // e.g. 150.5 priceBelow: stopLossPrice, // e.g. 140.0 callback: tradeCompleteCallback }); };

closePosition({ account, walletClient, publicClient, market_id, closePercentage, callback })

Execute a closing trade on a market where you have a current open position. You cannot close a position on a market that already has a pending trade (open or close) - the pending trade must be cancelled first.

  • account (Viem Account): The user’s account object.
  • walletClient (Viem WalletClient): A Viem WalletClient instance.
  • publicClient (Viem PublicClient): A Viem PublicClient instance.
  • market_id (string): The ID of the market to close.
  • closePercentage (number): The percentage of the position to close (from 1 to 100).
  • callback (optional, function): A callback function that receives the result of the operation (TTradeCallback).

Example (Closing a position):

const tradeCompleteCallback = (result) => { if (result.result === 'error') { console.error('Trade Error:', result.err || 'An unknown error occurred.'); } else { console.log('Trade successful:', result); } // Update UI state, e.g., setTradeExecuting(false) }; const closeMyPosition = (positionToClose, percentageToClose) => { // Assumes 'account', 'walletClient', and 'publicClient' are available from wagmi/viem sdk.closePosition({ account, walletClient, publicClient, market_id: positionToClose.market_id, closePercentage: percentageToClose, callback: tradeCompleteCallback }); };

Helper Functions

The SDK also exports a few utility functions for formatting values.

usdFormatter(input)

Format a number as a currency string (e.g., 0.00).

  • input (any): The value to format.

Returns: A string (e.g., "123.45").

tokenValueFormatter(param)

Format a token value for display - show only as many digits as are necessary and round the rest, e.g., 1.2345655647357 will show “1.2346” but 1234.5655647357 will show “1234.57”.

  • param (any): The value to format.

Returns: A formatted string.