@ritbit/v4-client-js 2.4.1 → 2.4.2

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 (296) hide show
  1. package/build/cjs/src/clients/composite-client.js +10 -9
  2. package/build/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  3. package/build/esm/src/clients/composite-client.d.ts +3 -3
  4. package/build/esm/src/clients/composite-client.d.ts.map +1 -1
  5. package/build/esm/src/clients/composite-client.js +10 -9
  6. package/build/esm/tsconfig.esm.tsbuildinfo +1 -1
  7. package/package.json +11 -3
  8. package/.env +0 -1
  9. package/.eslintignore +0 -2
  10. package/.eslintrc.js +0 -15
  11. package/.gitleaks.toml +0 -24
  12. package/.gitleaksignore +0 -1
  13. package/.nvmrc +0 -1
  14. package/.prettierignore +0 -3
  15. package/.prettierrc.json +0 -6
  16. package/.releaserc +0 -10
  17. package/.vscode/launch.json +0 -11
  18. package/__native__/__ios__/v4-native-client.js +0 -251395
  19. package/__native__/__ios__/v4-native-client.js.map +0 -1
  20. package/__tests__/clients/composite-client.test.ts +0 -140
  21. package/__tests__/helpers/baseClients.ts +0 -23
  22. package/__tests__/helpers/constants.ts +0 -131
  23. package/__tests__/lib/helpers.test.ts +0 -55
  24. package/__tests__/lib/util.test.ts +0 -77
  25. package/__tests__/lib/validation.test.ts +0 -289
  26. package/__tests__/modules/client/AccountEndpoints.test.ts +0 -236
  27. package/__tests__/modules/client/FaucetEndpoint.test.ts +0 -14
  28. package/__tests__/modules/client/MarketsEndpoints.test.ts +0 -84
  29. package/__tests__/modules/client/Transfers.test.ts +0 -44
  30. package/__tests__/modules/client/UtilityEndpoints.test.ts +0 -29
  31. package/__tests__/modules/client/ValidatorGetEndpoints.test.ts +0 -50
  32. package/__tests__/modules/client/ValidatorPostEndpoints.test.ts +0 -52
  33. package/__tests__/modules/client/constants.ts +0 -5
  34. package/__tests__/modules/onboarding.test.ts +0 -66
  35. package/build/cjs/__tests__/clients/composite-client.test.js +0 -130
  36. package/build/cjs/__tests__/helpers/baseClients.js +0 -29
  37. package/build/cjs/__tests__/helpers/constants.js +0 -110
  38. package/build/cjs/__tests__/lib/helpers.test.js +0 -46
  39. package/build/cjs/__tests__/lib/util.test.js +0 -67
  40. package/build/cjs/__tests__/lib/validation.test.js +0 -254
  41. package/build/cjs/__tests__/modules/client/AccountEndpoints.test.js +0 -171
  42. package/build/cjs/__tests__/modules/client/FaucetEndpoint.test.js +0 -15
  43. package/build/cjs/__tests__/modules/client/MarketsEndpoints.test.js +0 -69
  44. package/build/cjs/__tests__/modules/client/Transfers.test.js +0 -44
  45. package/build/cjs/__tests__/modules/client/UtilityEndpoints.test.js +0 -28
  46. package/build/cjs/__tests__/modules/client/ValidatorGetEndpoints.test.js +0 -46
  47. package/build/cjs/__tests__/modules/client/ValidatorPostEndpoints.test.js +0 -53
  48. package/build/cjs/__tests__/modules/client/constants.js +0 -7
  49. package/build/cjs/__tests__/modules/onboarding.test.js +0 -50
  50. package/build/cjs/examples/account_endpoints.js +0 -129
  51. package/build/cjs/examples/batch_cancel_orders_example.js +0 -93
  52. package/build/cjs/examples/composite_example.js +0 -50
  53. package/build/cjs/examples/constants.js +0 -35
  54. package/build/cjs/examples/faucet_endpoint.js +0 -23
  55. package/build/cjs/examples/gov_add_new_market.js +0 -77
  56. package/build/cjs/examples/human_readable_orders.json +0 -86
  57. package/build/cjs/examples/human_readable_short_term_orders.json +0 -42
  58. package/build/cjs/examples/json-encoding.js +0 -32
  59. package/build/cjs/examples/long_term_order_cancel_example.js +0 -63
  60. package/build/cjs/examples/markets_endpoints.js +0 -134
  61. package/build/cjs/examples/native_examples.js +0 -112
  62. package/build/cjs/examples/noble_example.js +0 -88
  63. package/build/cjs/examples/optimal_node.js +0 -70
  64. package/build/cjs/examples/permissioned_keys_example.js +0 -104
  65. package/build/cjs/examples/raw_orders.json +0 -130
  66. package/build/cjs/examples/short_term_order_cancel_example.js +0 -54
  67. package/build/cjs/examples/short_term_order_composite_example.js +0 -68
  68. package/build/cjs/examples/test.js +0 -50
  69. package/build/cjs/examples/transfer_example_deposit.js +0 -29
  70. package/build/cjs/examples/transfer_example_send.js +0 -42
  71. package/build/cjs/examples/transfer_example_subaccount_transfer.js +0 -29
  72. package/build/cjs/examples/transfer_example_withdraw.js +0 -30
  73. package/build/cjs/examples/transfer_example_withdraw_other.js +0 -42
  74. package/build/cjs/examples/utility_endpoints.js +0 -42
  75. package/build/cjs/examples/validator_get_example.js +0 -158
  76. package/build/cjs/examples/validator_post_example.js +0 -76
  77. package/build/cjs/examples/wallet_address.js +0 -22
  78. package/build/cjs/examples/websocket_example.js +0 -36
  79. package/build/cjs/examples/websocket_orderbook_example.js +0 -196
  80. package/build/esm/__tests__/clients/composite-client.test.d.ts +0 -2
  81. package/build/esm/__tests__/clients/composite-client.test.d.ts.map +0 -1
  82. package/build/esm/__tests__/clients/composite-client.test.js +0 -128
  83. package/build/esm/__tests__/helpers/baseClients.d.ts +0 -19
  84. package/build/esm/__tests__/helpers/baseClients.d.ts.map +0 -1
  85. package/build/esm/__tests__/helpers/baseClients.js +0 -22
  86. package/build/esm/__tests__/helpers/constants.d.ts +0 -19
  87. package/build/esm/__tests__/helpers/constants.d.ts.map +0 -1
  88. package/build/esm/__tests__/helpers/constants.js +0 -104
  89. package/build/esm/__tests__/lib/helpers.test.d.ts +0 -2
  90. package/build/esm/__tests__/lib/helpers.test.d.ts.map +0 -1
  91. package/build/esm/__tests__/lib/helpers.test.js +0 -41
  92. package/build/esm/__tests__/lib/util.test.d.ts +0 -2
  93. package/build/esm/__tests__/lib/util.test.d.ts.map +0 -1
  94. package/build/esm/__tests__/lib/util.test.js +0 -65
  95. package/build/esm/__tests__/lib/validation.test.d.ts +0 -2
  96. package/build/esm/__tests__/lib/validation.test.d.ts.map +0 -1
  97. package/build/esm/__tests__/lib/validation.test.js +0 -249
  98. package/build/esm/__tests__/modules/client/AccountEndpoints.test.d.ts +0 -2
  99. package/build/esm/__tests__/modules/client/AccountEndpoints.test.d.ts.map +0 -1
  100. package/build/esm/__tests__/modules/client/AccountEndpoints.test.js +0 -169
  101. package/build/esm/__tests__/modules/client/FaucetEndpoint.test.d.ts +0 -2
  102. package/build/esm/__tests__/modules/client/FaucetEndpoint.test.d.ts.map +0 -1
  103. package/build/esm/__tests__/modules/client/FaucetEndpoint.test.js +0 -13
  104. package/build/esm/__tests__/modules/client/MarketsEndpoints.test.d.ts +0 -2
  105. package/build/esm/__tests__/modules/client/MarketsEndpoints.test.d.ts.map +0 -1
  106. package/build/esm/__tests__/modules/client/MarketsEndpoints.test.js +0 -66
  107. package/build/esm/__tests__/modules/client/Transfers.test.d.ts +0 -2
  108. package/build/esm/__tests__/modules/client/Transfers.test.d.ts.map +0 -1
  109. package/build/esm/__tests__/modules/client/Transfers.test.js +0 -39
  110. package/build/esm/__tests__/modules/client/UtilityEndpoints.test.d.ts +0 -2
  111. package/build/esm/__tests__/modules/client/UtilityEndpoints.test.d.ts.map +0 -1
  112. package/build/esm/__tests__/modules/client/UtilityEndpoints.test.js +0 -26
  113. package/build/esm/__tests__/modules/client/ValidatorGetEndpoints.test.d.ts +0 -2
  114. package/build/esm/__tests__/modules/client/ValidatorGetEndpoints.test.d.ts.map +0 -1
  115. package/build/esm/__tests__/modules/client/ValidatorGetEndpoints.test.js +0 -44
  116. package/build/esm/__tests__/modules/client/ValidatorPostEndpoints.test.d.ts +0 -2
  117. package/build/esm/__tests__/modules/client/ValidatorPostEndpoints.test.d.ts.map +0 -1
  118. package/build/esm/__tests__/modules/client/ValidatorPostEndpoints.test.js +0 -48
  119. package/build/esm/__tests__/modules/client/constants.d.ts +0 -4
  120. package/build/esm/__tests__/modules/client/constants.d.ts.map +0 -1
  121. package/build/esm/__tests__/modules/client/constants.js +0 -4
  122. package/build/esm/__tests__/modules/onboarding.test.d.ts +0 -2
  123. package/build/esm/__tests__/modules/onboarding.test.d.ts.map +0 -1
  124. package/build/esm/__tests__/modules/onboarding.test.js +0 -48
  125. package/build/esm/examples/account_endpoints.d.ts +0 -5
  126. package/build/esm/examples/account_endpoints.d.ts.map +0 -1
  127. package/build/esm/examples/account_endpoints.js +0 -127
  128. package/build/esm/examples/batch_cancel_orders_example.d.ts +0 -2
  129. package/build/esm/examples/batch_cancel_orders_example.d.ts.map +0 -1
  130. package/build/esm/examples/batch_cancel_orders_example.js +0 -88
  131. package/build/esm/examples/composite_example.d.ts +0 -2
  132. package/build/esm/examples/composite_example.d.ts.map +0 -1
  133. package/build/esm/examples/composite_example.js +0 -45
  134. package/build/esm/examples/constants.d.ts +0 -13
  135. package/build/esm/examples/constants.d.ts.map +0 -1
  136. package/build/esm/examples/constants.js +0 -29
  137. package/build/esm/examples/faucet_endpoint.d.ts +0 -5
  138. package/build/esm/examples/faucet_endpoint.d.ts.map +0 -1
  139. package/build/esm/examples/faucet_endpoint.js +0 -21
  140. package/build/esm/examples/gov_add_new_market.d.ts +0 -2
  141. package/build/esm/examples/gov_add_new_market.d.ts.map +0 -1
  142. package/build/esm/examples/gov_add_new_market.js +0 -72
  143. package/build/esm/examples/human_readable_orders.json +0 -86
  144. package/build/esm/examples/human_readable_short_term_orders.json +0 -42
  145. package/build/esm/examples/json-encoding.d.ts +0 -2
  146. package/build/esm/examples/json-encoding.d.ts.map +0 -1
  147. package/build/esm/examples/json-encoding.js +0 -27
  148. package/build/esm/examples/long_term_order_cancel_example.d.ts +0 -2
  149. package/build/esm/examples/long_term_order_cancel_example.d.ts.map +0 -1
  150. package/build/esm/examples/long_term_order_cancel_example.js +0 -58
  151. package/build/esm/examples/markets_endpoints.d.ts +0 -5
  152. package/build/esm/examples/markets_endpoints.d.ts.map +0 -1
  153. package/build/esm/examples/markets_endpoints.js +0 -131
  154. package/build/esm/examples/native_examples.d.ts +0 -2
  155. package/build/esm/examples/native_examples.d.ts.map +0 -1
  156. package/build/esm/examples/native_examples.js +0 -110
  157. package/build/esm/examples/noble_example.d.ts +0 -2
  158. package/build/esm/examples/noble_example.d.ts.map +0 -1
  159. package/build/esm/examples/noble_example.js +0 -83
  160. package/build/esm/examples/optimal_node.d.ts +0 -2
  161. package/build/esm/examples/optimal_node.d.ts.map +0 -1
  162. package/build/esm/examples/optimal_node.js +0 -68
  163. package/build/esm/examples/permissioned_keys_example.d.ts +0 -2
  164. package/build/esm/examples/permissioned_keys_example.d.ts.map +0 -1
  165. package/build/esm/examples/permissioned_keys_example.js +0 -99
  166. package/build/esm/examples/raw_orders.json +0 -130
  167. package/build/esm/examples/short_term_order_cancel_example.d.ts +0 -2
  168. package/build/esm/examples/short_term_order_cancel_example.d.ts.map +0 -1
  169. package/build/esm/examples/short_term_order_cancel_example.js +0 -49
  170. package/build/esm/examples/short_term_order_composite_example.d.ts +0 -2
  171. package/build/esm/examples/short_term_order_composite_example.d.ts.map +0 -1
  172. package/build/esm/examples/short_term_order_composite_example.js +0 -63
  173. package/build/esm/examples/test.d.ts +0 -2
  174. package/build/esm/examples/test.d.ts.map +0 -1
  175. package/build/esm/examples/test.js +0 -45
  176. package/build/esm/examples/transfer_example_deposit.d.ts +0 -2
  177. package/build/esm/examples/transfer_example_deposit.d.ts.map +0 -1
  178. package/build/esm/examples/transfer_example_deposit.js +0 -24
  179. package/build/esm/examples/transfer_example_send.d.ts +0 -2
  180. package/build/esm/examples/transfer_example_send.d.ts.map +0 -1
  181. package/build/esm/examples/transfer_example_send.js +0 -37
  182. package/build/esm/examples/transfer_example_subaccount_transfer.d.ts +0 -2
  183. package/build/esm/examples/transfer_example_subaccount_transfer.d.ts.map +0 -1
  184. package/build/esm/examples/transfer_example_subaccount_transfer.js +0 -24
  185. package/build/esm/examples/transfer_example_withdraw.d.ts +0 -2
  186. package/build/esm/examples/transfer_example_withdraw.d.ts.map +0 -1
  187. package/build/esm/examples/transfer_example_withdraw.js +0 -25
  188. package/build/esm/examples/transfer_example_withdraw_other.d.ts +0 -2
  189. package/build/esm/examples/transfer_example_withdraw_other.d.ts.map +0 -1
  190. package/build/esm/examples/transfer_example_withdraw_other.js +0 -37
  191. package/build/esm/examples/utility_endpoints.d.ts +0 -5
  192. package/build/esm/examples/utility_endpoints.d.ts.map +0 -1
  193. package/build/esm/examples/utility_endpoints.js +0 -40
  194. package/build/esm/examples/validator_get_example.d.ts +0 -2
  195. package/build/esm/examples/validator_get_example.d.ts.map +0 -1
  196. package/build/esm/examples/validator_get_example.js +0 -156
  197. package/build/esm/examples/validator_post_example.d.ts +0 -2
  198. package/build/esm/examples/validator_post_example.d.ts.map +0 -1
  199. package/build/esm/examples/validator_post_example.js +0 -71
  200. package/build/esm/examples/wallet_address.d.ts +0 -2
  201. package/build/esm/examples/wallet_address.d.ts.map +0 -1
  202. package/build/esm/examples/wallet_address.js +0 -17
  203. package/build/esm/examples/websocket_example.d.ts +0 -2
  204. package/build/esm/examples/websocket_example.d.ts.map +0 -1
  205. package/build/esm/examples/websocket_example.js +0 -34
  206. package/build/esm/examples/websocket_orderbook_example.d.ts +0 -2
  207. package/build/esm/examples/websocket_orderbook_example.d.ts.map +0 -1
  208. package/build/esm/examples/websocket_orderbook_example.js +0 -194
  209. package/commitlint.config.js +0 -8
  210. package/examples/account_endpoints.ts +0 -129
  211. package/examples/batch_cancel_orders_example.ts +0 -130
  212. package/examples/composite_example.ts +0 -65
  213. package/examples/constants.ts +0 -42
  214. package/examples/faucet_endpoint.ts +0 -24
  215. package/examples/gov_add_new_market.json +0 -64
  216. package/examples/gov_add_new_market.ts +0 -95
  217. package/examples/human_readable_orders.json +0 -86
  218. package/examples/human_readable_short_term_orders.json +0 -42
  219. package/examples/json-encoding.ts +0 -33
  220. package/examples/long_term_order_cancel_example.ts +0 -87
  221. package/examples/markets_endpoints.ts +0 -134
  222. package/examples/native_examples.ts +0 -151
  223. package/examples/noble_example.ts +0 -107
  224. package/examples/optimal_node.ts +0 -70
  225. package/examples/permissioned_keys_example.ts +0 -162
  226. package/examples/raw_orders.json +0 -130
  227. package/examples/short_term_order_cancel_example.ts +0 -68
  228. package/examples/short_term_order_composite_example.ts +0 -80
  229. package/examples/test.ts +0 -65
  230. package/examples/transfer_example_deposit.ts +0 -28
  231. package/examples/transfer_example_send.ts +0 -60
  232. package/examples/transfer_example_subaccount_transfer.ts +0 -29
  233. package/examples/transfer_example_withdraw.ts +0 -31
  234. package/examples/transfer_example_withdraw_other.ts +0 -60
  235. package/examples/utility_endpoints.ts +0 -42
  236. package/examples/validator_get_example.ts +0 -160
  237. package/examples/validator_post_example.ts +0 -81
  238. package/examples/wallet_address.ts +0 -18
  239. package/examples/websocket_example.ts +0 -44
  240. package/examples/websocket_orderbook_example.ts +0 -239
  241. package/jest.config.js +0 -12
  242. package/jest.globalSetup.js +0 -5
  243. package/jest.setup.js +0 -1
  244. package/ritbit-v4-client-js-2.4.0.tgz +0 -0
  245. package/scripts/bump_version.sh +0 -16
  246. package/scripts/generate-cctp-protos.sh +0 -41
  247. package/scripts/mobile_build_pack.sh +0 -5
  248. package/scripts/publish-if-not-exists.sh +0 -21
  249. package/src/clients/composite-client.ts +0 -1469
  250. package/src/clients/constants.ts +0 -361
  251. package/src/clients/faucet-client.ts +0 -48
  252. package/src/clients/helpers/chain-helpers.ts +0 -231
  253. package/src/clients/helpers/request-helpers.ts +0 -71
  254. package/src/clients/indexer-client.ts +0 -61
  255. package/src/clients/lib/axios/axiosRequest.ts +0 -41
  256. package/src/clients/lib/axios/errors.ts +0 -41
  257. package/src/clients/lib/axios/index.ts +0 -7
  258. package/src/clients/lib/axios/types.ts +0 -6
  259. package/src/clients/lib/cctpProto.ts +0 -4197
  260. package/src/clients/lib/errors.ts +0 -63
  261. package/src/clients/lib/registry.ts +0 -93
  262. package/src/clients/modules/account.ts +0 -438
  263. package/src/clients/modules/composer.ts +0 -669
  264. package/src/clients/modules/get.ts +0 -791
  265. package/src/clients/modules/local-wallet.ts +0 -79
  266. package/src/clients/modules/markets.ts +0 -76
  267. package/src/clients/modules/post.ts +0 -1043
  268. package/src/clients/modules/proto-includes.ts +0 -34
  269. package/src/clients/modules/rest.ts +0 -40
  270. package/src/clients/modules/signer.ts +0 -139
  271. package/src/clients/modules/tendermintClient.ts +0 -168
  272. package/src/clients/modules/utility.ts +0 -47
  273. package/src/clients/modules/vault.ts +0 -23
  274. package/src/clients/native.ts +0 -1689
  275. package/src/clients/noble-client.ts +0 -108
  276. package/src/clients/socket-client.ts +0 -331
  277. package/src/clients/subaccount.ts +0 -57
  278. package/src/clients/types.ts +0 -191
  279. package/src/clients/validator-client.ts +0 -106
  280. package/src/index.ts +0 -19
  281. package/src/lib/constants.ts +0 -28
  282. package/src/lib/errors.ts +0 -38
  283. package/src/lib/helpers.ts +0 -99
  284. package/src/lib/onboarding.ts +0 -96
  285. package/src/lib/trading-key-utils.ts +0 -136
  286. package/src/lib/utils.ts +0 -84
  287. package/src/lib/validation.ts +0 -197
  288. package/src/network_optimizer.ts +0 -132
  289. package/src/types.ts +0 -44
  290. package/tasks.json +0 -16
  291. package/tsconfig.base.json +0 -21
  292. package/tsconfig.cjs.json +0 -10
  293. package/tsconfig.eslint.json +0 -14
  294. package/tsconfig.esm.json +0 -11
  295. package/tsconfig.json +0 -6
  296. package/webpack.config.js +0 -56
