From bd3e9959e6f358a25f5f9c6d7584ad97f39ef691 Mon Sep 17 00:00:00 2001 From: frederick-88 Date: Sat, 11 Apr 2026 03:26:30 +0700 Subject: [PATCH 1/2] feat: add MsgDecreasePositionMargin chain message to SDK --- .../sdk-ts/src/core/modules/exchange/index.ts | 2 + .../msgs/MsgDecreasePositionMargin.spec.ts | 101 ++++++++++++++ .../msgs/MsgDecreasePositionMargin.ts | 132 ++++++++++++++++++ packages/sdk-ts/src/core/modules/msgs.ts | 2 + .../sdk-ts/src/core/tx/eip712/MsgDecoder.ts | 16 +++ packages/sdk-ts/src/core/tx/eip712/maps.ts | 2 + scripts/eslint-rules/no-sdk-ts-barrel.js | 1 + 7 files changed, 256 insertions(+) create mode 100644 packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.spec.ts create mode 100644 packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.ts diff --git a/packages/sdk-ts/src/core/modules/exchange/index.ts b/packages/sdk-ts/src/core/modules/exchange/index.ts index abae52d05..bea356308 100644 --- a/packages/sdk-ts/src/core/modules/exchange/index.ts +++ b/packages/sdk-ts/src/core/modules/exchange/index.ts @@ -15,6 +15,7 @@ import MsgBatchCancelSpotOrders from './msgs/MsgBatchCancelSpotOrders.js' import MsgCancelDerivativeOrder from './msgs/MsgCancelDerivativeOrder.js' import MsgCreateSpotMarketOrder from './msgs/MsgCreateSpotMarketOrder.js' import MsgIncreasePositionMargin from './msgs/MsgIncreasePositionMargin.js' +import MsgDecreasePositionMargin from './msgs/MsgDecreasePositionMargin.js' import MsgInstantSpotMarketLaunch from './msgs/MsgInstantSpotMarketLaunch.js' import MsgUpdateDerivativeMarketV2 from './msgs/MsgUpdateDerivativeMarketV2.js' import MsgCancelBinaryOptionsOrder from './msgs/MsgCancelBinaryOptionsOrder.js' @@ -46,6 +47,7 @@ export { MsgBatchCancelSpotOrders, MsgCreateSpotMarketOrder, MsgIncreasePositionMargin, + MsgDecreasePositionMargin, MsgInstantSpotMarketLaunch, MsgCancelBinaryOptionsOrder, MsgUpdateDerivativeMarketV2, diff --git a/packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.spec.ts b/packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.spec.ts new file mode 100644 index 000000000..7edc19252 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.spec.ts @@ -0,0 +1,101 @@ +import snakecaseKeys from 'snakecase-keys' +import { EIP712Version } from '@injectivelabs/ts-types' +import { mockFactory, prepareEip712 } from '@injectivelabs/utils/test-utils' +import MsgDecreasePositionMargin from './MsgDecreasePositionMargin.js' +import { + getEip712TypedData, + getEip712TypedDataV2, +} from '../../../tx/eip712/eip712.js' +import { IndexerGrpcWeb3GwApi } from './../../../../client/indexer/grpc/IndexerGrpcWeb3GwApi.js' + +const params: MsgDecreasePositionMargin['params'] = { + marketId: mockFactory.injUsdtDerivativeMarket.marketId, + injectiveAddress: mockFactory.injectiveAddress, + srcSubaccountId: mockFactory.subaccountId, + dstSubaccountId: mockFactory.subaccountId2, + amount: '1000', +} + +const protoType = '/injective.exchange.v1beta1.MsgDecreasePositionMargin' +const protoTypeShort = 'exchange/MsgDecreasePositionMargin' +const protoParams = { + marketId: params.marketId, + sender: params.injectiveAddress, + sourceSubaccountId: params.srcSubaccountId, + destinationSubaccountId: params.dstSubaccountId, + amount: params.amount, +} +const protoParamsAmino = snakecaseKeys(protoParams) +const message = MsgDecreasePositionMargin.fromJSON(params) + +describe('MsgDecreasePositionMargin', () => { + it('generates proper proto', () => { + const proto = message.toProto() + + expect(proto).toStrictEqual({ + ...protoParams, + amount: '1000000000000000000000', + }) + }) + + it('generates proper data', () => { + const data = message.toData() + + expect(data).toStrictEqual({ + '@type': protoType, + ...protoParams, + amount: '1000000000000000000000', + }) + }) + + it('generates proper amino', () => { + const amino = message.toAmino() + + expect(amino).toStrictEqual({ + type: protoTypeShort, + value: protoParamsAmino, + }) + }) + + it('generates proper web3Gw', () => { + const web3 = message.toWeb3Gw() + + expect(web3).toStrictEqual({ + '@type': protoType, + ...protoParamsAmino, + }) + }) + + describe('generates proper EIP712 compared to the Web3Gw (chain)', () => { + const { endpoints, eip712Args, prepareEip712Request } = prepareEip712({ + messages: message, + }) + + // TODO: invalid Go type math.LegacyDec for field injective.exchange.v1beta1.MsgDecreasePositionMargin.amount + it.skip('EIP712 v1', async () => { + const eip712TypedData = getEip712TypedData(eip712Args) + + const txResponse = await new IndexerGrpcWeb3GwApi( + endpoints.indexer, + ).prepareEip712Request({ + ...prepareEip712Request, + eip712Version: EIP712Version.V1, + }) + + expect(eip712TypedData).toStrictEqual(JSON.parse(txResponse.data)) + }) + + it('EIP712 v2', async () => { + const eip712TypedData = getEip712TypedDataV2(eip712Args) + + const txResponse = await new IndexerGrpcWeb3GwApi( + endpoints.indexer, + ).prepareEip712Request({ + ...prepareEip712Request, + eip712Version: EIP712Version.V2, + }) + + expect(eip712TypedData).toStrictEqual(JSON.parse(txResponse.data)) + }) + }) +}) diff --git a/packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.ts b/packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.ts new file mode 100644 index 000000000..a86a83972 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/exchange/msgs/MsgDecreasePositionMargin.ts @@ -0,0 +1,132 @@ +import { toChainFormat } from '@injectivelabs/utils' +import * as InjectiveExchangeV1Beta1TxPb from '@injectivelabs/core-proto-ts-v2/generated/injective/exchange/v1beta1/tx_pb' +import { MsgBase } from '../../MsgBase.js' +import { numberToCosmosSdkDecString } from '../../../../utils/numbers.js' + +export declare namespace MsgDecreasePositionMargin { + export interface Params { + marketId: string + injectiveAddress: string + srcSubaccountId: string + dstSubaccountId: string + amount: string + } + + export type Proto = InjectiveExchangeV1Beta1TxPb.MsgDecreasePositionMargin +} + +const createMessage = (params: MsgDecreasePositionMargin.Params) => { + const message = InjectiveExchangeV1Beta1TxPb.MsgDecreasePositionMargin.create( + { + sender: params.injectiveAddress, + sourceSubaccountId: params.srcSubaccountId, + destinationSubaccountId: params.dstSubaccountId, + marketId: params.marketId, + amount: params.amount, + }, + ) + + return message +} + +/** + * @category Messages + */ +export default class MsgDecreasePositionMargin extends MsgBase< + MsgDecreasePositionMargin.Params, + MsgDecreasePositionMargin.Proto +> { + static fromJSON( + params: MsgDecreasePositionMargin.Params, + ): MsgDecreasePositionMargin { + return new MsgDecreasePositionMargin(params) + } + + public toProto() { + const { params: initialParams } = this + + const params = { + ...initialParams, + amount: toChainFormat(initialParams.amount).toFixed(), + } as MsgDecreasePositionMargin.Params + + return createMessage(params) + } + + public toData() { + const proto = this.toProto() + + return { + '@type': '/injective.exchange.v1beta1.MsgDecreasePositionMargin', + ...proto, + } + } + + public toAmino() { + const { params } = this + const message = { + sender: params.injectiveAddress, + source_subaccount_id: params.srcSubaccountId, + destination_subaccount_id: params.dstSubaccountId, + market_id: params.marketId, + amount: params.amount, + } + + return { + type: 'exchange/MsgDecreasePositionMargin', + value: message, + } + } + + public toWeb3Gw() { + const amino = this.toAmino() + const { value } = amino + + return { + '@type': '/injective.exchange.v1beta1.MsgDecreasePositionMargin', + ...value, + } + } + + public toEip712() { + const amino = this.toAmino() + const { type, value } = amino + + const messageAdjusted = { + ...value, + amount: toChainFormat(value.amount).toFixed(), + } + + return { + type, + value: messageAdjusted, + } + } + + public toEip712V2() { + const { params } = this + const web3gw = this.toWeb3Gw() + + const messageAdjusted = { + ...web3gw, + amount: numberToCosmosSdkDecString(params.amount), + } + + return messageAdjusted + } + + public toDirectSign() { + const proto = this.toProto() + + return { + type: '/injective.exchange.v1beta1.MsgDecreasePositionMargin', + message: proto, + } + } + + public toBinary(): Uint8Array { + return InjectiveExchangeV1Beta1TxPb.MsgDecreasePositionMargin.toBinary( + this.toProto(), + ) + } +} diff --git a/packages/sdk-ts/src/core/modules/msgs.ts b/packages/sdk-ts/src/core/modules/msgs.ts index c3103b72c..e44184d21 100644 --- a/packages/sdk-ts/src/core/modules/msgs.ts +++ b/packages/sdk-ts/src/core/modules/msgs.ts @@ -56,6 +56,7 @@ import type MsgBatchCancelSpotOrders from './exchange/msgs/MsgBatchCancelSpotOrd import type MsgCancelDerivativeOrder from './exchange/msgs/MsgCancelDerivativeOrder.js' import type MsgCreateSpotMarketOrder from './exchange/msgs/MsgCreateSpotMarketOrder.js' import type MsgIncreasePositionMargin from './exchange/msgs/MsgIncreasePositionMargin.js' +import type MsgDecreasePositionMargin from './exchange/msgs/MsgDecreasePositionMargin.js' import type MsgInstantSpotMarketLaunch from './exchange/msgs/MsgInstantSpotMarketLaunch.js' import type MsgCancelBinaryOptionsOrder from './exchange/msgs/MsgCancelBinaryOptionsOrder.js' import type MsgUpdateDerivativeMarketV2 from './exchange/msgs/MsgUpdateDerivativeMarketV2.js' @@ -107,6 +108,7 @@ export type ExchangeV1Msgs = | MsgBatchCancelSpotOrders | MsgCancelDerivativeOrder | MsgCreateSpotMarketOrder + | MsgDecreasePositionMargin | MsgIncreasePositionMargin | MsgInstantSpotMarketLaunch | MsgCancelBinaryOptionsOrder diff --git a/packages/sdk-ts/src/core/tx/eip712/MsgDecoder.ts b/packages/sdk-ts/src/core/tx/eip712/MsgDecoder.ts index 8572b9181..517516b02 100644 --- a/packages/sdk-ts/src/core/tx/eip712/MsgDecoder.ts +++ b/packages/sdk-ts/src/core/tx/eip712/MsgDecoder.ts @@ -3,6 +3,7 @@ import { getInjectiveAddress } from '../../../utils/index.js' import { toUtf8, uint8ArrayToHex } from '../../../utils/encoding.js' import { MsgSignData, + MsgDecreasePositionMargin, MsgIncreasePositionMargin, } from '../../modules/exchange/index.js' import type * as GoogleProtobufAnyPb from '@injectivelabs/core-proto-ts-v2/generated/google/protobuf/any_pb' @@ -28,6 +29,21 @@ export class MsgDecoder { }) } + case type.includes('MsgDecreasePositionMargin'): { + const msg = + InjectiveExchangeV1Beta1TxPb.MsgDecreasePositionMargin.fromBinary( + message.value, + ) + + return MsgDecreasePositionMargin.fromJSON({ + marketId: msg.marketId, + injectiveAddress: msg.sender, + srcSubaccountId: msg.sourceSubaccountId, + dstSubaccountId: msg.destinationSubaccountId, + amount: msg.amount, + }) + } + case type.includes('MsgSignData'): { const msg = InjectiveExchangeV1Beta1TxPb.MsgSignData.fromBinary( message.value, diff --git a/packages/sdk-ts/src/core/tx/eip712/maps.ts b/packages/sdk-ts/src/core/tx/eip712/maps.ts index 48fc1f915..2b2873608 100644 --- a/packages/sdk-ts/src/core/tx/eip712/maps.ts +++ b/packages/sdk-ts/src/core/tx/eip712/maps.ts @@ -368,6 +368,8 @@ export const protoTypeToAminoType = (type: string): string => { return 'exchange/MsgExternalTransfer' case 'injective.exchange.v1beta1.MsgIncreasePositionMargin': return 'exchange/MsgIncreasePositionMargin' + case 'injective.exchange.v1beta1.MsgDecreasePositionMargin': + return 'exchange/MsgDecreasePositionMargin' case 'injective.exchange.v1beta1.MsgLiquidatePosition': return 'exchange/MsgLiquidatePosition' case 'injective.exchange.v1beta1.MsgBatchUpdateOrders': diff --git a/scripts/eslint-rules/no-sdk-ts-barrel.js b/scripts/eslint-rules/no-sdk-ts-barrel.js index 168d20382..0b4075e0a 100644 --- a/scripts/eslint-rules/no-sdk-ts-barrel.js +++ b/scripts/eslint-rules/no-sdk-ts-barrel.js @@ -85,6 +85,7 @@ const SUBPATH_MAPPINGS = { MsgBatchCancelDerivativeOrders: '/core/modules', MsgBatchUpdateOrders: '/core/modules', MsgIncreasePositionMargin: '/core/modules', + MsgDecreasePositionMargin: '/core/modules', MsgLiquidatePosition: '/core/modules', MsgSubaccountTransfer: '/core/modules', MsgExternalTransfer: '/core/modules', From b7e1d93ad888fd3e7626665a42070f0a662d9a47 Mon Sep 17 00:00:00 2001 From: thomasRalee Date: Mon, 13 Apr 2026 15:26:08 +0800 Subject: [PATCH 2/2] fix: big number typing --- packages/utils/tsdown.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/utils/tsdown.config.ts b/packages/utils/tsdown.config.ts index 9dbdbd5de..12fa4f187 100644 --- a/packages/utils/tsdown.config.ts +++ b/packages/utils/tsdown.config.ts @@ -15,6 +15,7 @@ export default defineConfig({ outDir: 'dist', external: [ // External workspace dependencies + 'bignumber.js', '@injectivelabs/exceptions', '@injectivelabs/networks', '@injectivelabs/ts-types',