@ritbit/v4-client-js 1.3.17

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