_

Author profile photo
Swapgate team
September 12, 2024
~4 min read

The following methods are used to enhance the capabilities of your service using Swapgate.io’s exchange features.

Algorithm

Swapgate uses a dynamic rate system to generate exchange rate predictions, using liquidity provider market depth analysis. While the default flow will analyse the market depth and return a realistically-calculated result, the markup parameter can influence the rate returned by the rate prediction algorithm.

The markup parameter will influence the rate pre-calculation returned by our system on the following way:

final​=A calculated​​ ∗ (1 − K markup / 100​)

final Final amount to receive, predicted for the exchange
calculated Initial amount to receive predicted for the exchange
markup  markup parameter value

Based on the provided formula, a markup value of 0.3, provided for a 1 BTC → USDT exchange will yield the following results, making the final prediction price increased by 0.3%:

49549.728053855135 * (1 – 0.3 / 100) = 49401.07886969357

API

The rates data can be obtained through an API v1 call to the /api/v1/rates/public/one endpoint.

The API v1 does not require API key authorization or IP whitelisting.

Parameter Description Example
instrumentFromCurrencyTitle The name of the currency to be exchanged BTC
instrumentFromNetworkTitle The blockchain network of the currency to be exchanged BTC
instrumentToCurrencyTitle The name of the currency to be obtained USDT
instrumentToNetworkTitle The blockchain network of the currency to be obtained TRC20
rateMode The rate mode of the exchange, FLOATING or FIXED. FLOATING
claimedDepositAmount The deposit amount claimed to be paid by the client 1
markup The markup parameter 0.3

GET /api/v1/rates/public/one?instrumentFromCurrencyTitle=BTC&instrumentFromNetworkTitle=BTC&instrumentToCurrencyTitle=
USDT&instrumentToNetworkTitle=TRC20&rateMode=FLOATING&claimedDepositAmount=1&markup=0.3

{
	"instrumentFrom": {
		"currencyTitle": "BTC",
		"networkTitle": "BTC",
		"precisionDecimals": 11
	},
	"instrumentTo": {
		"currencyTitle": "USDT",
		"networkTitle": "TRC20",
		"precisionDecimals": 1
	},
	"depositRules": {
		"minAmount": "0.0010202831699481001984",
		"maxAmount": "0"
	},
	"withdrawalRules": {
		"minAmount": "51.324600057525118367",
		"maxAmount": "0",
		"withdrawalFeeRules": {
			"maxAmount": "1",
			"minAmount": "1"
		}
	},
	"minConfirmationsToWithdraw": 2,
	"minConfirmationsToTrade": 2,
	"updatedAt": "2024-08-05T13:31:44.315Z",
	"liquidityProviderPublicCode": "radio",
	"amountToGet": "50201.90689595",
	"amountToGive": "1",
	"marketMinAmount": "0.1",
	"enableFixedRate": true,
	"amountToGiveCurrencyTitle": "BTC",
	"rateMode": "FLOATING",
	"finalNetworkFeeAmount": "0",
	"platformFee_Absolute": null,
	"liquidityProviderQuotes": {
		"sellQuote": {
			"baseValue": "1",
			"quoteValue": "50304.27"
		},
		"buyQuote": {
			"baseValue": "50294.99",
			"quoteValue": "1"
		}
	},
	"price": "50201.90689595",
	"marketLeftPrice": "50304.27",
	"marketRightPrice": "0.000019882696069727819809",
	"marketAmountToGet": "50243.798064469251204",
	"marketAmountToGetUSDT": "50243.798064469251204",
	"quotesWithoutNetworkFee": {
		"sellQuote": {
			"baseValue": "1",
			"quoteValue": "50202.90689595"
		},
		"buyQuote": {
			"baseValue": "50294.99",
			"quoteValue": "0.997985"
		}
	},
	"quotes": {
		"sellQuote": {
			"baseValue": "1",
			"quoteValue": "50201.90689595"
		},
		"buyQuote": {
			"baseValue": "50294.99",
			"quoteValue": "0.99796512097183797717"
		}
	},
	"markup": "0.3"
}

Markup parameter in order flow

