tempo.ts 0.10.5 → 0.11.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 (224) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +0 -41
  3. package/dist/viem/Account.d.ts +8 -3
  4. package/dist/viem/Account.d.ts.map +1 -1
  5. package/dist/viem/Account.js +9 -2
  6. package/dist/viem/Account.js.map +1 -1
  7. package/dist/viem/Actions/amm.d.ts +1 -1
  8. package/dist/viem/Actions/amm.d.ts.map +1 -1
  9. package/dist/viem/Actions/amm.js +1 -2
  10. package/dist/viem/Actions/amm.js.map +1 -1
  11. package/dist/viem/Actions/dex.d.ts +0 -35
  12. package/dist/viem/Actions/dex.d.ts.map +1 -1
  13. package/dist/viem/Actions/dex.js +0 -43
  14. package/dist/viem/Actions/dex.js.map +1 -1
  15. package/dist/viem/Actions/fee.d.ts +1 -1
  16. package/dist/viem/Actions/fee.d.ts.map +1 -1
  17. package/dist/viem/Actions/fee.js +1 -1
  18. package/dist/viem/Actions/fee.js.map +1 -1
  19. package/dist/viem/Actions/nonce.d.ts.map +1 -1
  20. package/dist/viem/Actions/nonce.js +6 -4
  21. package/dist/viem/Actions/nonce.js.map +1 -1
  22. package/dist/viem/Actions/token.d.ts +1 -2
  23. package/dist/viem/Actions/token.d.ts.map +1 -1
  24. package/dist/viem/Actions/token.js +1 -2
  25. package/dist/viem/Actions/token.js.map +1 -1
  26. package/dist/viem/Chain.d.ts +34 -34
  27. package/dist/viem/Chain.d.ts.map +1 -1
  28. package/dist/viem/Chain.js +2 -0
  29. package/dist/viem/Chain.js.map +1 -1
  30. package/dist/viem/Formatters.d.ts.map +1 -1
  31. package/dist/viem/Formatters.js +5 -3
  32. package/dist/viem/Formatters.js.map +1 -1
  33. package/dist/viem/Transaction.d.ts +8 -5
  34. package/dist/viem/Transaction.d.ts.map +1 -1
  35. package/dist/viem/Transaction.js +13 -3
  36. package/dist/viem/Transaction.js.map +1 -1
  37. package/dist/viem/internal/types.d.ts +1 -1
  38. package/dist/viem/internal/types.d.ts.map +1 -1
  39. package/dist/wagmi/Actions/dex.d.ts +1 -45
  40. package/dist/wagmi/Actions/dex.d.ts.map +1 -1
  41. package/dist/wagmi/Actions/dex.js +0 -55
  42. package/dist/wagmi/Actions/dex.js.map +1 -1
  43. package/dist/wagmi/Connector.d.ts +1 -1
  44. package/dist/wagmi/Connector.d.ts.map +1 -1
  45. package/dist/wagmi/Connector.js +1 -2
  46. package/dist/wagmi/Connector.js.map +1 -1
  47. package/dist/wagmi/Hooks/dex.d.ts +3 -46
  48. package/dist/wagmi/Hooks/dex.d.ts.map +1 -1
  49. package/dist/wagmi/Hooks/dex.js +2 -54
  50. package/dist/wagmi/Hooks/dex.js.map +1 -1
  51. package/dist/wagmi/index.d.ts +1 -1
  52. package/dist/wagmi/index.d.ts.map +1 -1
  53. package/dist/wagmi/index.js +1 -1
  54. package/dist/wagmi/index.js.map +1 -1
  55. package/package.json +5 -23
  56. package/src/viem/Account.test.ts +1 -1
  57. package/src/viem/Account.ts +11 -2
  58. package/src/viem/Actions/account.ts +1 -1
  59. package/src/viem/Actions/amm.ts +1 -2
  60. package/src/viem/Actions/dex.test.ts +1 -195
  61. package/src/viem/Actions/dex.ts +0 -53
  62. package/src/viem/Actions/fee.test.ts +2 -2
  63. package/src/viem/Actions/fee.ts +1 -1
  64. package/src/viem/Actions/nonce.test.ts +27 -14
  65. package/src/viem/Actions/nonce.ts +6 -4
  66. package/src/viem/Actions/token.test.ts +18 -52
  67. package/src/viem/Actions/token.ts +1 -2
  68. package/src/viem/Chain.ts +3 -1
  69. package/src/viem/Decorator.ts +0 -30
  70. package/src/viem/Formatters.ts +9 -3
  71. package/src/viem/Transaction.ts +23 -7
  72. package/src/viem/e2e.test.ts +19 -0
  73. package/src/viem/index.ts +12 -1
  74. package/src/viem/internal/types.ts +1 -1
  75. package/src/wagmi/Actions/dex.test.ts +0 -26
  76. package/src/wagmi/Actions/dex.ts +1 -111
  77. package/src/wagmi/Actions/nonce.test.ts +8 -4
  78. package/src/wagmi/Actions/token.test.ts +2 -2
  79. package/src/wagmi/Connector.ts +1 -2
  80. package/src/wagmi/Hooks/dex.test.ts +0 -26
  81. package/src/wagmi/Hooks/dex.ts +1 -88
  82. package/src/wagmi/Hooks/nonce.test.ts +3 -3
  83. package/src/wagmi/index.ts +4 -1
  84. package/dist/chains.d.ts +0 -73
  85. package/dist/chains.d.ts.map +0 -1
  86. package/dist/chains.js +0 -51
  87. package/dist/chains.js.map +0 -1
  88. package/dist/ox/AuthorizationTempo.d.ts +0 -450
  89. package/dist/ox/AuthorizationTempo.d.ts.map +0 -1
  90. package/dist/ox/AuthorizationTempo.js +0 -433
  91. package/dist/ox/AuthorizationTempo.js.map +0 -1
  92. package/dist/ox/KeyAuthorization.d.ts +0 -356
  93. package/dist/ox/KeyAuthorization.d.ts.map +0 -1
  94. package/dist/ox/KeyAuthorization.js +0 -359
  95. package/dist/ox/KeyAuthorization.js.map +0 -1
  96. package/dist/ox/Order.d.ts +0 -92
  97. package/dist/ox/Order.d.ts.map +0 -1
  98. package/dist/ox/Order.js +0 -88
  99. package/dist/ox/Order.js.map +0 -1
  100. package/dist/ox/OrdersFilters.d.ts +0 -72
  101. package/dist/ox/OrdersFilters.d.ts.map +0 -1
  102. package/dist/ox/OrdersFilters.js +0 -100
  103. package/dist/ox/OrdersFilters.js.map +0 -1
  104. package/dist/ox/Pagination.d.ts +0 -128
  105. package/dist/ox/Pagination.d.ts.map +0 -1
  106. package/dist/ox/Pagination.js +0 -78
  107. package/dist/ox/Pagination.js.map +0 -1
  108. package/dist/ox/PoolId.d.ts +0 -18
  109. package/dist/ox/PoolId.d.ts.map +0 -1
  110. package/dist/ox/PoolId.js +0 -13
  111. package/dist/ox/PoolId.js.map +0 -1
  112. package/dist/ox/RpcSchema.d.ts +0 -32
  113. package/dist/ox/RpcSchema.d.ts.map +0 -1
  114. package/dist/ox/RpcSchema.js +0 -2
  115. package/dist/ox/RpcSchema.js.map +0 -1
  116. package/dist/ox/SignatureEnvelope.d.ts +0 -260
  117. package/dist/ox/SignatureEnvelope.d.ts.map +0 -1
  118. package/dist/ox/SignatureEnvelope.js +0 -477
  119. package/dist/ox/SignatureEnvelope.js.map +0 -1
  120. package/dist/ox/Tick.d.ts +0 -115
  121. package/dist/ox/Tick.d.ts.map +0 -1
  122. package/dist/ox/Tick.js +0 -127
  123. package/dist/ox/Tick.js.map +0 -1
  124. package/dist/ox/TokenId.d.ts +0 -25
  125. package/dist/ox/TokenId.d.ts.map +0 -1
  126. package/dist/ox/TokenId.js +0 -41
  127. package/dist/ox/TokenId.js.map +0 -1
  128. package/dist/ox/TokenRole.d.ts +0 -11
  129. package/dist/ox/TokenRole.d.ts.map +0 -1
  130. package/dist/ox/TokenRole.js +0 -22
  131. package/dist/ox/TokenRole.js.map +0 -1
  132. package/dist/ox/Transaction.d.ts +0 -201
  133. package/dist/ox/Transaction.d.ts.map +0 -1
  134. package/dist/ox/Transaction.js +0 -167
  135. package/dist/ox/Transaction.js.map +0 -1
  136. package/dist/ox/TransactionEnvelopeTempo.d.ts +0 -470
  137. package/dist/ox/TransactionEnvelopeTempo.d.ts.map +0 -1
  138. package/dist/ox/TransactionEnvelopeTempo.js +0 -547
  139. package/dist/ox/TransactionEnvelopeTempo.js.map +0 -1
  140. package/dist/ox/TransactionReceipt.d.ts +0 -155
  141. package/dist/ox/TransactionReceipt.d.ts.map +0 -1
  142. package/dist/ox/TransactionReceipt.js +0 -136
  143. package/dist/ox/TransactionReceipt.js.map +0 -1
  144. package/dist/ox/TransactionRequest.d.ts +0 -76
  145. package/dist/ox/TransactionRequest.d.ts.map +0 -1
  146. package/dist/ox/TransactionRequest.js +0 -93
  147. package/dist/ox/TransactionRequest.js.map +0 -1
  148. package/dist/ox/index.d.ts +0 -14
  149. package/dist/ox/index.d.ts.map +0 -1
  150. package/dist/ox/index.js +0 -14
  151. package/dist/ox/index.js.map +0 -1
  152. package/dist/prool/Instance.d.ts +0 -101
  153. package/dist/prool/Instance.d.ts.map +0 -1
  154. package/dist/prool/Instance.js +0 -136
  155. package/dist/prool/Instance.js.map +0 -1
  156. package/dist/prool/chain.json +0 -238
  157. package/dist/prool/index.d.ts +0 -2
  158. package/dist/prool/index.d.ts.map +0 -1
  159. package/dist/prool/index.js +0 -2
  160. package/dist/prool/index.js.map +0 -1
  161. package/dist/viem/Actions/account.d.ts +0 -40
  162. package/dist/viem/Actions/account.d.ts.map +0 -1
  163. package/dist/viem/Actions/account.js +0 -86
  164. package/dist/viem/Actions/account.js.map +0 -1
  165. package/dist/viem/Actions/index.d.ts +0 -10
  166. package/dist/viem/Actions/index.d.ts.map +0 -1
  167. package/dist/viem/Actions/index.js +0 -10
  168. package/dist/viem/Actions/index.js.map +0 -1
  169. package/dist/viem/Decorator.d.ts +0 -2810
  170. package/dist/viem/Decorator.d.ts.map +0 -1
  171. package/dist/viem/Decorator.js +0 -138
  172. package/dist/viem/Decorator.js.map +0 -1
  173. package/dist/viem/P256.d.ts +0 -2
  174. package/dist/viem/P256.d.ts.map +0 -1
  175. package/dist/viem/P256.js +0 -2
  176. package/dist/viem/P256.js.map +0 -1
  177. package/dist/viem/Secp256k1.d.ts +0 -2
  178. package/dist/viem/Secp256k1.d.ts.map +0 -1
  179. package/dist/viem/Secp256k1.js +0 -2
  180. package/dist/viem/Secp256k1.js.map +0 -1
  181. package/dist/viem/TokenIds.d.ts +0 -2
  182. package/dist/viem/TokenIds.d.ts.map +0 -1
  183. package/dist/viem/TokenIds.js +0 -2
  184. package/dist/viem/TokenIds.js.map +0 -1
  185. package/dist/viem/index.d.ts +0 -17
  186. package/dist/viem/index.d.ts.map +0 -1
  187. package/dist/viem/index.js +0 -17
  188. package/dist/viem/index.js.map +0 -1
  189. package/src/ox/AuthorizationTempo.test.ts +0 -1256
  190. package/src/ox/AuthorizationTempo.ts +0 -648
  191. package/src/ox/KeyAuthorization.test.ts +0 -1332
  192. package/src/ox/KeyAuthorization.ts +0 -540
  193. package/src/ox/Order.test.ts +0 -78
  194. package/src/ox/Order.ts +0 -125
  195. package/src/ox/OrdersFilters.test.ts +0 -182
  196. package/src/ox/OrdersFilters.ts +0 -125
  197. package/src/ox/Pagination.test.ts +0 -162
  198. package/src/ox/Pagination.ts +0 -164
  199. package/src/ox/PoolId.test.ts +0 -33
  200. package/src/ox/PoolId.ts +0 -27
  201. package/src/ox/RpcSchema.ts +0 -35
  202. package/src/ox/SignatureEnvelope.test.ts +0 -1876
  203. package/src/ox/SignatureEnvelope.ts +0 -791
  204. package/src/ox/Tick.test.ts +0 -281
  205. package/src/ox/Tick.ts +0 -181
  206. package/src/ox/TokenId.test.ts +0 -40
  207. package/src/ox/TokenId.ts +0 -50
  208. package/src/ox/TokenRole.test.ts +0 -16
  209. package/src/ox/TokenRole.ts +0 -27
  210. package/src/ox/Transaction.test.ts +0 -523
  211. package/src/ox/Transaction.ts +0 -332
  212. package/src/ox/TransactionEnvelopeTempo.test.ts +0 -1352
  213. package/src/ox/TransactionEnvelopeTempo.ts +0 -905
  214. package/src/ox/TransactionReceipt.ts +0 -190
  215. package/src/ox/TransactionRequest.ts +0 -147
  216. package/src/ox/e2e.test.ts +0 -1393
  217. package/src/ox/index.ts +0 -13
  218. package/src/prool/Instance.test.ts +0 -43
  219. package/src/prool/Instance.ts +0 -247
  220. package/src/prool/chain.json +0 -238
  221. package/src/prool/index.ts +0 -1
  222. package/src/viem/Actions/__snapshots__/dex.test.ts.snap +0 -850
  223. package/src/wagmi/Actions/__snapshots__/dex.test.ts.snap +0 -310
  224. package/src/wagmi/Hooks/__snapshots__/dex.test.ts.snap +0 -457
@@ -1,281 +0,0 @@
1
- import { Tick } from 'tempo.ts/ox'
2
- import { describe, expect, test } from 'vitest'
3
-
4
- describe('toPrice', () => {
5
- test('converts tick 0 to price 1', () => {
6
- expect(Tick.toPrice(0)).toBe('1')
7
- })
8
-
9
- test('converts positive ticks correctly', () => {
10
- expect(Tick.toPrice(100)).toBe('1.001')
11
- expect(Tick.toPrice(1000)).toBe('1.01')
12
- expect(Tick.toPrice(2000)).toBe('1.02')
13
- })
14
-
15
- test('converts negative ticks correctly', () => {
16
- expect(Tick.toPrice(-100)).toBe('0.999')
17
- expect(Tick.toPrice(-1000)).toBe('0.99')
18
- expect(Tick.toPrice(-2000)).toBe('0.98')
19
- })
20
-
21
- test('handles boundary values', () => {
22
- expect(Tick.toPrice(Tick.minTick)).toBe('0.98')
23
- expect(Tick.toPrice(Tick.maxTick)).toBe('1.02')
24
- })
25
-
26
- test('preserves exact 5 decimal precision', () => {
27
- expect(Tick.toPrice(1)).toBe('1.00001')
28
- expect(Tick.toPrice(-1)).toBe('0.99999')
29
- expect(Tick.toPrice(1234)).toBe('1.01234')
30
- })
31
-
32
- test('throws error when tick is below minimum', () => {
33
- expect(() => Tick.toPrice(-2001)).toThrow(Tick.TickOutOfBoundsError)
34
- expect(() => Tick.toPrice(-2001)).toThrow('Tick -2001 is out of bounds.')
35
- expect(() => Tick.toPrice(-3000)).toThrow(Tick.TickOutOfBoundsError)
36
- })
37
-
38
- test('throws error when tick is above maximum', () => {
39
- expect(() => Tick.toPrice(2001)).toThrow(Tick.TickOutOfBoundsError)
40
- expect(() => Tick.toPrice(2001)).toThrow('Tick 2001 is out of bounds.')
41
- expect(() => Tick.toPrice(3000)).toThrow(Tick.TickOutOfBoundsError)
42
- })
43
-
44
- test('handles edge cases near bounds', () => {
45
- expect(() => Tick.toPrice(-2000)).not.toThrow()
46
- expect(() => Tick.toPrice(2000)).not.toThrow()
47
- })
48
- })
49
-
50
- describe('fromPrice', () => {
51
- test('converts price 1.0 to tick 0', () => {
52
- expect(Tick.fromPrice('1.0')).toBe(0)
53
- expect(Tick.fromPrice('1.00000')).toBe(0)
54
- })
55
-
56
- test('converts prices above 1.0 correctly', () => {
57
- expect(Tick.fromPrice('1.001')).toBe(100)
58
- expect(Tick.fromPrice('1.01')).toBe(1000)
59
- expect(Tick.fromPrice('1.02')).toBe(2000)
60
- })
61
-
62
- test('converts prices below 1.0 correctly', () => {
63
- expect(Tick.fromPrice('0.999')).toBe(-100)
64
- expect(Tick.fromPrice('0.99')).toBe(-1000)
65
- expect(Tick.fromPrice('0.98')).toBe(-2000)
66
- })
67
-
68
- test('handles boundary values', () => {
69
- expect(Tick.fromPrice('0.98')).toBe(Tick.minTick)
70
- expect(Tick.fromPrice('1.02')).toBe(Tick.maxTick)
71
- })
72
-
73
- test('handles different decimal precisions', () => {
74
- expect(Tick.fromPrice('1.00001')).toBe(1)
75
- expect(Tick.fromPrice('1.0001')).toBe(10)
76
- expect(Tick.fromPrice('1.001')).toBe(100)
77
- expect(Tick.fromPrice('0.99999')).toBe(-1)
78
- })
79
-
80
- test('truncates beyond 5 decimal places', () => {
81
- // Should truncate, not round, extra decimals
82
- expect(Tick.fromPrice('1.000019')).toBe(1) // Takes first 5: 1.00001
83
- expect(Tick.fromPrice('1.000015')).toBe(1) // Takes first 5: 1.00001
84
- })
85
-
86
- test('validates string format', () => {
87
- expect(() => Tick.fromPrice('abc')).toThrow(Tick.InvalidPriceFormatError)
88
- expect(() => Tick.fromPrice('abc')).toThrow('Invalid price format')
89
- expect(() => Tick.fromPrice('1.2.3')).toThrow(Tick.InvalidPriceFormatError)
90
- expect(() => Tick.fromPrice('')).toThrow(Tick.InvalidPriceFormatError)
91
- })
92
-
93
- test('throws error when price results in tick below minimum', () => {
94
- expect(() => Tick.fromPrice('0.979')).toThrow(Tick.PriceOutOfBoundsError)
95
- expect(() => Tick.fromPrice('0.979')).toThrow(
96
- 'Price "0.979" results in tick -2100 which is out of bounds.',
97
- )
98
- expect(() => Tick.fromPrice('0.5')).toThrow(Tick.PriceOutOfBoundsError)
99
- })
100
-
101
- test('throws error when price results in tick above maximum', () => {
102
- expect(() => Tick.fromPrice('1.021')).toThrow(Tick.PriceOutOfBoundsError)
103
- expect(() => Tick.fromPrice('1.021')).toThrow(
104
- 'Price "1.021" results in tick 2100 which is out of bounds.',
105
- )
106
- expect(() => Tick.fromPrice('1.5')).toThrow(Tick.PriceOutOfBoundsError)
107
- })
108
-
109
- test('handles edge cases near bounds', () => {
110
- expect(() => Tick.fromPrice('0.98')).not.toThrow()
111
- expect(() => Tick.fromPrice('1.02')).not.toThrow()
112
- })
113
-
114
- test('handles whitespace', () => {
115
- expect(Tick.fromPrice(' 1.0 ')).toBe(0)
116
- expect(Tick.fromPrice(' 1.001 ')).toBe(100)
117
- })
118
- })
119
-
120
- describe('round-trip conversions', () => {
121
- test('tick -> price -> tick preserves tick values exactly', () => {
122
- const ticks = [-2000, -1000, -100, -1, 0, 1, 100, 1000, 2000]
123
- for (const tick of ticks) {
124
- const price = Tick.toPrice(tick)
125
- const roundTripTick = Tick.fromPrice(price)
126
- expect(roundTripTick).toBe(tick)
127
- }
128
- })
129
-
130
- test('price -> tick -> price preserves price strings exactly', () => {
131
- const prices = ['0.98', '0.99', '1', '1.01', '1.02']
132
- for (const price of prices) {
133
- const tick = Tick.fromPrice(price)
134
- const roundTripPrice = Tick.toPrice(tick)
135
- expect(roundTripPrice).toBe(price)
136
- }
137
- })
138
-
139
- test('handles arbitrary precision in input strings', () => {
140
- // Shorter decimal strings should round-trip correctly
141
- expect(Tick.toPrice(Tick.fromPrice('1.0'))).toBe('1')
142
- expect(Tick.toPrice(Tick.fromPrice('0.999'))).toBe('0.999')
143
-
144
- // Longer decimal strings get truncated to 5 decimals
145
- expect(Tick.toPrice(Tick.fromPrice('1.000019999'))).toBe('1.00001')
146
- })
147
- })
148
-
149
- describe('error handling', () => {
150
- test('InvalidPriceFormatError is catchable and has correct properties', () => {
151
- try {
152
- Tick.fromPrice('invalid')
153
- expect.fail('Should have thrown')
154
- } catch (error) {
155
- expect(error).toBeInstanceOf(Tick.InvalidPriceFormatError)
156
- expect(error).toHaveProperty('name', 'Tick.InvalidPriceFormatError')
157
- expect((error as Error).message).toContain('Invalid price format')
158
- expect((error as Error).message).toContain('invalid')
159
- expect((error as Error).message).toContain(
160
- 'Price must be a decimal number string',
161
- )
162
- }
163
- })
164
-
165
- test('TickOutOfBoundsError is catchable and has correct properties', () => {
166
- try {
167
- Tick.toPrice(-2001)
168
- expect.fail('Should have thrown')
169
- } catch (error) {
170
- expect(error).toBeInstanceOf(Tick.TickOutOfBoundsError)
171
- expect(error).toHaveProperty('name', 'Tick.TickOutOfBoundsError')
172
- // BaseError appends metaMessages to the message
173
- expect((error as Error).message).toContain('Tick -2001 is out of bounds.')
174
- expect((error as Error).message).toContain(
175
- 'Tick must be between -2000 and 2000.',
176
- )
177
- }
178
- })
179
-
180
- test('PriceOutOfBoundsError is catchable and has correct properties', () => {
181
- try {
182
- Tick.fromPrice('0.979')
183
- expect.fail('Should have thrown')
184
- } catch (error) {
185
- expect(error).toBeInstanceOf(Tick.PriceOutOfBoundsError)
186
- expect(error).toHaveProperty('name', 'Tick.PriceOutOfBoundsError')
187
- expect((error as Error).message).toContain(
188
- 'Price "0.979" results in tick -2100 which is out of bounds.',
189
- )
190
- expect((error as Error).message).toContain(
191
- 'Tick must be between -2000 and 2000.',
192
- )
193
- }
194
- })
195
-
196
- test('can distinguish between error types', () => {
197
- try {
198
- Tick.fromPrice('invalid')
199
- } catch (error) {
200
- if (error instanceof Tick.InvalidPriceFormatError) {
201
- expect(true).toBe(true) // Successfully caught as InvalidPriceFormatError
202
- } else {
203
- expect.fail('Should be InvalidPriceFormatError')
204
- }
205
- }
206
-
207
- try {
208
- Tick.toPrice(-2001)
209
- } catch (error) {
210
- if (error instanceof Tick.TickOutOfBoundsError) {
211
- expect(true).toBe(true) // Successfully caught as TickOutOfBoundsError
212
- } else {
213
- expect.fail('Should be TickOutOfBoundsError')
214
- }
215
- }
216
-
217
- try {
218
- Tick.fromPrice('0.979')
219
- } catch (error) {
220
- if (error instanceof Tick.PriceOutOfBoundsError) {
221
- expect(true).toBe(true) // Successfully caught as PriceOutOfBoundsError
222
- } else {
223
- expect.fail('Should be PriceOutOfBoundsError')
224
- }
225
- }
226
- })
227
- })
228
-
229
- describe('precision and edge cases', () => {
230
- test('handles very small price increments', () => {
231
- // 0.1 bps = 0.001% = 0.00001 in decimal
232
- expect(Tick.fromPrice('1.00001')).toBe(1)
233
- expect(Tick.fromPrice('1.00002')).toBe(2)
234
- })
235
-
236
- test('price scale maintains exact 5 decimal precision', () => {
237
- // The price scale is 100,000 which gives us exactly 5 decimal places
238
- const price0 = Tick.toPrice(0)
239
- const price1 = Tick.toPrice(1)
240
- expect(price0).toBe('1')
241
- expect(price1).toBe('1.00001')
242
-
243
- // Verify exact difference
244
- const diff = Number(price1) - Number(price0)
245
- expect(diff).toBeCloseTo(0.00001, 10)
246
- })
247
-
248
- test('symmetric around 1.0', () => {
249
- // +100 ticks should have same magnitude as -100 ticks from 1.0
250
- const priceUp = Tick.toPrice(100)
251
- const priceDown = Tick.toPrice(-100)
252
- expect(priceUp).toBe('1.001')
253
- expect(priceDown).toBe('0.999')
254
-
255
- const upDiff = Number(priceUp) - 1.0
256
- const downDiff = 1.0 - Number(priceDown)
257
- expect(upDiff).toBeCloseTo(downDiff, 10)
258
- })
259
-
260
- test('validates 2% range', () => {
261
- // At minimum tick, price should be exactly 2% below 1.0
262
- const minPrice = Tick.toPrice(Tick.minTick)
263
- expect(minPrice).toBe('0.98')
264
- expect((1.0 - Number(minPrice)) / 1.0).toBeCloseTo(0.02, 10)
265
-
266
- // At maximum tick, price should be exactly 2% above 1.0
267
- const maxPrice = Tick.toPrice(Tick.maxTick)
268
- expect(maxPrice).toBe('1.02')
269
- expect((Number(maxPrice) - 1.0) / 1.0).toBeCloseTo(0.02, 10)
270
- })
271
-
272
- test('no floating point precision errors', () => {
273
- // String-based parsing should eliminate float precision issues
274
- expect(Tick.fromPrice('0.99999')).toBe(-1)
275
- expect(Tick.fromPrice('1.00001')).toBe(1)
276
-
277
- // These would potentially fail with float arithmetic
278
- expect(Tick.fromPrice('0.98001')).toBe(-1999)
279
- expect(Tick.fromPrice('1.01999')).toBe(1999)
280
- })
281
- })
package/src/ox/Tick.ts DELETED
@@ -1,181 +0,0 @@
1
- import * as Errors from 'ox/Errors'
2
-
3
- /**
4
- * Minimum allowed tick value.
5
- */
6
- export const minTick = -2000
7
-
8
- /**
9
- * Maximum allowed tick value.
10
- */
11
- export const maxTick = 2000
12
-
13
- /**
14
- * Price scaling factor (5 decimal places for 0.1 bps precision).
15
- *
16
- * @description
17
- * The DEX uses a tick-based pricing system where:
18
- * - Tick size: 0.1 bps (basis points)
19
- * - Price range: ±2% from 1.0 (ticks from -2000 to +2000)
20
- */
21
- export const priceScale = 100_000
22
-
23
- /**
24
- * Tick type.
25
- */
26
- export type Tick = number
27
-
28
- /**
29
- * Converts a tick to a price string.
30
- *
31
- * @example
32
- * ```ts
33
- * import { Tick } from 'tempo.ts/viem'
34
- *
35
- * // Tick 0 = price of 1.0
36
- * const price1 = Tick.toPrice(0) // "1"
37
- *
38
- * // Tick 100 = price of 1.001 (0.1% higher)
39
- * const price2 = Tick.toPrice(100) // "1.001"
40
- *
41
- * // Tick -100 = price of 0.999 (0.1% lower)
42
- * const price3 = Tick.toPrice(-100) // "0.999"
43
- * ```
44
- *
45
- * @param tick - The tick value (range: -2000 to +2000).
46
- * @returns The price as a string with exact decimal representation.
47
- * @throws {TickOutOfBoundsError} If tick is out of bounds.
48
- */
49
- export function toPrice(tick: toPrice.Tick): toPrice.ReturnType {
50
- if (tick < minTick || tick > maxTick) {
51
- throw new TickOutOfBoundsError({ tick })
52
- }
53
- // Use integer arithmetic to avoid floating point errors
54
- const price = priceScale + tick
55
- const whole = Math.floor(price / priceScale)
56
-
57
- let decimal = (price % priceScale).toString().padStart(5, '0')
58
- decimal = decimal.replace(/0+$/, '')
59
-
60
- if (decimal.length === 0) return whole.toString()
61
- return `${whole}.${decimal}`
62
- }
63
-
64
- export declare namespace toPrice {
65
- export type Tick = number
66
- export type ReturnType = string
67
- }
68
-
69
- /**
70
- * Converts a price string to a tick.
71
- *
72
- * @example
73
- * ```ts
74
- * import { Tick } from 'tempo.ts/viem'
75
- *
76
- * // Price of 1.0 = tick 0
77
- * const tick1 = Tick.fromPrice('1.0') // 0
78
- * const tick2 = Tick.fromPrice('1.00000') // 0
79
- *
80
- * // Price of 1.001 = tick 100
81
- * const tick3 = Tick.fromPrice('1.001') // 100
82
- *
83
- * // Price of 0.999 = tick -100
84
- * const tick4 = Tick.fromPrice('0.999') // -100
85
- * ```
86
- *
87
- * @param price - The price as a string (e.g., "1.001", "0.999").
88
- * @returns The tick value.
89
- * @throws {InvalidPriceTypeError} If the price is not a string.
90
- * @throws {InvalidPriceFormatError} If the price format is invalid.
91
- * @throws {PriceOutOfBoundsError} If the resulting tick is out of bounds.
92
- */
93
- export function fromPrice(price: fromPrice.Price): fromPrice.ReturnType {
94
- const priceStr = price.trim()
95
- if (!/^-?\d+(\.\d+)?$/.test(priceStr))
96
- throw new InvalidPriceFormatError({ price })
97
-
98
- // Parse price using string manipulation to avoid float precision issues
99
- const [w, d = '0'] = priceStr.split('.')
100
- const whole = BigInt(w!)
101
-
102
- // Pad or truncate decimal to exactly 5 digits
103
- const decimal = BigInt(d.padEnd(5, '0').slice(0, 5))
104
-
105
- // Calculate price
106
- const priceInt = whole * BigInt(priceScale) + decimal
107
-
108
- // Calculate tick
109
- const tick = Number(priceInt - BigInt(priceScale))
110
-
111
- if (tick < minTick || tick > maxTick)
112
- throw new PriceOutOfBoundsError({ price, tick })
113
-
114
- return tick
115
- }
116
-
117
- export declare namespace fromPrice {
118
- export type Price = string
119
- export type ReturnType = number
120
- }
121
-
122
- /**
123
- * Error thrown when a tick value is out of the allowed bounds.
124
- */
125
- export class TickOutOfBoundsError extends Errors.BaseError {
126
- override readonly name = 'Tick.TickOutOfBoundsError'
127
-
128
- constructor(options: TickOutOfBoundsError.Options) {
129
- super(`Tick ${options.tick} is out of bounds.`, {
130
- metaMessages: [`Tick must be between ${minTick} and ${maxTick}.`],
131
- })
132
- }
133
- }
134
-
135
- export declare namespace TickOutOfBoundsError {
136
- export type Options = {
137
- tick: number
138
- }
139
- }
140
-
141
- /**
142
- * Error thrown when a price string has an invalid format.
143
- */
144
- export class InvalidPriceFormatError extends Errors.BaseError {
145
- override readonly name = 'Tick.InvalidPriceFormatError'
146
-
147
- constructor(options: InvalidPriceFormatError.Options) {
148
- super(`Invalid price format: "${options.price}".`, {
149
- metaMessages: ['Price must be a decimal number string (e.g., "1.001").'],
150
- })
151
- }
152
- }
153
-
154
- export declare namespace InvalidPriceFormatError {
155
- export type Options = {
156
- price: string
157
- }
158
- }
159
-
160
- /**
161
- * Error thrown when a price string results in an out-of-bounds tick.
162
- */
163
- export class PriceOutOfBoundsError extends Errors.BaseError {
164
- override readonly name = 'Tick.PriceOutOfBoundsError'
165
-
166
- constructor(options: PriceOutOfBoundsError.Options) {
167
- super(
168
- `Price "${options.price}" results in tick ${options.tick} which is out of bounds.`,
169
- {
170
- metaMessages: [`Tick must be between ${minTick} and ${maxTick}.`],
171
- },
172
- )
173
- }
174
- }
175
-
176
- export declare namespace PriceOutOfBoundsError {
177
- export type Options = {
178
- price: string
179
- tick: number
180
- }
181
- }
@@ -1,40 +0,0 @@
1
- import { TokenId } from 'tempo.ts/ox'
2
- import { expect, test } from 'vitest'
3
-
4
- test('from', () => {
5
- expect(TokenId.from(0n)).toBe(0n)
6
- expect(TokenId.from(0x1)).toBe(1n)
7
- expect(TokenId.from(0xdef)).toBe(0xdefn)
8
- expect(TokenId.from('0x20c0000000000000000000000000000000000000')).toBe(0n)
9
- expect(TokenId.from('0x20c0000000000000000000000000000000000001')).toBe(1n)
10
- expect(TokenId.from('0x20c0000000000000000000000000000000000def')).toBe(
11
- 0xdefn,
12
- )
13
- })
14
-
15
- test('fromAddress', () => {
16
- expect(
17
- TokenId.fromAddress('0x20c0000000000000000000000000000000000000'),
18
- ).toBe(0n)
19
- expect(
20
- TokenId.fromAddress('0x20c0000000000000000000000000000000000001'),
21
- ).toBe(1n)
22
- expect(
23
- TokenId.fromAddress('0x20c0000000000000000000000000000000000def'),
24
- ).toBe(0xdefn)
25
- })
26
-
27
- test('toAddress', () => {
28
- expect(TokenId.toAddress(0n)).toBe(
29
- '0x20c0000000000000000000000000000000000000',
30
- )
31
- expect(TokenId.toAddress('0x20c0000000000000000000000000000000000000')).toBe(
32
- '0x20c0000000000000000000000000000000000000',
33
- )
34
- expect(TokenId.toAddress(1n)).toBe(
35
- '0x20c0000000000000000000000000000000000001',
36
- )
37
- expect(TokenId.toAddress(0xdefn)).toBe(
38
- '0x20c0000000000000000000000000000000000def',
39
- )
40
- })
package/src/ox/TokenId.ts DELETED
@@ -1,50 +0,0 @@
1
- import * as Address from 'ox/Address'
2
- import * as Hex from 'ox/Hex'
3
-
4
- const tip20Prefix = '0x20c0'
5
-
6
- export type TokenId = bigint
7
- export type TokenIdOrAddress = TokenId | Address.Address
8
-
9
- /**
10
- * Converts a token ID or address to a token ID.
11
- *
12
- * @param tokenIdOrAddress - The token ID or address.
13
- * @returns The token ID.
14
- */
15
- export function from(tokenIdOrAddress: TokenIdOrAddress | number): TokenId {
16
- if (
17
- typeof tokenIdOrAddress === 'bigint' ||
18
- typeof tokenIdOrAddress === 'number'
19
- )
20
- return BigInt(tokenIdOrAddress)
21
- return fromAddress(tokenIdOrAddress)
22
- }
23
-
24
- /**
25
- * Converts a TIP20 token address to a token ID.
26
- *
27
- * @param address - The token address.
28
- * @returns The token ID.
29
- */
30
- export function fromAddress(address: Address.Address): TokenId {
31
- if (!address.toLowerCase().startsWith(tip20Prefix))
32
- throw new Error('invalid tip20 address.')
33
- return Hex.toBigInt(Hex.slice(address, tip20Prefix.length))
34
- }
35
-
36
- /**
37
- * Converts a TIP20 token ID to an address.
38
- *
39
- * @param tokenId - The token ID.
40
- * @returns The address.
41
- */
42
- export function toAddress(tokenId: TokenIdOrAddress): Address.Address {
43
- if (typeof tokenId === 'string') {
44
- Address.assert(tokenId)
45
- return tokenId
46
- }
47
-
48
- const tokenIdHex = Hex.fromNumber(tokenId, { size: 18 })
49
- return Hex.concat(tip20Prefix, tokenIdHex)
50
- }
@@ -1,16 +0,0 @@
1
- import { Hash, Hex } from 'ox'
2
- import { TokenRole } from 'tempo.ts/ox'
3
- import { expect, test } from 'vitest'
4
-
5
- test('serialize', () => {
6
- TokenRole.roles.forEach((role) => {
7
- if (role === 'defaultAdmin')
8
- expect(TokenRole.serialize(role)).toBe(
9
- '0x0000000000000000000000000000000000000000000000000000000000000000',
10
- )
11
- else
12
- expect(TokenRole.serialize(role)).toBe(
13
- Hash.keccak256(Hex.fromString(TokenRole.toPreHashed[role])),
14
- )
15
- })
16
- })
@@ -1,27 +0,0 @@
1
- import * as Hash from 'ox/Hash'
2
- import * as Hex from 'ox/Hex'
3
-
4
- export const roles = [
5
- 'defaultAdmin',
6
- 'pause',
7
- 'unpause',
8
- 'issuer',
9
- 'burnBlocked',
10
- ] as const
11
- export type TokenRole = (typeof roles)[number]
12
-
13
- export const toPreHashed = {
14
- defaultAdmin: 'DEFAULT_ADMIN_ROLE',
15
- pause: 'PAUSE_ROLE',
16
- unpause: 'UNPAUSE_ROLE',
17
- issuer: 'ISSUER_ROLE',
18
- burnBlocked: 'BURN_BLOCKED_ROLE',
19
- } as const satisfies Record<TokenRole, string>
20
-
21
- export function serialize(role: TokenRole) {
22
- if (role === 'defaultAdmin')
23
- return '0x0000000000000000000000000000000000000000000000000000000000000000'
24
- return Hash.keccak256(
25
- Hex.fromString(toPreHashed[role as keyof typeof toPreHashed] ?? role),
26
- )
27
- }