@clober/v2-sdk 0.0.1-a → 0.0.1-b

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 (297) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.yaml +34 -0
  3. package/.github/workflows/ci.yaml +88 -0
  4. package/.github/workflows/deployer.yaml +19 -0
  5. package/.nvmrc +1 -0
  6. package/.prettierignore +6 -0
  7. package/.prettierrc +7 -0
  8. package/package.json +8 -4
  9. package/src/.graphclient/index.ts +1695 -0
  10. package/src/.graphclient/schema.graphql +1116 -0
  11. package/src/.graphclient/sources/clober-v2/introspectionSchema.ts +14481 -0
  12. package/src/.graphclient/sources/clober-v2/schema.graphql +1116 -0
  13. package/src/.graphclient/sources/clober-v2/types.ts +1133 -0
  14. package/src/.graphclientrc.yml +12 -0
  15. package/src/abis/core/controller-abi.ts +985 -0
  16. package/src/abis/core/params-abi.ts +59 -0
  17. package/src/apis/currency.ts +92 -0
  18. package/src/apis/graphql/books.graphql +25 -0
  19. package/src/apis/graphql/open-order.graphql +29 -0
  20. package/src/apis/graphql/open-orders.graphql +29 -0
  21. package/src/apis/market.ts +85 -0
  22. package/src/apis/open-order.ts +145 -0
  23. package/src/approval.ts +82 -0
  24. package/src/call.ts +705 -0
  25. package/src/constants/action.ts +9 -0
  26. package/src/constants/addresses.ts +17 -0
  27. package/src/constants/chain.ts +12 -0
  28. package/src/constants/currency.ts +15 -0
  29. package/src/constants/fee.ts +4 -0
  30. package/src/constants/price.ts +3 -0
  31. package/src/constants/subgraph-url.ts +8 -0
  32. package/src/index.ts +5 -0
  33. package/src/model/book.ts +166 -0
  34. package/src/model/currency.ts +6 -0
  35. package/src/model/depth.ts +11 -0
  36. package/src/model/fee-policy.ts +51 -0
  37. package/src/model/market.ts +320 -0
  38. package/src/model/open-order.ts +16 -0
  39. package/src/signature.ts +196 -0
  40. package/src/type.ts +38 -0
  41. package/src/utils/approval.ts +48 -0
  42. package/{dist/esm/utils/book-id.js → src/utils/book-id.ts} +19 -9
  43. package/src/utils/build-transaction.ts +39 -0
  44. package/src/utils/decimals.ts +22 -0
  45. package/src/utils/market.ts +74 -0
  46. package/src/utils/math.ts +117 -0
  47. package/src/utils/prices.ts +29 -0
  48. package/src/utils/tick.ts +104 -0
  49. package/src/utils/time.ts +6 -0
  50. package/src/utils/unit.ts +43 -0
  51. package/src/view.ts +258 -0
  52. package/test/book-id.test.ts +101 -0
  53. package/test/fee-policy.test.ts +228 -0
  54. package/test/get-expected-input.test.ts +206 -0
  55. package/test/get-expected-output.test.ts +206 -0
  56. package/test/limit-order.test.ts +279 -0
  57. package/test/market-order.test.ts +245 -0
  58. package/test/market.test.ts +68 -0
  59. package/test/math.test.ts +91 -0
  60. package/test/open-order.test.ts +112 -0
  61. package/test/open.test.ts +15 -0
  62. package/test/tick.test.ts +230 -0
  63. package/test/tsconfig.json +12 -0
  64. package/test/utils/chain.ts +12 -0
  65. package/test/utils/constants.ts +25 -0
  66. package/test/utils/currency.ts +44 -0
  67. package/test/utils/depth.ts +148 -0
  68. package/test/utils/test-chain.ts +26 -0
  69. package/test/vitest.config.ts +15 -0
  70. package/tsconfig.base.json +37 -0
  71. package/tsconfig.build.json +9 -0
  72. package/tsconfig.json +9 -0
  73. package/dist/cjs/.graphclient/index.js +0 -243
  74. package/dist/cjs/.graphclient/index.js.map +0 -1
  75. package/dist/cjs/.graphclient/sources/clober-v2/introspectionSchema.js +0 -14482
  76. package/dist/cjs/.graphclient/sources/clober-v2/introspectionSchema.js.map +0 -1
  77. package/dist/cjs/.graphclient/sources/clober-v2/types.js +0 -4
  78. package/dist/cjs/.graphclient/sources/clober-v2/types.js.map +0 -1
  79. package/dist/cjs/abis/core/controller-abi.js +0 -989
  80. package/dist/cjs/abis/core/controller-abi.js.map +0 -1
  81. package/dist/cjs/abis/core/params-abi.js +0 -62
  82. package/dist/cjs/abis/core/params-abi.js.map +0 -1
  83. package/dist/cjs/apis/currency.js +0 -87
  84. package/dist/cjs/apis/currency.js.map +0 -1
  85. package/dist/cjs/apis/market.js +0 -63
  86. package/dist/cjs/apis/market.js.map +0 -1
  87. package/dist/cjs/apis/open-order.js +0 -90
  88. package/dist/cjs/apis/open-order.js.map +0 -1
  89. package/dist/cjs/approval.js +0 -74
  90. package/dist/cjs/approval.js.map +0 -1
  91. package/dist/cjs/call.js +0 -545
  92. package/dist/cjs/call.js.map +0 -1
  93. package/dist/cjs/constants/action.js +0 -14
  94. package/dist/cjs/constants/action.js.map +0 -1
  95. package/dist/cjs/constants/addresses.js +0 -13
  96. package/dist/cjs/constants/addresses.js.map +0 -1
  97. package/dist/cjs/constants/chain.js +0 -13
  98. package/dist/cjs/constants/chain.js.map +0 -1
  99. package/dist/cjs/constants/currency.js +0 -12
  100. package/dist/cjs/constants/currency.js.map +0 -1
  101. package/dist/cjs/constants/fee.js +0 -7
  102. package/dist/cjs/constants/fee.js.map +0 -1
  103. package/dist/cjs/constants/price.js +0 -6
  104. package/dist/cjs/constants/price.js.map +0 -1
  105. package/dist/cjs/constants/subgraph-url.js +0 -8
  106. package/dist/cjs/constants/subgraph-url.js.map +0 -1
  107. package/dist/cjs/index.js +0 -22
  108. package/dist/cjs/index.js.map +0 -1
  109. package/dist/cjs/model/book.js +0 -130
  110. package/dist/cjs/model/book.js.map +0 -1
  111. package/dist/cjs/model/currency.js +0 -3
  112. package/dist/cjs/model/currency.js.map +0 -1
  113. package/dist/cjs/model/depth.js +0 -3
  114. package/dist/cjs/model/depth.js.map +0 -1
  115. package/dist/cjs/model/fee-policy.js +0 -42
  116. package/dist/cjs/model/fee-policy.js.map +0 -1
  117. package/dist/cjs/model/market.js +0 -215
  118. package/dist/cjs/model/market.js.map +0 -1
  119. package/dist/cjs/model/open-order.js +0 -3
  120. package/dist/cjs/model/open-order.js.map +0 -1
  121. package/dist/cjs/package.json +0 -1
  122. package/dist/cjs/signature.js +0 -178
  123. package/dist/cjs/signature.js.map +0 -1
  124. package/dist/cjs/tsconfig.build.tsbuildinfo +0 -1
  125. package/dist/cjs/type.js +0 -6
  126. package/dist/cjs/type.js.map +0 -1
  127. package/dist/cjs/utils/approval.js +0 -46
  128. package/dist/cjs/utils/approval.js.map +0 -1
  129. package/dist/cjs/utils/book-id.js +0 -25
  130. package/dist/cjs/utils/book-id.js.map +0 -1
  131. package/dist/cjs/utils/build-transaction.js +0 -31
  132. package/dist/cjs/utils/build-transaction.js.map +0 -1
  133. package/dist/cjs/utils/decimals.js +0 -17
  134. package/dist/cjs/utils/decimals.js.map +0 -1
  135. package/dist/cjs/utils/market.js +0 -53
  136. package/dist/cjs/utils/market.js.map +0 -1
  137. package/dist/cjs/utils/math.js +0 -83
  138. package/dist/cjs/utils/math.js.map +0 -1
  139. package/dist/cjs/utils/prices.js +0 -22
  140. package/dist/cjs/utils/prices.js.map +0 -1
  141. package/dist/cjs/utils/tick.js +0 -106
  142. package/dist/cjs/utils/tick.js.map +0 -1
  143. package/dist/cjs/utils/time.js +0 -9
  144. package/dist/cjs/utils/time.js.map +0 -1
  145. package/dist/cjs/utils/unit.js +0 -38
  146. package/dist/cjs/utils/unit.js.map +0 -1
  147. package/dist/cjs/view.js +0 -185
  148. package/dist/cjs/view.js.map +0 -1
  149. package/dist/esm/.graphclient/index.js +0 -233
  150. package/dist/esm/.graphclient/index.js.map +0 -1
  151. package/dist/esm/.graphclient/sources/clober-v2/introspectionSchema.js +0 -14480
  152. package/dist/esm/.graphclient/sources/clober-v2/introspectionSchema.js.map +0 -1
  153. package/dist/esm/.graphclient/sources/clober-v2/types.js +0 -3
  154. package/dist/esm/.graphclient/sources/clober-v2/types.js.map +0 -1
  155. package/dist/esm/abis/core/controller-abi.js +0 -986
  156. package/dist/esm/abis/core/controller-abi.js.map +0 -1
  157. package/dist/esm/abis/core/params-abi.js +0 -59
  158. package/dist/esm/abis/core/params-abi.js.map +0 -1
  159. package/dist/esm/apis/currency.js +0 -83
  160. package/dist/esm/apis/currency.js.map +0 -1
  161. package/dist/esm/apis/market.js +0 -59
  162. package/dist/esm/apis/market.js.map +0 -1
  163. package/dist/esm/apis/open-order.js +0 -85
  164. package/dist/esm/apis/open-order.js.map +0 -1
  165. package/dist/esm/approval.js +0 -70
  166. package/dist/esm/approval.js.map +0 -1
  167. package/dist/esm/call.js +0 -535
  168. package/dist/esm/call.js.map +0 -1
  169. package/dist/esm/constants/action.js +0 -11
  170. package/dist/esm/constants/action.js.map +0 -1
  171. package/dist/esm/constants/addresses.js +0 -10
  172. package/dist/esm/constants/addresses.js.map +0 -1
  173. package/dist/esm/constants/chain.js +0 -10
  174. package/dist/esm/constants/chain.js.map +0 -1
  175. package/dist/esm/constants/currency.js +0 -9
  176. package/dist/esm/constants/currency.js.map +0 -1
  177. package/dist/esm/constants/fee.js +0 -4
  178. package/dist/esm/constants/fee.js.map +0 -1
  179. package/dist/esm/constants/price.js +0 -3
  180. package/dist/esm/constants/price.js.map +0 -1
  181. package/dist/esm/constants/subgraph-url.js +0 -5
  182. package/dist/esm/constants/subgraph-url.js.map +0 -1
  183. package/dist/esm/index.js +0 -6
  184. package/dist/esm/index.js.map +0 -1
  185. package/dist/esm/model/book.js +0 -126
  186. package/dist/esm/model/book.js.map +0 -1
  187. package/dist/esm/model/currency.js +0 -2
  188. package/dist/esm/model/currency.js.map +0 -1
  189. package/dist/esm/model/depth.js +0 -2
  190. package/dist/esm/model/depth.js.map +0 -1
  191. package/dist/esm/model/fee-policy.js +0 -38
  192. package/dist/esm/model/fee-policy.js.map +0 -1
  193. package/dist/esm/model/market.js +0 -211
  194. package/dist/esm/model/market.js.map +0 -1
  195. package/dist/esm/model/open-order.js +0 -2
  196. package/dist/esm/model/open-order.js.map +0 -1
  197. package/dist/esm/package.json +0 -1
  198. package/dist/esm/signature.js +0 -174
  199. package/dist/esm/signature.js.map +0 -1
  200. package/dist/esm/tsconfig.build.tsbuildinfo +0 -1
  201. package/dist/esm/type.js +0 -2
  202. package/dist/esm/type.js.map +0 -1
  203. package/dist/esm/utils/approval.js +0 -42
  204. package/dist/esm/utils/approval.js.map +0 -1
  205. package/dist/esm/utils/book-id.js.map +0 -1
  206. package/dist/esm/utils/build-transaction.js +0 -27
  207. package/dist/esm/utils/build-transaction.js.map +0 -1
  208. package/dist/esm/utils/decimals.js +0 -12
  209. package/dist/esm/utils/decimals.js.map +0 -1
  210. package/dist/esm/utils/market.js +0 -49
  211. package/dist/esm/utils/market.js.map +0 -1
  212. package/dist/esm/utils/math.js +0 -78
  213. package/dist/esm/utils/math.js.map +0 -1
  214. package/dist/esm/utils/prices.js +0 -17
  215. package/dist/esm/utils/prices.js.map +0 -1
  216. package/dist/esm/utils/tick.js +0 -100
  217. package/dist/esm/utils/tick.js.map +0 -1
  218. package/dist/esm/utils/time.js +0 -5
  219. package/dist/esm/utils/time.js.map +0 -1
  220. package/dist/esm/utils/unit.js +0 -34
  221. package/dist/esm/utils/unit.js.map +0 -1
  222. package/dist/esm/view.js +0 -177
  223. package/dist/esm/view.js.map +0 -1
  224. package/dist/types/.graphclient/index.d.ts +0 -1281
  225. package/dist/types/.graphclient/index.d.ts.map +0 -1
  226. package/dist/types/.graphclient/sources/clober-v2/introspectionSchema.d.ts +0 -3
  227. package/dist/types/.graphclient/sources/clober-v2/introspectionSchema.d.ts.map +0 -1
  228. package/dist/types/.graphclient/sources/clober-v2/types.d.ts +0 -984
  229. package/dist/types/.graphclient/sources/clober-v2/types.d.ts.map +0 -1
  230. package/dist/types/abis/core/controller-abi.d.ts +0 -757
  231. package/dist/types/abis/core/controller-abi.d.ts.map +0 -1
  232. package/dist/types/abis/core/params-abi.d.ts +0 -21
  233. package/dist/types/abis/core/params-abi.d.ts.map +0 -1
  234. package/dist/types/apis/currency.d.ts +0 -4
  235. package/dist/types/apis/currency.d.ts.map +0 -1
  236. package/dist/types/apis/market.d.ts +0 -4
  237. package/dist/types/apis/market.d.ts.map +0 -1
  238. package/dist/types/apis/open-order.d.ts +0 -5
  239. package/dist/types/apis/open-order.d.ts.map +0 -1
  240. package/dist/types/approval.d.ts +0 -32
  241. package/dist/types/approval.d.ts.map +0 -1
  242. package/dist/types/call.d.ts +0 -234
  243. package/dist/types/call.d.ts.map +0 -1
  244. package/dist/types/constants/action.d.ts +0 -10
  245. package/dist/types/constants/action.d.ts.map +0 -1
  246. package/dist/types/constants/addresses.d.ts +0 -9
  247. package/dist/types/constants/addresses.d.ts.map +0 -1
  248. package/dist/types/constants/chain.d.ts +0 -9
  249. package/dist/types/constants/chain.d.ts.map +0 -1
  250. package/dist/types/constants/currency.d.ts +0 -8
  251. package/dist/types/constants/currency.d.ts.map +0 -1
  252. package/dist/types/constants/fee.d.ts +0 -4
  253. package/dist/types/constants/fee.d.ts.map +0 -1
  254. package/dist/types/constants/price.d.ts +0 -3
  255. package/dist/types/constants/price.d.ts.map +0 -1
  256. package/dist/types/constants/subgraph-url.d.ts +0 -5
  257. package/dist/types/constants/subgraph-url.d.ts.map +0 -1
  258. package/dist/types/index.d.ts +0 -6
  259. package/dist/types/index.d.ts.map +0 -1
  260. package/dist/types/model/book.d.ts +0 -31
  261. package/dist/types/model/book.d.ts.map +0 -1
  262. package/dist/types/model/currency.d.ts +0 -7
  263. package/dist/types/model/currency.d.ts.map +0 -1
  264. package/dist/types/model/depth.d.ts +0 -11
  265. package/dist/types/model/depth.d.ts.map +0 -1
  266. package/dist/types/model/fee-policy.d.ts +0 -15
  267. package/dist/types/model/fee-policy.d.ts.map +0 -1
  268. package/dist/types/model/market.d.ts +0 -44
  269. package/dist/types/model/market.d.ts.map +0 -1
  270. package/dist/types/model/open-order.d.ts +0 -28
  271. package/dist/types/model/open-order.d.ts.map +0 -1
  272. package/dist/types/signature.d.ts +0 -40
  273. package/dist/types/signature.d.ts.map +0 -1
  274. package/dist/types/type.d.ts +0 -34
  275. package/dist/types/type.d.ts.map +0 -1
  276. package/dist/types/utils/approval.d.ts +0 -3
  277. package/dist/types/utils/approval.d.ts.map +0 -1
  278. package/dist/types/utils/book-id.d.ts +0 -2
  279. package/dist/types/utils/book-id.d.ts.map +0 -1
  280. package/dist/types/utils/build-transaction.d.ts +0 -5
  281. package/dist/types/utils/build-transaction.d.ts.map +0 -1
  282. package/dist/types/utils/decimals.d.ts +0 -3
  283. package/dist/types/utils/decimals.d.ts.map +0 -1
  284. package/dist/types/utils/market.d.ts +0 -7
  285. package/dist/types/utils/market.d.ts.map +0 -1
  286. package/dist/types/utils/math.d.ts +0 -3
  287. package/dist/types/utils/math.d.ts.map +0 -1
  288. package/dist/types/utils/prices.d.ts +0 -3
  289. package/dist/types/utils/prices.d.ts.map +0 -1
  290. package/dist/types/utils/tick.d.ts +0 -4
  291. package/dist/types/utils/tick.d.ts.map +0 -1
  292. package/dist/types/utils/time.d.ts +0 -2
  293. package/dist/types/utils/time.d.ts.map +0 -1
  294. package/dist/types/utils/unit.d.ts +0 -4
  295. package/dist/types/utils/unit.d.ts.map +0 -1
  296. package/dist/types/view.d.ts +0 -129
  297. package/dist/types/view.d.ts.map +0 -1
