@zoguxprotocol/client-js 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/__native__/__ios__/v4-native-client.js +785 -23
  2. package/__native__/__ios__/v4-native-client.js.map +1 -1
  3. package/__tests__/clients/composite-client.test.ts +7 -1
  4. package/__tests__/helpers/constants.ts +14 -3
  5. package/__tests__/lib/composer-spot-perp.test.ts +84 -0
  6. package/__tests__/lib/validation.test.ts +83 -3
  7. package/build/cjs/__tests__/clients/composite-client.test.js +6 -1
  8. package/build/cjs/__tests__/helpers/constants.js +14 -5
  9. package/build/cjs/__tests__/lib/composer-spot-perp.test.js +78 -0
  10. package/build/cjs/__tests__/lib/validation.test.js +69 -4
  11. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/cosmos/bundle.js +126 -126
  12. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/bundle.js +168 -162
  13. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/events/events.js +37 -5
  14. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/protocol/v1/subaccount.js +46 -2
  15. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/rpc.tx.js +2 -1
  16. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/transfer.js +326 -2
  17. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.js +132 -2
  18. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.rpc.msg.js +31 -1
  19. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/spot_position.js +82 -0
  20. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/subaccount.js +20 -3
  21. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.js +125 -0
  22. package/build/cjs/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.rpc.msg.js +51 -0
  23. package/build/cjs/src/clients/constants.js +8 -3
  24. package/build/cjs/src/clients/lib/registry.js +11 -6
  25. package/build/cjs/src/clients/modules/account.js +13 -1
  26. package/build/cjs/src/clients/modules/composer.js +42 -1
  27. package/build/cjs/src/clients/modules/post.js +41 -1
  28. package/build/cjs/src/clients/types.js +1 -1
  29. package/build/cjs/src/lib/validation.js +53 -1
  30. package/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  31. package/build/esm/__tests__/clients/composite-client.test.js +6 -1
  32. package/build/esm/__tests__/helpers/constants.d.ts +2 -1
  33. package/build/esm/__tests__/helpers/constants.d.ts.map +1 -1
  34. package/build/esm/__tests__/helpers/constants.js +13 -4
  35. package/build/esm/__tests__/lib/composer-spot-perp.test.d.ts +2 -0
  36. package/build/esm/__tests__/lib/composer-spot-perp.test.d.ts.map +1 -0
  37. package/build/esm/__tests__/lib/composer-spot-perp.test.js +73 -0
  38. package/build/esm/__tests__/lib/validation.test.js +71 -6
  39. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/cosmos/bundle.d.ts +158 -158
  40. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/cosmos/bundle.js +126 -126
  41. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/bundle.d.ts +551 -476
  42. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/bundle.d.ts.map +1 -1
  43. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/bundle.js +168 -162
  44. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/events/events.d.ts +14 -1
  45. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/events/events.d.ts.map +1 -1
  46. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/events/events.js +38 -6
  47. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/protocol/v1/subaccount.d.ts +27 -0
  48. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/protocol/v1/subaccount.d.ts.map +1 -1
  49. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/indexer/protocol/v1/subaccount.js +45 -1
  50. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/rpc.tx.d.ts +1 -0
  51. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/rpc.tx.d.ts.map +1 -1
  52. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/rpc.tx.js +2 -1
  53. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/transfer.d.ts +156 -0
  54. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/transfer.d.ts.map +1 -1
  55. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/transfer.js +325 -1
  56. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.d.ts +79 -0
  57. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.d.ts.map +1 -1
  58. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.js +131 -1
  59. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.rpc.msg.d.ts +29 -2
  60. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.rpc.msg.d.ts.map +1 -1
  61. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/sending/tx.rpc.msg.js +33 -3
  62. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/spot_position.d.ts +30 -0
  63. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/spot_position.d.ts.map +1 -0
  64. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/spot_position.js +46 -0
  65. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/subaccount.d.ts +16 -1
  66. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/subaccount.d.ts.map +1 -1
  67. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/subaccount.js +20 -3
  68. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.d.ts +41 -0
  69. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.d.ts.map +1 -0
  70. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.js +89 -0
  71. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.rpc.msg.d.ts +16 -0
  72. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.rpc.msg.d.ts.map +1 -0
  73. package/build/esm/node_modules/@zoguxprotocol/proto/src/codegen/zogux/subaccounts/tx.rpc.msg.js +14 -0
  74. package/build/esm/src/clients/constants.d.ts +5 -0
  75. package/build/esm/src/clients/constants.d.ts.map +1 -1
  76. package/build/esm/src/clients/constants.js +6 -1
  77. package/build/esm/src/clients/lib/registry.d.ts.map +1 -1
  78. package/build/esm/src/clients/lib/registry.js +9 -4
  79. package/build/esm/src/clients/modules/account.d.ts +5 -0
  80. package/build/esm/src/clients/modules/account.d.ts.map +1 -1
  81. package/build/esm/src/clients/modules/account.js +13 -1
  82. package/build/esm/src/clients/modules/composer.d.ts +5 -0
  83. package/build/esm/src/clients/modules/composer.d.ts.map +1 -1
  84. package/build/esm/src/clients/modules/composer.js +43 -2
  85. package/build/esm/src/clients/modules/post.d.ts +15 -0
  86. package/build/esm/src/clients/modules/post.d.ts.map +1 -1
  87. package/build/esm/src/clients/modules/post.js +41 -1
  88. package/build/esm/src/clients/types.d.ts +14 -0
  89. package/build/esm/src/clients/types.d.ts.map +1 -1
  90. package/build/esm/src/clients/types.js +1 -1
  91. package/build/esm/src/lib/validation.d.ts +11 -1
  92. package/build/esm/src/lib/validation.d.ts.map +1 -1
  93. package/build/esm/src/lib/validation.js +51 -1
  94. package/build/esm/tsconfig.esm.tsbuildinfo +1 -1
  95. package/package.json +2 -2
  96. package/src/clients/constants.ts +5 -0
  97. package/src/clients/lib/registry.ts +16 -1
  98. package/src/clients/modules/account.ts +17 -0
  99. package/src/clients/modules/composer.ts +83 -0
  100. package/src/clients/modules/post.ts +146 -0
  101. package/src/clients/types.ts +9 -0
  102. package/src/lib/validation.ts +62 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoguxprotocol/client-js",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "General client library for the new Zogux system (v4 decentralized)",
