Deep dive into API concepts
This page provides information on how to generate the following API headers and params:
Header / Param | Used in: |
---|---|
If you are using the Typescript SDK or the JS SDK, you will generally not need to provide these headers as long as you upgrade to the following versions:
- Typescript SDK:
>= 1.35.5
- JS SDK:
>= 1.17
IMX-Timestamp
(string)
The IMX-Timestamp
can be generated by this example Javascript function:
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:
Param | Message |
---|---|
IMX-Signature | IMX-Timestamp |
x-imx-eth-signature | The 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_signature | See below |
How to get the message for the auth_signature
?
The auth_signature
param is used in the mintTokens request.
- Put together an object like the following Javascript example:
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: '',
};
- Create a hash of that object that becomes the
message
to be signed to get theauth_signature
:
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:
export async function signRaw(
message: string,
signer: Signer
): Promise<string> {
const signature = deserializeSignature(await signer.signMessage(message));
return serializeEthSignature(signature);
}
Where deserializeSignature()
looks like:
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:
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:
Action | Endpoint(s) requiring stark_signature | Endpoint(s) providing payload_hash to be signed |
---|---|---|
Create orders | createOrder | getSignableOrderV1 getSignableOrder |
Cancel orders | cancelOrder | getSignableCancelOrder |
Create transfers | createTransfer createTransferV1 | getSignableTransfer getSignableTransferV1 |
Create withdrawals | createWithdrawal | getSignableWithdrawal |
Create trades | createTrade | getSignableTrade |
Create exchange transfers | createExchangeTransfer | getExchangeSignableTransfer |
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 Typescript SDK to generate the Stark signers. See instructions here.
Use the Stark signer to sign the payload_hash
in Step 1:
- Typescript SDK
const starkSignature = await starkSigner.signMessage(payloadHash);