tempo.ts 0.1.5 → 0.2.0

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 (276) hide show
  1. package/README.md +33 -2
  2. package/dist/chains.d.ts +509 -115
  3. package/dist/chains.d.ts.map +1 -1
  4. package/dist/chains.js +18 -9
  5. package/dist/chains.js.map +1 -1
  6. package/dist/ox/Order.d.ts +92 -0
  7. package/dist/ox/Order.d.ts.map +1 -0
  8. package/dist/ox/Order.js +88 -0
  9. package/dist/ox/Order.js.map +1 -0
  10. package/dist/ox/OrdersFilters.d.ts +72 -0
  11. package/dist/ox/OrdersFilters.d.ts.map +1 -0
  12. package/dist/ox/OrdersFilters.js +100 -0
  13. package/dist/ox/OrdersFilters.js.map +1 -0
  14. package/dist/ox/Pagination.d.ts +128 -0
  15. package/dist/ox/Pagination.d.ts.map +1 -0
  16. package/dist/ox/Pagination.js +78 -0
  17. package/dist/ox/Pagination.js.map +1 -0
  18. package/dist/ox/PoolId.d.ts +18 -0
  19. package/dist/ox/PoolId.d.ts.map +1 -0
  20. package/dist/ox/PoolId.js +13 -0
  21. package/dist/ox/PoolId.js.map +1 -0
  22. package/dist/ox/RpcSchema.d.ts +32 -0
  23. package/dist/ox/RpcSchema.d.ts.map +1 -0
  24. package/dist/ox/RpcSchema.js +2 -0
  25. package/dist/ox/RpcSchema.js.map +1 -0
  26. package/dist/ox/SignatureEnvelope.d.ts +1 -1
  27. package/dist/ox/SignatureEnvelope.d.ts.map +1 -1
  28. package/dist/ox/SignatureEnvelope.js.map +1 -1
  29. package/dist/{viem → ox}/Tick.d.ts +4 -0
  30. package/dist/ox/Tick.d.ts.map +1 -0
  31. package/dist/ox/Tick.js.map +1 -0
  32. package/dist/ox/Transaction.d.ts.map +1 -1
  33. package/dist/ox/Transaction.js +2 -1
  34. package/dist/ox/Transaction.js.map +1 -1
  35. package/dist/ox/TransactionEnvelopeAA.d.ts +6 -6
  36. package/dist/ox/TransactionEnvelopeAA.d.ts.map +1 -1
  37. package/dist/ox/TransactionEnvelopeAA.js +4 -2
  38. package/dist/ox/TransactionEnvelopeAA.js.map +1 -1
  39. package/dist/ox/TransactionRequest.d.ts +4 -0
  40. package/dist/ox/TransactionRequest.d.ts.map +1 -1
  41. package/dist/ox/TransactionRequest.js.map +1 -1
  42. package/dist/ox/index.d.ts +6 -0
  43. package/dist/ox/index.d.ts.map +1 -1
  44. package/dist/ox/index.js +6 -0
  45. package/dist/ox/index.js.map +1 -1
  46. package/dist/prool/Instance.d.ts.map +1 -1
  47. package/dist/prool/Instance.js +20 -4
  48. package/dist/prool/Instance.js.map +1 -1
  49. package/dist/viem/Abis.d.ts +1469 -1082
  50. package/dist/viem/Abis.d.ts.map +1 -1
  51. package/dist/viem/Abis.js +932 -671
  52. package/dist/viem/Abis.js.map +1 -1
  53. package/dist/viem/Account.d.ts +150 -0
  54. package/dist/viem/Account.d.ts.map +1 -0
  55. package/dist/viem/Account.js +221 -0
  56. package/dist/viem/Account.js.map +1 -0
  57. package/dist/viem/Actions/amm.d.ts +80 -118
  58. package/dist/viem/Actions/amm.d.ts.map +1 -1
  59. package/dist/viem/Actions/amm.js +47 -116
  60. package/dist/viem/Actions/amm.js.map +1 -1
  61. package/dist/viem/Actions/dex.d.ts +889 -633
  62. package/dist/viem/Actions/dex.d.ts.map +1 -1
  63. package/dist/viem/Actions/dex.js +99 -0
  64. package/dist/viem/Actions/dex.js.map +1 -1
  65. package/dist/viem/Actions/fee.d.ts +3 -17
  66. package/dist/viem/Actions/fee.d.ts.map +1 -1
  67. package/dist/viem/Actions/fee.js.map +1 -1
  68. package/dist/viem/Actions/index.d.ts +1 -0
  69. package/dist/viem/Actions/index.d.ts.map +1 -1
  70. package/dist/viem/Actions/index.js +1 -0
  71. package/dist/viem/Actions/index.js.map +1 -1
  72. package/dist/viem/Actions/reward.d.ts +3236 -0
  73. package/dist/viem/Actions/reward.d.ts.map +1 -0
  74. package/dist/viem/Actions/reward.js +725 -0
  75. package/dist/viem/Actions/reward.js.map +1 -0
  76. package/dist/viem/Actions/token.d.ts +4295 -2646
  77. package/dist/viem/Actions/token.d.ts.map +1 -1
  78. package/dist/viem/Actions/token.js +214 -335
  79. package/dist/viem/Actions/token.js.map +1 -1
  80. package/dist/viem/Addresses.d.ts +1 -2
  81. package/dist/viem/Addresses.d.ts.map +1 -1
  82. package/dist/viem/Addresses.js +1 -2
  83. package/dist/viem/Addresses.js.map +1 -1
  84. package/dist/viem/Chain.d.ts +38 -12
  85. package/dist/viem/Chain.d.ts.map +1 -1
  86. package/dist/viem/Chain.js +27 -18
  87. package/dist/viem/Chain.js.map +1 -1
  88. package/dist/viem/Decorator.d.ts +959 -405
  89. package/dist/viem/Decorator.d.ts.map +1 -1
  90. package/dist/viem/Decorator.js +13 -5
  91. package/dist/viem/Decorator.js.map +1 -1
  92. package/dist/viem/Formatters.d.ts +8 -1
  93. package/dist/viem/Formatters.d.ts.map +1 -1
  94. package/dist/viem/Formatters.js +17 -0
  95. package/dist/viem/Formatters.js.map +1 -1
  96. package/dist/viem/P256.d.ts +2 -0
  97. package/dist/viem/P256.d.ts.map +1 -0
  98. package/dist/viem/P256.js +2 -0
  99. package/dist/viem/P256.js.map +1 -0
  100. package/dist/viem/Secp256k1.d.ts +2 -0
  101. package/dist/viem/Secp256k1.d.ts.map +1 -0
  102. package/dist/viem/Secp256k1.js +2 -0
  103. package/dist/viem/Secp256k1.js.map +1 -0
  104. package/dist/viem/TokenIds.d.ts +1 -2
  105. package/dist/viem/TokenIds.d.ts.map +1 -1
  106. package/dist/viem/TokenIds.js +1 -2
  107. package/dist/viem/TokenIds.js.map +1 -1
  108. package/dist/viem/Transaction.d.ts +1 -1
  109. package/dist/viem/Transaction.d.ts.map +1 -1
  110. package/dist/viem/Transaction.js +46 -5
  111. package/dist/viem/Transaction.js.map +1 -1
  112. package/dist/viem/WebAuthnP256.d.ts +79 -0
  113. package/dist/viem/WebAuthnP256.d.ts.map +1 -0
  114. package/dist/viem/WebAuthnP256.js +95 -0
  115. package/dist/viem/WebAuthnP256.js.map +1 -0
  116. package/dist/viem/WebCryptoP256.d.ts +2 -0
  117. package/dist/viem/WebCryptoP256.d.ts.map +1 -0
  118. package/dist/viem/WebCryptoP256.js +2 -0
  119. package/dist/viem/WebCryptoP256.js.map +1 -0
  120. package/dist/viem/index.d.ts +6 -3
  121. package/dist/viem/index.d.ts.map +1 -1
  122. package/dist/viem/index.js +6 -3
  123. package/dist/viem/index.js.map +1 -1
  124. package/dist/viem/internal/account.d.ts +24 -0
  125. package/dist/viem/internal/account.d.ts.map +1 -0
  126. package/dist/viem/internal/account.js +68 -0
  127. package/dist/viem/internal/account.js.map +1 -0
  128. package/dist/viem/internal/types.d.ts +10 -0
  129. package/dist/viem/internal/types.d.ts.map +1 -1
  130. package/dist/wagmi/Actions/amm.d.ts +428 -0
  131. package/dist/wagmi/Actions/amm.d.ts.map +1 -0
  132. package/dist/wagmi/Actions/amm.js +472 -0
  133. package/dist/wagmi/Actions/amm.js.map +1 -0
  134. package/dist/wagmi/Actions/dex.d.ts +908 -0
  135. package/dist/wagmi/Actions/dex.d.ts.map +1 -0
  136. package/dist/wagmi/Actions/dex.js +1023 -0
  137. package/dist/wagmi/Actions/dex.js.map +1 -0
  138. package/dist/wagmi/Actions/fee.d.ts +111 -0
  139. package/dist/wagmi/Actions/fee.d.ts.map +1 -0
  140. package/dist/wagmi/Actions/fee.js +126 -0
  141. package/dist/wagmi/Actions/fee.js.map +1 -0
  142. package/dist/wagmi/Actions/index.d.ts +6 -0
  143. package/dist/wagmi/Actions/index.d.ts.map +1 -0
  144. package/dist/wagmi/Actions/index.js +6 -0
  145. package/dist/wagmi/Actions/index.js.map +1 -0
  146. package/dist/wagmi/Actions/reward.d.ts +348 -0
  147. package/dist/wagmi/Actions/reward.d.ts.map +1 -0
  148. package/dist/wagmi/Actions/reward.js +388 -0
  149. package/dist/wagmi/Actions/reward.js.map +1 -0
  150. package/dist/wagmi/Actions/token.d.ts +1546 -0
  151. package/dist/wagmi/Actions/token.d.ts.map +1 -0
  152. package/dist/wagmi/Actions/token.js +1712 -0
  153. package/dist/wagmi/Actions/token.js.map +1 -0
  154. package/dist/wagmi/Connector.d.ts +73 -0
  155. package/dist/wagmi/Connector.d.ts.map +1 -0
  156. package/dist/wagmi/Connector.js +249 -0
  157. package/dist/wagmi/Connector.js.map +1 -0
  158. package/dist/wagmi/Hooks/amm.d.ts +421 -0
  159. package/dist/wagmi/Hooks/amm.d.ts.map +1 -0
  160. package/dist/wagmi/Hooks/amm.js +504 -0
  161. package/dist/wagmi/Hooks/amm.js.map +1 -0
  162. package/dist/wagmi/Hooks/dex.d.ts +816 -0
  163. package/dist/wagmi/Hooks/dex.d.ts.map +1 -0
  164. package/dist/wagmi/Hooks/dex.js +973 -0
  165. package/dist/wagmi/Hooks/dex.js.map +1 -0
  166. package/dist/wagmi/Hooks/fee.d.ts +97 -0
  167. package/dist/wagmi/Hooks/fee.d.ts.map +1 -0
  168. package/dist/wagmi/Hooks/fee.js +109 -0
  169. package/dist/wagmi/Hooks/fee.js.map +1 -0
  170. package/dist/wagmi/Hooks/index.d.ts +6 -0
  171. package/dist/wagmi/Hooks/index.d.ts.map +1 -0
  172. package/dist/wagmi/Hooks/index.js +6 -0
  173. package/dist/wagmi/Hooks/index.js.map +1 -0
  174. package/dist/wagmi/Hooks/reward.d.ts +307 -0
  175. package/dist/wagmi/Hooks/reward.d.ts.map +1 -0
  176. package/dist/wagmi/Hooks/reward.js +349 -0
  177. package/dist/wagmi/Hooks/reward.js.map +1 -0
  178. package/dist/wagmi/Hooks/token.d.ts +1388 -0
  179. package/dist/wagmi/Hooks/token.d.ts.map +1 -0
  180. package/dist/wagmi/Hooks/token.js +1657 -0
  181. package/dist/wagmi/Hooks/token.js.map +1 -0
  182. package/dist/wagmi/index.d.ts +4 -0
  183. package/dist/wagmi/index.d.ts.map +1 -0
  184. package/dist/wagmi/index.js +4 -0
  185. package/dist/wagmi/index.js.map +1 -0
  186. package/package.json +54 -10
  187. package/src/chains.ts +19 -9
  188. package/src/ox/Order.test.ts +78 -0
  189. package/src/ox/Order.ts +125 -0
  190. package/src/ox/OrdersFilters.test.ts +182 -0
  191. package/src/ox/OrdersFilters.ts +125 -0
  192. package/src/ox/Pagination.test.ts +162 -0
  193. package/src/ox/Pagination.ts +164 -0
  194. package/src/ox/PoolId.test.ts +33 -0
  195. package/src/ox/PoolId.ts +27 -0
  196. package/src/ox/RpcSchema.ts +35 -0
  197. package/src/ox/SignatureEnvelope.ts +3 -1
  198. package/src/{viem → ox}/Tick.test.ts +1 -1
  199. package/src/{viem → ox}/Tick.ts +5 -0
  200. package/src/ox/Transaction.test.ts +1 -1
  201. package/src/ox/Transaction.ts +2 -1
  202. package/src/ox/TransactionEnvelopeAA.test.ts +239 -96
  203. package/src/ox/TransactionEnvelopeAA.ts +9 -7
  204. package/src/ox/TransactionRequest.ts +4 -0
  205. package/src/ox/index.ts +6 -0
  206. package/src/prool/Instance.ts +51 -37
  207. package/src/prool/internal/chain.json +104 -52
  208. package/src/tsconfig.json +9 -0
  209. package/src/viem/Abis.ts +972 -710
  210. package/src/viem/Account.ts +279 -0
  211. package/src/viem/Actions/__snapshots__/dex.test.ts.snap +850 -0
  212. package/src/viem/Actions/amm.test.ts +98 -169
  213. package/src/viem/Actions/amm.ts +68 -155
  214. package/src/viem/Actions/dex.test.ts +563 -484
  215. package/src/viem/Actions/dex.ts +173 -0
  216. package/src/viem/Actions/fee.test.ts +23 -34
  217. package/src/viem/Actions/fee.ts +7 -0
  218. package/src/viem/Actions/index.ts +1 -0
  219. package/src/viem/Actions/policy.test.ts +19 -33
  220. package/src/viem/Actions/reward.test.ts +457 -0
  221. package/src/viem/Actions/reward.ts +999 -0
  222. package/src/viem/Actions/token.test.ts +453 -287
  223. package/src/viem/Actions/token.ts +452 -540
  224. package/src/viem/Addresses.ts +1 -2
  225. package/src/viem/Chain.ts +70 -20
  226. package/src/viem/Decorator.test.ts +2 -1
  227. package/src/viem/Decorator.ts +996 -421
  228. package/src/viem/Formatters.ts +31 -5
  229. package/src/viem/P256.ts +1 -0
  230. package/src/viem/Secp256k1.ts +1 -0
  231. package/src/viem/TokenIds.ts +1 -2
  232. package/src/viem/Transaction.ts +53 -7
  233. package/src/viem/WebAuthnP256.ts +140 -0
  234. package/src/viem/WebCryptoP256.ts +1 -0
  235. package/src/viem/e2e.test.ts +1126 -297
  236. package/src/viem/index.ts +6 -3
  237. package/src/viem/internal/account.ts +107 -0
  238. package/src/viem/internal/types.ts +9 -0
  239. package/src/wagmi/Actions/__snapshots__/dex.test.ts.snap +310 -0
  240. package/src/wagmi/Actions/amm.test.ts +198 -0
  241. package/src/wagmi/Actions/amm.ts +691 -0
  242. package/src/wagmi/Actions/dex.test.ts +1507 -0
  243. package/src/wagmi/Actions/dex.ts +1640 -0
  244. package/src/wagmi/Actions/fee.test.ts +63 -0
  245. package/src/wagmi/Actions/fee.ts +208 -0
  246. package/src/wagmi/Actions/index.ts +5 -0
  247. package/src/wagmi/Actions/reward.test.ts +210 -0
  248. package/src/wagmi/Actions/reward.ts +632 -0
  249. package/src/wagmi/Actions/token.test.ts +1308 -0
  250. package/src/wagmi/Actions/token.ts +2613 -0
  251. package/src/wagmi/Connector.test.ts +53 -0
  252. package/src/wagmi/Connector.ts +367 -0
  253. package/src/wagmi/Hooks/__snapshots__/dex.test.ts.snap +457 -0
  254. package/src/wagmi/Hooks/amm.test.ts +424 -0
  255. package/src/wagmi/Hooks/amm.ts +806 -0
  256. package/src/wagmi/Hooks/dex.test.ts +1017 -0
  257. package/src/wagmi/Hooks/dex.ts +1685 -0
  258. package/src/wagmi/Hooks/fee.test.ts +166 -0
  259. package/src/wagmi/Hooks/fee.ts +206 -0
  260. package/src/wagmi/Hooks/index.ts +5 -0
  261. package/src/wagmi/Hooks/reward.test.ts +219 -0
  262. package/src/wagmi/Hooks/reward.ts +672 -0
  263. package/src/wagmi/Hooks/token.test.ts +1670 -0
  264. package/src/wagmi/Hooks/token.ts +2906 -0
  265. package/src/wagmi/index.ts +3 -0
  266. package/src/wagmi/internal/types.ts +16 -0
  267. package/dist/viem/Client.d.ts +0 -27
  268. package/dist/viem/Client.d.ts.map +0 -1
  269. package/dist/viem/Client.js +0 -28
  270. package/dist/viem/Client.js.map +0 -1
  271. package/dist/viem/Tick.d.ts.map +0 -1
  272. package/dist/viem/Tick.js.map +0 -1
  273. package/src/viem/Client.bench-d.ts +0 -8
  274. package/src/viem/Client.test.ts +0 -178
  275. package/src/viem/Client.ts +0 -91
  276. /package/dist/{viem → ox}/Tick.js +0 -0
@@ -1,91 +1,22 @@
1
- import { Actions, Addresses, createTempoClient, Tick } from 'tempo.ts/viem'
2
- import { parseEther, publicActions } from 'viem'
3
- import { mnemonicToAccount } from 'viem/accounts'
4
- import { describe, expect, test } from 'vitest'
5
- import { tempoTest } from '../../../test/viem/config.js'
6
-
7
- const account = mnemonicToAccount(
8
- 'test test test test test test test test test test test junk',
9
- )
10
-
11
- const client = createTempoClient({
12
- account,
13
- chain: tempoTest,
14
- pollingInterval: 100,
15
- }).extend(publicActions)
16
-
17
- async function setupTokenPair() {
18
- // Create quote token
19
- const { token: quoteToken } = await Actions.token.createSync(client, {
20
- name: 'Test Quote Token',
21
- symbol: 'QUOTE',
22
- currency: 'USD',
23
- })
24
-
25
- // Create base token
26
- const { token: baseToken } = await Actions.token.createSync(client, {
27
- name: 'Test Base Token',
28
- symbol: 'BASE',
29
- currency: 'USD',
30
- quoteToken,
31
- })
32
-
33
- // Grant issuer role to mint base tokens
34
- await Actions.token.grantRolesSync(client, {
35
- token: baseToken,
36
- roles: ['issuer'],
37
- to: client.account.address,
38
- })
39
-
40
- // Grant issuer role to mint quote tokens
41
- await Actions.token.grantRolesSync(client, {
42
- token: quoteToken,
43
- roles: ['issuer'],
44
- to: client.account.address,
45
- })
46
-
47
- // Mint base tokens
48
- await Actions.token.mintSync(client, {
49
- token: baseToken,
50
- to: account.address,
51
- amount: parseEther('10000'),
52
- })
53
-
54
- // Mint quote tokens
55
- await Actions.token.mintSync(client, {
56
- token: quoteToken,
57
- to: account.address,
58
- amount: parseEther('10000'),
59
- })
60
-
61
- // Approve DEX to spend base tokens
62
- await Actions.token.approveSync(client, {
63
- token: baseToken,
64
- spender: Addresses.stablecoinExchange,
65
- amount: parseEther('10000'),
66
- })
67
-
68
- // Approve DEX to spend quote tokens
69
- await Actions.token.approveSync(client, {
70
- token: quoteToken,
71
- spender: Addresses.stablecoinExchange,
72
- amount: parseEther('10000'),
73
- })
74
-
75
- // Create the pair on the DEX
76
- return await Actions.dex.createPairSync(client, {
77
- base: baseToken,
78
- })
79
- }
1
+ import * as Address from 'ox/Address'
2
+ import { Actions, Tick } from 'tempo.ts/viem'
3
+ import { parseUnits } from 'viem'
4
+ import { beforeAll, describe, expect, test } from 'vitest'
5
+ import {
6
+ accounts,
7
+ client,
8
+ setupOrders,
9
+ setupTokenPair,
10
+ } from '../../../test/viem/config.js'
80
11
 
81
12
  describe('buy', () => {
82
13
  test('default', async () => {
83
- const { base, quote } = await setupTokenPair()
14
+ const { base, quote } = await setupTokenPair(client)
84
15
 
85
16
  // Place ask order to create liquidity
86
17
  await Actions.dex.placeSync(client, {
87
18
  token: base,
88
- amount: parseEther('500'),
19
+ amount: parseUnits('500', 6),
89
20
  type: 'sell',
90
21
  tick: Tick.fromPrice('1.001'),
91
22
  })
@@ -99,8 +30,8 @@ describe('buy', () => {
99
30
  const { receipt } = await Actions.dex.buySync(client, {
100
31
  tokenIn: quote,
101
32
  tokenOut: base,
102
- amountOut: parseEther('100'),
103
- maxAmountIn: parseEther('150'),
33
+ amountOut: parseUnits('100', 6),
34
+ maxAmountIn: parseUnits('150', 6),
104
35
  })
105
36
 
106
37
  expect(receipt).toBeDefined()
@@ -116,12 +47,12 @@ describe('buy', () => {
116
47
  })
117
48
 
118
49
  test('behavior: respects maxAmountIn', async () => {
119
- const { base, quote } = await setupTokenPair()
50
+ const { base, quote } = await setupTokenPair(client)
120
51
 
121
52
  // Place ask order at high price
122
53
  await Actions.dex.placeSync(client, {
123
54
  token: base,
124
- amount: parseEther('500'),
55
+ amount: parseUnits('500', 6),
125
56
  type: 'sell',
126
57
  tick: Tick.fromPrice('1.01'), // 1% above peg
127
58
  })
@@ -131,27 +62,14 @@ describe('buy', () => {
131
62
  Actions.dex.buySync(client, {
132
63
  tokenIn: quote,
133
64
  tokenOut: base,
134
- amountOut: parseEther('100'),
135
- maxAmountIn: parseEther('50'), // Way too low for 1% premium
65
+ amountOut: parseUnits('100', 6),
66
+ maxAmountIn: parseUnits('50', 6), // Way too low for 1% premium
136
67
  }),
137
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
138
- [ContractFunctionExecutionError: The contract function "swapExactAmountOut" reverted.
139
-
140
- Error: MaxInputExceeded()
141
-
142
- Contract Call:
143
- address: 0xdec0000000000000000000000000000000000000
144
- function: swapExactAmountOut(address tokenIn, address tokenOut, uint128 amountOut, uint128 maxAmountIn)
145
- args: (0x20C0000000000000000000000000000000000004, 0x20c0000000000000000000000000000000000005, 100000000000000000000, 50000000000000000000)
146
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
147
-
148
- Docs: https://viem.sh/docs/contract/writeContract
149
- Version: viem@2.38.3]
150
- `)
68
+ ).rejects.toThrow('The contract function "swapExactAmountOut" reverted')
151
69
  })
152
70
 
153
71
  test('behavior: fails with insufficient liquidity', async () => {
154
- const { base, quote } = await setupTokenPair()
72
+ const { base, quote } = await setupTokenPair(client)
155
73
 
156
74
  // Don't place any orders - no liquidity
157
75
 
@@ -160,89 +78,71 @@ describe('buy', () => {
160
78
  Actions.dex.buySync(client, {
161
79
  tokenIn: quote,
162
80
  tokenOut: base,
163
- amountOut: parseEther('100'),
164
- maxAmountIn: parseEther('150'),
81
+ amountOut: parseUnits('100', 6),
82
+ maxAmountIn: parseUnits('150', 6),
165
83
  }),
166
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
167
- [ContractFunctionExecutionError: The contract function "swapExactAmountOut" reverted.
168
-
169
- Error: InsufficientLiquidity()
170
-
171
- Contract Call:
172
- address: 0xdec0000000000000000000000000000000000000
173
- function: swapExactAmountOut(address tokenIn, address tokenOut, uint128 amountOut, uint128 maxAmountIn)
174
- args: (0x20C0000000000000000000000000000000000004, 0x20c0000000000000000000000000000000000005, 100000000000000000000, 150000000000000000000)
175
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
176
-
177
- Docs: https://viem.sh/docs/contract/writeContract
178
- Version: viem@2.38.3]
179
- `)
84
+ ).rejects.toThrow('The contract function "swapExactAmountOut" reverted')
180
85
  })
181
86
  })
182
87
 
183
88
  describe('cancel', () => {
184
89
  test('default', async () => {
185
- const { base, quote } = await setupTokenPair()
90
+ const { base, quote } = await setupTokenPair(client)
186
91
 
187
92
  // Place a bid order
188
93
  const { orderId } = await Actions.dex.placeSync(client, {
189
94
  token: base,
190
- amount: parseEther('100'),
95
+ amount: parseUnits('100', 6),
191
96
  type: 'buy',
192
97
  tick: Tick.fromPrice('1.001'),
193
98
  })
194
99
 
195
100
  // Check initial DEX balance (should be 0)
196
101
  const dexBalanceBefore = await Actions.dex.getBalance(client, {
197
- account: account.address,
102
+ account: client.account.address,
198
103
  token: quote,
199
104
  })
200
105
  expect(dexBalanceBefore).toBe(0n)
201
106
 
202
107
  // Cancel the order
203
- const { receipt, ...result } = await Actions.dex.cancelSync(client, {
204
- orderId,
205
- })
108
+ const { receipt, orderId: returnedOrderId } = await Actions.dex.cancelSync(
109
+ client,
110
+ {
111
+ orderId,
112
+ },
113
+ )
206
114
 
207
115
  expect(receipt).toBeDefined()
208
116
  expect(receipt.status).toBe('success')
209
- expect(result.orderId).toBe(orderId)
210
- expect(result).toMatchInlineSnapshot(`
211
- {
212
- "orderId": 1n,
213
- }
214
- `)
117
+ expect(returnedOrderId).toBe(orderId)
215
118
 
216
119
  // Check DEX balance after cancel - tokens should be refunded to internal balance
217
120
  const dexBalanceAfter = await Actions.dex.getBalance(client, {
218
- account: account.address,
121
+ account: client.account.address,
219
122
  token: quote,
220
123
  })
221
124
  expect(dexBalanceAfter).toBeGreaterThan(0n)
222
125
  })
223
126
 
224
127
  test('behavior: only maker can cancel', async () => {
225
- const { base } = await setupTokenPair()
128
+ const { base } = await setupTokenPair(client)
226
129
 
227
130
  // Account places order
228
131
  const { orderId } = await Actions.dex.placeSync(client, {
229
132
  token: base,
230
- amount: parseEther('100'),
133
+ amount: parseUnits('100', 6),
231
134
  type: 'buy',
232
135
  tick: Tick.fromPrice('1.001'),
233
136
  })
234
137
 
235
138
  // Create another account
236
- const account2 = mnemonicToAccount(
237
- 'test test test test test test test test test test test junk',
238
- { accountIndex: 1 },
239
- )
139
+ const account2 = accounts[1]
240
140
 
241
141
  // Transfer gas to account2
242
142
  await Actions.token.transferSync(client, {
243
143
  to: account2.address,
244
- amount: parseEther('1'),
245
- token: Addresses.defaultFeeToken,
144
+ amount: parseUnits('1', 6),
145
+ token: 1n,
246
146
  })
247
147
 
248
148
  // Account2 tries to cancel - should fail
@@ -251,44 +151,18 @@ describe('cancel', () => {
251
151
  account: account2,
252
152
  orderId,
253
153
  }),
254
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
255
- [ContractFunctionExecutionError: The contract function "cancel" reverted.
256
-
257
- Error: Unauthorized()
258
-
259
- Contract Call:
260
- address: 0xdec0000000000000000000000000000000000000
261
- function: cancel(uint128 orderId)
262
- args: (1)
263
- sender: 0x8C8d35429F74ec245F8Ef2f4Fd1e551cFF97d650
264
-
265
- Docs: https://viem.sh/docs/contract/writeContract
266
- Version: viem@2.38.3]
267
- `)
154
+ ).rejects.toThrow('The contract function "cancel" reverted')
268
155
  })
269
156
 
270
157
  test('behavior: cannot cancel non-existent order', async () => {
271
- await setupTokenPair()
158
+ await setupTokenPair(client)
272
159
 
273
160
  // Try to cancel an order that doesn't exist
274
161
  await expect(
275
162
  Actions.dex.cancelSync(client, {
276
163
  orderId: 999n,
277
164
  }),
278
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
279
- [ContractFunctionExecutionError: The contract function "cancel" reverted.
280
-
281
- Error: OrderDoesNotExist()
282
-
283
- Contract Call:
284
- address: 0xdec0000000000000000000000000000000000000
285
- function: cancel(uint128 orderId)
286
- args: (999)
287
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
288
-
289
- Docs: https://viem.sh/docs/contract/writeContract
290
- Version: viem@2.38.3]
291
- `)
165
+ ).rejects.toThrow('The contract function "cancel" reverted')
292
166
  })
293
167
  })
294
168
 
@@ -300,31 +174,28 @@ describe('createPair', () => {
300
174
  currency: 'USD',
301
175
  })
302
176
 
303
- const { receipt, ...result } = await Actions.dex.createPairSync(client, {
304
- base: baseToken,
305
- })
177
+ const { receipt, key, base, quote } = await Actions.dex.createPairSync(
178
+ client,
179
+ {
180
+ base: baseToken,
181
+ },
182
+ )
306
183
 
307
184
  expect(receipt).toBeDefined()
308
185
  expect(receipt.status).toBe('success')
309
-
310
- const { key, ...rest } = result
311
186
  expect(key).toBeDefined()
312
- expect(rest).toMatchInlineSnapshot(`
313
- {
314
- "base": "0x20C0000000000000000000000000000000000004",
315
- "quote": "0x20C0000000000000000000000000000000000000",
316
- }
317
- `)
187
+ expect(base).toBe(baseToken)
188
+ expect(quote).toBeDefined()
318
189
  })
319
190
  })
320
191
 
321
192
  describe('getBalance', () => {
322
193
  test('default', async () => {
323
- const { base, quote } = await setupTokenPair()
194
+ const { base, quote } = await setupTokenPair(client)
324
195
 
325
196
  // Initial balance should be 0
326
197
  const initialBalance = await Actions.dex.getBalance(client, {
327
- account: account.address,
198
+ account: client.account.address,
328
199
  token: quote,
329
200
  })
330
201
  expect(initialBalance).toBe(0n)
@@ -332,7 +203,7 @@ describe('getBalance', () => {
332
203
  // Place and cancel order to create internal balance
333
204
  const { orderId } = await Actions.dex.placeSync(client, {
334
205
  token: base,
335
- amount: parseEther('50'),
206
+ amount: parseUnits('50', 6),
336
207
  type: 'buy',
337
208
  tick: Tick.fromPrice('1.0005'),
338
209
  })
@@ -343,19 +214,16 @@ describe('getBalance', () => {
343
214
 
344
215
  // Now balance should be > 0 (refunded quote tokens)
345
216
  const balance = await Actions.dex.getBalance(client, {
346
- account: account.address,
217
+ account: client.account.address,
347
218
  token: quote,
348
219
  })
349
220
  expect(balance).toBeGreaterThan(0n)
350
221
  })
351
222
 
352
223
  test('behavior: check different account', async () => {
353
- const { quote } = await setupTokenPair()
224
+ const { quote } = await setupTokenPair(client)
354
225
 
355
- const account2 = mnemonicToAccount(
356
- 'test test test test test test test test test test test junk',
357
- { accountIndex: 1 },
358
- )
226
+ const account2 = accounts[1]
359
227
 
360
228
  // Check account2's balance (should be 0)
361
229
  const balance = await Actions.dex.getBalance(client, {
@@ -366,12 +234,12 @@ describe('getBalance', () => {
366
234
  })
367
235
 
368
236
  test('behavior: balances are per-token', async () => {
369
- const { base, quote } = await setupTokenPair()
237
+ const { base, quote } = await setupTokenPair(client)
370
238
 
371
239
  // Create balance in quote token
372
240
  const { orderId } = await Actions.dex.placeSync(client, {
373
241
  token: base,
374
- amount: parseEther('100'),
242
+ amount: parseUnits('100', 6),
375
243
  type: 'buy',
376
244
  tick: Tick.fromPrice('1.001'),
377
245
  })
@@ -379,14 +247,14 @@ describe('getBalance', () => {
379
247
 
380
248
  // Check quote balance (should have refunded tokens)
381
249
  const quoteBalance = await Actions.dex.getBalance(client, {
382
- account: account.address,
250
+ account: client.account.address,
383
251
  token: quote,
384
252
  })
385
253
  expect(quoteBalance).toBeGreaterThan(0n)
386
254
 
387
255
  // Check base balance (should still be 0)
388
256
  const baseBalance = await Actions.dex.getBalance(client, {
389
- account: account.address,
257
+ account: client.account.address,
390
258
  token: base,
391
259
  })
392
260
  expect(baseBalance).toBe(0n)
@@ -395,12 +263,12 @@ describe('getBalance', () => {
395
263
 
396
264
  describe('getBuyQuote', () => {
397
265
  test('default', async () => {
398
- const { base, quote } = await setupTokenPair()
266
+ const { base, quote } = await setupTokenPair(client)
399
267
 
400
268
  // Place ask orders to create liquidity
401
269
  await Actions.dex.placeSync(client, {
402
270
  token: base,
403
- amount: parseEther('500'),
271
+ amount: parseUnits('500', 6),
404
272
  type: 'sell',
405
273
  tick: Tick.fromPrice('1.001'),
406
274
  })
@@ -409,16 +277,16 @@ describe('getBuyQuote', () => {
409
277
  const amountIn = await Actions.dex.getBuyQuote(client, {
410
278
  tokenIn: quote,
411
279
  tokenOut: base,
412
- amountOut: parseEther('100'),
280
+ amountOut: parseUnits('100', 6),
413
281
  })
414
282
 
415
283
  expect(amountIn).toBeGreaterThan(0n)
416
284
  // Should be approximately 100 * 1.001 = 100.1
417
- expect(amountIn).toBeGreaterThan(parseEther('100'))
285
+ expect(amountIn).toBeGreaterThan(parseUnits('100', 6))
418
286
  })
419
287
 
420
288
  test('behavior: fails with no liquidity', async () => {
421
- const { base, quote } = await setupTokenPair()
289
+ const { base, quote } = await setupTokenPair(client)
422
290
 
423
291
  // No orders placed - no liquidity
424
292
 
@@ -427,32 +295,22 @@ describe('getBuyQuote', () => {
427
295
  Actions.dex.getBuyQuote(client, {
428
296
  tokenIn: quote,
429
297
  tokenOut: base,
430
- amountOut: parseEther('100'),
298
+ amountOut: parseUnits('100', 6),
431
299
  }),
432
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
433
- [ContractFunctionExecutionError: The contract function "quoteSwapExactAmountOut" reverted.
434
-
435
- Error: InsufficientLiquidity()
436
-
437
- Contract Call:
438
- address: 0xdec0000000000000000000000000000000000000
439
- function: quoteSwapExactAmountOut(address tokenIn, address tokenOut, uint128 amountOut)
440
- args: (0x20C0000000000000000000000000000000000004, 0x20c0000000000000000000000000000000000005, 100000000000000000000)
441
-
442
- Docs: https://viem.sh/docs/contract/readContract
443
- Version: viem@2.38.3]
444
- `)
300
+ ).rejects.toThrow(
301
+ 'The contract function "quoteSwapExactAmountOut" reverted',
302
+ )
445
303
  })
446
304
  })
447
305
 
448
306
  describe('getOrder', () => {
449
307
  test('default', async () => {
450
- const { base } = await setupTokenPair()
308
+ const { base } = await setupTokenPair(client)
451
309
 
452
310
  // Place an order to get an order ID
453
311
  const { orderId } = await Actions.dex.placeSync(client, {
454
312
  token: base,
455
- amount: parseEther('100'),
313
+ amount: parseUnits('100', 6),
456
314
  type: 'buy',
457
315
  tick: Tick.fromPrice('1.001'),
458
316
  })
@@ -466,18 +324,18 @@ describe('getOrder', () => {
466
324
  expect(order.maker).toBe(client.account.address)
467
325
  expect(order.isBid).toBe(true)
468
326
  expect(order.tick).toBe(Tick.fromPrice('1.001'))
469
- expect(order.amount).toBe(parseEther('100'))
470
- expect(order.remaining).toBe(parseEther('100'))
327
+ expect(order.amount).toBe(parseUnits('100', 6))
328
+ expect(order.remaining).toBe(parseUnits('100', 6))
471
329
  expect(order.isFlip).toBe(false)
472
330
  })
473
331
 
474
332
  test('behavior: returns flip order details', async () => {
475
- const { base } = await setupTokenPair()
333
+ const { base } = await setupTokenPair(client)
476
334
 
477
335
  // Place a flip order
478
336
  const { orderId } = await Actions.dex.placeFlipSync(client, {
479
337
  token: base,
480
- amount: parseEther('50'),
338
+ amount: parseUnits('50', 6),
481
339
  type: 'buy',
482
340
  tick: Tick.fromPrice('1.001'),
483
341
  flipTick: Tick.fromPrice('1.002'),
@@ -492,41 +350,29 @@ describe('getOrder', () => {
492
350
  expect(order.maker).toBe(client.account.address)
493
351
  expect(order.isBid).toBe(true)
494
352
  expect(order.tick).toBe(Tick.fromPrice('1.001'))
495
- expect(order.amount).toBe(parseEther('50'))
353
+ expect(order.amount).toBe(parseUnits('50', 6))
496
354
  expect(order.isFlip).toBe(true)
497
355
  expect(order.flipTick).toBe(Tick.fromPrice('1.002'))
498
356
  })
499
357
 
500
358
  test('behavior: fails for non-existent order', async () => {
501
- await setupTokenPair()
359
+ await setupTokenPair(client)
502
360
 
503
361
  // Try to get an order that doesn't exist
504
362
  await expect(
505
363
  Actions.dex.getOrder(client, {
506
364
  orderId: 999n,
507
365
  }),
508
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
509
- [ContractFunctionExecutionError: The contract function "getOrder" reverted.
510
-
511
- Error: OrderDoesNotExist()
512
-
513
- Contract Call:
514
- address: 0xdec0000000000000000000000000000000000000
515
- function: getOrder(uint128 orderId)
516
- args: (999)
517
-
518
- Docs: https://viem.sh/docs/contract/readContract
519
- Version: viem@2.38.3]
520
- `)
366
+ ).rejects.toThrow('The contract function "getOrder" reverted')
521
367
  })
522
368
 
523
369
  test('behavior: reflects order state after partial fill', async () => {
524
- const { base, quote } = await setupTokenPair()
370
+ const { base, quote } = await setupTokenPair(client)
525
371
 
526
372
  // Place a large sell order
527
373
  const { orderId } = await Actions.dex.placeSync(client, {
528
374
  token: base,
529
- amount: parseEther('500'),
375
+ amount: parseUnits('500', 6),
530
376
  type: 'sell',
531
377
  tick: Tick.fromPrice('1.001'),
532
378
  })
@@ -535,34 +381,34 @@ describe('getOrder', () => {
535
381
  const orderBefore = await Actions.dex.getOrder(client, {
536
382
  orderId,
537
383
  })
538
- expect(orderBefore.amount).toBe(parseEther('500'))
539
- expect(orderBefore.remaining).toBe(parseEther('500'))
384
+ expect(orderBefore.amount).toBe(parseUnits('500', 6))
385
+ expect(orderBefore.remaining).toBe(parseUnits('500', 6))
540
386
 
541
387
  // Partially fill the order with a buy
542
388
  await Actions.dex.buySync(client, {
543
389
  tokenIn: quote,
544
390
  tokenOut: base,
545
- amountOut: parseEther('100'),
546
- maxAmountIn: parseEther('150'),
391
+ amountOut: parseUnits('100', 6),
392
+ maxAmountIn: parseUnits('150', 6),
547
393
  })
548
394
 
549
395
  // Get order state after partial fill
550
396
  const orderAfter = await Actions.dex.getOrder(client, {
551
397
  orderId,
552
398
  })
553
- expect(orderAfter.amount).toBe(parseEther('500')) // amount unchanged
554
- expect(orderAfter.remaining).toBeLessThan(parseEther('500')) // remaining decreased
399
+ expect(orderAfter.amount).toBe(parseUnits('500', 6)) // amount unchanged
400
+ expect(orderAfter.remaining).toBeLessThan(parseUnits('500', 6)) // remaining decreased
555
401
  })
556
402
 
557
403
  test('behavior: linked list pointers for multiple orders at same tick', async () => {
558
- const { base } = await setupTokenPair()
404
+ const { base } = await setupTokenPair(client)
559
405
 
560
406
  const tick = Tick.fromPrice('1.001')
561
407
 
562
408
  // Place first order
563
409
  const { orderId: orderId1 } = await Actions.dex.placeSync(client, {
564
410
  token: base,
565
- amount: parseEther('100'),
411
+ amount: parseUnits('100', 6),
566
412
  type: 'buy',
567
413
  tick,
568
414
  })
@@ -570,7 +416,7 @@ describe('getOrder', () => {
570
416
  // Place second order at same tick
571
417
  const { orderId: orderId2 } = await Actions.dex.placeSync(client, {
572
418
  token: base,
573
- amount: parseEther('50'),
419
+ amount: parseUnits('50', 6),
574
420
  type: 'buy',
575
421
  tick,
576
422
  })
@@ -591,16 +437,364 @@ describe('getOrder', () => {
591
437
  })
592
438
  })
593
439
 
440
+ describe('getOrders', () => {
441
+ let bases: Address.Address[] = []
442
+ beforeAll(async () => {
443
+ ;({ bases } = await setupOrders(client))
444
+ })
445
+
446
+ test('default', async () => {
447
+ // Get orders with default pagination
448
+ const response = await Actions.dex.getOrders(client, {
449
+ limit: 10,
450
+ })
451
+
452
+ expect(response).matchSnapshot()
453
+
454
+ // Get orders with cursor
455
+ const response2 = await Actions.dex.getOrders(client, {
456
+ cursor: response.nextCursor!,
457
+ limit: 10,
458
+ })
459
+
460
+ expect(response2).matchSnapshot()
461
+ })
462
+
463
+ test.skip('behavior: filter by baseToken', async () => {
464
+ // Get orders filtered by base1
465
+ const response = await Actions.dex.getOrders(client, {
466
+ filters: {
467
+ baseToken: bases[0],
468
+ },
469
+ limit: 5,
470
+ })
471
+
472
+ // Verify all orders match the filter
473
+ expect(response.orders.length).toBeGreaterThan(0)
474
+ expect(response.orders.every((order) => order.baseToken === bases[0])).toBe(
475
+ true,
476
+ )
477
+
478
+ expect(response).matchSnapshot()
479
+ })
480
+
481
+ test('behavior: filter by isBid', async () => {
482
+ // Get only buy orders
483
+ const buyOrders = await Actions.dex.getOrders(client, {
484
+ filters: {
485
+ isBid: true,
486
+ },
487
+ limit: 5,
488
+ })
489
+
490
+ // Verify all orders are buy orders
491
+ expect(buyOrders.orders.length).toBeGreaterThan(0)
492
+ expect(buyOrders.orders.every((order) => order.isBid === true)).toBe(true)
493
+
494
+ expect(buyOrders).matchSnapshot()
495
+
496
+ // Get only sell orders
497
+ const sellOrders = await Actions.dex.getOrders(client, {
498
+ filters: {
499
+ isBid: false,
500
+ },
501
+ limit: 5,
502
+ })
503
+
504
+ // Verify all orders are sell orders
505
+ expect(sellOrders.orders.length).toBeGreaterThan(0)
506
+ expect(sellOrders.orders.every((order) => order.isBid === false)).toBe(true)
507
+
508
+ expect(sellOrders).matchSnapshot()
509
+ })
510
+
511
+ test('behavior: filter by maker', async () => {
512
+ // Filter by account's address
513
+ const response = await Actions.dex.getOrders(client, {
514
+ filters: {
515
+ maker: client.account.address,
516
+ },
517
+ limit: 5,
518
+ })
519
+
520
+ // Verify all orders are from the maker
521
+ expect(response.orders.length).toBeGreaterThan(0)
522
+ expect(
523
+ response.orders.every((order) =>
524
+ Address.isEqual(order.maker, client.account.address),
525
+ ),
526
+ ).toBe(true)
527
+
528
+ expect(response).matchSnapshot()
529
+ })
530
+
531
+ test('behavior: filter by isFlip', async () => {
532
+ // Get only non-flip orders (setupOrders creates non-flip orders)
533
+ const response = await Actions.dex.getOrders(client, {
534
+ filters: {
535
+ isFlip: false,
536
+ },
537
+ limit: 5,
538
+ })
539
+
540
+ // Verify all orders are non-flip orders
541
+ expect(response.orders.length).toBeGreaterThan(0)
542
+ expect(response.orders.every((order) => order.isFlip === false)).toBe(true)
543
+
544
+ expect(response).matchSnapshot()
545
+ })
546
+
547
+ test('behavior: filter by remaining range', async () => {
548
+ // Get orders with remaining between 100 and 300
549
+ const response = await Actions.dex.getOrders(client, {
550
+ filters: {
551
+ remaining: {
552
+ min: parseUnits('100', 6),
553
+ max: parseUnits('300', 6),
554
+ },
555
+ },
556
+ limit: 5,
557
+ })
558
+
559
+ // Verify all orders are within the range
560
+ expect(response.orders.length).toBeGreaterThan(0)
561
+ expect(
562
+ response.orders.every(
563
+ (order) =>
564
+ order.remaining >= parseUnits('100', 6) &&
565
+ order.remaining <= parseUnits('300', 6),
566
+ ),
567
+ ).toBe(true)
568
+
569
+ expect(response).matchSnapshot()
570
+ })
571
+
572
+ test('behavior: filter by tick range', async () => {
573
+ // Get orders with tick between -100 and 100
574
+ const response = await Actions.dex.getOrders(client, {
575
+ filters: {
576
+ tick: {
577
+ min: -100,
578
+ max: 100,
579
+ },
580
+ },
581
+ limit: 5,
582
+ })
583
+
584
+ // Verify all orders are within the tick range
585
+ expect(response.orders.length).toBeGreaterThan(0)
586
+ expect(
587
+ response.orders.every((order) => order.tick >= -100 && order.tick <= 100),
588
+ ).toBe(true)
589
+
590
+ expect(response).matchSnapshot()
591
+ })
592
+
593
+ test('behavior: multiple filters combined', async () => {
594
+ // Filter by multiple conditions
595
+ const response = await Actions.dex.getOrders(client, {
596
+ filters: {
597
+ baseToken: bases[0],
598
+ isBid: true,
599
+ },
600
+ limit: 5,
601
+ })
602
+
603
+ // Verify all orders match all filters
604
+ expect(response.orders.length).toBeGreaterThan(0)
605
+ expect(
606
+ response.orders.every(
607
+ (order) => order.baseToken === bases[0] && order.isBid === true,
608
+ ),
609
+ ).toBe(true)
610
+
611
+ expect(response).matchSnapshot()
612
+ })
613
+
614
+ test('behavior: empty result', async () => {
615
+ await setupTokenPair(client)
616
+
617
+ // Get orders with filter that matches nothing
618
+ const response = await Actions.dex.getOrders(client, {
619
+ filters: {
620
+ maker: '0x0000000000000000000000000000000000000001',
621
+ },
622
+ })
623
+
624
+ // Verify empty result
625
+ expect(response.orders).toHaveLength(0)
626
+ expect(response.nextCursor).toBeNull()
627
+
628
+ expect(response).matchSnapshot()
629
+ })
630
+ })
631
+
632
+ describe('getOrderbook', () => {
633
+ test('default', async () => {
634
+ const { base, quote } = await setupTokenPair(client)
635
+
636
+ // Get orderbook information
637
+ const book = await Actions.dex.getOrderbook(client, {
638
+ base,
639
+ quote,
640
+ })
641
+
642
+ expect(book).toBeDefined()
643
+ expect(book.base).toBe(base)
644
+ expect(book.quote).toBe(quote)
645
+ expect(book.bestBidTick).toBeDefined()
646
+ expect(book.bestAskTick).toBeDefined()
647
+ })
648
+
649
+ test('behavior: shows best bid and ask after orders placed', async () => {
650
+ const { base, quote } = await setupTokenPair(client)
651
+
652
+ const bidTick = Tick.fromPrice('0.999')
653
+ const askTick = Tick.fromPrice('1.001')
654
+
655
+ // Place a bid order
656
+ await Actions.dex.placeSync(client, {
657
+ token: base,
658
+ amount: parseUnits('100', 6),
659
+ type: 'buy',
660
+ tick: bidTick,
661
+ })
662
+
663
+ // Place an ask order
664
+ await Actions.dex.placeSync(client, {
665
+ token: base,
666
+ amount: parseUnits('100', 6),
667
+ type: 'sell',
668
+ tick: askTick,
669
+ })
670
+
671
+ // Get orderbook
672
+ const book = await Actions.dex.getOrderbook(client, {
673
+ base,
674
+ quote,
675
+ })
676
+
677
+ expect(book.bestBidTick).toBe(bidTick)
678
+ expect(book.bestAskTick).toBe(askTick)
679
+ })
680
+
681
+ test('behavior: best ticks update after better orders placed', async () => {
682
+ const { base, quote } = await setupTokenPair(client)
683
+
684
+ // Place initial bid at 0.999
685
+ await Actions.dex.placeSync(client, {
686
+ token: base,
687
+ amount: parseUnits('100', 6),
688
+ type: 'buy',
689
+ tick: Tick.fromPrice('0.999'),
690
+ })
691
+
692
+ // Get orderbook
693
+ const bookBefore = await Actions.dex.getOrderbook(client, {
694
+ base,
695
+ quote,
696
+ })
697
+ expect(bookBefore.bestBidTick).toBe(Tick.fromPrice('0.999'))
698
+
699
+ // Place better bid at 1.0
700
+ await Actions.dex.placeSync(client, {
701
+ token: base,
702
+ amount: parseUnits('100', 6),
703
+ type: 'buy',
704
+ tick: Tick.fromPrice('1.0'),
705
+ })
706
+
707
+ // Get orderbook again
708
+ const bookAfter = await Actions.dex.getOrderbook(client, {
709
+ base,
710
+ quote,
711
+ })
712
+ expect(bookAfter.bestBidTick).toBe(Tick.fromPrice('1.0'))
713
+ })
714
+
715
+ test.skip('behavior: best ticks update after order cancellation', async () => {
716
+ const { base, quote } = await setupTokenPair(client)
717
+
718
+ // Place two bid orders at different ticks
719
+ await Actions.dex.placeSync(client, {
720
+ token: base,
721
+ amount: parseUnits('50', 6),
722
+ type: 'buy',
723
+ tick: Tick.fromPrice('0.999'),
724
+ })
725
+
726
+ const { orderId } = await Actions.dex.placeSync(client, {
727
+ token: base,
728
+ amount: parseUnits('100', 6),
729
+ type: 'buy',
730
+ tick: Tick.fromPrice('1.0'),
731
+ })
732
+
733
+ // Get orderbook - best bid should be 1.0
734
+ const bookBefore = await Actions.dex.getOrderbook(client, {
735
+ base,
736
+ quote,
737
+ })
738
+ expect(bookBefore.bestBidTick).toBe(Tick.fromPrice('1.0'))
739
+
740
+ // Cancel the better order
741
+ await Actions.dex.cancelSync(client, { orderId })
742
+
743
+ // Get orderbook again - best bid should fall back to 0.999
744
+ const bookAfter = await Actions.dex.getOrderbook(client, {
745
+ base,
746
+ quote,
747
+ })
748
+ expect(bookAfter.bestBidTick).toBe(Tick.fromPrice('0.999'))
749
+ })
750
+
751
+ test('behavior: multiple pairs have independent orderbooks', async () => {
752
+ const { base: base1, quote: quote1 } = await setupTokenPair(client)
753
+ const { base: base2, quote: quote2 } = await setupTokenPair(client)
754
+
755
+ // Place order on first pair
756
+ await Actions.dex.placeSync(client, {
757
+ token: base1,
758
+ amount: parseUnits('100', 6),
759
+ type: 'buy',
760
+ tick: Tick.fromPrice('1.001'),
761
+ })
762
+
763
+ // Place order on second pair at different tick
764
+ await Actions.dex.placeSync(client, {
765
+ token: base2,
766
+ amount: parseUnits('100', 6),
767
+ type: 'buy',
768
+ tick: Tick.fromPrice('0.999'),
769
+ })
770
+
771
+ // Get orderbooks
772
+ const book1 = await Actions.dex.getOrderbook(client, {
773
+ base: base1,
774
+ quote: quote1,
775
+ })
776
+
777
+ const book2 = await Actions.dex.getOrderbook(client, {
778
+ base: base2,
779
+ quote: quote2,
780
+ })
781
+
782
+ // Each pair should have its own best tick
783
+ expect(book1.bestBidTick).toBe(Tick.fromPrice('1.001'))
784
+ expect(book2.bestBidTick).toBe(Tick.fromPrice('0.999'))
785
+ })
786
+ })
787
+
594
788
  describe('getPriceLevel', () => {
595
789
  test('default', async () => {
596
- const { base } = await setupTokenPair()
790
+ const { base } = await setupTokenPair(client)
597
791
 
598
792
  const tick = Tick.fromPrice('1.001')
599
793
 
600
794
  // Place an order to create liquidity at this tick
601
795
  const { orderId } = await Actions.dex.placeSync(client, {
602
796
  token: base,
603
- amount: parseEther('100'),
797
+ amount: parseUnits('100', 6),
604
798
  type: 'buy',
605
799
  tick,
606
800
  })
@@ -619,7 +813,7 @@ describe('getPriceLevel', () => {
619
813
  })
620
814
 
621
815
  test('behavior: empty price level', async () => {
622
- const { base } = await setupTokenPair()
816
+ const { base } = await setupTokenPair(client)
623
817
 
624
818
  const tick = Tick.fromPrice('1.001')
625
819
 
@@ -637,14 +831,14 @@ describe('getPriceLevel', () => {
637
831
  })
638
832
 
639
833
  test('behavior: multiple orders at same tick', async () => {
640
- const { base } = await setupTokenPair()
834
+ const { base } = await setupTokenPair(client)
641
835
 
642
836
  const tick = Tick.fromPrice('1.001')
643
837
 
644
838
  // Place first order
645
839
  const { orderId: orderId1 } = await Actions.dex.placeSync(client, {
646
840
  token: base,
647
- amount: parseEther('100'),
841
+ amount: parseUnits('100', 6),
648
842
  type: 'buy',
649
843
  tick,
650
844
  })
@@ -652,7 +846,7 @@ describe('getPriceLevel', () => {
652
846
  // Place second order at same tick
653
847
  const { orderId: orderId2 } = await Actions.dex.placeSync(client, {
654
848
  token: base,
655
- amount: parseEther('50'),
849
+ amount: parseUnits('50', 6),
656
850
  type: 'buy',
657
851
  tick,
658
852
  })
@@ -667,18 +861,18 @@ describe('getPriceLevel', () => {
667
861
  expect(level.head).toBe(orderId1) // head should be first order
668
862
  expect(level.tail).toBe(orderId2) // tail should be last order
669
863
  // Total liquidity should be sum of both orders (approximately)
670
- expect(level.totalLiquidity).toBeGreaterThan(parseEther('145'))
864
+ expect(level.totalLiquidity).toBeGreaterThan(parseUnits('145', 6))
671
865
  })
672
866
 
673
867
  test('behavior: bid vs ask sides', async () => {
674
- const { base } = await setupTokenPair()
868
+ const { base } = await setupTokenPair(client)
675
869
 
676
870
  const tick = Tick.fromPrice('1.001')
677
871
 
678
872
  // Place a buy order (bid)
679
873
  await Actions.dex.placeSync(client, {
680
874
  token: base,
681
- amount: parseEther('100'),
875
+ amount: parseUnits('100', 6),
682
876
  type: 'buy',
683
877
  tick,
684
878
  })
@@ -686,7 +880,7 @@ describe('getPriceLevel', () => {
686
880
  // Place a sell order (ask) at same tick
687
881
  await Actions.dex.placeSync(client, {
688
882
  token: base,
689
- amount: parseEther('50'),
883
+ amount: parseUnits('50', 6),
690
884
  type: 'sell',
691
885
  tick,
692
886
  })
@@ -712,21 +906,21 @@ describe('getPriceLevel', () => {
712
906
  })
713
907
 
714
908
  test('behavior: liquidity changes after order cancellation', async () => {
715
- const { base } = await setupTokenPair()
909
+ const { base } = await setupTokenPair(client)
716
910
 
717
911
  const tick = Tick.fromPrice('1.001')
718
912
 
719
913
  // Place orders
720
914
  const { orderId: orderId1 } = await Actions.dex.placeSync(client, {
721
915
  token: base,
722
- amount: parseEther('100'),
916
+ amount: parseUnits('100', 6),
723
917
  type: 'buy',
724
918
  tick,
725
919
  })
726
920
 
727
921
  await Actions.dex.placeSync(client, {
728
922
  token: base,
729
- amount: parseEther('50'),
923
+ amount: parseUnits('50', 6),
730
924
  type: 'buy',
731
925
  tick,
732
926
  })
@@ -755,14 +949,14 @@ describe('getPriceLevel', () => {
755
949
  })
756
950
 
757
951
  test('behavior: liquidity changes after partial fill', async () => {
758
- const { base, quote } = await setupTokenPair()
952
+ const { base, quote } = await setupTokenPair(client)
759
953
 
760
954
  const tick = Tick.fromPrice('1.001')
761
955
 
762
956
  // Place sell order
763
957
  await Actions.dex.placeSync(client, {
764
958
  token: base,
765
- amount: parseEther('500'),
959
+ amount: parseUnits('500', 6),
766
960
  type: 'sell',
767
961
  tick,
768
962
  })
@@ -778,8 +972,8 @@ describe('getPriceLevel', () => {
778
972
  await Actions.dex.buySync(client, {
779
973
  tokenIn: quote,
780
974
  tokenOut: base,
781
- amountOut: parseEther('100'),
782
- maxAmountIn: parseEther('150'),
975
+ amountOut: parseUnits('100', 6),
976
+ maxAmountIn: parseUnits('150', 6),
783
977
  })
784
978
 
785
979
  // Get level after fill
@@ -794,12 +988,12 @@ describe('getPriceLevel', () => {
794
988
  })
795
989
 
796
990
  test('behavior: tick at boundaries', async () => {
797
- const { base } = await setupTokenPair()
991
+ const { base } = await setupTokenPair(client)
798
992
 
799
993
  // Place order at min tick
800
994
  await Actions.dex.placeSync(client, {
801
995
  token: base,
802
- amount: parseEther('10'),
996
+ amount: parseUnits('10', 6),
803
997
  type: 'sell',
804
998
  tick: Tick.minTick,
805
999
  })
@@ -815,7 +1009,7 @@ describe('getPriceLevel', () => {
815
1009
  // Place order at max tick
816
1010
  await Actions.dex.placeSync(client, {
817
1011
  token: base,
818
- amount: parseEther('10'),
1012
+ amount: parseUnits('10', 6),
819
1013
  type: 'buy',
820
1014
  tick: Tick.maxTick,
821
1015
  })
@@ -832,12 +1026,12 @@ describe('getPriceLevel', () => {
832
1026
 
833
1027
  describe('getSellQuote', () => {
834
1028
  test('default', async () => {
835
- const { base, quote } = await setupTokenPair()
1029
+ const { base, quote } = await setupTokenPair(client)
836
1030
 
837
1031
  // Place bid orders to create liquidity
838
1032
  await Actions.dex.placeSync(client, {
839
1033
  token: base,
840
- amount: parseEther('500'),
1034
+ amount: parseUnits('500', 6),
841
1035
  type: 'buy',
842
1036
  tick: Tick.fromPrice('0.999'),
843
1037
  })
@@ -846,100 +1040,91 @@ describe('getSellQuote', () => {
846
1040
  const amountOut = await Actions.dex.getSellQuote(client, {
847
1041
  tokenIn: base,
848
1042
  tokenOut: quote,
849
- amountIn: parseEther('100'),
1043
+ amountIn: parseUnits('100', 6),
850
1044
  })
851
1045
 
852
1046
  expect(amountOut).toBeGreaterThan(0n)
853
1047
  // Should be approximately 100 * 0.999 = 99.9
854
- expect(amountOut).toBeLessThan(parseEther('100'))
1048
+ expect(amountOut).toBeLessThan(parseUnits('100', 6))
855
1049
  })
856
1050
 
857
1051
  test('behavior: fails with no liquidity', async () => {
858
- const { base, quote } = await setupTokenPair()
1052
+ const { base, quote } = await setupTokenPair(client)
859
1053
 
860
1054
  // Quote should fail with no liquidity
861
1055
  await expect(
862
1056
  Actions.dex.getSellQuote(client, {
863
1057
  tokenIn: base,
864
1058
  tokenOut: quote,
865
- amountIn: parseEther('100'),
1059
+ amountIn: parseUnits('100', 6),
866
1060
  }),
867
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
868
- [ContractFunctionExecutionError: The contract function "quoteSwapExactAmountIn" reverted.
869
-
870
- Error: InsufficientLiquidity()
871
-
872
- Contract Call:
873
- address: 0xdec0000000000000000000000000000000000000
874
- function: quoteSwapExactAmountIn(address tokenIn, address tokenOut, uint128 amountIn)
875
- args: (0x20c0000000000000000000000000000000000005, 0x20C0000000000000000000000000000000000004, 100000000000000000000)
876
-
877
- Docs: https://viem.sh/docs/contract/readContract
878
- Version: viem@2.38.3]
879
- `)
1061
+ ).rejects.toThrow('The contract function "quoteSwapExactAmountIn" reverted')
880
1062
  })
881
1063
  })
882
1064
 
883
1065
  describe('place', () => {
884
1066
  test('default', async () => {
885
1067
  // Setup token pair
886
- const { base } = await setupTokenPair()
1068
+ const { base } = await setupTokenPair(client)
887
1069
 
888
1070
  // Place a sell order
889
- const { receipt, ...result } = await Actions.dex.placeSync(client, {
890
- token: base,
891
- amount: parseEther('100'),
892
- type: 'sell',
893
- tick: Tick.fromPrice('1.001'),
894
- })
1071
+ const { receipt, orderId, token, ...result } = await Actions.dex.placeSync(
1072
+ client,
1073
+ {
1074
+ token: base,
1075
+ amount: parseUnits('100', 6),
1076
+ type: 'sell',
1077
+ tick: Tick.fromPrice('1.001'),
1078
+ },
1079
+ )
895
1080
 
896
1081
  expect(receipt).toBeDefined()
897
1082
  expect(receipt.status).toBe('success')
898
- expect(result.orderId).toBeGreaterThan(0n)
1083
+ expect(orderId).toBeGreaterThan(0n)
1084
+ expect(token).toBe(base)
899
1085
  expect(result).toMatchInlineSnapshot(`
900
1086
  {
901
- "amount": 100000000000000000000n,
1087
+ "amount": 100000000n,
902
1088
  "isBid": false,
903
1089
  "maker": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
904
- "orderId": 1n,
905
1090
  "tick": 100,
906
- "token": "0x20c0000000000000000000000000000000000005",
907
1091
  }
908
1092
  `)
909
1093
 
910
1094
  // Place a buy order
911
- const { receipt: receipt2, ...result2 } = await Actions.dex.placeSync(
912
- client,
913
- {
914
- token: base,
915
- amount: parseEther('100'),
916
- type: 'buy',
917
- tick: Tick.fromPrice('1.001'),
918
- },
919
- )
1095
+ const {
1096
+ receipt: receipt2,
1097
+ orderId: orderId2,
1098
+ token: token2,
1099
+ ...result2
1100
+ } = await Actions.dex.placeSync(client, {
1101
+ token: base,
1102
+ amount: parseUnits('100', 6),
1103
+ type: 'buy',
1104
+ tick: Tick.fromPrice('1.001'),
1105
+ })
920
1106
  expect(receipt2.status).toBe('success')
921
- expect(result2.orderId).toBeGreaterThan(0n)
1107
+ expect(orderId2).toBeGreaterThan(0n)
1108
+ expect(token2).toBe(base)
922
1109
  expect(result2).toMatchInlineSnapshot(`
923
1110
  {
924
- "amount": 100000000000000000000n,
1111
+ "amount": 100000000n,
925
1112
  "isBid": true,
926
1113
  "maker": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
927
- "orderId": 2n,
928
1114
  "tick": 100,
929
- "token": "0x20c0000000000000000000000000000000000005",
930
1115
  }
931
1116
  `)
932
1117
  })
933
1118
 
934
1119
  test('behavior: tick at boundaries', async () => {
935
- const { base } = await setupTokenPair()
1120
+ const { base } = await setupTokenPair(client)
936
1121
 
937
1122
  // Test at min tick (-2000)
938
1123
  const { receipt: receipt1, ...result1 } = await Actions.dex.placeSync(
939
1124
  client,
940
1125
  {
941
1126
  token: base,
942
- amount: parseEther('10'),
1127
+ amount: parseUnits('10', 6),
943
1128
  type: 'sell',
944
1129
  tick: Tick.minTick,
945
1130
  },
@@ -952,7 +1137,7 @@ describe('place', () => {
952
1137
  client,
953
1138
  {
954
1139
  token: base,
955
- amount: parseEther('10'),
1140
+ amount: parseUnits('10', 6),
956
1141
  type: 'buy',
957
1142
  tick: Tick.maxTick,
958
1143
  },
@@ -962,59 +1147,31 @@ describe('place', () => {
962
1147
  })
963
1148
 
964
1149
  test('behavior: tick validation fails outside bounds', async () => {
965
- const { base } = await setupTokenPair()
1150
+ const { base } = await setupTokenPair(client)
966
1151
 
967
1152
  // Test tick above max tix should fail
968
1153
  await expect(
969
1154
  Actions.dex.placeSync(client, {
970
1155
  token: base,
971
- amount: parseEther('10'),
1156
+ amount: parseUnits('10', 6),
972
1157
  type: 'buy',
973
1158
  tick: Tick.maxTick + 1,
974
1159
  }),
975
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
976
- [ContractFunctionExecutionError: The contract function "place" reverted.
977
-
978
- Error: TickOutOfBounds(int16 tick)
979
- (2001)
980
-
981
- Contract Call:
982
- address: 0xdec0000000000000000000000000000000000000
983
- function: place(address token, uint128 amount, bool isBid, int16 tick)
984
- args: (0x20c0000000000000000000000000000000000005, 10000000000000000000, true, 2001)
985
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
986
-
987
- Docs: https://viem.sh/docs/contract/writeContract
988
- Version: viem@2.38.3]
989
- `)
1160
+ ).rejects.toThrow('The contract function "place" reverted')
990
1161
 
991
1162
  // Test tick below min tick should fail
992
1163
  await expect(
993
1164
  Actions.dex.placeSync(client, {
994
1165
  token: base,
995
- amount: parseEther('10'),
1166
+ amount: parseUnits('10', 6),
996
1167
  type: 'sell',
997
1168
  tick: Tick.minTick - 1,
998
1169
  }),
999
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1000
- [ContractFunctionExecutionError: The contract function "place" reverted.
1001
-
1002
- Error: TickOutOfBounds(int16 tick)
1003
- (-2001)
1004
-
1005
- Contract Call:
1006
- address: 0xdec0000000000000000000000000000000000000
1007
- function: place(address token, uint128 amount, bool isBid, int16 tick)
1008
- args: (0x20c0000000000000000000000000000000000005, 10000000000000000000, false, -2001)
1009
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1010
-
1011
- Docs: https://viem.sh/docs/contract/writeContract
1012
- Version: viem@2.38.3]
1013
- `)
1170
+ ).rejects.toThrow('The contract function "place" reverted')
1014
1171
  })
1015
1172
 
1016
1173
  test('behavior: transfers from wallet', async () => {
1017
- const { base, quote } = await setupTokenPair()
1174
+ const { base, quote } = await setupTokenPair(client)
1018
1175
 
1019
1176
  // Get balances before placing order
1020
1177
  const baseBalanceBefore = await Actions.token.getBalance(client, {
@@ -1025,7 +1182,7 @@ describe('place', () => {
1025
1182
  })
1026
1183
 
1027
1184
  // Place a buy order - should transfer quote tokens to escrow
1028
- const orderAmount = parseEther('100')
1185
+ const orderAmount = parseUnits('100', 6)
1029
1186
  const tick = Tick.fromPrice('1.001')
1030
1187
  await Actions.dex.placeSync(client, {
1031
1188
  token: base,
@@ -1055,14 +1212,14 @@ describe('place', () => {
1055
1212
  })
1056
1213
 
1057
1214
  test('behavior: multiple orders at same tick', async () => {
1058
- const { base } = await setupTokenPair()
1215
+ const { base } = await setupTokenPair(client)
1059
1216
 
1060
1217
  const tick = Tick.fromPrice('1.0005')
1061
1218
 
1062
1219
  // Place first order
1063
1220
  const { orderId: orderId1 } = await Actions.dex.placeSync(client, {
1064
1221
  token: base,
1065
- amount: parseEther('100'),
1222
+ amount: parseUnits('100', 6),
1066
1223
  type: 'buy',
1067
1224
  tick,
1068
1225
  })
@@ -1070,7 +1227,7 @@ describe('place', () => {
1070
1227
  // Place second order at same tick
1071
1228
  const { orderId: orderId2 } = await Actions.dex.placeSync(client, {
1072
1229
  token: base,
1073
- amount: parseEther('50'),
1230
+ amount: parseUnits('50', 6),
1074
1231
  type: 'buy',
1075
1232
  tick,
1076
1233
  })
@@ -1082,41 +1239,41 @@ describe('place', () => {
1082
1239
 
1083
1240
  describe('placeFlip', () => {
1084
1241
  test('default', async () => {
1085
- const { base } = await setupTokenPair()
1242
+ const { base } = await setupTokenPair(client)
1086
1243
 
1087
1244
  // Place a flip bid order
1088
- const { receipt, ...result } = await Actions.dex.placeFlipSync(client, {
1089
- token: base,
1090
- amount: parseEther('100'),
1091
- type: 'buy',
1092
- tick: Tick.fromPrice('1.001'),
1093
- flipTick: Tick.fromPrice('1.002'),
1094
- })
1245
+ const { receipt, orderId, token, ...result } =
1246
+ await Actions.dex.placeFlipSync(client, {
1247
+ token: base,
1248
+ amount: parseUnits('100', 6),
1249
+ type: 'buy',
1250
+ tick: Tick.fromPrice('1.001'),
1251
+ flipTick: Tick.fromPrice('1.002'),
1252
+ })
1095
1253
 
1096
1254
  expect(receipt).toBeDefined()
1097
1255
  expect(receipt.status).toBe('success')
1098
- expect(result.orderId).toBeGreaterThan(0n)
1256
+ expect(orderId).toBeGreaterThan(0n)
1257
+ expect(token).toBe(base)
1099
1258
  expect(result.flipTick).toBe(Tick.fromPrice('1.002'))
1100
1259
  expect(result).toMatchInlineSnapshot(`
1101
1260
  {
1102
- "amount": 100000000000000000000n,
1261
+ "amount": 100000000n,
1103
1262
  "flipTick": 200,
1104
1263
  "isBid": true,
1105
1264
  "maker": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
1106
- "orderId": 1n,
1107
1265
  "tick": 100,
1108
- "token": "0x20c0000000000000000000000000000000000005",
1109
1266
  }
1110
1267
  `)
1111
1268
  })
1112
1269
 
1113
1270
  test('behavior: flip bid requires flipTick > tick', async () => {
1114
- const { base } = await setupTokenPair()
1271
+ const { base } = await setupTokenPair(client)
1115
1272
 
1116
1273
  // Valid: flipTick > tick for bid
1117
1274
  const { receipt: receipt1 } = await Actions.dex.placeFlipSync(client, {
1118
1275
  token: base,
1119
- amount: parseEther('10'),
1276
+ amount: parseUnits('10', 6),
1120
1277
  type: 'buy',
1121
1278
  tick: Tick.fromPrice('1.0005'),
1122
1279
  flipTick: Tick.fromPrice('1.001'),
@@ -1127,57 +1284,31 @@ describe('placeFlip', () => {
1127
1284
  await expect(
1128
1285
  Actions.dex.placeFlipSync(client, {
1129
1286
  token: base,
1130
- amount: parseEther('10'),
1287
+ amount: parseUnits('10', 6),
1131
1288
  type: 'buy',
1132
1289
  tick: Tick.fromPrice('1.001'),
1133
1290
  flipTick: Tick.fromPrice('1.001'), // Equal
1134
1291
  }),
1135
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1136
- [ContractFunctionExecutionError: The contract function "placeFlip" reverted.
1137
-
1138
- Error: InvalidFlipTick()
1139
-
1140
- Contract Call:
1141
- address: 0xdec0000000000000000000000000000000000000
1142
- function: placeFlip(address token, uint128 amount, bool isBid, int16 tick, int16 flipTick)
1143
- args: (0x20c0000000000000000000000000000000000005, 10000000000000000000, true, 100, 100)
1144
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1145
-
1146
- Docs: https://viem.sh/docs/contract/writeContract
1147
- Version: viem@2.38.3]
1148
- `)
1292
+ ).rejects.toThrow('The contract function "placeFlip" reverted')
1149
1293
 
1150
1294
  await expect(
1151
1295
  Actions.dex.placeFlipSync(client, {
1152
1296
  token: base,
1153
- amount: parseEther('10'),
1297
+ amount: parseUnits('10', 6),
1154
1298
  type: 'buy',
1155
1299
  tick: Tick.fromPrice('1.001'),
1156
1300
  flipTick: Tick.fromPrice('1.0005'), // Less than
1157
1301
  }),
1158
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1159
- [ContractFunctionExecutionError: The contract function "placeFlip" reverted.
1160
-
1161
- Error: InvalidFlipTick()
1162
-
1163
- Contract Call:
1164
- address: 0xdec0000000000000000000000000000000000000
1165
- function: placeFlip(address token, uint128 amount, bool isBid, int16 tick, int16 flipTick)
1166
- args: (0x20c0000000000000000000000000000000000005, 10000000000000000000, true, 100, 50)
1167
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1168
-
1169
- Docs: https://viem.sh/docs/contract/writeContract
1170
- Version: viem@2.38.3]
1171
- `)
1302
+ ).rejects.toThrow('The contract function "placeFlip" reverted')
1172
1303
  })
1173
1304
 
1174
1305
  test('behavior: flip ask requires flipTick < tick', async () => {
1175
- const { base } = await setupTokenPair()
1306
+ const { base } = await setupTokenPair(client)
1176
1307
 
1177
1308
  // Valid: flipTick < tick for ask
1178
1309
  const { receipt: receipt1 } = await Actions.dex.placeFlipSync(client, {
1179
1310
  token: base,
1180
- amount: parseEther('10'),
1311
+ amount: parseUnits('10', 6),
1181
1312
  type: 'sell',
1182
1313
  tick: Tick.fromPrice('1.001'),
1183
1314
  flipTick: Tick.fromPrice('1.0005'),
@@ -1188,57 +1319,31 @@ describe('placeFlip', () => {
1188
1319
  await expect(
1189
1320
  Actions.dex.placeFlipSync(client, {
1190
1321
  token: base,
1191
- amount: parseEther('10'),
1322
+ amount: parseUnits('10', 6),
1192
1323
  type: 'sell',
1193
1324
  tick: Tick.fromPrice('1.0005'),
1194
1325
  flipTick: Tick.fromPrice('1.0005'), // Equal
1195
1326
  }),
1196
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1197
- [ContractFunctionExecutionError: The contract function "placeFlip" reverted.
1198
-
1199
- Error: InvalidFlipTick()
1200
-
1201
- Contract Call:
1202
- address: 0xdec0000000000000000000000000000000000000
1203
- function: placeFlip(address token, uint128 amount, bool isBid, int16 tick, int16 flipTick)
1204
- args: (0x20c0000000000000000000000000000000000005, 10000000000000000000, false, 50, 50)
1205
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1206
-
1207
- Docs: https://viem.sh/docs/contract/writeContract
1208
- Version: viem@2.38.3]
1209
- `)
1327
+ ).rejects.toThrow('The contract function "placeFlip" reverted')
1210
1328
 
1211
1329
  await expect(
1212
1330
  Actions.dex.placeFlipSync(client, {
1213
1331
  token: base,
1214
- amount: parseEther('10'),
1332
+ amount: parseUnits('10', 6),
1215
1333
  type: 'sell',
1216
1334
  tick: Tick.fromPrice('1.0005'),
1217
1335
  flipTick: Tick.fromPrice('1.001'), // Greater than
1218
1336
  }),
1219
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1220
- [ContractFunctionExecutionError: The contract function "placeFlip" reverted.
1221
-
1222
- Error: InvalidFlipTick()
1223
-
1224
- Contract Call:
1225
- address: 0xdec0000000000000000000000000000000000000
1226
- function: placeFlip(address token, uint128 amount, bool isBid, int16 tick, int16 flipTick)
1227
- args: (0x20c0000000000000000000000000000000000005, 10000000000000000000, false, 50, 100)
1228
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1229
-
1230
- Docs: https://viem.sh/docs/contract/writeContract
1231
- Version: viem@2.38.3]
1232
- `)
1337
+ ).rejects.toThrow('The contract function "placeFlip" reverted')
1233
1338
  })
1234
1339
 
1235
1340
  test('behavior: flip ticks at boundaries', async () => {
1236
- const { base } = await setupTokenPair()
1341
+ const { base } = await setupTokenPair(client)
1237
1342
 
1238
1343
  // Flip order with ticks at extreme boundaries
1239
1344
  const { receipt } = await Actions.dex.placeFlipSync(client, {
1240
1345
  token: base,
1241
- amount: parseEther('10'),
1346
+ amount: parseUnits('10', 6),
1242
1347
  type: 'buy',
1243
1348
  tick: Tick.minTick,
1244
1349
  flipTick: Tick.maxTick,
@@ -1249,12 +1354,12 @@ describe('placeFlip', () => {
1249
1354
 
1250
1355
  describe('sell', () => {
1251
1356
  test('default', async () => {
1252
- const { base, quote } = await setupTokenPair()
1357
+ const { base, quote } = await setupTokenPair(client)
1253
1358
 
1254
1359
  // Place bid order to create liquidity
1255
1360
  await Actions.dex.placeSync(client, {
1256
1361
  token: base,
1257
- amount: parseEther('500'),
1362
+ amount: parseUnits('500', 6),
1258
1363
  type: 'buy',
1259
1364
  tick: Tick.fromPrice('0.999'),
1260
1365
  })
@@ -1263,8 +1368,8 @@ describe('sell', () => {
1263
1368
  const { receipt } = await Actions.dex.sellSync(client, {
1264
1369
  tokenIn: base,
1265
1370
  tokenOut: quote,
1266
- amountIn: parseEther('100'),
1267
- minAmountOut: parseEther('50'),
1371
+ amountIn: parseUnits('100', 6),
1372
+ minAmountOut: parseUnits('50', 6),
1268
1373
  })
1269
1374
 
1270
1375
  expect(receipt).toBeDefined()
@@ -1272,12 +1377,12 @@ describe('sell', () => {
1272
1377
  })
1273
1378
 
1274
1379
  test('behavior: respects minAmountOut', async () => {
1275
- const { base, quote } = await setupTokenPair()
1380
+ const { base, quote } = await setupTokenPair(client)
1276
1381
 
1277
1382
  // Place bid order at low price
1278
1383
  await Actions.dex.placeSync(client, {
1279
1384
  token: base,
1280
- amount: parseEther('500'),
1385
+ amount: parseUnits('500', 6),
1281
1386
  type: 'buy',
1282
1387
  tick: Tick.fromPrice('0.99'), // 1% below peg
1283
1388
  })
@@ -1287,27 +1392,14 @@ describe('sell', () => {
1287
1392
  Actions.dex.sellSync(client, {
1288
1393
  tokenIn: base,
1289
1394
  tokenOut: quote,
1290
- amountIn: parseEther('100'),
1291
- minAmountOut: parseEther('150'), // Way too high
1395
+ amountIn: parseUnits('100', 6),
1396
+ minAmountOut: parseUnits('150', 6), // Way too high
1292
1397
  }),
1293
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1294
- [ContractFunctionExecutionError: The contract function "swapExactAmountIn" reverted.
1295
-
1296
- Error: InsufficientOutput()
1297
-
1298
- Contract Call:
1299
- address: 0xdec0000000000000000000000000000000000000
1300
- function: swapExactAmountIn(address tokenIn, address tokenOut, uint128 amountIn, uint128 minAmountOut)
1301
- args: (0x20c0000000000000000000000000000000000005, 0x20C0000000000000000000000000000000000004, 100000000000000000000, 150000000000000000000)
1302
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1303
-
1304
- Docs: https://viem.sh/docs/contract/writeContract
1305
- Version: viem@2.38.3]
1306
- `)
1398
+ ).rejects.toThrow('The contract function "swapExactAmountIn" reverted')
1307
1399
  })
1308
1400
 
1309
1401
  test('behavior: fails with insufficient liquidity', async () => {
1310
- const { base, quote } = await setupTokenPair()
1402
+ const { base, quote } = await setupTokenPair(client)
1311
1403
 
1312
1404
  // No orders - no liquidity
1313
1405
 
@@ -1316,29 +1408,16 @@ describe('sell', () => {
1316
1408
  Actions.dex.sellSync(client, {
1317
1409
  tokenIn: base,
1318
1410
  tokenOut: quote,
1319
- amountIn: parseEther('100'),
1320
- minAmountOut: parseEther('50'),
1411
+ amountIn: parseUnits('100', 6),
1412
+ minAmountOut: parseUnits('50', 6),
1321
1413
  }),
1322
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1323
- [ContractFunctionExecutionError: The contract function "swapExactAmountIn" reverted.
1324
-
1325
- Error: InsufficientLiquidity()
1326
-
1327
- Contract Call:
1328
- address: 0xdec0000000000000000000000000000000000000
1329
- function: swapExactAmountIn(address tokenIn, address tokenOut, uint128 amountIn, uint128 minAmountOut)
1330
- args: (0x20c0000000000000000000000000000000000005, 0x20C0000000000000000000000000000000000004, 100000000000000000000, 50000000000000000000)
1331
- sender: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1332
-
1333
- Docs: https://viem.sh/docs/contract/writeContract
1334
- Version: viem@2.38.3]
1335
- `)
1414
+ ).rejects.toThrow('The contract function "swapExactAmountIn" reverted')
1336
1415
  })
1337
1416
  })
1338
1417
 
1339
1418
  describe('watchFlipOrderPlaced', () => {
1340
1419
  test('default', async () => {
1341
- const { base } = await setupTokenPair()
1420
+ const { base } = await setupTokenPair(client)
1342
1421
 
1343
1422
  const receivedOrders: Array<{
1344
1423
  args: Actions.dex.watchFlipOrderPlaced.Args
@@ -1355,7 +1434,7 @@ describe('watchFlipOrderPlaced', () => {
1355
1434
  // Place flip order
1356
1435
  await Actions.dex.placeFlipSync(client, {
1357
1436
  token: base,
1358
- amount: parseEther('100'),
1437
+ amount: parseUnits('100', 6),
1359
1438
  type: 'buy',
1360
1439
  tick: Tick.fromPrice('1.001'),
1361
1440
  flipTick: Tick.fromPrice('1.002'),
@@ -1374,7 +1453,7 @@ describe('watchFlipOrderPlaced', () => {
1374
1453
 
1375
1454
  describe('watchOrderCancelled', () => {
1376
1455
  test('default', async () => {
1377
- const { base } = await setupTokenPair()
1456
+ const { base } = await setupTokenPair(client)
1378
1457
 
1379
1458
  const receivedCancellations: Array<{
1380
1459
  args: Actions.dex.watchOrderCancelled.Args
@@ -1391,7 +1470,7 @@ describe('watchOrderCancelled', () => {
1391
1470
  // Place order
1392
1471
  const { orderId } = await Actions.dex.placeSync(client, {
1393
1472
  token: base,
1394
- amount: parseEther('100'),
1473
+ amount: parseUnits('100', 6),
1395
1474
  type: 'buy',
1396
1475
  tick: Tick.fromPrice('1.001'),
1397
1476
  })
@@ -1411,19 +1490,19 @@ describe('watchOrderCancelled', () => {
1411
1490
  })
1412
1491
 
1413
1492
  test('behavior: filter by orderId', async () => {
1414
- const { base } = await setupTokenPair()
1493
+ const { base } = await setupTokenPair(client)
1415
1494
 
1416
1495
  // Place two orders
1417
1496
  const { orderId: orderId1 } = await Actions.dex.placeSync(client, {
1418
1497
  token: base,
1419
- amount: parseEther('100'),
1498
+ amount: parseUnits('100', 6),
1420
1499
  type: 'buy',
1421
1500
  tick: Tick.fromPrice('1.001'),
1422
1501
  })
1423
1502
 
1424
1503
  const { orderId: orderId2 } = await Actions.dex.placeSync(client, {
1425
1504
  token: base,
1426
- amount: parseEther('50'),
1505
+ amount: parseUnits('50', 6),
1427
1506
  type: 'buy',
1428
1507
  tick: Tick.fromPrice('1.001'),
1429
1508
  })
@@ -1467,7 +1546,7 @@ describe.todo('watchOrderFilled')
1467
1546
 
1468
1547
  describe('watchOrderPlaced', () => {
1469
1548
  test('default', async () => {
1470
- const { base } = await setupTokenPair()
1549
+ const { base } = await setupTokenPair(client)
1471
1550
 
1472
1551
  const receivedOrders: Array<{
1473
1552
  args: Actions.dex.watchOrderPlaced.Args
@@ -1484,7 +1563,7 @@ describe('watchOrderPlaced', () => {
1484
1563
  // Place first order
1485
1564
  await Actions.dex.placeSync(client, {
1486
1565
  token: base,
1487
- amount: parseEther('100'),
1566
+ amount: parseUnits('100', 6),
1488
1567
  type: 'buy',
1489
1568
  tick: Tick.fromPrice('1.001'),
1490
1569
  })
@@ -1492,7 +1571,7 @@ describe('watchOrderPlaced', () => {
1492
1571
  // Place second order
1493
1572
  await Actions.dex.placeSync(client, {
1494
1573
  token: base,
1495
- amount: parseEther('50'),
1574
+ amount: parseUnits('50', 6),
1496
1575
  type: 'sell',
1497
1576
  tick: Tick.fromPrice('0.999'),
1498
1577
  })
@@ -1502,17 +1581,17 @@ describe('watchOrderPlaced', () => {
1502
1581
 
1503
1582
  expect(receivedOrders).toHaveLength(2)
1504
1583
  expect(receivedOrders[0]?.args.isBid).toBe(true)
1505
- expect(receivedOrders[0]?.args.amount).toBe(parseEther('100'))
1584
+ expect(receivedOrders[0]?.args.amount).toBe(parseUnits('100', 6))
1506
1585
  expect(receivedOrders[1]?.args.isBid).toBe(false)
1507
- expect(receivedOrders[1]?.args.amount).toBe(parseEther('50'))
1586
+ expect(receivedOrders[1]?.args.amount).toBe(parseUnits('50', 6))
1508
1587
  } finally {
1509
1588
  unwatch()
1510
1589
  }
1511
1590
  })
1512
1591
 
1513
1592
  test('behavior: filter by token', async () => {
1514
- const { base } = await setupTokenPair()
1515
- const { base: base2 } = await setupTokenPair()
1593
+ const { base } = await setupTokenPair(client)
1594
+ const { base: base2 } = await setupTokenPair(client)
1516
1595
 
1517
1596
  const receivedOrders: Array<{
1518
1597
  args: Actions.dex.watchOrderPlaced.Args
@@ -1531,7 +1610,7 @@ describe('watchOrderPlaced', () => {
1531
1610
  // Place order on base (should be captured)
1532
1611
  await Actions.dex.placeSync(client, {
1533
1612
  token: base,
1534
- amount: parseEther('100'),
1613
+ amount: parseUnits('100', 6),
1535
1614
  type: 'buy',
1536
1615
  tick: Tick.fromPrice('1.001'),
1537
1616
  })
@@ -1539,7 +1618,7 @@ describe('watchOrderPlaced', () => {
1539
1618
  // Place order on base2 (should NOT be captured)
1540
1619
  await Actions.dex.placeSync(client, {
1541
1620
  token: base2,
1542
- amount: parseEther('50'),
1621
+ amount: parseUnits('50', 6),
1543
1622
  type: 'buy',
1544
1623
  tick: Tick.fromPrice('1.001'),
1545
1624
  })
@@ -1559,12 +1638,12 @@ describe('watchOrderPlaced', () => {
1559
1638
 
1560
1639
  describe('withdraw', () => {
1561
1640
  test('default', async () => {
1562
- const { base, quote } = await setupTokenPair()
1641
+ const { base, quote } = await setupTokenPair(client)
1563
1642
 
1564
1643
  // Create internal balance
1565
1644
  const { orderId } = await Actions.dex.placeSync(client, {
1566
1645
  token: base,
1567
- amount: parseEther('100'),
1646
+ amount: parseUnits('100', 6),
1568
1647
  type: 'buy',
1569
1648
  tick: Tick.fromPrice('1.001'),
1570
1649
  })
@@ -1573,7 +1652,7 @@ describe('withdraw', () => {
1573
1652
 
1574
1653
  // Get DEX balance
1575
1654
  const dexBalance = await Actions.dex.getBalance(client, {
1576
- account: account.address,
1655
+ account: client.account.address,
1577
1656
  token: quote,
1578
1657
  })
1579
1658
  expect(dexBalance).toBeGreaterThan(0n)
@@ -1594,7 +1673,7 @@ describe('withdraw', () => {
1594
1673
 
1595
1674
  // Check DEX balance is now 0
1596
1675
  const dexBalanceAfter = await Actions.dex.getBalance(client, {
1597
- account: account.address,
1676
+ account: client.account.address,
1598
1677
  token: quote,
1599
1678
  })
1600
1679
  expect(dexBalanceAfter).toBe(0n)