5
5
  "main": "build/cjs/src/index.js",
6
6
  "module": "build/esm/src/index.js",
@@ -55,7 +55,7 @@
55
55
  "@osmonauts/lcd": "^0.6.0",
56
56
  "@scure/bip32": "^1.1.5",
57
57
  "@scure/bip39": "^1.1.1",
58
- "@zoguxprotocol/proto": "0.1.6",
58
+ "@zoguxprotocol/proto": "0.1.7",
59
59
  "axios": "1.1.3",
60
60
  "bech32": "^1.1.4",
61
61
  "bignumber.js": "^9.1.1",
@@ -101,6 +101,11 @@ export const TYPE_URL_MSG_CREATE_TRANSFER = '/zogux.sending.MsgCreateTransfer';
101
101
  export const TYPE_URL_MSG_WITHDRAW_FROM_SUBACCOUNT =
102
102
  '/zogux.sending.MsgWithdrawFromSubaccount';
103
103
  export const TYPE_URL_MSG_DEPOSIT_TO_SUBACCOUNT = '/zogux.sending.MsgDepositToSubaccount';
104
+ export const TYPE_URL_MSG_TRANSFER_SPOT_TO_PERP = '/zogux.sending.MsgTransferSpotToPerp';
105
+ export const TYPE_URL_MSG_TRANSFER_PERP_TO_SPOT = '/zogux.sending.MsgTransferPerpToSpot';
106
+ export const TYPE_URL_MSG_CREATE_TRANSFER_SPOT = '/zogux.sending.MsgCreateTransferSpot';
107
+ export const TYPE_URL_MSG_DEPOSIT_TO_SPOT = '/zogux.sending.MsgDepositToSpot';
108
+ export const TYPE_URL_MSG_WITHDRAW_FROM_SPOT = '/zogux.sending.MsgWithdrawFromSpot';
104
109
 