Algorithm

The markup parameter must also be passed during the order creation to ensure valid order commission. With the markup parameter passed, Swapgate will apply the following formula to the order commission algorithm:

withdrawal = A exchange * (1 – (C platform(%) + K markup) / 100)

withdrawal Amount of currency sent to the client as the exchange result
exchange Amount of currency that Swapgate had available after performing our trading strategy
platform(%) Commission percent defined by Swapgate
markup  markup parameter value

Based on the provided formula, a markup value of 0.3 provided during order creation, will increase Swapgate commission percent by 0.3.
In the following example Swapgate commission is set to 1 percent:

withdrawal = A exchange * (1 – (1 + 0.3) / 100)

Using the previous example, an exchange of 1 BTC to USDT based on the market price of 50243.798064469251204 BTC:USDT will yield the following client withdrawal amount:

50243.798064469251204 * (1 – (1 + 0.3) / 100) = 49590.62868963115

Based on the provided formula, a markup value of 0.3 provided during order creation, will increase Swapgate commission percent by 0.3.
After an exchange with a markup parameter enters the COMPLETED state, the markup parameter will be used in the partner margin calculation formula:

affiliate = C platform * (C affiliate(%) / 100) + C platform * (K markup / 100)

affiliate Amount of currency sent to the affiliate’s wallet per exchange (affiliate margin)
platform Amount of currency that Swapgate gained from the exchange (platform margin)
affiliate(%) Commission percent defined for the affiliate
markup  markup parameter value

Passing the markup parameter

During order creation, Swapgate API accepts the markup parameter alongside other order creation parameters:


{
	"rateMode": "FLOATING",
	"instrumentFrom": {
		"currencyTitle": "USDT",
		"networkTitle": "TRC20"
	},
	"instrumentTo": {
		"currencyTitle": "BTC",
		"networkTitle": "BTC"
	},
	"destinationAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
	"destinationAddressMemo": null,
	"refundAddress": null,
	"refundAddressMemo": null,
	"claimedNetworkFee": null,
	"legacyOrderId": null,
	"referrerId": "aff_616",
	"claimedDepositAmount": "125000",
	"utmData": [],
	"browserFingerprint": "6b3add86bec11616427d069556a33548"
	"markup": "0.2" // <-- here
}

The markup multiplier value is passed alongside other parameters.

Using API v2

Using the v2 API endpoints requires additional authorization setup. Without the necessary authorization parameters, v2 endpoints will throw 403 Forbidden errors.
The integration is composed of two steps – creating an API key and integrating its usage in the API requests. By creating an API key, our b2b customers will receive a key pair to sign their requests alongside a list of whitelisted IP addresses that can access the API endpoints.