@@ -0,0 +1,112 @@
1
+ import { expect, test } from 'vitest'
2
+ import {
3
+ getOpenOrders,
4
+ getOpenOrder,
5
+ claimOrders,
6
+ setApprovalOfOpenOrdersForAll,
7
+ cancelOrders,
8
+ } from '@clober/v2-sdk'
9
+
10
+ import { cloberTestChain } from './utils/test-chain'
11
+ import { account, publicClient, walletClient } from './utils/constants'
12
+
13
+ const IS_LOCAL = process.env.IS_LOCAL === 'true'
14
+
15
+ test.runIf(IS_LOCAL)('get open orders by user address', async () => {
16
+ const openOrders = await getOpenOrders(
17
+ cloberTestChain.id,
18
+ '0xf18Be2a91cF31Fc3f8D828b6c714e1806a75e0AA',
19
+ {
20
+ rpcUrl: publicClient.transport.url!,
21
+ },
22
+ )
23
+ expect(openOrders.length).toBeGreaterThan(0)
24
+ })
25
+
26
+ test.runIf(IS_LOCAL)('get undefined open orders', async () => {
27
+ expect(
28
+ await getOpenOrder(cloberTestChain.id, '200', {
29
+ rpcUrl: publicClient.transport.url!,
30
+ }).catch((e) => e.message),
31
+ ).toEqual('Open order not found: 200')
32
+ })
33
+
34
+ test.runIf(IS_LOCAL)('claim all orders', async () => {
35
+ const openOrders = (
36
+ await getOpenOrders(cloberTestChain.id, account.address, {
37
+ rpcUrl: publicClient.transport.url!,
38
+ })
39
+ ).slice(0, 5)
40
+ expect(
41
+ await claimOrders(
42
+ cloberTestChain.id,
43
+ account.address,
44
+ openOrders.map((order) => order.id),
45
+ { rpcUrl: publicClient.transport.url! },
46
+ ).catch((e) => e.message),
47
+ ).toEqual(`
48
+ import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
49
+
50
+ const hash = await setApprovalOfOpenOrdersForAll(
51
+ ${cloberTestChain.id},
52
+ privateKeyToAccount('0x...')
53
+ )
54
+ `)
55
+
56
+ // be sure to approve before claim
57
+ await publicClient.waitForTransactionReceipt({
58
+ hash: (await setApprovalOfOpenOrdersForAll(cloberTestChain.id, account, {
59
+ rpcUrl: publicClient.transport.url!,
60
+ }))!,
61
+ })
62
+
63
+ const transaction = await claimOrders(
64
+ cloberTestChain.id,
65
+ account.address,
66
+ openOrders.map((order) => order.id),
67
+ { rpcUrl: publicClient.transport.url! },
68
+ )
69
+
70
+ await walletClient.sendTransaction({ ...transaction, account })
71
+ })
72
+
73
+ test.runIf(IS_LOCAL)('cancel all orders', async () => {
74
+ const openOrders = (
75
+ await getOpenOrders(cloberTestChain.id, account.address, {
76
+ rpcUrl: publicClient.transport.url!,
77
+ })
78
+ )
79
+ .filter((order) => order.cancelable)
80
+ .slice(0, 5)
81
+ expect(
82
+ await cancelOrders(
83
+ cloberTestChain.id,
84
+ account.address,
85
+ openOrders.map((order) => order.id),
86
+ { rpcUrl: publicClient.transport.url! },
87
+ ).catch((e) => e.message),
88
+ ).toEqual(`
89
+ import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
90
+
91
+ const hash = await setApprovalOfOpenOrdersForAll(
92
+ ${cloberTestChain.id},
93
+ privateKeyToAccount('0x...')
94
+ )
95
+ `)
96
+
97
+ // be sure to approve before cancel
98
+ await publicClient.waitForTransactionReceipt({
99
+ hash: (await setApprovalOfOpenOrdersForAll(cloberTestChain.id, account, {
100
+ rpcUrl: publicClient.transport.url!,
101
+ }))!,
102
+ })
103
+
104
+ const transaction = await cancelOrders(
105
+ cloberTestChain.id,
106
+ account.address,
107
+ openOrders.map((order) => order.id),
108
+ { rpcUrl: publicClient.transport.url! },
109
+ )
110
+
111
+ await walletClient.sendTransaction({ ...transaction, account })
112
+ })
@@ -0,0 +1,15 @@
1
+ import { expect, test } from 'vitest'
2
+ import { openMarket } from '@clober/v2-sdk'
3
+
4
+ import { publicClient } from './utils/constants'
5
+ import { cloberTestChain } from './utils/test-chain'
6
+
7
+ test('try already open market', async () => {
8
+ const transaction = await openMarket(
9
+ cloberTestChain.id,
10
+ '0x0000000000000000000000000000000000000000',
11
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
12
+ { rpcUrl: publicClient.transport.url! },
13
+ )
14
+ expect(transaction).toBeUndefined()
15
+ })
@@ -0,0 +1,230 @@
1
+ import { expect, test } from 'vitest'
2
+ import { getAddress } from 'viem'
3
+
4
+ import { fromPrice, toPrice } from '../src/utils/tick'
5
+ import { baseToQuote, quoteToBase } from '../src/utils/decimals'
6
+
7
+ import { publicClient } from './utils/constants'
8
+
9
+ const _abi = [
10
+ {
11
+ inputs: [
12
+ {
13
+ internalType: 'Tick',
14
+ name: 'tick',
15
+ type: 'int24',
16
+ },
17
+ {
18
+ internalType: 'uint256',
19
+ name: 'base',
20
+ type: 'uint256',
21
+ },
22
+ {
23
+ internalType: 'bool',
24
+ name: 'roundingUp',
25
+ type: 'bool',
26
+ },
27
+ ],
28
+ name: 'baseToQuote',
29
+ outputs: [
30
+ {
31
+ internalType: 'uint256',
32
+ name: '',
33
+ type: 'uint256',
34
+ },
35
+ ],
36
+ stateMutability: 'pure',
37
+ type: 'function',
38
+ },
39
+ {
40
+ inputs: [
41
+ {
42
+ internalType: 'uint256',
43
+ name: 'price',
44
+ type: 'uint256',
45
+ },
46
+ ],
47
+ name: 'fromPrice',
48
+ outputs: [
49
+ {
50
+ internalType: 'int24',
51
+ name: '',
52
+ type: 'int24',
53
+ },
54
+ ],
55
+ stateMutability: 'pure',
56
+ type: 'function',
57
+ },
58
+ {
59
+ inputs: [
60
+ {
61
+ internalType: 'Tick',
62
+ name: 'tick',
63
+ type: 'int24',
64
+ },
65
+ {
66
+ internalType: 'uint256',
67
+ name: 'quote',
68
+ type: 'uint256',
69
+ },
70
+ {
71
+ internalType: 'bool',
72
+ name: 'roundingUp',
73
+ type: 'bool',
74
+ },
75
+ ],
76
+ name: 'quoteToBase',
77
+ outputs: [
78
+ {
79
+ internalType: 'uint256',
80
+ name: '',
81
+ type: 'uint256',
82
+ },
83
+ ],
84
+ stateMutability: 'pure',
85
+ type: 'function',
86
+ },
87
+ {
88
+ inputs: [
89
+ {
90
+ internalType: 'int24',
91
+ name: 'tick',
92
+ type: 'int24',
93
+ },
94
+ ],
95
+ name: 'toPrice',
96
+ outputs: [
97
+ {
98
+ internalType: 'uint256',
99
+ name: 'price',
100
+ type: 'uint256',
101
+ },
102
+ ],
103
+ stateMutability: 'pure',
104
+ type: 'function',
105
+ },
106
+ ] as const
107
+
108
+ const TICK_WRAPPER_ADDRESS =
109
+ '0xBEB8502F63A7c34a9591D3Fd1eEBca18a41FA0c8' as `0x${string}`
110
+
111
+ const MAX_TICK = Math.pow(2, 19) - 1
112
+ const MIN_TICK = -1 * MAX_TICK
113
+
114
+ const MIN_PRICE = 1350587n
115
+ const MAX_PRICE = 4647684107270898330752324302845848816923571339324334n
116
+
117
+ const randomInteger = (start: number, end: number) => {
118
+ return Math.floor(Math.random() * (end - start + 1) + start)
119
+ }
120
+
121
+ test('index to price', async () => {
122
+ const randomPriceIndices = [
123
+ MIN_TICK,
124
+ ...Array.from({ length: 500 }, () => randomInteger(-500000, 500000)),
125
+ MAX_TICK,
126
+ ]
127
+ const actualPrices = (
128
+ (await publicClient.multicall({
129
+ contracts: randomPriceIndices.map((priceIndex) => ({
130
+ address: getAddress(TICK_WRAPPER_ADDRESS),
131
+ abi: _abi,
132
+ functionName: 'toPrice',
133
+ args: [priceIndex],
134
+ })),
135
+ })) as { result: bigint }[]
136
+ ).map(({ result }) => result)
137
+
138
+ const expectedPrices = randomPriceIndices.map((priceIndex) =>
139
+ toPrice(BigInt(priceIndex)),
140
+ )
141
+ expect(expectedPrices).toEqual(actualPrices)
142
+ })
143
+
144
+ test('price to index', async () => {
145
+ const randomPriceIndices = [
146
+ MIN_TICK,
147
+ ...Array.from({ length: 500 }, () => randomInteger(-500000, 500000)),
148
+ MAX_TICK,
149
+ ]
150
+
151
+ const actualPrices = (
152
+ (await publicClient.multicall({
153
+ contracts: randomPriceIndices.map((priceIndex) => ({
154
+ address: TICK_WRAPPER_ADDRESS,
155
+ abi: _abi,
156
+ functionName: 'toPrice',
157
+ args: [priceIndex],
158
+ })),
159
+ })) as { result: bigint }[]
160
+ ).map(({ result }) => result)
161
+
162
+ const actualPriceIndices = (
163
+ (await publicClient.multicall({
164
+ contracts: actualPrices.map((price) => ({
165
+ address: TICK_WRAPPER_ADDRESS,
166
+ abi: _abi,
167
+ functionName: 'fromPrice',
168
+ args: [price],
169
+ })),
170
+ })) as { result: number }[]
171
+ ).map(({ result }) => BigInt(result))
172
+ const expectedPriceIndices = actualPrices.map((price) => fromPrice(price))
173
+ expect(expectedPriceIndices).toEqual(actualPriceIndices)
174
+ })
175
+
176
+ test('price to index for min and max', async () => {
177
+ const actualPrices = [MIN_PRICE, MAX_PRICE]
178
+ const actualPriceIndices = (
179
+ (await publicClient.multicall({
180
+ contracts: actualPrices.map((price) => ({
181
+ address: TICK_WRAPPER_ADDRESS,
182
+ abi: _abi,
183
+ functionName: 'fromPrice',
184
+ args: [price],
185
+ })),
186
+ })) as { result: number }[]
187
+ ).map(({ result }) => BigInt(result))
188
+ const expectedPriceIndices = actualPrices.map((price) => fromPrice(price))
189
+ expect(expectedPriceIndices).toEqual(actualPriceIndices)
190
+ })
191
+
192
+ test('quote to base', async () => {
193
+ const randomPriceIndices = Array.from({ length: 100 }, () =>
194
+ randomInteger(-100000, 100000),
195
+ )
196
+ const actual = (
197
+ (await publicClient.multicall({
198
+ contracts: randomPriceIndices.map((priceIndex) => ({
199
+ address: TICK_WRAPPER_ADDRESS,
200
+ abi: _abi,
201
+ functionName: 'quoteToBase',
202
+ args: [priceIndex, 1000000n, true],
203
+ })),
204
+ })) as { result: bigint }[]
205
+ ).map(({ result }) => result)
206
+ const expected = randomPriceIndices.map((priceIndex) =>
207
+ quoteToBase(BigInt(priceIndex), 1000000n, true),
208
+ )
209
+ expect(expected).toEqual(actual)
210
+ })
211
+
212
+ test('base to quote', async () => {
213
+ const randomPriceIndices = Array.from({ length: 100 }, () =>
214
+ randomInteger(-100000, 100000),
215
+ )
216
+ const actual = (
217
+ (await publicClient.multicall({
218
+ contracts: randomPriceIndices.map((priceIndex) => ({
219
+ address: TICK_WRAPPER_ADDRESS,
220
+ abi: _abi,
221
+ functionName: 'baseToQuote',
222
+ args: [priceIndex, 1000000n, true],
223
+ })),
224
+ })) as { result: bigint }[]
225
+ ).map(({ result }) => result)
226
+ const expected = randomPriceIndices.map((priceIndex) =>
227
+ baseToQuote(BigInt(priceIndex), 1000000n, true),
228
+ )
229
+ expect(expected).toEqual(actual)
230
+ })
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "../tsconfig.base.json",
3
+ "include": ["*.ts"],
4
+ "compilerOptions": {
5
+ "types": ["node"],
6
+ "lib": ["DOM"],
7
+ "baseUrl": ".",
8
+ "paths": {
9
+ "@clober/v2-sdk": ["../src/index.ts"]
10
+ },
11
+ }
12
+ }
@@ -0,0 +1,12 @@
1
+ import { createPublicClient, http } from 'viem'
2
+ import { arbitrumSepolia } from 'viem/chains'
3
+
4
+ import { FORK_URL } from './constants'
5
+
6
+ export const fetchBlockNumer = async (): Promise<bigint> => {
7
+ const publicClient = createPublicClient({
8
+ chain: arbitrumSepolia,
9
+ transport: http(FORK_URL),
10
+ })
11
+ return publicClient.getBlockNumber()
12
+ }
@@ -0,0 +1,25 @@
1
+ import * as dotenv from 'dotenv'
2
+ import { privateKeyToAccount } from 'viem/accounts'
3
+ import { createPublicClient, createWalletClient, http } from 'viem'
4
+
5
+ import { cloberTestChain } from './test-chain'
6
+
7
+ dotenv.config()
8
+
9
+ export const FORK_URL =
10
+ process.env.ARBITRUM_SEPOLIA_RPC_URL ||
11
+ 'https://arbitrum-sepolia-archive.allthatnode.com'
12
+ export const account = privateKeyToAccount(
13
+ process.env.DEV_PRIVATE_KEY as `0x${string}`,
14
+ )
15
+
16
+ export const publicClient = createPublicClient({
17
+ chain: cloberTestChain,
18
+ transport: http(FORK_URL),
19
+ })
20
+
21
+ export const walletClient = createWalletClient({
22
+ chain: cloberTestChain,
23
+ account,
24
+ transport: http(FORK_URL),
25
+ })
@@ -0,0 +1,44 @@
1
+ import { createPublicClient, http } from 'viem'
2
+
3
+ import { CHAIN_IDS } from '../../src'
4
+ import { CHAIN_MAP } from '../../src/constants/chain'
5
+
6
+ const _abi = [
7
+ {
8
+ inputs: [
9
+ {
10
+ internalType: 'address',
11
+ name: 'account',
12
+ type: 'address',
13
+ },
14
+ ],
15
+ name: 'balanceOf',
16
+ outputs: [
17
+ {
18
+ internalType: 'uint256',
19
+ name: '',
20
+ type: 'uint256',
21
+ },
22
+ ],
23
+ stateMutability: 'view',
24
+ type: 'function',
25
+ },
26
+ ] as const
27
+
28
+ export const fetchTokenBalance = async (
29
+ chainId: CHAIN_IDS,
30
+ token: `0x${string}`,
31
+ userAddress: `0x${string}`,
32
+ rpcUrl: string,
33
+ ): Promise<bigint> => {
34
+ const publicClient = createPublicClient({
35
+ chain: CHAIN_MAP[chainId],
36
+ transport: http(rpcUrl),
37
+ })
38
+ return publicClient.readContract({
39
+ address: token,
40
+ abi: _abi,
41
+ functionName: 'balanceOf',
42
+ args: [userAddress],
43
+ })
44
+ }
@@ -0,0 +1,148 @@
1
+ import { createPublicClient, http, isAddressEqual } from 'viem'
2
+ import { arbitrumSepolia } from 'viem/chains'
3
+
4
+ import { CHAIN_MAP, CHAIN_IDS } from '../../src/constants/chain'
5
+ import { getMarketId } from '../../src/utils/market'
6
+ import { formatPrice } from '../../src/utils/prices'
7
+ import { invertPrice, toPrice } from '../../src/utils/tick'
8
+ import { fetchCurrency } from '../../src/apis/currency'
9
+ import { toBookId } from '../../src/utils/book-id'
10
+ import { CONTRACT_ADDRESSES } from '../../src/constants/addresses'
11
+
12
+ import { cloberTestChain } from './test-chain'
13
+
14
+ const MAX_TICK = 2n ** 19n - 1n
15
+ const _abi = [
16
+ {
17
+ inputs: [
18
+ {
19
+ internalType: 'BookId',
20
+ name: 'id',
21
+ type: 'uint192',
22
+ },
23
+ {
24
+ internalType: 'Tick',
25
+ name: 'tick',
26
+ type: 'int24',
27
+ },
28
+ {
29
+ internalType: 'uint256',
30
+ name: 'n',
31
+ type: 'uint256',
32
+ },
33
+ ],
34
+ name: 'getLiquidity',
35
+ outputs: [
36
+ {
37
+ components: [
38
+ {
39
+ internalType: 'Tick',
40
+ name: 'tick',
41
+ type: 'int24',
42
+ },
43
+ {
44
+ internalType: 'uint64',
45
+ name: 'depth',
46
+ type: 'uint64',
47
+ },
48
+ ],
49
+ internalType: 'struct IBookViewer.Liquidity[]',
50
+ name: 'liquidity',
51
+ type: 'tuple[]',
52
+ },
53
+ ],
54
+ stateMutability: 'view',
55
+ type: 'function',
56
+ },
57
+ ] as const
58
+
59
+ const fetchDepth = async (
60
+ chainId: CHAIN_IDS,
61
+ inputToken: `0x${string}`,
62
+ outputToken: `0x${string}`,
63
+ bookId: bigint,
64
+ rpcUrl: string,
65
+ ): Promise<
66
+ {
67
+ price: number
68
+ amount: bigint
69
+ }[]
70
+ > => {
71
+ const { quoteTokenAddress, baseTokenAddress } = getMarketId(chainId, [
72
+ outputToken,
73
+ inputToken,
74
+ ])
75
+ const isBid = isAddressEqual(inputToken, quoteTokenAddress)
76
+ const [quoteCurrency, baseCurrency] = await Promise.all([
77
+ fetchCurrency(chainId, quoteTokenAddress, rpcUrl),
78
+ fetchCurrency(chainId, baseTokenAddress, rpcUrl),
79
+ ])
80
+ const publicClient = createPublicClient({
81
+ chain: CHAIN_MAP[chainId],
82
+ transport: http(rpcUrl),
83
+ })
84
+ const depths = await publicClient.readContract({
85
+ address: CONTRACT_ADDRESSES[arbitrumSepolia.id]!.BookViewer,
86
+ abi: _abi,
87
+ functionName: 'getLiquidity',
88
+ args: [bookId, Number(MAX_TICK), 50n],
89
+ })
90
+ return depths.map(({ tick, depth }: { tick: number; depth: bigint }) => ({
91
+ price: isBid
92
+ ? formatPrice(
93
+ toPrice(BigInt(tick)),
94
+ quoteCurrency.decimals,
95
+ baseCurrency.decimals,
96
+ )
97
+ : formatPrice(
98
+ invertPrice(toPrice(BigInt(tick))),
99
+ quoteCurrency.decimals,
100
+ baseCurrency.decimals,
101
+ ),
102
+ amount: depth,
103
+ }))
104
+ }
105
+
106
+ export const fetchAskDepth = async (rpcUrl: string) => {
107
+ const askBookId = toBookId(
108
+ '0x0000000000000000000000000000000000000000',
109
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
110
+ 10n ** 12n,
111
+ )
112
+ return fetchDepth(
113
+ cloberTestChain.id,
114
+ '0x0000000000000000000000000000000000000000',
115
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
116
+ askBookId,
117
+ rpcUrl,
118
+ )
119
+ }
120
+
121
+ export const fetchBidDepth = async (rpcUrl: string) => {
122
+ const bidBookId = toBookId(
123
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
124
+ '0x0000000000000000000000000000000000000000',
125
+ 1n,
126
+ )
127
+ return fetchDepth(
128
+ cloberTestChain.id,
129
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
130
+ '0x0000000000000000000000000000000000000000',
131
+ bidBookId,
132
+ rpcUrl,
133
+ )
134
+ }
135
+
136
+ export const getSize = (
137
+ depth: { price: number; amount: bigint }[],
138
+ from: number,
139
+ to: number,
140
+ ) => {
141
+ return Number(
142
+ (
143
+ depth.find(({ price }) => from <= price && price <= to) ?? {
144
+ amount: 0n,
145
+ }
146
+ ).amount,
147
+ )
148
+ }
@@ -0,0 +1,26 @@
1
+ import { Chain } from 'viem'
2
+ import { arbitrumSepolia } from 'viem/chains'
3
+
4
+ export const cloberTestChain: Chain = {
5
+ id: arbitrumSepolia.id,
6
+ name: 'Clober Test Chain',
7
+ nativeCurrency: {
8
+ name: 'Ether',
9
+ symbol: 'ETH',
10
+ decimals: 18,
11
+ },
12
+ rpcUrls: {
13
+ default: {
14
+ http: [''],
15
+ },
16
+ public: {
17
+ http: [''],
18
+ },
19
+ },
20
+ contracts: {
21
+ multicall3: {
22
+ address: '0xca11bde05977b3631167028862be2a173976ca11',
23
+ blockCreated: 81930,
24
+ },
25
+ },
26
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ envDir: '.',
5
+ test: {
6
+ disableConsoleIntercept: false,
7
+ environment: 'node',
8
+ include: ['*.test.ts'],
9
+ alias: {
10
+ '@clober/v2-sdk': '../src/index.ts',
11
+ },
12
+ testTimeout: 40000000,
13
+ hookTimeout: 40000000,
14
+ },
15
+ })
@@ -0,0 +1,37 @@
1
+ {
2
+ "include": [],
3
+ "compilerOptions": {
4
+ // Incremental builds
5
+ "incremental": true,
6
+
7
+ // Type checking
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "useDefineForClassFields": true,
11
+ "exactOptionalPropertyTypes": true,
12
+ "noFallthroughCasesInSwitch": true,
13
+ "noImplicitOverride": true,
14
+ "noImplicitReturns": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noUncheckedIndexedAccess": true,
18
+
19
+ // Modules
20
+ "module": "ES2022",
21
+ "moduleResolution": "node",
22
+
23
+ // JavaScript support
24
+ "allowJs": false,
25
+ "checkJs": false,
26
+
27
+ // Interop constraints
28
+ "forceConsistentCasingInFileNames": true,
29
+
30
+ // Language and environment
31
+ "lib": ["ESNext"],
32
+ "target": "ESNext",
33
+
34
+ // Sourcemaps
35
+ "sourceMap": true
36
+ }
37
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "include": ["src/**/*.ts"],
4
+ "exclude": ["src/**/*.test.ts"],
5
+ "compilerOptions": {
6
+ "types": ["node"],
7
+ "lib": ["DOM"]
8
+ }
9
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "include": ["src/**/*.ts"],
4
+ "exclude": ["src/**/*.test.ts"],
5
+ "compilerOptions": {
6
+ "types": ["node"],
7
+ "lib": ["DOM"]
8
+ }
9
+ }