105
110
  // x/affiliates
106
111
  export const TYPE_URL_MSG_REGISTER_AFFILIATE = '/zogux.affiliates.MsgRegisterAffiliate';
@@ -16,8 +16,12 @@ import { MsgCreateOracleMarket } from '@zoguxprotocol/proto/src/codegen/zogux/pr
16
16
  import {
17
17
  MsgWithdrawFromSubaccount,
18
18
  MsgDepositToSubaccount,
19
+ MsgTransferSpotToPerp,
20
+ MsgTransferPerpToSpot,
21
+ MsgCreateTransferSpot,
22
+ MsgDepositToSpot,
23
+ MsgWithdrawFromSpot,
19
24
  } from '@zoguxprotocol/proto/src/codegen/zogux/sending/transfer';
20
- import { MsgCreateTransfer } from '@zoguxprotocol/proto/src/codegen/zogux/sending/tx';
21
25
  import {
22
26
  MsgDepositToMegavault,
23
27
  MsgWithdrawFromMegavault,
@@ -34,6 +38,11 @@ import {
34
38
  TYPE_URL_MSG_CREATE_TRANSFER,
35
39
  TYPE_URL_MSG_WITHDRAW_FROM_SUBACCOUNT,
36
40
  TYPE_URL_MSG_DEPOSIT_TO_SUBACCOUNT,
41
+ TYPE_URL_MSG_TRANSFER_SPOT_TO_PERP,
42
+ TYPE_URL_MSG_TRANSFER_PERP_TO_SPOT,
43
+ TYPE_URL_MSG_CREATE_TRANSFER_SPOT,
44
+ TYPE_URL_MSG_DEPOSIT_TO_SPOT,
45
+ TYPE_URL_MSG_WITHDRAW_FROM_SPOT,
37
46
  TYPE_URL_BATCH_CANCEL,
38
47
  TYPE_URL_MSG_DEPOSIT_TO_MEGAVAULT,
39
48
  TYPE_URL_MSG_WITHDRAW_FROM_MEGAVAULT,
@@ -42,6 +51,7 @@ import {
42
51
  TYPE_URL_MSG_ADD_AUTHENTICATOR,
43
52
  TYPE_URL_MSG_REMOVE_AUTHENTICATOR,
44
53
  } from '../constants';
54
+ import { MsgCreateTransfer } from '../types';
45
55
 
46
56
  export const registry: ReadonlyArray<[string, GeneratedType]> = [];
47
57
  export function generateRegistry(): Registry {
@@ -73,6 +83,11 @@ export function generateRegistry(): Registry {
73
83
  [TYPE_URL_MSG_CREATE_TRANSFER, MsgCreateTransfer as GeneratedType],
74
84
  [TYPE_URL_MSG_WITHDRAW_FROM_SUBACCOUNT, MsgWithdrawFromSubaccount as GeneratedType],
75
85
  [TYPE_URL_MSG_DEPOSIT_TO_SUBACCOUNT, MsgDepositToSubaccount as GeneratedType],
86
+ [TYPE_URL_MSG_TRANSFER_SPOT_TO_PERP, MsgTransferSpotToPerp as GeneratedType],
87
+ [TYPE_URL_MSG_TRANSFER_PERP_TO_SPOT, MsgTransferPerpToSpot as GeneratedType],
88
+ [TYPE_URL_MSG_CREATE_TRANSFER_SPOT, MsgCreateTransferSpot as GeneratedType],
89
+ [TYPE_URL_MSG_DEPOSIT_TO_SPOT, MsgDepositToSpot as GeneratedType],
90
+ [TYPE_URL_MSG_WITHDRAW_FROM_SPOT, MsgWithdrawFromSpot as GeneratedType],
76
91
 
77
92
  // affiliates
78
93
  [TYPE_URL_MSG_REGISTER_AFFILIATE, MsgRegisterAffiliate as GeneratedType],
@@ -70,6 +70,23 @@ export default class AccountClient extends RestClient {
70
70
  });
71
71
  }
72
72
 
73
+ /**
74
+ * Spot asset positions (spot balance per subaccount/asset).
75
+ * Use for display and validation when building Spot→Perp or Perp→Spot transfers.
76
+ */
77
+ async getSpotAssetPositions(
78
+ address: string,
79
+ subaccountNumber: number,
80
+ limit?: number | null,
81
+ ): Promise<Data> {
82
+ const uri = '/v4/spotAssetPositions';
83
+ return this.get(uri, {
84
+ address,
85
+ subaccountNumber,
86
+ limit,
87
+ });
88
+ }
89
+
73
90
  // ------ Transfers ------ //
74
91
 
75
92
  async getTransfersBetween(
@@ -45,6 +45,11 @@ import {
45
45
  TYPE_URL_MSG_CREATE_TRANSFER,
46
46
  TYPE_URL_MSG_WITHDRAW_FROM_SUBACCOUNT,
47
47
  TYPE_URL_MSG_DEPOSIT_TO_SUBACCOUNT,
48
+ TYPE_URL_MSG_TRANSFER_SPOT_TO_PERP,
49
+ TYPE_URL_MSG_TRANSFER_PERP_TO_SPOT,
50
+ TYPE_URL_MSG_CREATE_TRANSFER_SPOT,
51
+ TYPE_URL_MSG_DEPOSIT_TO_SPOT,
52
+ TYPE_URL_MSG_WITHDRAW_FROM_SPOT,
48
53
  TYPE_URL_MSG_DELEGATE,
49
54
  TYPE_URL_MSG_UNDELEGATE,
50
55
  TYPE_URL_MSG_WITHDRAW_DELEGATOR_REWARD,
@@ -338,6 +343,84 @@ export class Composer {
338
343
  };
339
344
  }
340
345
 
346
+ public composeMsgTransferSpotToPerp(
347
+ senderAddress: string,
348
+ senderSubaccountNumber: number,
349
+ recipientOwner: string,
350
+ recipientSubaccountNumber: number,
351
+ assetId: number,
352
+ quantums: Long,
353
+ ): EncodeObject {
354
+ const senderSubaccountId: SubaccountId = { owner: senderAddress, number: senderSubaccountNumber };
355
+ const recipientSubaccountId: SubaccountId = { owner: recipientOwner, number: recipientSubaccountNumber };
356
+ return {
357
+ typeUrl: TYPE_URL_MSG_TRANSFER_SPOT_TO_PERP,
358
+ value: {
359
+ sender: senderAddress,
360
+ senderSubaccountId,
361
+ recipientSubaccountId,
362
+ assetId,
363
+ quantums,
364
+ },
365
+ };
366
+ }
367
+
368
+ public composeMsgTransferPerpToSpot(
369
+ senderAddress: string,
370
+ senderSubaccountNumber: number,
371
+ recipientOwner: string,
372
+ recipientSubaccountNumber: number,
373
+ assetId: number,
374
+ quantums: Long,
375
+ ): EncodeObject {
376
+ const senderSubaccountId: SubaccountId = { owner: senderAddress, number: senderSubaccountNumber };
377
+ const recipientSubaccountId: SubaccountId = { owner: recipientOwner, number: recipientSubaccountNumber };
378
+ return {
379
+ typeUrl: TYPE_URL_MSG_TRANSFER_PERP_TO_SPOT,
380
+ value: {
381
+ sender: senderAddress,
382
+ senderSubaccountId,
383
+ recipientSubaccountId,
384
+ assetId,
385
+ quantums,
386
+ },
387
+ };
388
+ }
389
+
390
+ public composeMsgCreateTransferSpot(
391
+ senderAddress: string,
392
+ senderSubaccountNumber: number,
393
+ recipientOwner: string,
394
+ recipientSubaccountNumber: number,
395
+ assetId: number,
396
+ quantums: Long,
397
+ ): EncodeObject {
398
+ const senderSubaccountId: SubaccountId = { owner: senderAddress, number: senderSubaccountNumber };
399
+ const recipientSubaccountId: SubaccountId = { owner: recipientOwner, number: recipientSubaccountNumber };
400
+ return { typeUrl: TYPE_URL_MSG_CREATE_TRANSFER_SPOT, value: { sender: senderAddress, senderSubaccountId, recipientSubaccountId, assetId, quantums } };
401
+ }
402
+
403
+ public composeMsgDepositToSpot(
404
+ address: string,
405
+ subaccountNumber: number,
406
+ assetId: number,
407
+ quantums: Long,
408
+ ): EncodeObject {
409
+ const recipient: SubaccountId = { owner: address, number: subaccountNumber };
410
+ return { typeUrl: TYPE_URL_MSG_DEPOSIT_TO_SPOT, value: { sender: address, recipient, assetId, quantums } };
411
+ }
412
+
413
+ public composeMsgWithdrawFromSpot(
414
+ address: string,
415
+ subaccountNumber: number,
416
+ assetId: number,
417
+ quantums: Long,
418
+ recipient: string = address,
419
+ ): EncodeObject {
420
+ const sender: SubaccountId = { owner: address, number: subaccountNumber };
421
+ return { typeUrl: TYPE_URL_MSG_WITHDRAW_FROM_SPOT, value: { sender, recipient, assetId, quantums } };
422
+ }
423
+
341
424
  // ------------ x/bank ------------
342
425
  public composeMsgSendToken(
343
426
  address: string,
@@ -43,6 +43,11 @@ import {
43
43
  protobuf.util.Long = Long;
44
44
  protobuf.configure();
45
45
 
46
+ /**
47
+ * Post signs and broadcasts transactions. All messages are built via this.composer;
48
+ * when adding a new message type, follow: constants (TYPE_URL) → lib/registry.ts →
49
+ * composer.composeMsg* → Post method that calls composer and passes to send().
50
+ */
46
51
  export class Post {
47
52
  public readonly composer: Composer;
48
53
  private readonly registry: Registry;
@@ -757,6 +762,147 @@ export class Post {
757
762
  });
758
763
  }
759
764
 
765
+ async transferSpotToPerp(
766
+ subaccount: SubaccountInfo,
767
+ recipientOwner: string,
768
+ recipientSubaccountNumber: number,
769
+ assetId: number,
770
+ quantums: Long,
771
+ broadcastMode?: BroadcastMode,
772
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
773
+ const msg = await this.transferSpotToPerpMsg(
774
+ subaccount.address,
775
+ subaccount.subaccountNumber,
776
+ recipientOwner,
777
+ recipientSubaccountNumber,
778
+ assetId,
779
+ quantums,
780
+ );
781
+ return this.send(subaccount, () => Promise.resolve([msg]), false, undefined, undefined, broadcastMode);
782
+ }
783
+
784
+ async transferSpotToPerpMsg(
785
+ senderAddress: string,
786
+ senderSubaccountNumber: number,
787
+ recipientOwner: string,
788
+ recipientSubaccountNumber: number,
789
+ assetId: number,
790
+ quantums: Long,
791
+ ): Promise<EncodeObject> {
792
+ return Promise.resolve(
793
+ this.composer.composeMsgTransferSpotToPerp(
794
+ senderAddress,
795
+ senderSubaccountNumber,
796
+ recipientOwner,
797
+ recipientSubaccountNumber,
798
+ assetId,
799
+ quantums,
800
+ ),
801
+ );
802
+ }
803
+
804
+ async transferPerpToSpot(
805
+ subaccount: SubaccountInfo,
806
+ recipientOwner: string,
807
+ recipientSubaccountNumber: number,
808
+ assetId: number,
809
+ quantums: Long,
810
+ broadcastMode?: BroadcastMode,
811
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
812
+ const msg = await this.transferPerpToSpotMsg(
813
+ subaccount.address,
814
+ subaccount.subaccountNumber,
815
+ recipientOwner,
816
+ recipientSubaccountNumber,
817
+ assetId,
818
+ quantums,
819
+ );
820
+ return this.send(subaccount, () => Promise.resolve([msg]), false, undefined, undefined, broadcastMode);
821
+ }
822
+
823
+ async transferPerpToSpotMsg(
824
+ senderAddress: string,
825
+ senderSubaccountNumber: number,
826
+ recipientOwner: string,
827
+ recipientSubaccountNumber: number,
828
+ assetId: number,
829
+ quantums: Long,
830
+ ): Promise<EncodeObject> {
831
+ return Promise.resolve(
832
+ this.composer.composeMsgTransferPerpToSpot(
833
+ senderAddress,
834
+ senderSubaccountNumber,
835
+ recipientOwner,
836
+ recipientSubaccountNumber,
837
+ assetId,
838
+ quantums,
839
+ ),
840
+ );
841
+ }
842
+
843
+ async createTransferSpot(
844
+ subaccount: SubaccountInfo,
845
+ recipientOwner: string,
846
+ recipientSubaccountNumber: number,
847
+ assetId: number,
848
+ quantums: Long,
849
+ broadcastMode?: BroadcastMode,
850
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
851
+ const msg = await this.createTransferSpotMsg(subaccount.address, subaccount.subaccountNumber, recipientOwner, recipientSubaccountNumber, assetId, quantums);
852
+ return this.send(subaccount, () => Promise.resolve([msg]), false, undefined, undefined, broadcastMode);
853
+ }
854
+
855
+ async createTransferSpotMsg(
856
+ senderAddress: string,
857
+ senderSubaccountNumber: number,
858
+ recipientOwner: string,
859
+ recipientSubaccountNumber: number,
860
+ assetId: number,
861
+ quantums: Long,
862
+ ): Promise<EncodeObject> {
863
+ return Promise.resolve(this.composer.composeMsgCreateTransferSpot(senderAddress, senderSubaccountNumber, recipientOwner, recipientSubaccountNumber, assetId, quantums));
864
+ }
865
+
866
+ async depositToSpot(
867
+ subaccount: SubaccountInfo,
868
+ assetId: number,
869
+ quantums: Long,
870
+ broadcastMode?: BroadcastMode,
871
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
872
+ const msg = await this.depositToSpotMsg(subaccount.address, subaccount.subaccountNumber, assetId, quantums);
873
+ return this.send(subaccount, () => Promise.resolve([msg]), false, undefined, undefined, broadcastMode);
874
+ }
875
+
876
+ async depositToSpotMsg(
877
+ address: string,
878
+ subaccountNumber: number,
879
+ assetId: number,
880
+ quantums: Long,
881
+ ): Promise<EncodeObject> {
882
+ return Promise.resolve(this.composer.composeMsgDepositToSpot(address, subaccountNumber, assetId, quantums));
883
+ }
884
+
885
+ async withdrawFromSpot(
886
+ subaccount: SubaccountInfo,
887
+ assetId: number,
888
+ quantums: Long,
889
+ recipient?: string,
890
+ broadcastMode?: BroadcastMode,
891
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
892
+ const msg = await this.withdrawFromSpotMsg(subaccount.address, subaccount.subaccountNumber, assetId, quantums, recipient);
893
+ return this.send(subaccount, () => Promise.resolve([msg]), false, undefined, undefined, broadcastMode);
894
+ }
895
+
896
+ async withdrawFromSpotMsg(
897
+ address: string,
898
+ subaccountNumber: number,
899
+ assetId: number,
900
+ quantums: Long,
901
+ recipient?: string,
902
+ ): Promise<EncodeObject> {
903
+ return Promise.resolve(this.composer.composeMsgWithdrawFromSpot(address, subaccountNumber, assetId, quantums, recipient));
904
+ }
905
+
760
906
  async sendToken(
761
907
  subaccount: SubaccountInfo,
762
908
  recipient: string,
@@ -188,4 +188,13 @@ export type GovAddNewMarketParams = {
188
188
  delayBlocks: number;
189
189
  };
190
190
 
191
+ /** Payload shape for MsgTransferSpotToPerp and MsgTransferPerpToSpot (spot–perp transfer). */
192
+ export interface ISpotPerpTransferMessage {
193
+ sender: string;
194
+ senderSubaccountId: { owner: string; number: number };
195
+ recipientSubaccountId: { owner: string; number: number };
196
+ assetId: number;
197
+ quantums: Long | bigint;
198
+ }
199
+
191
200
  export * from './modules/proto-includes';
@@ -8,6 +8,7 @@ import {
8
8
  ICancelOrder,
9
9
  IPlaceOrder,
10
10
  IBatchCancelOrder,
11
+ ISpotPerpTransferMessage,
11
12
  } from '../clients/types';
12
13
  import { UserError } from './errors';
13
14
 
@@ -145,6 +146,67 @@ export function validateTransferMessage(transfer: Transfer): UserError | undefin
145
146
  return undefined;
146
147
  }
147
148
 
149
+ /**
150
+ * Validates fields for MsgTransferSpotToPerp / MsgTransferPerpToSpot (spot–perp transfer).
151
+ * Checks: quantums > 0, subaccount numbers in range, sender and subaccount owners are valid Bech32.
152
+ */
153
+ function validateSpotPerpTransferMessage(
154
+ msg: ISpotPerpTransferMessage,
155
+ ): UserError | undefined {
156
+ if (!verifySubaccountNumber(msg.senderSubaccountId?.number ?? -1)) {
157
+ return new UserError(
158
+ `senderSubaccountNumber: ${msg.senderSubaccountId?.number ?? 'missing'} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
159
+ );
160
+ }
161
+ if (!verifySubaccountNumber(msg.recipientSubaccountId?.number ?? -1)) {
162
+ return new UserError(
163
+ `recipientSubaccountNumber: ${msg.recipientSubaccountId?.number ?? 'missing'} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
164
+ );
165
+ }
166
+ const quantumsZero =
167
+ typeof msg.quantums === 'bigint'
168
+ ? msg.quantums <= BigInt(0)
169
+ : msg.quantums.lessThanOrEqual(Long.ZERO);
170
+ if (quantumsZero) {
171
+ return new UserError(`quantums: ${msg.quantums} cannot be <= 0`);
172
+ }
173
+ const senderError = verifyIsBech32(msg.sender);
174
+ if (senderError !== undefined) {
175
+ return new UserError(senderError.toString());
176
+ }
177
+ const senderOwner = msg.senderSubaccountId?.owner;
178
+ if (senderOwner !== undefined) {
179
+ const err = verifyIsBech32(senderOwner);
180
+ if (err !== undefined) return new UserError(err.toString());
181
+ }
182
+ const recipientOwner = msg.recipientSubaccountId?.owner;
183
+ if (recipientOwner !== undefined) {
184
+ const err = verifyIsBech32(recipientOwner);
185
+ if (err !== undefined) return new UserError(err.toString());
186
+ }
187
+ return undefined;
188
+ }
189
+
190
+ /**
191
+ * @describe validateTransferSpotToPerpMessage validates that a Spot→Perp transfer message has
192
+ * fields that would be valid on-chain.
193
+ */
194
+ export function validateTransferSpotToPerpMessage(
195
+ msg: ISpotPerpTransferMessage,
196
+ ): UserError | undefined {
197
+ return validateSpotPerpTransferMessage(msg);
198
+ }
199
+
200
+ /**
201
+ * @describe validateTransferPerpToSpotMessage validates that a Perp→Spot transfer message has
202
+ * fields that would be valid on-chain.
203
+ */
204
+ export function validateTransferPerpToSpotMessage(
205
+ msg: ISpotPerpTransferMessage,
206
+ ): UserError | undefined {
207
+ return validateSpotPerpTransferMessage(msg);
208
+ }
209
+
148
210
  function verifyGoodTilBlock(goodTilBlock: number | undefined): boolean {
149
211
  if (goodTilBlock === undefined) {
150
212
  return false;