Note: you must have an active authorization cookie to perform /api/v1/users/* requests.

Creating an API key

While creating the API key, an array of whitelisted IPs must be passed:


POST /api/v1/users/generate-api-key

Request:
{
	"name": "test",
	"whiteListIp": ["127.0.0.1"],
	"isActive": true
}

Response:
{
	"apiId": 40,
	"name": "test",
	"isActive": true,
	"publicKey": "ZgzycV6Sf78BZKuyIAiz+0Bor002+0/rx1gLKsmYCsY=",
	"secretKey": "a482a8e3a3ff9aeadefb11d3d8c11253e7e8412e05ef2b8599016cc87a64b7d6",
	"whiteListIp": [
		"127.0.0.1"
	],
	"createdAt": "2024-08-05T13:54:18.427Z"
}

The response will contain the key pair that is required to use during API v2 authorization.

Note: The secretKey field will be displayed only once, during API key creation. We advise to save it immediately after creating the API key.

Listing your API keys

If your integration requires more than one API key to be used, you can easily list them through the list endpoint:


GET /api/v1/users/list-api-key

[
	{
		"apiId": 40,
		"name": "test",
		"isActive": true,
		"settings": {},
		"publicKey": "ZgzycV6Sf78BZKuyIAiz+0Bor002+0/rx1gLKsmYCsY=",
		"whiteListIp": [
			"127.0.0.1"
		],
		"createdAt": "2024-08-05T13:54:18.427Z"
	}
]

Managing your API keys

Managing existing API keys can be done through our b2b customer support line. This includes:

  • Deleting API keys
  • Adding new whitelisted IPs to an existing API key
  • Updating and adding settings for an API key (ex.: min/max values for markup value)
  • Deactivating API keys

Using the API key

API v2 requires 3 headers to be set on every request:

Header Value
x-api-public-key Your public key obtained during API key creation
x-api-timestamp UNIX timestamp
x-api-signature A signature of the request

The signature value is generated using hmac sha256. The data passed is string concatenation of the timestamp, the string representation of the request body and the public key, while the private key is used as the key to the hmac function:


function signRequest(requestBody) {
  const timestamp = new Date().getTime();
  const publicKey = "ZgzycV6Sf78BZKuyIAiz+0Bor002+0/rx1gLKsmYCsY=";
	const privateKey = "a482a8e3a3ff9aeadefb11d3d8c11253e7e8412e05ef2b8599016cc87a64b7d6";
	
	const encoder = new TextEncoder();
	const data = encoder.encode(
		timestamp + JSON.stringify(requestBody) + publicKey,
	);
	
	const hmac = createHmac('sha256', privateKey);
	const dataSign = hmac.update(data);
	const signature = dataSign.digest('base64');
	
	return signature;
}

signRequest({ myKey: "myValue" })

Sample integration code


const { createHmac } = require('crypto');

const API_PREFIX = 'https://swapgate.io/api/';
const PUBKEY = 'public_key'; // changeme
const PRIVKEY = 'private_key'; // changeme

function signRequest(requestBody, timestamp) {
  const encoder = new TextEncoder();
  const data = encoder.encode(timestamp + JSON.stringify(requestBody) + PUBKEY);

  const hmac = createHmac('sha256', PRIVKEY);
  const dataSign = hmac.update(data);
  const signature = dataSign.digest('base64');

  return signature;
}

async function createOrder() {
  const clientBrowserFingerprint = '6b3add86bec11616427d069556a33548';
  const orderRateMode = 'FLOATING';
  const depositAmount = '1';
  const clientDestinationAddress = 'TUhw6S1HyXDhycKvTec3x7HNGQfNn3Vhpc';
  const clientDestinationAddressMemo = null;
  const markup = '0.3';
  const instrumentFromCurrencyTitle = 'BTC';
  const instrumentFromNetworkTitle = 'BTC';

  const instrumentToCurrencyTitle = 'USDT';
  const instrumentToNetworkTitle = 'TRC20';

  // Step 1. Prepate createOrder request body using obtained rate data

  const createOrderRequestBody = {
    rateMode: orderRateMode,
    instrumentFrom: {
      currencyTitle: instrumentFromCurrencyTitle,
      networkTitle: instrumentFromNetworkTitle,
    },
    instrumentTo: {
      currencyTitle: instrumentToCurrencyTitle,
      networkTitle: instrumentToNetworkTitle,
    },
    destinationAddress: clientDestinationAddress,
    destinationAddressMemo: clientDestinationAddressMemo,
    refundAddress: null,
    refundAddressMemo: null,
    markup: markup,
    claimedNetworkFee: null,
    legacyOrderId: null,
    referrerId: null,
    claimedDepositAmount: depositAmount,
    utmData: [],
    browserFingerprint: clientBrowserFingerprint,
  };

  // Step 2. Prepare signature based on key pair and createOrder request data

  const timestamp = new Date().getTime();
  const signature = signRequest(createOrderRequestBody, timestamp);

  // Step 3. Call API v2 create-order endpoint

  const order = JSON.parse(
    await (
      await fetch(`${API_PREFIX}v2/orders/public/create`, {
        method: 'POST',
        headers: {
          'x-api-public-key': PUBKEY,
          'x-api-timestamp': timestamp,
          'x-api-signature': signature,
          'content-type': 'application/json; charset=utf-8',
        },
        body: JSON.stringify(createOrderRequestBody),
      })
    ).text(),
  );

  console.log('order', order);
}

void createOrder();
Share article: