exchange module is the heart of the Injective Chain which enables fully decentralized spot and derivative exchange.
It is the sine qua non module of the chain and integrates tightly with the auction, insurance, oracle, and peggy modules.
The exchange protocol enables traders to create and trade on arbitrary spot and derivative markets.
The entire process of orderbook management, trade execution, order matching and settlement occurs on chain through the logic codified by the exchange module.
Messages
Let’s explore (and provide examples) the Messages that the Exchange module exports and we can use to interact with the Injective chain.MsgDeposit
This Message is used to send coins from the Bank module to a wallet’s subaccountCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { toChainFormat } from "@injectivelabs/utils";
import { MsgDeposit } from "@injectivelabs/sdk-ts/core/modules";
import { getEthereumAddress } from "@injectivelabs/sdk-ts/utils";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const amount = {
denom: "inj",
amount: toChainFormat(1).toFixed(),
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgDeposit.fromJSON({
amount,
subaccountId,
injectiveAddress,
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgWithdraw
This Message is used to send coins from the wallet’s subaccount back to the users Bank fundsCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { toChainFormat } from "@injectivelabs/utils";
import { MsgWithdraw } from "@injectivelabs/sdk-ts/core/modules";
import { getEthereumAddress } from "@injectivelabs/sdk-ts/utils";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const amount = {
denom: "inj",
amount: toChainFormat(1).toFixed(),
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgWithdraw.fromJSON({
amount,
subaccountId,
injectiveAddress,
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgCreateSpotLimitOrder
This Message is used to create a spot limit orderCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgCreateSpotLimitOrder } from "@injectivelabs/sdk-ts/core/modules";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import {
getEthereumAddress,
getSpotMarketTensMultiplier,
spotPriceToChainPriceToFixed,
spotQuantityToChainQuantityToFixed,
} from "@injectivelabs/sdk-ts/utils";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const feeRecipient = "inj1...";
const market = {
marketId: "0x...",
baseDecimals: 18,
quoteDecimals: 6,
minPriceTickSize: "" /* fetched from the chain */,
minQuantityTickSize: "" /* fetched from the chain */,
priceTensMultiplier:
"" /** can be fetched from getSpotMarketTensMultiplier */,
quantityTensMultiplier:
"" /** can be fetched from getSpotMarketTensMultiplier */,
};
const order = {
price: 1,
quantity: 1,
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgCreateSpotLimitOrder.fromJSON({
subaccountId,
injectiveAddress,
orderType: 1 /* Buy */,
price: spotPriceToChainPriceToFixed({
value: order.price,
tensMultiplier: market.priceTensMultiplier,
baseDecimals: market.baseDecimals,
quoteDecimals: market.quoteDecimals,
}),
quantity: spotQuantityToChainQuantityToFixed({
value: order.quantity,
tensMultiplier: market.quantityTensMultiplier,
baseDecimals: market.baseDecimals,
}),
marketId: market.marketId,
feeRecipient: feeRecipient,
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgCreateSpotMarketOrder
This Message is used to create a spot market orderCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgCreateSpotMarketOrder } from "@injectivelabs/sdk-ts/core/modules";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import {
getEthereumAddress,
getSpotMarketTensMultiplier,
spotPriceToChainPriceToFixed,
spotQuantityToChainQuantityToFixed,
} from "@injectivelabs/sdk-ts/utils";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const feeRecipient = "inj1...";
const market = {
marketId: "0x...",
baseDecimals: 18,
quoteDecimals: 6,
minPriceTickSize: "" /* fetched from the chain */,
minQuantityTickSize: "" /* fetched from the chain */,
priceTensMultiplier:
"" /** can be fetched from getSpotMarketTensMultiplier */,
quantityTensMultiplier:
"" /** can be fetched from getSpotMarketTensMultiplier */,
};
const order = {
price: 10,
quantity: 1,
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgCreateSpotMarketOrder.fromJSON({
subaccountId,
injectiveAddress,
orderType: 1 /* Buy */,
price: spotPriceToChainPriceToFixed({
value: order.price,
tensMultiplier: market.priceTensMultiplier,
baseDecimals: market.baseDecimals,
quoteDecimals: market.quoteDecimals,
}),
quantity: spotQuantityToChainQuantityToFixed({
value: order.quantity,
tensMultiplier: market.quantityTensMultiplier,
baseDecimals: market.baseDecimals,
}),
marketId: market.marketId,
feeRecipient: feeRecipient,
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgCreateDerivativeLimitOrder
This Message is used to create a derivative limit orderCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import { MsgCreateDerivativeLimitOrder } from "@injectivelabs/sdk-ts/core/modules";
import {
getEthereumAddress,
getDerivativeMarketTensMultiplier,
derivativePriceToChainPriceToFixed,
derivativeQuantityToChainQuantityToFixed,
derivativeMarginToChainMarginToFixed,
} from "@injectivelabs/sdk-ts/utils";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const feeRecipient = "inj1...";
const market = {
marketId: "0x...",
baseDecimals: 18,
quoteDecimals: 6,
minPriceTickSize: "" /* fetched from the chain */,
minQuantityTickSize: "" /* fetched from the chain */,
priceTensMultiplier:
"" /** can be fetched from getDerivativeMarketTensMultiplier */,
quantityTensMultiplier:
"" /** can be fetched from getDerivativeMarketTensMultiplier */,
};
const order = {
price: 10,
quantity: 1,
margin: 10,
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgCreateDerivativeLimitOrder.fromJSON({
orderType: 1 /* Buy */,
triggerPrice: "0",
injectiveAddress,
price: derivativePriceToChainPriceToFixed({
value: order.price,
quoteDecimals: market.quoteDecimals,
}),
quantity: derivativeQuantityToChainQuantityToFixed({ value: order.quantity }),
margin: derivativeMarginToChainMarginToFixed({
value: order.margin,
quoteDecimals: market.quoteDecimals,
}),
marketId: market.marketId,
feeRecipient: feeRecipient,
subaccountId: subaccountId,
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgCreateDerivativeMarketOrder
This Message is used to create a derivative market orderCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import { MsgCreateDerivativeMarketOrder } from "@injectivelabs/sdk-ts/core/modules";
import {
getEthereumAddress,
getDerivativeMarketTensMultiplier,
derivativePriceToChainPriceToFixed,
derivativeQuantityToChainQuantityToFixed,
derivativeMarginToChainMarginToFixed,
} from "@injectivelabs/sdk-ts/utils";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const feeRecipient = "inj1...";
const market = {
marketId: "0x...",
baseDecimals: 18,
quoteDecimals: 6,
minPriceTickSize: "" /* fetched from the chain */,
minQuantityTickSize: "" /* fetched from the chain */,
priceTensMultiplier:
"" /** can be fetched from getDerivativeMarketTensMultiplier */,
quantityTensMultiplier:
"" /** can be fetched from getDerivativeMarketTensMultiplier */,
};
const order = {
price: 10,
quantity: 1,
margin: 10,
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgCreateDerivativeMarketOrder.fromJSON({
orderType: 1 /* Buy */,
triggerPrice: "0",
injectiveAddress,
price: derivativePriceToChainPriceToFixed({
value: order.price,
tensMultiplier: market.priceTensMultiplier,
quoteDecimals: market.quoteDecimals,
}),
quantity: derivativeQuantityToChainQuantityToFixed({
value: order.quantity,
tensMultiplier: market.quantityTensMultiplier,
}),
margin: derivativeMarginToChainMarginToFixed({
value: order.margin,
quoteDecimals: market.quoteDecimals,
tensMultiplier: market.priceTensMultiplier,
}),
marketId: market.marketId,
feeRecipient: feeRecipient,
subaccountId: subaccountId,
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgBatchUpdateOrders
This Message is used to batch update orders on the chainCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { OrderSide } from "@injectivelabs/sdk-ts/types";
import { MsgBatchUpdateOrders } from "@injectivelabs/sdk-ts/core/modules";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import { GrpcOrderType } from "@injectivelabs/sdk-ts/client/chain";
import {
getEthereumAddress,
getDerivativeMarketTensMultiplier,
derivativePriceToChainPriceToFixed,
derivativeQuantityToChainQuantityToFixed,
derivativeMarginToChainMarginToFixed,
spotPriceToChainPriceToFixed,
spotQuantityToChainQuantityToFixed,
} from "@injectivelabs/sdk-ts/utils";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const feeRecipient = "inj1...";
const derivativeMarket = {
marketId: "0x...",
baseDecimals: 18,
quoteDecimals: 6,
minPriceTickSize: "" /* fetched from the chain */,
minQuantityTickSize: "" /* fetched from the chain */,
priceTensMultiplier:
"" /** can be fetched from getDerivativeMarketTensMultiplier */,
quantityTensMultiplier:
"" /** can be fetched from getDerivativeMarketTensMultiplier */,
};
const derivativeOrder = {
price: 10,
quantity: 1,
margin: 10,
orderType: OrderSide.Buy,
};
const spotMarket = {
marketId: "0x...",
baseDecimals: 18,
quoteDecimals: 6,
minPriceTickSize: "" /* fetched from the chain */,
minQuantityTickSize: "" /* fetched from the chain */,
priceTensMultiplier:
"" /** can be fetched from getSpotMarketTensMultiplier */,
quantityTensMultiplier:
"" /** can be fetched from getSpotMarketTensMultiplier */,
};
const spotOrder = {
price: 10,
quantity: 1,
margin: 10,
orderType: OrderSide.Buy,
};
const ethereumAddress = getEthereumAddress(injectiveAddress);
const subaccountIndex = 0;
const suffix = "0".repeat(23) + subaccountIndex;
const subaccountId = ethereumAddress + suffix;
const msg = MsgBatchUpdateOrders.fromJSON({
injectiveAddress,
subaccountId: subaccountId,
derivativeOrdersToCreate: [
{
orderType: derivativeOrder.orderType as GrpcOrderType,
price: derivativePriceToChainPriceToFixed({
value: derivativeOrder.price,
quoteDecimals: 6 /* USDT has 6 decimals */,
}),
quantity: derivativeQuantityToChainQuantityToFixed({
value: derivativeOrder.quantity,
}),
margin: derivativeMarginToChainMarginToFixed({
value: derivativeOrder.margin,
quoteDecimals: 6 /* USDT has 6 decimals */,
}),
marketId: derivativeMarket.marketId,
feeRecipient: injectiveAddress,
},
],
spotOrdersToCreate: [
{
orderType: spotOrder.orderType as GrpcOrderType,
price: spotPriceToChainPriceToFixed({
value: spotOrder.price,
baseDecimals: 18 /* INJ has 18 decimals */,
quoteDecimals: 6 /* USDT has 6 decimals */,
}),
quantity: spotQuantityToChainQuantityToFixed({
value: spotOrder.quantity,
baseDecimals: 18 /* INJ has 18 decimals */,
}),
marketId: spotMarket.marketId,
feeRecipient: injectiveAddress,
},
],
});
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgBatchCancelSpotOrders
This Message is used to batch cancel spot orders on the chainCopy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import { MsgBatchCancelSpotOrders } from "@injectivelabs/sdk-ts/core/modules";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const orders = [
{
marketId: "0x...",
subaccountId: "0x...",
orderHash: "0x...",
},
{
marketId: "0x...",
subaccountId: "0x...",
orderHash: "0x...",
},
];
const messages = orders.map((order) =>
MsgBatchCancelSpotOrders.fromJSON({
injectiveAddress,
orders: [
{
marketId: order.marketId,
subaccountId: order.subaccountId,
orderHash: order.orderHash,
},
],
})
);
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: messages,
});
console.log(txHash);
MsgBatchCancelDerivativeOrders
Copy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import { MsgBatchCancelDerivativeOrders } from "@injectivelabs/sdk-ts/core/modules";
const privateKey = "0x...";
const injectiveAddress = "inj1...";
const orders = [
{
marketId: "0x...",
subaccountId: "0x...",
orderHash: "0x...",
},
{
marketId: "0x...",
subaccountId: "0x...",
orderHash: "0x...",
},
];
const messages = orders.map((order) =>
MsgBatchCancelDerivativeOrders.fromJSON({
injectiveAddress,
orders: [
{
marketId: order.marketId,
subaccountId: order.subaccountId,
orderHash: order.orderHash,
},
],
})
);
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: messages,
});
console.log(txHash);
MsgRewardsOptOut
This Message is used to opt out of the Trade & Earn program.Copy
Ask AI
import { Network } from "@injectivelabs/networks";
import { MsgRewardsOptOut } from "@injectivelabs/sdk-ts/core/modules";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
const privateKey = "0x...";
const injectiveAddress = "inj...";
const msg = MsgRewardsOptOut.fromJSON({ sender: injectiveAddress });
const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.Testnet,
}).broadcast({
msgs: msg,
});
console.log(txHash);
MsgExternalTransfer
This message is used to transfer balance from one subaccount to another subaccount. Note:- You cannot transfer from your default subaccountId since that balance is now associated with your Injective address in the bank module. Therefore, in order for
MsgExternalTransferto work, you will need to transfer from a non-default subaccountId.
- you can query your existing subaccountIds via the account portfolio api.
- If you have existing non-default subaccounts, you’ll want to do a MsgDeposit to one of your existing non-default subaccountIds and use that subaccountId as the
srcSubaccountIdbelow. - If you don’t have existing non-default subaccounts, you can do a MsgDeposit to a new default subaccountId, which would be done via importing
getSubaccountIdfromsdk-tsand setting thesubaccountIdfield in MsgDeposit togetSubaccountId(injectiveAddress, 1).
Copy
Ask AI
import { toChainFormat } from "@injectivelabs/utils";
import { Network } from "@injectivelabs/networks";
import { MsgExternalTransfer } from "@injectivelabs/sdk-ts/core/modules";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
const injectiveAddress = "inj...";
const srcSubaccountId = "0x...";
const dstSubaccountId = `0x...`;
// INJ token details
const INJ_DENOM = "inj";
const INJ_DECIMALS = 18;
/* format amount to add to the burn auction pool */
const amount = {
denom: INJ_DENOM,
amount: toChainFormat(1, INJ_DECIMALS).toFixed(),
};
/* create message in proto format */
const msg = MsgExternalTransfer.fromJSON({
amount,
dstSubaccountId,
srcSubaccountId,
injectiveAddress,
});
const privateKey = "0x...";
/* broadcast transaction */
const txHash = await new MsgBroadcasterWithPk({
network: Network.Testnet,
privateKey,
}).broadcast({
msgs: msg,
});
console.log(txHash);
