Skip to main content

Deep dive into API concepts

This page provides information on how to generate the following API headers and params:

Header / ParamUsed in:
Upgrade your SDK to avoid generating these headers

If you are using the Core SDK or the JS SDK, you will generally not need to provide these headers as long as you upgrade to the following versions:

  • Core SDK: >= 1.0.0-beta.2
  • JS SDK: >= 1.17

IMX-Timestamp (string)

The IMX-Timestamp can be generated by this example Javascript function:

Javascript
const timestamp = Math.floor(Date.now() / 1000).toString();

x-imx-eth-address (string)

This is the public Ethereum address of the user executing the transaction.

IMX-Signature (string), x-imx-eth-signature (string), auth_signature (string)

1. Get Ethereum signer

Signers are abstractions of user accounts that can be used to sign transactions. A user's private key is required to generate them. Read more here.

In order to generate the IMX-Signature and x-imx-eth-signature headers, we need an Ethereum signer for the user.

See here on how to generate these signers.

2. Get message

Different messages are required by the different attributes:

ParamMessage
IMX-SignatureIMX-Timestamp
x-imx-eth-signatureThe message to be signed depends on each transaction. Typically, it contains information about the transaction that requires the user signature.

The messages required for the following endpoints are:
auth_signatureSee below

How to get the message for the auth_signature?

The auth_signature param is used in the mintTokens request.

  1. Put together an object like the following Javascript example:
Javascript
const object = {
contract_address: "string",
royalties: [ // Optional
{
recipient: "string",
percentage: 10, // max 100
},
],
users: [
{
ether_key: "string",
tokens: [
{
id: "string",
blueprint: "string",
royalties: [ // Optional
{
recipient: "string",
percentage: 10, // max 100
},
]
}
]
}
],
auth_signature: '',
};
  1. Create a hash of that object that becomes the message to be signed to get the auth_signature:
Javascript
import { keccak256 } from '@ethersproject/keccak256';
import { toUtf8Bytes } from '@ethersproject/strings';

const message = keccak256(toUtf8Bytes(JSON.stringify(object)));

3. Serialize the signature

Implement a function using the signer and message obtained in the previous steps like the following Typescript example:

Typescript
export async function signRaw(
message: string,
signer: Signer
): Promise<string> {
const signature = deserializeSignature(await signer.signMessage(message));
return serializeEthSignature(signature);
}

Where deserializeSignature() looks like:

Typescript
import BN from 'bn.js'; // https://www.npmjs.com/package/bn.js
import * as encUtils from 'enc-utils'; // https://www.npmjs.com/package/enc-utils

type SignatureOptions = {
r: BN;
s: BN;
recoveryParam: number | null | undefined;
};

function importRecoveryParam(v: string): number | undefined {
return v.trim()
? new BN(v, 16).cmp(new BN(27)) !== -1
? new BN(v, 16).sub(new BN(27)).toNumber()
: new BN(v, 16).toNumber()
: undefined;
}

function deserializeSignature(sig: string, size = 64): SignatureOptions {
sig = encUtils.removeHexPrefix(sig);
return {
r: new BN(sig.substring(0, size), 'hex'),
s: new BN(sig.substring(size, size * 2), 'hex'),
recoveryParam: importRecoveryParam(sig.substring(size * 2, size * 2 + 2)),
};
}

and serializeEthSignature() looks like:

Typescript
function serializeEthSignature(sig: SignatureOptions): string {
// This is because golang appends a recovery param
// https://github.com/ethers-io/ethers.js/issues/823
return encUtils.addHexPrefix(
encUtils.padLeft(sig.r.toString(16), 64) +
encUtils.padLeft(sig.s.toString(16), 64) +
encUtils.padLeft(sig.recoveryParam?.toString(16) || '', 2)
);
}

stark_signature (string)

The stark_signature is required in the request body params of certain endpoints. It is obtained by using a Stark signer to sign the payload_hash produced in the response of the following corresponding endpoints:

ActionEndpoint(s) requiring stark_signatureEndpoint(s) providing payload_hash to be signed
Create orderscreateOrdergetSignableOrderV1
getSignableOrder
Cancel orderscancelOrdergetSignableCancelOrder
Create transferscreateTransfer
createTransferV1
getSignableTransfer
getSignableTransferV1
Create withdrawalscreateWithdrawalgetSignableWithdrawal
Create tradescreateTradegetSignableTrade
Create exchange transferscreateExchangeTransfergetExchangeSignableTransfer

1. Get message to be signed

Call the corresponding endpoint to the one requiring the stark_signature that gets the payload_hash to be signed (ie. the endpoint that provides the payload_hash for the createWithdrawal endpoint is the getSignableWithdrawal endpoint).

2. Generate Stark signer and sign the message

Use the Core SDK to generate the Stark signers. See instructions here.

Use the Stark signer to sign the payload_hash in Step 1:

const starkSignature = await starkSigner.signMessage(payloadHash);