@@ -1,1469 +0,0 @@
1
- import { Coin } from '@cosmjs/amino';
2
- import { EncodeObject } from '@cosmjs/proto-signing';
3
- import { Account, GasPrice, IndexedTx, StdFee } from '@cosmjs/stargate';
4
- import { Method, tendermint37 } from '@cosmjs/tendermint-rpc';
5
- import { GetAuthenticatorsResponse } from '@ritbit/v4-proto/src/codegen/ritbit/accountplus/query';
6
- import {
7
- Order_ConditionType,
8
- Order_TimeInForce,
9
- } from '@ritbit/v4-proto/src/codegen/ritbit/clob/order';
10
- import { parseUnits } from 'ethers';
11
- import Long from 'long';
12
- import protobuf from 'protobufjs';
13
-
14
- type BroadcastTxAsyncResponse = tendermint37.BroadcastTxAsyncResponse;
15
- type BroadcastTxSyncResponse = tendermint37.BroadcastTxSyncResponse;
16
-
17
- import { bigIntToBytes } from '../lib/helpers';
18
- import { isStatefulOrder, verifyOrderFlags } from '../lib/validation';
19
- import { GovAddNewMarketParams, OrderFlags } from '../types';
20
- import {
21
- Authenticator,
22
- AuthenticatorType,
23
- Network,
24
- OrderExecution,
25
- OrderSide,
26
- OrderTimeInForce,
27
- OrderType,
28
- SHORT_BLOCK_FORWARD,
29
- SHORT_BLOCK_WINDOW,
30
- SelectedGasDenom,
31
- } from './constants';
32
- import {
33
- calculateQuantums,
34
- calculateSubticks,
35
- calculateSide,
36
- calculateTimeInForce,
37
- calculateOrderFlags,
38
- calculateClientMetadata,
39
- calculateConditionType,
40
- calculateConditionalOrderTriggerSubticks,
41
- calculateVaultQuantums,
42
- } from './helpers/chain-helpers';
43
- import { IndexerClient } from './indexer-client';
44
- import { UserError } from './lib/errors';
45
- import { generateRegistry } from './lib/registry';
46
- import LocalWallet from './modules/local-wallet';
47
- import { SubaccountInfo } from './subaccount';
48
- import { BroadcastMode, OrderBatch } from './types';
49
- import { ValidatorClient } from './validator-client';
50
-
51
- // Required for encoding and decoding queries that are of type Long.
52
- // Must be done once but since the individal modules should be usable
53
- // - must be set in each module that encounters encoding/decoding Longs.
54
- // Reference: https://github.com/protobufjs/protobuf.js/issues/921
55
- protobuf.util.Long = Long;
56
- protobuf.configure();
57
-
58
- export interface MarketInfo {
59
- clobPairId: number;
60
- atomicResolution: number;
61
- stepBaseQuantums: number;
62
- quantumConversionExponent: number;
63
- subticksPerTick: number;
64
- }
65
-
66
- export interface OrderBatchWithMarketId {
67
- marketId: string;
68
- clobPairId?: number;
69
- clientIds: number[];
70
- }
71
-
72
- export type PlaceOrderPayload = {
73
- subaccountNumber: number;
74
- marketId: string;
75
- type: OrderType;
76
- side: OrderSide;
77
- price: number;
78
- size: number;
79
- clientId: number;
80
- timeInForce?: OrderTimeInForce;
81
- goodTilTimeInSeconds?: number;
82
- execution?: OrderExecution;
83
- postOnly?: boolean;
84
- reduceOnly?: boolean;
85
- triggerPrice?: number;
86
- marketInfo?: MarketInfo;
87
- currentHeight?: number;
88
- goodTilBlock?: number;
89
- };
90
-
91
- export type CancelRawOrderPayload = {
92
- subaccountNumber: number;
93
- clientId: number;
94
- orderFlags: OrderFlags;
95
- clobPairId: number;
96
- goodTilBlock?: number;
97
- goodTilBlockTime?: number;
98
- };
99
-
100
- export type TransferToSubaccountPayload = {
101
- sourceSubaccountNumber: number;
102
- recipientSubaccountNumber: number;
103
- transferAmount: string;
104
- };
105
-
106
- export class CompositeClient {
107
- public readonly network: Network;
108
- public gasDenom: SelectedGasDenom = SelectedGasDenom.USDC;
109
- private _indexerClient: IndexerClient;
110
- private _validatorClient?: ValidatorClient;
111
-
112
- static async connect(network: Network): Promise<CompositeClient> {
113
- const client = new CompositeClient(network);
114
- await client.initialize();
115
- return client;
116
- }
117
-
118
- private constructor(network: Network, apiTimeout?: number) {
119
- this.network = network;
120
- this._indexerClient = new IndexerClient(network.indexerConfig, apiTimeout);
121
- }
122
-
123
- private async initialize(): Promise<void> {
124
- this._validatorClient = await ValidatorClient.connect(this.network.validatorConfig);
125
- }
126
-
127
- get indexerClient(): IndexerClient {
128
- /**
129
- * Get the validator client
130
- */
131
- return this._indexerClient!;
132
- }
133
-
134
- get validatorClient(): ValidatorClient {
135
- /**
136
- * Get the validator client
137
- */
138
- return this._validatorClient!;
139
- }
140
-
141
- get selectedGasDenom(): SelectedGasDenom | undefined {
142
- if (!this._validatorClient) return undefined;
143
- return this._validatorClient.selectedGasDenom;
144
- }
145
-
146
- setSelectedGasDenom(gasDenom: SelectedGasDenom): void {
147
- if (!this._validatorClient) throw new Error('Validator client not initialized');
148
- this._validatorClient.setSelectedGasDenom(gasDenom);
149
- }
150
-
151
- async populateAccountNumberCache(
152
- address: string
153
- ): Promise<{ typeUrl: string } | undefined> {
154
- if (!this._validatorClient) throw new Error('Validator client not initialized');
155
- return this._validatorClient.populateAccountNumberCache(address);
156
- }
157
-
158
- /**
159
- * @description Sign a list of messages with a wallet.
160
- * the calling function is responsible for creating the messages.
161
- *
162
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
163
- * at any point.
164
- * @returns The Signature.
165
- */
166
- async sign(
167
- subaccount: SubaccountInfo,
168
- messaging: () => Promise<EncodeObject[]>,
169
- zeroFee: boolean,
170
- gasPrice?: GasPrice,
171
- memo?: string,
172
- account?: () => Promise<Account>,
173
- ): Promise<Uint8Array> {
174
- return this.validatorClient.post.sign(subaccount, messaging, zeroFee, gasPrice, memo, account);
175
- }
176
-
177
- /**
178
- * @description Send a list of messages with a wallet.
179
- * the calling function is responsible for creating the messages.
180
- *
181
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
182
- * at any point.
183
- * @returns The Transaction Hash.
184
- */
185
- async send(
186
- subaccount: SubaccountInfo,
187
- messaging: () => Promise<EncodeObject[]>,
188
- zeroFee: boolean,
189
- gasPrice?: GasPrice,
190
- memo?: string,
191
- broadcastMode?: BroadcastMode,
192
- account?: () => Promise<Account>,
193
- gasAdjustment?: number,
194
- additionalFeeCoins?: Coin[],
195
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
196
- return this.validatorClient.post.send(
197
- subaccount,
198
- messaging,
199
- zeroFee,
200
- gasPrice,
201
- memo,
202
- broadcastMode,
203
- account,
204
- gasAdjustment,
205
- additionalFeeCoins,
206
- );
207
- }
208
-
209
- /**
210
- * @description Send a signed transaction.
211
- *
212
- * @param signedTransaction The signed transaction to send.
213
- *
214
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
215
- * at any point.
216
- * @returns The Transaction Hash.
217
- */
218
- async sendSignedTransaction(
219
- signedTransaction: Uint8Array,
220
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
221
- return this.validatorClient.post.sendSignedTransaction(signedTransaction);
222
- }
223
-
224
- /**
225
- * @description Simulate a list of messages with a wallet.
226
- * the calling function is responsible for creating the messages.
227
- *
228
- * To send multiple messages with gas estimate:
229
- * 1. Client is responsible for creating the messages.
230
- * 2. Call simulate() to get the gas estimate.
231
- * 3. Call send() to send the messages.
232
- *
233
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
234
- * at any point.
235
- * @returns The gas estimate.
236
- */
237
- async simulate(
238
- subaccount: SubaccountInfo,
239
- messaging: () => Promise<EncodeObject[]>,
240
- gasPrice?: GasPrice,
241
- memo?: string,
242
- account?: () => Promise<Account>,
243
- ): Promise<StdFee> {
244
- return this.validatorClient.post.simulate(subaccount, messaging, gasPrice, memo, account);
245
- }
246
-
247
- /**
248
- * @description Calculate the goodTilBlock value for a SHORT_TERM order
249
- *
250
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
251
- * at any point.
252
- * @returns The goodTilBlock value
253
- */
254
-
255
- private async calculateGoodTilBlock(
256
- orderFlags: OrderFlags,
257
- currentHeight?: number,
258
- goodTilBlock?: number,
259
- ): Promise<number> {
260
- if (orderFlags === OrderFlags.SHORT_TERM) {
261
- if (goodTilBlock !== undefined && goodTilBlock !== 0 && goodTilBlock !== null) {
262
- return Promise.resolve(goodTilBlock);
263
- } else {
264
- const height = currentHeight ?? (await this.validatorClient.get.latestBlockHeight());
265
- return height + SHORT_BLOCK_FORWARD;
266
- }
267
- } else {
268
- return Promise.resolve(0);
269
- }
270
- }
271
-
272
- /**
273
- * @description Validate the goodTilBlock value for a SHORT_TERM order
274
- *
275
- * @param goodTilBlock Number of blocks from the current block height the order will
276
- * be valid for.
277
- *
278
- * @throws UserError if the goodTilBlock value is not valid given latest block height and
279
- * SHORT_BLOCK_WINDOW.
280
- */
281
- private async validateGoodTilBlock(goodTilBlock: number): Promise<void> {
282
- const height = await this.validatorClient.get.latestBlockHeight();
283
- const nextValidBlockHeight = height + 1;
284
- const lowerBound = nextValidBlockHeight;
285
- const upperBound = nextValidBlockHeight + SHORT_BLOCK_WINDOW;
286
- if (goodTilBlock < lowerBound || goodTilBlock > upperBound) {
287
- throw new UserError(`Invalid Short-Term order GoodTilBlock.
288
- Should be greater-than-or-equal-to ${lowerBound} and less-than-or-equal-to ${upperBound}.
289
- Provided good til block: ${goodTilBlock}`);
290
- }
291
- }
292
-
293
- /**
294
- * @description Calculate the goodTilBlockTime value for a LONG_TERM order
295
- * the calling function is responsible for creating the messages.
296
- *
297
- * @param goodTilTimeInSeconds The goodTilTimeInSeconds of the order to place.
298
- *
299
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
300
- * at any point.
301
- * @returns The goodTilBlockTime value
302
- */
303
- private calculateGoodTilBlockTime(goodTilTimeInSeconds: number): number {
304
- const now = new Date();
305
- const millisecondsPerSecond = 1000;
306
- const interval = goodTilTimeInSeconds * millisecondsPerSecond;
307
- const future = new Date(now.valueOf() + interval);
308
- return Math.round(future.getTime() / 1000);
309
- }
310
-
311
- /**
312
- * @description Place a short term order with human readable input.
313
- *
314
- * Use human readable form of input, including price and size
315
- * The quantum and subticks are calculated and submitted
316
- *
317
- * @param subaccount The subaccount to place the order under
318
- * @param marketId The market to place the order on
319
- * @param side The side of the order to place
320
- * @param price The price of the order to place
321
- * @param size The size of the order to place
322
- * @param clientId The client id of the order to place
323
- * @param timeInForce The time in force of the order to place
324
- * @param goodTilBlock The goodTilBlock of the order to place
325
- * @param reduceOnly The reduceOnly of the order to place
326
- *
327
- *
328
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
329
- * at any point.
330
- * @returns The transaction hash.
331
- */
332
- async placeShortTermOrder(
333
- subaccount: SubaccountInfo,
334
- marketId: string,
335
- side: OrderSide,
336
- price: number,
337
- size: number,
338
- clientId: number,
339
- goodTilBlock: number,
340
- timeInForce: Order_TimeInForce,
341
- reduceOnly: boolean,
342
- memo?: string,
343
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
344
- const msgs: Promise<EncodeObject[]> = new Promise((resolve, reject) => {
345
- const msg = this.placeShortTermOrderMessage(
346
- subaccount,
347
- marketId,
348
- side,
349
- price,
350
- size,
351
- clientId,
352
- goodTilBlock,
353
- timeInForce,
354
- reduceOnly,
355
- );
356
- msg
357
- .then((it) => {
358
- resolve([it]);
359
- })
360
- .catch((err) => {
361
- console.log(err);
362
- reject(err);
363
- });
364
- });
365
- const account: Promise<Account> = this.validatorClient.post.account(
366
- subaccount.address,
367
- undefined,
368
- );
369
- return this.send(
370
- subaccount,
371
- () => msgs,
372
- true,
373
- undefined,
374
- memo,
375
- undefined,
376
- () => account,
377
- );
378
- }
379
-
380
- /**
381
- * @description Place an order with human readable input.
382
- *
383
- * Only MARKET and LIMIT types are supported right now
384
- * Use human readable form of input, including price and size
385
- * The quantum and subticks are calculated and submitted
386
- *
387
- * @param subaccount The subaccount to place the order on.
388
- * @param marketId The market to place the order on.
389
- * @param type The type of order to place.
390
- * @param side The side of the order to place.
391
- * @param price The price of the order to place.
392
- * @param size The size of the order to place.
393
- * @param clientId The client id of the order to place.
394
- * @param timeInForce The time in force of the order to place.
395
- * @param goodTilTimeInSeconds The goodTilTimeInSeconds of the order to place.
396
- * @param execution The execution of the order to place.
397
- * @param postOnly The postOnly of the order to place.
398
- * @param reduceOnly The reduceOnly of the order to place.
399
- * @param triggerPrice The trigger price of conditional orders.
400
- * @param marketInfo optional market information for calculating quantums and subticks.
401
- * This can be constructed from Indexer API. If set to null, additional round
402
- * trip to Indexer API will be made.
403
- * @param currentHeight Current block height. This can be obtained from ValidatorClient.
404
- * If set to null, additional round trip to ValidatorClient will be made.
405
- *
406
- *
407
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
408
- * at any point.
409
- * @returns The transaction hash.
410
- */
411
- async placeOrder(
412
- subaccount: SubaccountInfo,
413
- marketId: string,
414
- type: OrderType,
415
- side: OrderSide,
416
- price: number,
417
- size: number,
418
- clientId: number,
419
- timeInForce?: OrderTimeInForce,
420
- goodTilTimeInSeconds?: number,
421
- execution?: OrderExecution,
422
- postOnly?: boolean,
423
- reduceOnly?: boolean,
424
- triggerPrice?: number,
425
- marketInfo?: MarketInfo,
426
- currentHeight?: number,
427
- goodTilBlock?: number,
428
- memo?: string,
429
- broadcastMode?: BroadcastMode,
430
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
431
- const msgs: Promise<EncodeObject[]> = new Promise((resolve) => {
432
- const msg = this.placeOrderMessage(
433
- subaccount,
434
- marketId,
435
- type,
436
- side,
437
- price,
438
- size,
439
- clientId,
440
- timeInForce,
441
- goodTilTimeInSeconds,
442
- execution,
443
- postOnly,
444
- reduceOnly,
445
- triggerPrice,
446
- marketInfo,
447
- currentHeight,
448
- goodTilBlock,
449
- );
450
- msg
451
- .then((it) => resolve([it]))
452
- .catch((err) => {
453
- throw err;
454
- });
455
- });
456
- const orderFlags = calculateOrderFlags(type, timeInForce);
457
- const account: Promise<Account> = this.validatorClient.post.account(
458
- subaccount.address,
459
- orderFlags,
460
- );
461
- return this.send(
462
- subaccount,
463
- () => msgs,
464
- true,
465
- undefined,
466
- memo,
467
- broadcastMode,
468
- () => account,
469
- );
470
- }
471
-
472
- /**
473
- * @description Calculate and create the place order message
474
- *
475
- * Only MARKET and LIMIT types are supported right now
476
- * Use human readable form of input, including price and size
477
- * The quantum and subticks are calculated and submitted
478
- *
479
- * @param subaccount The subaccount to place the order under
480
- * @param marketId The market to place the order on
481
- * @param type The type of order to place
482
- * @param side The side of the order to place
483
- * @param price The price of the order to place
484
- * @param size The size of the order to place
485
- * @param clientId The client id of the order to place
486
- * @param timeInForce The time in force of the order to place
487
- * @param goodTilTimeInSeconds The goodTilTimeInSeconds of the order to place
488
- * @param execution The execution of the order to place
489
- * @param postOnly The postOnly of the order to place
490
- * @param reduceOnly The reduceOnly of the order to place
491
- *
492
- *
493
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
494
- * at any point.
495
- * @returns The message to be passed into the protocol
496
- */
497
- private async placeOrderMessage(
498
- subaccount: SubaccountInfo,
499
- marketId: string,
500
- type: OrderType,
501
- side: OrderSide,
502
- price: number,
503
- size: number,
504
- clientId: number,
505
- timeInForce?: OrderTimeInForce,
506
- goodTilTimeInSeconds?: number,
507
- execution?: OrderExecution,
508
- postOnly?: boolean,
509
- reduceOnly?: boolean,
510
- triggerPrice?: number,
511
- marketInfo?: MarketInfo,
512
- currentHeight?: number,
513
- goodTilBlock?: number,
514
- ): Promise<EncodeObject> {
515
- const orderFlags = calculateOrderFlags(type, timeInForce);
516
-
517
- const result = await Promise.all([
518
- this.calculateGoodTilBlock(orderFlags, currentHeight, goodTilBlock),
519
- this.retrieveMarketInfo(marketId, marketInfo),
520
- ]);
521
- const desiredGoodTilBlock = result[0];
522
- const clobPairId = result[1].clobPairId;
523
- const atomicResolution = result[1].atomicResolution;
524
- const stepBaseQuantums = result[1].stepBaseQuantums;
525
- const quantumConversionExponent = result[1].quantumConversionExponent;
526
- const subticksPerTick = result[1].subticksPerTick;
527
- const orderSide = calculateSide(side);
528
- const quantums = calculateQuantums(size, atomicResolution, stepBaseQuantums);
529
- const subticks = calculateSubticks(
530
- price,
531
- atomicResolution,
532
- quantumConversionExponent,
533
- subticksPerTick,
534
- );
535
- const orderTimeInForce = calculateTimeInForce(type, timeInForce, execution, postOnly);
536
- let goodTilBlockTime = 0;
537
- if (orderFlags === OrderFlags.LONG_TERM || orderFlags === OrderFlags.CONDITIONAL) {
538
- if (goodTilTimeInSeconds == null) {
539
- throw new Error('goodTilTimeInSeconds must be set for LONG_TERM or CONDITIONAL order');
540
- } else {
541
- goodTilBlockTime = this.calculateGoodTilBlockTime(goodTilTimeInSeconds);
542
- }
543
- }
544
- const clientMetadata = calculateClientMetadata(type);
545
- const conditionalType = calculateConditionType(type);
546
- const conditionalOrderTriggerSubticks = calculateConditionalOrderTriggerSubticks(
547
- type,
548
- atomicResolution,
549
- quantumConversionExponent,
550
- subticksPerTick,
551
- triggerPrice,
552
- );
553
- return this.validatorClient.post.composer.composeMsgPlaceOrder(
554
- subaccount.address,
555
- subaccount.subaccountNumber,
556
- clientId,
557
- clobPairId,
558
- orderFlags,
559
- desiredGoodTilBlock,
560
- goodTilBlockTime,
561
- orderSide,
562
- quantums,
563
- subticks,
564
- orderTimeInForce,
565
- reduceOnly ?? false,
566
- clientMetadata,
567
- conditionalType,
568
- conditionalOrderTriggerSubticks,
569
- );
570
- }
571
-
572
- private async retrieveMarketInfo(marketId: string, marketInfo?: MarketInfo): Promise<MarketInfo> {
573
- if (marketInfo) {
574
- return Promise.resolve(marketInfo);
575
- } else {
576
- const marketsResponse = await this.indexerClient.markets.getPerpetualMarkets(marketId);
577
- const market = marketsResponse.markets[marketId];
578
- const clobPairId = market.clobPairId;
579
- const atomicResolution = market.atomicResolution;
580
- const stepBaseQuantums = market.stepBaseQuantums;
581
- const quantumConversionExponent = market.quantumConversionExponent;
582
- const subticksPerTick = market.subticksPerTick;
583
- return {
584
- clobPairId,
585
- atomicResolution,
586
- stepBaseQuantums,
587
- quantumConversionExponent,
588
- subticksPerTick,
589
- };
590
- }
591
- }
592
-
593
- /**
594
- * @description Calculate and create the short term place order message
595
- *
596
- * Use human readable form of input, including price and size
597
- * The quantum and subticks are calculated and submitted
598
- *
599
- * @param subaccount The subaccount to place the order under
600
- * @param marketId The market to place the order on
601
- * @param side The side of the order to place
602
- * @param price The price of the order to place
603
- * @param size The size of the order to place
604
- * @param clientId The client id of the order to place
605
- * @param timeInForce The time in force of the order to place
606
- * @param goodTilBlock The goodTilBlock of the order to place
607
- * @param reduceOnly The reduceOnly of the order to place
608
- *
609
- *
610
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
611
- * at any point.
612
- * @returns The message to be passed into the protocol
613
- */
614
- private async placeShortTermOrderMessage(
615
- subaccount: SubaccountInfo,
616
- marketId: string,
617
- side: OrderSide,
618
- price: number,
619
- size: number,
620
- clientId: number,
621
- goodTilBlock: number,
622
- timeInForce: Order_TimeInForce,
623
- reduceOnly: boolean,
624
- ): Promise<EncodeObject> {
625
- await this.validateGoodTilBlock(goodTilBlock);
626
-
627
- const marketsResponse = await this.indexerClient.markets.getPerpetualMarkets(marketId);
628
- const market = marketsResponse.markets[marketId];
629
- const clobPairId = market.clobPairId;
630
- const atomicResolution = market.atomicResolution;
631
- const stepBaseQuantums = market.stepBaseQuantums;
632
- const quantumConversionExponent = market.quantumConversionExponent;
633
- const subticksPerTick = market.subticksPerTick;
634
- const orderSide = calculateSide(side);
635
- const quantums = calculateQuantums(size, atomicResolution, stepBaseQuantums);
636
- const subticks = calculateSubticks(
637
- price,
638
- atomicResolution,
639
- quantumConversionExponent,
640
- subticksPerTick,
641
- );
642
- const orderFlags = OrderFlags.SHORT_TERM;
643
- return this.validatorClient.post.composer.composeMsgPlaceOrder(
644
- subaccount.address,
645
- subaccount.subaccountNumber,
646
- clientId,
647
- clobPairId,
648
- orderFlags,
649
- goodTilBlock,
650
- 0, // Short term orders use goodTilBlock.
651
- orderSide,
652
- quantums,
653
- subticks,
654
- timeInForce,
655
- reduceOnly,
656
- 0, // Client metadata is 0 for short term orders.
657
- Order_ConditionType.CONDITION_TYPE_UNSPECIFIED, // Short term orders cannot be conditional.
658
- Long.fromInt(0), // Short term orders cannot be conditional.
659
- );
660
- }
661
-
662
- /**
663
- * @description Cancel an order with order information from web socket or REST.
664
- *
665
- * @param subaccount The subaccount to cancel the order from
666
- * @param clientId The client id of the order to cancel
667
- * @param orderFlags The order flags of the order to cancel
668
- * @param clobPairId The clob pair id of the order to cancel
669
- * @param goodTilBlock The goodTilBlock of the order to cancel
670
- * @param goodTilBlockTime The goodTilBlockTime of the order to cancel
671
- *
672
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
673
- * at any point.
674
- * @returns The transaction hash.
675
- */
676
- async cancelRawOrder(
677
- subaccount: SubaccountInfo,
678
- clientId: number,
679
- orderFlags: OrderFlags,
680
- clobPairId: number,
681
- goodTilBlock?: number,
682
- goodTilBlockTime?: number,
683
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
684
- return this.validatorClient.post.cancelOrder(
685
- subaccount,
686
- clientId,
687
- orderFlags,
688
- clobPairId,
689
- goodTilBlock,
690
- goodTilBlockTime,
691
- );
692
- }
693
-
694
- /**
695
- * @description Cancel an order with human readable input.
696
- *
697
- * @param subaccount The subaccount to cancel the order from
698
- * @param clientId The client id of the order to cancel
699
- * @param orderFlags The order flags of the order to cancel
700
- * @param marketId The market to cancel the order on
701
- * @param goodTilBlock The goodTilBlock of the order to cancel
702
- * @param goodTilBlockTime The goodTilBlockTime of the order to cancel
703
- *
704
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
705
- * at any point.
706
- * @returns The transaction hash.
707
- */
708
- async cancelOrder(
709
- subaccount: SubaccountInfo,
710
- clientId: number,
711
- orderFlags: OrderFlags,
712
- marketId: string,
713
- goodTilBlock?: number,
714
- goodTilTimeInSeconds?: number,
715
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
716
- const marketsResponse = await this.indexerClient.markets.getPerpetualMarkets(marketId);
717
- const market = marketsResponse.markets[marketId];
718
- const clobPairId = market.clobPairId;
719
-
720
- if (!verifyOrderFlags(orderFlags)) {
721
- throw new Error(`Invalid order flags: ${orderFlags}`);
722
- }
723
-
724
- let goodTilBlockTime;
725
- if (isStatefulOrder(orderFlags)) {
726
- if (goodTilTimeInSeconds === undefined || goodTilTimeInSeconds === 0) {
727
- throw new Error('goodTilTimeInSeconds must be set for LONG_TERM or CONDITIONAL order');
728
- }
729
- if (goodTilBlock !== 0) {
730
- throw new Error(
731
- 'goodTilBlock should be zero since LONG_TERM or CONDITIONAL orders ' +
732
- 'use goodTilTimeInSeconds instead of goodTilBlock.',
733
- );
734
- }
735
- goodTilBlockTime = this.calculateGoodTilBlockTime(goodTilTimeInSeconds);
736
- } else {
737
- if (goodTilBlock === undefined || goodTilBlock === 0) {
738
- throw new Error('goodTilBlock must be non-zero for SHORT_TERM orders');
739
- }
740
- if (goodTilTimeInSeconds !== undefined && goodTilTimeInSeconds !== 0) {
741
- throw new Error(
742
- 'goodTilTimeInSeconds should be zero since SHORT_TERM orders use goodTilBlock instead of goodTilTimeInSeconds.',
743
- );
744
- }
745
- }
746
-
747
- return this.validatorClient.post.cancelOrder(
748
- subaccount,
749
- clientId,
750
- orderFlags,
751
- clobPairId,
752
- goodTilBlock,
753
- goodTilBlockTime,
754
- );
755
- }
756
-
757
- /**
758
- * @description Batch cancel short term orders using marketId to clobPairId translation.
759
- *
760
- * @param subaccount The subaccount to cancel the order from
761
- * @param shortTermOrders The list of short term order batches to cancel with marketId
762
- * @param goodTilBlock The goodTilBlock of the order to cancel
763
- * @returns The transaction hash.
764
- */
765
- async batchCancelShortTermOrdersWithMarketId(
766
- subaccount: SubaccountInfo,
767
- shortTermOrders: OrderBatchWithMarketId[],
768
- goodTilBlock: number,
769
- broadcastMode?: BroadcastMode,
770
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
771
- const orderBatches = await Promise.all(
772
- shortTermOrders.map(async ({ marketId, clobPairId, clientIds }) => ({
773
- clobPairId: (
774
- clobPairId ??
775
- (await this.indexerClient.markets.getPerpetualMarkets(marketId)).markets[marketId]
776
- ).clobPairId,
777
- clientIds,
778
- })),
779
- );
780
-
781
- return this.validatorClient.post.batchCancelShortTermOrders(
782
- subaccount,
783
- orderBatches,
784
- goodTilBlock,
785
- broadcastMode,
786
- );
787
- }
788
-
789
- /**
790
- * @description Batch cancel short term orders using clobPairId.
791
- *
792
- * @param subaccount The subaccount to cancel the order from
793
- * @param shortTermOrders The list of short term order batches to cancel with clobPairId
794
- * @param goodTilBlock The goodTilBlock of the order to cancel
795
- * @returns The transaction hash.
796
- */
797
- async batchCancelShortTermOrdersWithClobPairId(
798
- subaccount: SubaccountInfo,
799
- shortTermOrders: OrderBatch[],
800
- goodTilBlock: number,
801
- broadcastMode?: BroadcastMode,
802
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
803
- return this.validatorClient.post.batchCancelShortTermOrders(
804
- subaccount,
805
- shortTermOrders,
806
- goodTilBlock,
807
- broadcastMode,
808
- );
809
- }
810
-
811
- /**
812
- * @description Transfer from a subaccount to another subaccount
813
- *
814
- * @param subaccount The subaccount to transfer from
815
- * @param recipientAddress The recipient address
816
- * @param recipientSubaccountNumber The recipient subaccount number
817
- * @param amount The amount to transfer
818
- *
819
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
820
- * at any point.
821
- * @returns The transaction hash.
822
- */
823
- async transferToSubaccount(
824
- subaccount: SubaccountInfo,
825
- recipientAddress: string,
826
- recipientSubaccountNumber: number,
827
- amount: string,
828
- memo?: string,
829
- broadcastMode?: BroadcastMode,
830
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
831
- const msgs: Promise<EncodeObject[]> = new Promise((resolve) => {
832
- const msg = this.transferToSubaccountMessage(
833
- subaccount,
834
- recipientAddress,
835
- recipientSubaccountNumber,
836
- amount,
837
- );
838
- resolve([msg]);
839
- });
840
- return this.send(
841
- subaccount,
842
- () => msgs,
843
- false,
844
- undefined,
845
- memo,
846
- broadcastMode ?? Method.BroadcastTxCommit,
847
- );
848
- }
849
-
850
- /**
851
- * @description Create message to transfer from a subaccount to another subaccount
852
- *
853
- * @param subaccount The subaccount to transfer from
854
- * @param recipientAddress The recipient address
855
- * @param recipientSubaccountNumber The recipient subaccount number
856
- * @param amount The amount to transfer
857
- *
858
- *
859
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
860
- * at any point.
861
- * @returns The message
862
- */
863
- transferToSubaccountMessage(
864
- subaccount: SubaccountInfo,
865
- recipientAddress: string,
866
- recipientSubaccountNumber: number,
867
- amount: string,
868
- ): EncodeObject {
869
- const validatorClient = this._validatorClient;
870
- if (validatorClient === undefined) {
871
- throw new Error('validatorClient not set');
872
- }
873
- const quantums = parseUnits(amount, validatorClient.config.denoms.USDC_DECIMALS);
874
- if (quantums > BigInt(Long.MAX_VALUE.toString())) {
875
- throw new Error('amount to large');
876
- }
877
- if (quantums < 0) {
878
- throw new Error('amount must be positive');
879
- }
880
-
881
- return this.validatorClient.post.composer.composeMsgTransfer(
882
- subaccount.address,
883
- subaccount.subaccountNumber,
884
- recipientAddress,
885
- recipientSubaccountNumber,
886
- 0,
887
- Long.fromString(quantums.toString()),
888
- );
889
- }
890
-
891
- /**
892
- * @description Deposit from wallet to subaccount
893
- *
894
- * @param subaccount The subaccount to deposit to
895
- * @param amount The amount to deposit
896
- *
897
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
898
- * at any point.
899
- * @returns The transaction hash.
900
- */
901
- async depositToSubaccount(
902
- subaccount: SubaccountInfo,
903
- amount: string,
904
- memo?: string,
905
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
906
- const msgs: Promise<EncodeObject[]> = new Promise((resolve) => {
907
- const msg = this.depositToSubaccountMessage(subaccount, amount);
908
- resolve([msg]);
909
- });
910
- return this.validatorClient.post.send(subaccount, () => msgs, false, undefined, memo);
911
- }
912
-
913
- /**
914
- * @description Create message to deposit from wallet to subaccount
915
- *
916
- * @param subaccount The subaccount to deposit to
917
- * @param amount The amount to deposit
918
- *
919
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
920
- * at any point.
921
- * @returns The message
922
- */
923
- depositToSubaccountMessage(subaccount: SubaccountInfo, amount: string): EncodeObject {
924
- const validatorClient = this._validatorClient;
925
- if (validatorClient === undefined) {
926
- throw new Error('validatorClient not set');
927
- }
928
- const quantums = parseUnits(amount, validatorClient.config.denoms.USDC_DECIMALS);
929
- if (quantums > BigInt(Long.MAX_VALUE.toString())) {
930
- throw new Error('amount to large');
931
- }
932
- if (quantums < 0) {
933
- throw new Error('amount must be positive');
934
- }
935
-
936
- return this.validatorClient.post.composer.composeMsgDepositToSubaccount(
937
- subaccount.address,
938
- subaccount.subaccountNumber,
939
- 0,
940
- Long.fromString(quantums.toString()),
941
- );
942
- }
943
-
944
- /**
945
- * @description Withdraw from subaccount to wallet
946
- *
947
- * @param subaccount The subaccount to withdraw from
948
- * @param amount The amount to withdraw
949
- * @param recipient The recipient address, default to subaccount address
950
- *
951
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
952
- * at any point.
953
- * @returns The transaction hash
954
- */
955
- async withdrawFromSubaccount(
956
- subaccount: SubaccountInfo,
957
- amount: string,
958
- recipient?: string,
959
- memo?: string,
960
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
961
- const msgs: Promise<EncodeObject[]> = new Promise((resolve) => {
962
- const msg = this.withdrawFromSubaccountMessage(subaccount, amount, recipient);
963
- resolve([msg]);
964
- });
965
- return this.send(subaccount, () => msgs, false, undefined, memo);
966
- }
967
-
968
- /**
969
- * @description Create message to withdraw from subaccount to wallet
970
- * with human readable input.
971
- *
972
- * @param subaccount The subaccount to withdraw from
973
- * @param amount The amount to withdraw
974
- * @param recipient The recipient address
975
- *
976
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
977
- * at any point.
978
- * @returns The message
979
- */
980
- withdrawFromSubaccountMessage(
981
- subaccount: SubaccountInfo,
982
- amount: string,
983
- recipient?: string,
984
- ): EncodeObject {
985
- const validatorClient = this._validatorClient;
986
- if (validatorClient === undefined) {
987
- throw new Error('validatorClient not set');
988
- }
989
- const quantums = parseUnits(amount, validatorClient.config.denoms.USDC_DECIMALS);
990
- if (quantums > BigInt(Long.MAX_VALUE.toString())) {
991
- throw new Error('amount to large');
992
- }
993
- if (quantums < 0) {
994
- throw new Error('amount must be positive');
995
- }
996
-
997
- return this.validatorClient.post.composer.composeMsgWithdrawFromSubaccount(
998
- subaccount.address,
999
- subaccount.subaccountNumber,
1000
- 0,
1001
- Long.fromString(quantums.toString()),
1002
- recipient,
1003
- );
1004
- }
1005
-
1006
- /**
1007
- * @description Create message to withdraw from account to EVM chain (bridge withdrawal).
1008
- *
1009
- * @param sender Cosmos address of the sender
1010
- * @param amount Amount in min units (string)
1011
- * @param ethRecipient Recipient address on EVM chain
1012
- * @param ethChainId Target EVM chain ID
1013
- * @param assetId Asset ID in Cosmos
1014
- *
1015
- * @returns The message
1016
- */
1017
- withdrawalMessage(
1018
- sender: string,
1019
- amount: string,
1020
- ethRecipient: string,
1021
- ethChainId: number,
1022
- assetId: number,
1023
- ): EncodeObject {
1024
- const validatorClient = this._validatorClient;
1025
- if (validatorClient === undefined) {
1026
- throw new Error('validatorClient not set');
1027
- }
1028
-
1029
- return this.validatorClient.post.composer.composeMsgWithdrawal(
1030
- sender,
1031
- amount,
1032
- ethRecipient,
1033
- ethChainId,
1034
- assetId,
1035
- );
1036
- }
1037
-
1038
- /**
1039
- * @description Create message to send chain token from subaccount to wallet
1040
- * with human readable input.
1041
- *
1042
- * @param subaccount The subaccount to withdraw from
1043
- * @param amount The amount to withdraw
1044
- * @param recipient The recipient address
1045
- *
1046
- * @throws UnexpectedClientError if a malformed response is returned with no GRPC error
1047
- * at any point.
1048
- * @returns The message
1049
- */
1050
- sendTokenMessage(wallet: LocalWallet, amount: string, recipient: string): EncodeObject {
1051
- const address = wallet.address;
1052
- if (address === undefined) {
1053
- throw new UserError('wallet address is not set. Call connectWallet() first');
1054
- }
1055
- const { CHAINTOKEN_DENOM: chainTokenDenom, CHAINTOKEN_DECIMALS: chainTokenDecimals } =
1056
- this._validatorClient?.config.denoms || {};
1057
-
1058
- if (chainTokenDenom === undefined || chainTokenDecimals === undefined) {
1059
- throw new Error('Chain token denom not set in validator config');
1060
- }
1061
-
1062
- const quantums = parseUnits(amount, chainTokenDecimals);
1063
-
1064
- return this.validatorClient.post.composer.composeMsgSendToken(
1065
- address,
1066
- recipient,
1067
- chainTokenDenom,
1068
- quantums.toString(),
1069
- );
1070
- }
1071
-
1072
- async signPlaceOrder(
1073
- subaccount: SubaccountInfo,
1074
- marketId: string,
1075
- type: OrderType,
1076
- side: OrderSide,
1077
- price: number,
1078
- // trigger_price: number, // not used for MARKET and LIMIT
1079
- size: number,
1080
- clientId: number,
1081
- timeInForce: OrderTimeInForce,
1082
- goodTilTimeInSeconds: number,
1083
- execution: OrderExecution,
1084
- postOnly: boolean,
1085
- reduceOnly: boolean,
1086
- ): Promise<string> {
1087
- const msgs: Promise<EncodeObject[]> = new Promise((resolve) => {
1088
- const msg = this.placeOrderMessage(
1089
- subaccount,
1090
- marketId,
1091
- type,
1092
- side,
1093
- price,
1094
- // trigger_price: number, // not used for MARKET and LIMIT
1095
- size,
1096
- clientId,
1097
- timeInForce,
1098
- goodTilTimeInSeconds,
1099
- execution,
1100
- postOnly,
1101
- reduceOnly,
1102
- );
1103
- msg
1104
- .then((it) => resolve([it]))
1105
- .catch((err) => {
1106
- console.log(err);
1107
- });
1108
- });
1109
- const signature = await this.sign(subaccount, () => msgs, true);
1110
-
1111
- return Buffer.from(signature).toString('base64');
1112
- }
1113
-
1114
- async signCancelOrder(
1115
- subaccount: SubaccountInfo,
1116
- clientId: number,
1117
- orderFlags: OrderFlags,
1118
- clobPairId: number,
1119
- goodTilBlock: number,
1120
- goodTilBlockTime: number,
1121
- ): Promise<string> {
1122
- const msgs: Promise<EncodeObject[]> = new Promise((resolve) => {
1123
- const msg = this.validatorClient.post.composer.composeMsgCancelOrder(
1124
- subaccount.address,
1125
- subaccount.subaccountNumber,
1126
- clientId,
1127
- clobPairId,
1128
- orderFlags,
1129
- goodTilBlock,
1130
- goodTilBlockTime,
1131
- );
1132
- resolve([msg]);
1133
- });
1134
- const signature = await this.sign(subaccount, () => msgs, true);
1135
-
1136
- return Buffer.from(signature).toString('base64');
1137
- }
1138
-
1139
- async bulkCancelAndTransferAndPlaceStatefulOrders(
1140
- subaccount: SubaccountInfo,
1141
- // these are executed in this order, all in one block, and all succeed or all fail
1142
- cancelOrderPayloads: CancelRawOrderPayload[],
1143
- transferToSubaccountPayload: TransferToSubaccountPayload | undefined,
1144
- placeOrderPayloads: PlaceOrderPayload[],
1145
- memo?: string,
1146
- broadcastMode?: BroadcastMode,
1147
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1148
- if (cancelOrderPayloads.some((c) => c.orderFlags === OrderFlags.SHORT_TERM)) {
1149
- throw new Error('SHORT_TERM cancels cannot be batched');
1150
- }
1151
-
1152
- if (
1153
- placeOrderPayloads.some(
1154
- (placePayload) =>
1155
- calculateOrderFlags(placePayload.type, placePayload.timeInForce) ===
1156
- OrderFlags.SHORT_TERM,
1157
- )
1158
- ) {
1159
- throw new Error('SHORT_TERM orders cannot be batched');
1160
- }
1161
-
1162
- const account: Promise<Account> = this.validatorClient.post.account(
1163
- subaccount.address,
1164
- undefined,
1165
- );
1166
-
1167
- const msgs: Promise<EncodeObject[]> = (async () => {
1168
- const cancelMsgPromises = cancelOrderPayloads.map(async (cancelPayload) => {
1169
- const cancelSubaccount = subaccount.cloneWithSubaccount(cancelPayload.subaccountNumber);
1170
- return this.validatorClient.post.cancelOrderMsg(
1171
- cancelSubaccount.address,
1172
- cancelSubaccount.subaccountNumber,
1173
- cancelPayload.clientId,
1174
- cancelPayload.orderFlags,
1175
- cancelPayload.clobPairId,
1176
- cancelPayload.goodTilBlock,
1177
- cancelPayload.goodTilBlockTime,
1178
- );
1179
- });
1180
-
1181
- const transferMsg = (() => {
1182
- if (transferToSubaccountPayload == null) {
1183
- return undefined;
1184
- }
1185
- const transferSubaccount = subaccount.cloneWithSubaccount(
1186
- transferToSubaccountPayload.sourceSubaccountNumber,
1187
- );
1188
- return this.transferToSubaccountMessage(
1189
- transferSubaccount,
1190
- transferSubaccount.address,
1191
- transferToSubaccountPayload.recipientSubaccountNumber,
1192
- transferToSubaccountPayload.transferAmount,
1193
- );
1194
- })();
1195
-
1196
- const placeOrderMsgPromises = placeOrderPayloads.map((placePayload) => {
1197
- const placeSubaccount = subaccount.cloneWithSubaccount(placePayload.subaccountNumber);
1198
- return this.placeOrderMessage(
1199
- placeSubaccount,
1200
- placePayload.marketId,
1201
- placePayload.type,
1202
- placePayload.side,
1203
- placePayload.price,
1204
- placePayload.size,
1205
- placePayload.clientId,
1206
- placePayload.timeInForce,
1207
- placePayload.goodTilTimeInSeconds,
1208
- placePayload.execution,
1209
- placePayload.postOnly,
1210
- placePayload.reduceOnly,
1211
- placePayload.triggerPrice,
1212
- placePayload.marketInfo,
1213
- placePayload.currentHeight,
1214
- placePayload.goodTilBlock,
1215
- );
1216
- });
1217
-
1218
- return Promise.all([
1219
- ...cancelMsgPromises,
1220
- ...(transferMsg != null ? [transferMsg] : []),
1221
- ...placeOrderMsgPromises,
1222
- ]);
1223
- })();
1224
-
1225
- return this.send(
1226
- subaccount,
1227
- () => msgs,
1228
- true,
1229
- undefined,
1230
- memo,
1231
- broadcastMode ?? Method.BroadcastTxCommit,
1232
- () => account,
1233
- );
1234
- }
1235
-
1236
- // vaults
1237
-
1238
- async depositToMegavault(
1239
- subaccount: SubaccountInfo,
1240
- amountUsdc: number,
1241
- broadcastMode?: BroadcastMode,
1242
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1243
- return this.validatorClient.post.depositToMegavault(
1244
- subaccount,
1245
- bigIntToBytes(calculateVaultQuantums(amountUsdc)),
1246
- broadcastMode,
1247
- );
1248
- }
1249
-
1250
- depositToMegavaultMessage(subaccount: SubaccountInfo, amountUsdc: number): EncodeObject {
1251
- return this.validatorClient.post.depositToMegavaultMsg(
1252
- subaccount.address,
1253
- subaccount.subaccountNumber,
1254
- bigIntToBytes(calculateVaultQuantums(amountUsdc)),
1255
- );
1256
- }
1257
-
1258
- async withdrawFromMegavault(
1259
- subaccount: SubaccountInfo,
1260
- shares: number,
1261
- minAmount: number,
1262
- broadcastMode?: BroadcastMode,
1263
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1264
- return this.validatorClient.post.withdrawFromMegavault(
1265
- subaccount,
1266
- bigIntToBytes(BigInt(Math.floor(shares))),
1267
- bigIntToBytes(calculateVaultQuantums(minAmount)),
1268
- broadcastMode,
1269
- );
1270
- }
1271
-
1272
- withdrawFromMegavaultMessage(
1273
- subaccount: SubaccountInfo,
1274
- shares: number,
1275
- minAmount: number,
1276
- ): EncodeObject {
1277
- return this.validatorClient.post.withdrawFromMegavaultMsg(
1278
- subaccount.address,
1279
- subaccount.subaccountNumber,
1280
- bigIntToBytes(BigInt(Math.floor(shares))),
1281
- bigIntToBytes(calculateVaultQuantums(minAmount)),
1282
- );
1283
- }
1284
-
1285
- /**
1286
- * @description Submit a governance proposal to add a new market.
1287
- *
1288
- * @param params Parameters neeeded to create a new market.
1289
- * @param title Title of the gov proposal.
1290
- * @param summary Summary of the gov proposal.
1291
- * @param initialDepositAmount Initial deposit amount of the gov proposal.
1292
- * @param proposer proposer of the gov proposal.
1293
- *
1294
- * @returns the transaction hash.
1295
- */
1296
- async submitGovAddNewMarketProposal(
1297
- wallet: LocalWallet,
1298
- params: GovAddNewMarketParams,
1299
- title: string,
1300
- summary: string,
1301
- initialDepositAmount: string,
1302
- memo?: string,
1303
- metadata?: string,
1304
- expedited?: boolean,
1305
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1306
- const msg: Promise<EncodeObject[]> = new Promise((resolve) => {
1307
- const composer = this.validatorClient.post.composer;
1308
- const registry = generateRegistry();
1309
- const msgs: EncodeObject[] = [];
1310
-
1311
- const isDydxUsd = params.ticker.toLowerCase() === 'dydx-usd';
1312
-
1313
- // x/prices.MsgCreateOracleMarket
1314
- const createOracleMarket = composer.composeMsgCreateOracleMarket(
1315
- params.id,
1316
- params.ticker,
1317
- params.priceExponent,
1318
- params.minExchanges,
1319
- params.minPriceChange,
1320
- params.exchangeConfigJson,
1321
- );
1322
-
1323
- // x/perpetuals.MsgCreatePerpetual
1324
- const createPerpetual = composer.composeMsgCreatePerpetual(
1325
- params.id,
1326
- isDydxUsd ? 1000001 : params.id,
1327
- params.ticker,
1328
- params.atomicResolution,
1329
- params.liquidityTier,
1330
- params.marketType,
1331
- );
1332
-
1333
- // x/clob.MsgCreateClobPair
1334
- const createClobPair = composer.composeMsgCreateClobPair(
1335
- params.id,
1336
- params.id,
1337
- params.quantumConversionExponent,
1338
- params.stepBaseQuantums,
1339
- params.subticksPerTick,
1340
- );
1341
-
1342
- // x/clob.MsgUpdateClobPair
1343
- const updateClobPair = composer.composeMsgUpdateClobPair(
1344
- params.id,
1345
- params.id,
1346
- params.quantumConversionExponent,
1347
- params.stepBaseQuantums,
1348
- params.subticksPerTick,
1349
- );
1350
-
1351
- // x/delaymsg.MsgDelayMessage
1352
- const delayMessage = composer.composeMsgDelayMessage(
1353
- // IMPORTANT: must wrap messages in Any type to fit into delaymsg.
1354
- composer.wrapMessageAsAny(registry, updateClobPair),
1355
- params.delayBlocks,
1356
- );
1357
-
1358
- // The order matters.
1359
- if (!isDydxUsd) {
1360
- msgs.push(createOracleMarket);
1361
- }
1362
- msgs.push(createPerpetual);
1363
- msgs.push(createClobPair);
1364
- msgs.push(delayMessage);
1365
-
1366
- // x/gov.v1.MsgSubmitProposal
1367
- const submitProposal = composer.composeMsgSubmitProposal(
1368
- title,
1369
- initialDepositAmount,
1370
- this.validatorClient.config.denoms, // use the client denom.
1371
- summary,
1372
- // IMPORTANT: must wrap messages in Any type for gov's submit proposal.
1373
- composer.wrapMessageArrAsAny(registry, msgs),
1374
- wallet.address!, // proposer
1375
- metadata,
1376
- expedited,
1377
- );
1378
-
1379
- resolve([submitProposal]);
1380
- });
1381
-
1382
- return this.send(SubaccountInfo.forLocalWallet(wallet), () => msg, false, undefined, memo);
1383
- }
1384
-
1385
- async createMarketPermissionless(
1386
- subaccount: SubaccountInfo,
1387
- ticker: string,
1388
- broadcastMode?: BroadcastMode,
1389
- gasAdjustment?: number,
1390
- memo?: string,
1391
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1392
- return this.validatorClient.post.createMarketPermissionless(
1393
- ticker,
1394
- subaccount,
1395
- broadcastMode,
1396
- gasAdjustment,
1397
- memo,
1398
- );
1399
- }
1400
-
1401
- async addAuthenticator(
1402
- subaccount: SubaccountInfo,
1403
- authenticatorType: AuthenticatorType,
1404
- data: Uint8Array,
1405
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1406
- // Validate the provided authenticators before sending to the validator
1407
- const authenticator: Authenticator = {
1408
- type: authenticatorType,
1409
- config: JSON.parse(new TextDecoder().decode(data)),
1410
- };
1411
- if (!this.validateAuthenticator(authenticator)) {
1412
- throw new Error(
1413
- 'Invalid authenticator, please ensure the authenticator permissions are correct',
1414
- );
1415
- }
1416
-
1417
- return this.validatorClient.post.addAuthenticator(subaccount, authenticatorType, data);
1418
- }
1419
-
1420
- async removeAuthenticator(
1421
- subaccount: SubaccountInfo,
1422
- id: string,
1423
- ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1424
- return this.validatorClient.post.removeAuthenticator(subaccount, Long.fromString(id));
1425
- }
1426
-
1427
- async getAuthenticators(address: string): Promise<GetAuthenticatorsResponse> {
1428
- return this.validatorClient.get.getAuthenticators(address);
1429
- }
1430
-
1431
- validateAuthenticator(authenticator: Authenticator): boolean {
1432
- const decodeCompositeConfig = (config: unknown): Authenticator[] | null => {
1433
- if (Array.isArray(config)) {
1434
- return config as Authenticator[];
1435
- }
1436
- if (typeof config === 'string') {
1437
- try {
1438
- const decoded = Buffer.from(config, 'base64').toString('utf8');
1439
- const parsed = JSON.parse(decoded);
1440
- return Array.isArray(parsed) ? (parsed as Authenticator[]) : null;
1441
- } catch {
1442
- return null;
1443
- }
1444
- }
1445
- return null;
1446
- };
1447
-
1448
- const checkAuthenticator = (auth: Authenticator): boolean => {
1449
- if (auth.type === AuthenticatorType.SIGNATURE_VERIFICATION) {
1450
- return true;
1451
- }
1452
-
1453
- if (auth.type === AuthenticatorType.ANY_OF || auth.type === AuthenticatorType.ALL_OF) {
1454
- const subAuthenticators = decodeCompositeConfig(auth.config);
1455
- if (subAuthenticators == null) {
1456
- return false;
1457
- }
1458
- if (auth.type === AuthenticatorType.ANY_OF) {
1459
- return subAuthenticators.every((nested) => checkAuthenticator(nested));
1460
- }
1461
- return subAuthenticators.some((nested) => checkAuthenticator(nested));
1462
- }
1463
-
1464
- return false;
1465
- };
1466
-
1467
- return checkAuthenticator(authenticator);
1468
- }
1469
- }