@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,279 @@
1
+ import { expect, test } from 'vitest'
2
+ import { limitOrder, signERC20Permit } from '@clober/v2-sdk'
3
+ import { formatUnits } from 'viem'
4
+ import { arbitrumSepolia } from 'viem/chains'
5
+
6
+ import { fetchTokenBalance } from './utils/currency'
7
+ import { fetchAskDepth, fetchBidDepth, getSize } from './utils/depth'
8
+ import { account, publicClient, walletClient } from './utils/constants'
9
+ import { cloberTestChain } from './utils/test-chain'
10
+
11
+ const IS_LOCAL = process.env.IS_LOCAL === 'true'
12
+
13
+ test.runIf(IS_LOCAL)('limit order in not open market', async () => {
14
+ expect(
15
+ await limitOrder(
16
+ arbitrumSepolia.id,
17
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
18
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
19
+ '0x0000000000000000000000000000000000000000',
20
+ '10',
21
+ '1000',
22
+ { rpcUrl: publicClient.transport.url! },
23
+ ).catch((e) => e.message),
24
+ ).toEqual(`
25
+ import { openMarket } from '@clober/v2-sdk'
26
+
27
+ const transaction = await openMarket(
28
+ ${cloberTestChain.id},
29
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
30
+ '0x0000000000000000000000000000000000000000',
31
+ )
32
+ `)
33
+ })
34
+
35
+ test.runIf(IS_LOCAL)('make bid order', async () => {
36
+ const signature = await signERC20Permit(
37
+ cloberTestChain.id,
38
+ account,
39
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
40
+ '1000',
41
+ { rpcUrl: publicClient.transport.url! },
42
+ )
43
+ const transaction = await limitOrder(
44
+ cloberTestChain.id,
45
+ account.address,
46
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
47
+ '0x0000000000000000000000000000000000000000',
48
+ '1000',
49
+ '0.01',
50
+ { signature, rpcUrl: publicClient.transport.url!, postOnly: true },
51
+ )
52
+
53
+ const [beforeBalance, beforeDepth] = await Promise.all([
54
+ fetchTokenBalance(
55
+ cloberTestChain.id,
56
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
57
+ account.address,
58
+ publicClient.transport.url!,
59
+ ),
60
+ fetchBidDepth(publicClient.transport.url!),
61
+ ])
62
+
63
+ const hash = await walletClient.sendTransaction({
64
+ ...transaction!,
65
+ account,
66
+ gasPrice: transaction!.gasPrice! * 2n,
67
+ })
68
+ const receipt = await publicClient.waitForTransactionReceipt({ hash })
69
+ expect(receipt.status).toBe('success')
70
+
71
+ const [afterBalance, afterDepth] = await Promise.all([
72
+ fetchTokenBalance(
73
+ cloberTestChain.id,
74
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
75
+ account.address,
76
+ publicClient.transport.url!,
77
+ ),
78
+ fetchBidDepth(publicClient.transport.url!),
79
+ ])
80
+
81
+ expect(beforeBalance - afterBalance).toEqual(1000000000n)
82
+ expect(getSize(afterDepth, 0, 0.01)).greaterThan(
83
+ getSize(beforeDepth, 0, 0.01),
84
+ )
85
+ })
86
+
87
+ test.runIf(IS_LOCAL)('make ask order', async () => {
88
+ const transaction = await limitOrder(
89
+ cloberTestChain.id,
90
+ account.address,
91
+ '0x0000000000000000000000000000000000000000',
92
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
93
+ '0.001',
94
+ '8000.01',
95
+ { rpcUrl: publicClient.transport.url!, postOnly: true },
96
+ )
97
+
98
+ const [beforeBalance, beforeDepth] = await Promise.all([
99
+ publicClient.getBalance({
100
+ address: account.address,
101
+ }),
102
+ fetchAskDepth(publicClient.transport.url!),
103
+ ])
104
+
105
+ const hash = await walletClient.sendTransaction({
106
+ ...transaction!,
107
+ account,
108
+ gasPrice: transaction!.gasPrice! * 2n,
109
+ })
110
+ const receipt = await publicClient.waitForTransactionReceipt({ hash })
111
+ expect(receipt.status).toBe('success')
112
+
113
+ const [afterBalance, afterDepth] = await Promise.all([
114
+ publicClient.getBalance({
115
+ address: account.address,
116
+ }),
117
+ fetchAskDepth(publicClient.transport.url!),
118
+ ])
119
+
120
+ expect(Number(beforeBalance - afterBalance)).greaterThan(Number(10n ** 15n))
121
+ expect(getSize(afterDepth, 8000, 8001)).greaterThan(
122
+ getSize(beforeDepth, 8000, 8001),
123
+ )
124
+ })
125
+
126
+ test.runIf(IS_LOCAL)('limit bid order', async () => {
127
+ const beforeBidDepth = await fetchBidDepth(publicClient.transport.url!)
128
+ const makeTx = await limitOrder(
129
+ cloberTestChain.id,
130
+ account.address,
131
+ '0x0000000000000000000000000000000000000000',
132
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
133
+ '0.001',
134
+ beforeBidDepth.length === 0
135
+ ? '5001'
136
+ : (beforeBidDepth[0]!.price + 1).toString(),
137
+ { rpcUrl: publicClient.transport.url!, postOnly: true },
138
+ )
139
+ await publicClient.waitForTransactionReceipt({
140
+ hash: await walletClient.sendTransaction({
141
+ ...makeTx!,
142
+ account,
143
+ gasPrice: makeTx!.gasPrice! * 2n,
144
+ }),
145
+ })
146
+
147
+ const [beforeUSDCBalance, beforeETHBalance] = await Promise.all([
148
+ fetchTokenBalance(
149
+ cloberTestChain.id,
150
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
151
+ account.address,
152
+ publicClient.transport.url!,
153
+ ),
154
+ publicClient.getBalance({
155
+ address: account.address,
156
+ }),
157
+ ])
158
+ const signature = await signERC20Permit(
159
+ cloberTestChain.id,
160
+ account,
161
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
162
+ '100000',
163
+ { rpcUrl: publicClient.transport.url! },
164
+ )
165
+ const transaction = await limitOrder(
166
+ cloberTestChain.id,
167
+ account.address,
168
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
169
+ '0x0000000000000000000000000000000000000000',
170
+ '100000',
171
+ beforeBidDepth.length === 0
172
+ ? '5002'
173
+ : (beforeBidDepth[0]!.price + 2).toString(),
174
+ { signature, rpcUrl: publicClient.transport.url! },
175
+ )
176
+
177
+ const hash = await walletClient.sendTransaction({
178
+ ...transaction!,
179
+ account,
180
+ gasPrice: transaction!.gasPrice! * 2n,
181
+ })
182
+ const receipt = await publicClient.waitForTransactionReceipt({ hash })
183
+ expect(receipt.status).toBe('success')
184
+
185
+ const [afterUSDCBalance, afterETHBalance] = await Promise.all([
186
+ fetchTokenBalance(
187
+ cloberTestChain.id,
188
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
189
+ account.address,
190
+ publicClient.transport.url!,
191
+ ),
192
+ publicClient.getBalance({
193
+ address: account.address,
194
+ }),
195
+ ])
196
+
197
+ expect(beforeUSDCBalance - afterUSDCBalance).toEqual(100000000000n)
198
+ expect(Number(formatUnits(afterETHBalance, 18))).greaterThan(
199
+ Number(formatUnits(beforeETHBalance, 18)),
200
+ )
201
+ })
202
+
203
+ test.runIf(IS_LOCAL)('limit ask order', async () => {
204
+ const beforeAskDepth = await fetchAskDepth(publicClient.transport.url!)
205
+ const signature = await signERC20Permit(
206
+ cloberTestChain.id,
207
+ account,
208
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
209
+ '100',
210
+ { rpcUrl: publicClient.transport.url! },
211
+ )
212
+ const makeTx = await limitOrder(
213
+ cloberTestChain.id,
214
+ account.address,
215
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
216
+ '0x0000000000000000000000000000000000000000',
217
+ '100',
218
+ beforeAskDepth.length === 0
219
+ ? '4999'
220
+ : (beforeAskDepth[0]!.price - 1).toString(),
221
+ { signature, rpcUrl: publicClient.transport.url!, postOnly: true },
222
+ )
223
+ await publicClient.waitForTransactionReceipt({
224
+ hash: await walletClient.sendTransaction({
225
+ ...makeTx!,
226
+ account,
227
+ gasPrice: makeTx!.gasPrice! * 2n,
228
+ }),
229
+ })
230
+
231
+ const transaction = await limitOrder(
232
+ cloberTestChain.id,
233
+ account.address,
234
+ '0x0000000000000000000000000000000000000000',
235
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
236
+ '0.001',
237
+ beforeAskDepth.length === 0
238
+ ? '4998'
239
+ : (beforeAskDepth[0]!.price - 2).toString(),
240
+ { rpcUrl: publicClient.transport.url! },
241
+ )
242
+
243
+ const [beforeUSDCBalance, beforeETHBalance] = await Promise.all([
244
+ fetchTokenBalance(
245
+ cloberTestChain.id,
246
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
247
+ account.address,
248
+ publicClient.transport.url!,
249
+ ),
250
+ publicClient.getBalance({
251
+ address: account.address,
252
+ }),
253
+ ])
254
+
255
+ const hash = await walletClient.sendTransaction({
256
+ ...transaction!,
257
+ account,
258
+ gasPrice: transaction!.gasPrice! * 2n,
259
+ })
260
+ const receipt = await publicClient.waitForTransactionReceipt({ hash })
261
+ expect(receipt.status).toBe('success')
262
+
263
+ const [afterUSDCBalance, afterETHBalance] = await Promise.all([
264
+ fetchTokenBalance(
265
+ cloberTestChain.id,
266
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
267
+ account.address,
268
+ publicClient.transport.url!,
269
+ ),
270
+ publicClient.getBalance({
271
+ address: account.address,
272
+ }),
273
+ ])
274
+
275
+ expect(beforeETHBalance - afterETHBalance).toBeGreaterThan(1000000000000000)
276
+ expect(Number(formatUnits(afterUSDCBalance, 18))).greaterThan(
277
+ Number(formatUnits(beforeUSDCBalance, 18)),
278
+ )
279
+ })
@@ -0,0 +1,245 @@
1
+ import { expect, test } from 'vitest'
2
+ import { marketOrder } from '@clober/v2-sdk'
3
+
4
+ import { cloberTestChain } from './utils/test-chain'
5
+ import { publicClient } from './utils/constants'
6
+
7
+ const IS_LOCAL = process.env.IS_LOCAL === 'true'
8
+
9
+ test.runIf(IS_LOCAL)('market order in not open market', async () => {
10
+ expect(
11
+ await marketOrder(
12
+ cloberTestChain.id,
13
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
14
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
15
+ '0x0000000000000000000000000000000000000000',
16
+ '10',
17
+ { rpcUrl: publicClient.transport.url! },
18
+ ).catch((e) => e.message),
19
+ ).toEqual(`
20
+ import { openMarket } from '@clober/v2-sdk'
21
+
22
+ const transaction = await openMarket(
23
+ ${cloberTestChain.id},
24
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
25
+ '0x0000000000000000000000000000000000000000',
26
+ )
27
+ `)
28
+ })
29
+
30
+ // test('market bid with unlimited slippage', async () => {
31
+ // const signature = await signERC20Permit(
32
+ // cloberTestChain.id,
33
+ // account,
34
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
35
+ // '100',
36
+ // { rpcUrl: publicClient.transport.url! },
37
+ // )
38
+ // const transaction = await marketOrder(
39
+ // cloberTestChain.id,
40
+ // account.address,
41
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
42
+ // '0x0000000000000000000000000000000000000000',
43
+ // '100',
44
+ // { signature, rpcUrl: publicClient.transport.url! },
45
+ // )
46
+ //
47
+ // const [beforeUSDCBalance, beforeETHBalance, beforeAskDepth] =
48
+ // await Promise.all([
49
+ // fetchTokenBalance(
50
+ // cloberTestChain.id,
51
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
52
+ // account.address,
53
+ // publicClient.transport.url!,
54
+ // ),
55
+ // publicClient.getBalance({
56
+ // address: account.address,
57
+ // }),
58
+ // fetchAskDepth(publicClient.transport.url!),
59
+ // ])
60
+ // expect(beforeAskDepth.length).toBeGreaterThan(0)
61
+ //
62
+ // await walletClient.sendTransaction({ ...transaction!, account })
63
+ //
64
+ // const [afterUSDCBalance, afterETHBalance, afterAskDepth] = await Promise.all([
65
+ // fetchTokenBalance(
66
+ // cloberTestChain.id,
67
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
68
+ // account.address,
69
+ // publicClient.transport.url!,
70
+ // ),
71
+ // publicClient.getBalance({
72
+ // address: account.address,
73
+ // }),
74
+ // fetchAskDepth(publicClient.transport.url!),
75
+ // ])
76
+ //
77
+ // expect(Number(beforeUSDCBalance)).toBeGreaterThan(Number(afterUSDCBalance))
78
+ // expect(Number(afterETHBalance)).toBeGreaterThan(Number(beforeETHBalance))
79
+ // expect(beforeAskDepth.length).toBeGreaterThan(afterAskDepth.length)
80
+ // expect(afterAskDepth.length).toBe(0)
81
+ // })
82
+ //
83
+ // test('market ask with unlimited slippage', async () => {
84
+ // const transaction = await marketOrder(
85
+ // cloberTestChain.id,
86
+ // account.address,
87
+ // '0x0000000000000000000000000000000000000000',
88
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
89
+ // '10',
90
+ // { rpcUrl: publicClient.transport.url! },
91
+ // )
92
+ //
93
+ // const [beforeUSDCBalance, beforeETHBalance, beforeBidDepth] =
94
+ // await Promise.all([
95
+ // fetchTokenBalance(
96
+ // cloberTestChain.id,
97
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
98
+ // account.address,
99
+ // publicClient.transport.url!,
100
+ // ),
101
+ // publicClient.getBalance({
102
+ // address: account.address,
103
+ // }),
104
+ // fetchBidDepth(publicClient.transport.url!),
105
+ // ])
106
+ // expect(beforeBidDepth.length).toBeGreaterThan(0)
107
+ //
108
+ // await walletClient.sendTransaction({ ...transaction!, account })
109
+ //
110
+ // const [afterUSDCBalance, afterETHBalance, afterBidDepth] = await Promise.all([
111
+ // fetchTokenBalance(
112
+ // cloberTestChain.id,
113
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
114
+ // account.address,
115
+ // publicClient.transport.url!,
116
+ // ),
117
+ // publicClient.getBalance({
118
+ // address: account.address,
119
+ // }),
120
+ // fetchBidDepth(publicClient.transport.url!),
121
+ // ])
122
+ //
123
+ // expect(Number(afterUSDCBalance)).toBeGreaterThan(Number(beforeUSDCBalance))
124
+ // expect(Number(beforeETHBalance)).toBeGreaterThan(Number(afterETHBalance))
125
+ // expect(beforeBidDepth.length).toBeGreaterThan(afterBidDepth.length)
126
+ // expect(afterBidDepth.length).toBe(0)
127
+ // })
128
+ //
129
+ // test('market bid with slippage tolerate', async () => {
130
+ // const market = await getMarket(
131
+ // cloberTestChain.id,
132
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
133
+ // '0x0000000000000000000000000000000000000000',
134
+ // { rpcUrl: publicClient.transport.url! },
135
+ // )
136
+ // const signature = await signERC20Permit(
137
+ // cloberTestChain.id,
138
+ // account,
139
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
140
+ // '1000000',
141
+ // { rpcUrl: publicClient.transport.url! },
142
+ // )
143
+ // const transaction = await marketOrder(
144
+ // cloberTestChain.id,
145
+ // account.address,
146
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
147
+ // '0x0000000000000000000000000000000000000000',
148
+ // '1000000',
149
+ // {
150
+ // signature,
151
+ // rpcUrl: publicClient.transport.url!,
152
+ // limitPrice: (market.asks[0]!.price + 1).toString(),
153
+ // },
154
+ // )
155
+ //
156
+ // const [beforeUSDCBalance, beforeETHBalance, beforeAskDepth] =
157
+ // await Promise.all([
158
+ // fetchTokenBalance(
159
+ // cloberTestChain.id,
160
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
161
+ // account.address,
162
+ // publicClient.transport.url!,
163
+ // ),
164
+ // publicClient.getBalance({
165
+ // address: account.address,
166
+ // }),
167
+ // fetchAskDepth(publicClient.transport.url!),
168
+ // ])
169
+ // expect(beforeAskDepth.length).toBeGreaterThan(1)
170
+ //
171
+ // await walletClient.sendTransaction({ ...transaction!, account })
172
+ //
173
+ // const [afterUSDCBalance, afterETHBalance, afterAskDepth] = await Promise.all([
174
+ // fetchTokenBalance(
175
+ // cloberTestChain.id,
176
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
177
+ // account.address,
178
+ // publicClient.transport.url!,
179
+ // ),
180
+ // publicClient.getBalance({
181
+ // address: account.address,
182
+ // }),
183
+ // fetchAskDepth(publicClient.transport.url!),
184
+ // ])
185
+ //
186
+ // expect(Number(beforeUSDCBalance)).toBeGreaterThan(Number(afterUSDCBalance))
187
+ // expect(Number(afterETHBalance)).toBeGreaterThan(Number(beforeETHBalance))
188
+ // expect(beforeAskDepth.length).toBeGreaterThan(afterAskDepth.length)
189
+ // expect(afterAskDepth.length).toBeGreaterThan(0)
190
+ // })
191
+ //
192
+ // test('market ask with slippage tolerate', async () => {
193
+ // const market = await getMarket(
194
+ // cloberTestChain.id,
195
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
196
+ // '0x0000000000000000000000000000000000000000',
197
+ // { rpcUrl: publicClient.transport.url! },
198
+ // )
199
+ // const transaction = await marketOrder(
200
+ // cloberTestChain.id,
201
+ // account.address,
202
+ // '0x0000000000000000000000000000000000000000',
203
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
204
+ // '10',
205
+ // {
206
+ // rpcUrl: publicClient.transport.url!,
207
+ // limitPrice: (market.bids[0]!.price - 1).toString(),
208
+ // },
209
+ // )
210
+ //
211
+ // const [beforeUSDCBalance, beforeETHBalance, beforeBidDepth] =
212
+ // await Promise.all([
213
+ // fetchTokenBalance(
214
+ // cloberTestChain.id,
215
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
216
+ // account.address,
217
+ // publicClient.transport.url!,
218
+ // ),
219
+ // publicClient.getBalance({
220
+ // address: account.address,
221
+ // }),
222
+ // fetchBidDepth(publicClient.transport.url!),
223
+ // ])
224
+ // expect(beforeBidDepth.length).toBeGreaterThan(1)
225
+ //
226
+ // await walletClient.sendTransaction({ ...transaction!, account })
227
+ //
228
+ // const [afterUSDCBalance, afterETHBalance, afterBidDepth] = await Promise.all([
229
+ // fetchTokenBalance(
230
+ // cloberTestChain.id,
231
+ // '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
232
+ // account.address,
233
+ // publicClient.transport.url!,
234
+ // ),
235
+ // publicClient.getBalance({
236
+ // address: account.address,
237
+ // }),
238
+ // fetchBidDepth(publicClient.transport.url!),
239
+ // ])
240
+ //
241
+ // expect(Number(afterUSDCBalance)).toBeGreaterThan(Number(beforeUSDCBalance))
242
+ // expect(Number(beforeETHBalance)).toBeGreaterThan(Number(afterETHBalance))
243
+ // expect(beforeBidDepth.length).toBeGreaterThan(afterBidDepth.length)
244
+ // expect(afterBidDepth.length).toBeGreaterThan(0)
245
+ // })
@@ -0,0 +1,68 @@
1
+ import { expect, test } from 'vitest'
2
+ import { arbitrumSepolia } from 'viem/chains'
3
+ import { getAddress } from 'viem'
4
+ import { getMarket } from '@clober/v2-sdk'
5
+
6
+ import { publicClient } from './utils/constants'
7
+
8
+ test('fetch open market', async () => {
9
+ const market = await getMarket(
10
+ arbitrumSepolia.id,
11
+ '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
12
+ '0x0000000000000000000000000000000000000000',
13
+ { rpcUrl: publicClient.transport.url! },
14
+ )
15
+
16
+ expect(market.makerFee).toEqual(-0.03)
17
+ expect(market.takerFee).toEqual(0.1)
18
+
19
+ expect(market.quote.address).toEqual(
20
+ getAddress('0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'),
21
+ )
22
+ expect(market.quote.symbol).toEqual('MT')
23
+ expect(market.quote.name).toEqual('MockERC20')
24
+ expect(market.quote.decimals).toEqual(6)
25
+
26
+ expect(market.base.address).toEqual(
27
+ getAddress('0x0000000000000000000000000000000000000000'),
28
+ )
29
+ expect(market.base.symbol).toEqual('ETH')
30
+ expect(market.base.name).toEqual('Ethereum')
31
+ expect(market.base.decimals).toEqual(18)
32
+
33
+ expect(market.bidBookOpen).toEqual(true)
34
+ expect(market.askBookOpen).toEqual(true)
35
+ })
36
+
37
+ test('fetch empty market', async () => {
38
+ const market = await getMarket(
39
+ arbitrumSepolia.id,
40
+ '0x447ad4a108b5540c220f9f7e83723ac87c0f8fd8',
41
+ '0x0000000000000000000000000000000000000000',
42
+ { rpcUrl: publicClient.transport.url! },
43
+ )
44
+ expect(market.bidBookOpen).toEqual(true)
45
+ })
46
+
47
+ // @dev: this test will be fail when the market is open
48
+ test('fetch not open market', async () => {
49
+ const market = await getMarket(
50
+ arbitrumSepolia.id,
51
+ '0xf18Be2a91cF31Fc3f8D828b6c714e1806a75e0AA',
52
+ '0x0000000000000000000000000000000000000000',
53
+ { rpcUrl: publicClient.transport.url! },
54
+ )
55
+ expect(market.bidBookOpen).toEqual(false)
56
+ expect(market.askBookOpen).toEqual(false)
57
+ })
58
+
59
+ test('fetch invalid market', async () => {
60
+ expect(
61
+ await getMarket(
62
+ arbitrumSepolia.id,
63
+ '0x0000000000000000000000000000000000000000',
64
+ '0x0000000000000000000000000000000000000000',
65
+ { rpcUrl: publicClient.transport.url! },
66
+ ).catch((e) => e.message),
67
+ ).toEqual('Token0 and token1 must be different')
68
+ })
@@ -0,0 +1,91 @@
1
+ import { expect, test } from 'vitest'
2
+ import { getAddress } from 'viem'
3
+
4
+ import { lnWad } from '../src/utils/math'
5
+
6
+ import { publicClient } from './utils/constants'
7
+
8
+ const _abi = [
9
+ {
10
+ inputs: [
11
+ {
12
+ internalType: 'uint256',
13
+ name: 'a',
14
+ type: 'uint256',
15
+ },
16
+ {
17
+ internalType: 'uint256',
18
+ name: 'b',
19
+ type: 'uint256',
20
+ },
21
+ {
22
+ internalType: 'bool',
23
+ name: 'roundingUp',
24
+ type: 'bool',
25
+ },
26
+ ],
27
+ name: 'divide',
28
+ outputs: [
29
+ {
30
+ internalType: 'uint256',
31
+ name: '',
32
+ type: 'uint256',
33
+ },
34
+ ],
35
+ stateMutability: 'pure',
36
+ type: 'function',
37
+ },
38
+ {
39
+ inputs: [
40
+ {
41
+ internalType: 'int256',
42
+ name: 'x',
43
+ type: 'int256',
44
+ },
45
+ ],
46
+ name: 'lnWad',
47
+ outputs: [
48
+ {
49
+ internalType: 'int256',
50
+ name: '',
51
+ type: 'int256',
52
+ },
53
+ ],
54
+ stateMutability: 'pure',
55
+ type: 'function',
56
+ },
57
+ ] as const
58
+
59
+ const MATH_WRAPPER_ADDRESS = '0x98d55f0AaEda3bad7815C8F3d8f8882e6B702D26'
60
+
61
+ const randomInteger = (start: number, end: number) => {
62
+ return Math.floor(Math.random() * (end - start + 1) + start)
63
+ }
64
+
65
+ const MIN_PRICE = 1350587n
66
+ const MAX_PRICE = 4647684107270898330752324302845848816923571339324334n
67
+
68
+ test('lnWad', async () => {
69
+ const randomValues = [
70
+ MIN_PRICE,
71
+ ...Array.from({ length: 500 }, () =>
72
+ randomInteger(Number(MIN_PRICE + 1n), Number(MAX_PRICE - 1n)),
73
+ ),
74
+ MAX_PRICE,
75
+ ]
76
+ const actualValues = (
77
+ (await publicClient.multicall({
78
+ contracts: randomValues.map((value) => ({
79
+ address: getAddress(MATH_WRAPPER_ADDRESS),
80
+ abi: _abi,
81
+ functionName: 'lnWad',
82
+ args: [value],
83
+ })),
84
+ })) as { result: bigint }[]
85
+ ).map(({ result }) => result)
86
+
87
+ const expectedValues = randomValues.map((priceIndex) =>
88
+ lnWad(BigInt(priceIndex)),
89
+ )
90
+ expect(expectedValues).toEqual(actualValues)
91
+ })