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.
- package/CHANGELOG.md +30 -0
- package/README.md +0 -41
- package/dist/viem/Account.d.ts +8 -3
- package/dist/viem/Account.d.ts.map +1 -1
- package/dist/viem/Account.js +9 -2
- package/dist/viem/Account.js.map +1 -1
- package/dist/viem/Actions/amm.d.ts +1 -1
- package/dist/viem/Actions/amm.d.ts.map +1 -1
- package/dist/viem/Actions/amm.js +1 -2
- package/dist/viem/Actions/amm.js.map +1 -1
- package/dist/viem/Actions/dex.d.ts +0 -35
- package/dist/viem/Actions/dex.d.ts.map +1 -1
- package/dist/viem/Actions/dex.js +0 -43
- package/dist/viem/Actions/dex.js.map +1 -1
- package/dist/viem/Actions/fee.d.ts +1 -1
- package/dist/viem/Actions/fee.d.ts.map +1 -1
- package/dist/viem/Actions/fee.js +1 -1
- package/dist/viem/Actions/fee.js.map +1 -1
- package/dist/viem/Actions/nonce.d.ts.map +1 -1
- package/dist/viem/Actions/nonce.js +6 -4
- package/dist/viem/Actions/nonce.js.map +1 -1
- package/dist/viem/Actions/token.d.ts +1 -2
- package/dist/viem/Actions/token.d.ts.map +1 -1
- package/dist/viem/Actions/token.js +1 -2
- package/dist/viem/Actions/token.js.map +1 -1
- package/dist/viem/Chain.d.ts +34 -34
- package/dist/viem/Chain.d.ts.map +1 -1
- package/dist/viem/Chain.js +2 -0
- package/dist/viem/Chain.js.map +1 -1
- package/dist/viem/Formatters.d.ts.map +1 -1
- package/dist/viem/Formatters.js +5 -3
- package/dist/viem/Formatters.js.map +1 -1
- package/dist/viem/Transaction.d.ts +8 -5
- package/dist/viem/Transaction.d.ts.map +1 -1
- package/dist/viem/Transaction.js +13 -3
- package/dist/viem/Transaction.js.map +1 -1
- package/dist/viem/internal/types.d.ts +1 -1
- package/dist/viem/internal/types.d.ts.map +1 -1
- package/dist/wagmi/Actions/dex.d.ts +1 -45
- package/dist/wagmi/Actions/dex.d.ts.map +1 -1
- package/dist/wagmi/Actions/dex.js +0 -55
- package/dist/wagmi/Actions/dex.js.map +1 -1
- package/dist/wagmi/Connector.d.ts +1 -1
- package/dist/wagmi/Connector.d.ts.map +1 -1
- package/dist/wagmi/Connector.js +1 -2
- package/dist/wagmi/Connector.js.map +1 -1
- package/dist/wagmi/Hooks/dex.d.ts +3 -46
- package/dist/wagmi/Hooks/dex.d.ts.map +1 -1
- package/dist/wagmi/Hooks/dex.js +2 -54
- package/dist/wagmi/Hooks/dex.js.map +1 -1
- package/dist/wagmi/index.d.ts +1 -1
- package/dist/wagmi/index.d.ts.map +1 -1
- package/dist/wagmi/index.js +1 -1
- package/dist/wagmi/index.js.map +1 -1
- package/package.json +5 -23
- package/src/viem/Account.test.ts +1 -1
- package/src/viem/Account.ts +11 -2
- package/src/viem/Actions/account.ts +1 -1
- package/src/viem/Actions/amm.ts +1 -2
- package/src/viem/Actions/dex.test.ts +1 -195
- package/src/viem/Actions/dex.ts +0 -53
- package/src/viem/Actions/fee.test.ts +2 -2
- package/src/viem/Actions/fee.ts +1 -1
- package/src/viem/Actions/nonce.test.ts +27 -14
- package/src/viem/Actions/nonce.ts +6 -4
- package/src/viem/Actions/token.test.ts +18 -52
- package/src/viem/Actions/token.ts +1 -2
- package/src/viem/Chain.ts +3 -1
- package/src/viem/Decorator.ts +0 -30
- package/src/viem/Formatters.ts +9 -3
- package/src/viem/Transaction.ts +23 -7
- package/src/viem/e2e.test.ts +19 -0
- package/src/viem/index.ts +12 -1
- package/src/viem/internal/types.ts +1 -1
- package/src/wagmi/Actions/dex.test.ts +0 -26
- package/src/wagmi/Actions/dex.ts +1 -111
- package/src/wagmi/Actions/nonce.test.ts +8 -4
- package/src/wagmi/Actions/token.test.ts +2 -2
- package/src/wagmi/Connector.ts +1 -2
- package/src/wagmi/Hooks/dex.test.ts +0 -26
- package/src/wagmi/Hooks/dex.ts +1 -88
- package/src/wagmi/Hooks/nonce.test.ts +3 -3
- package/src/wagmi/index.ts +4 -1
- package/dist/chains.d.ts +0 -73
- package/dist/chains.d.ts.map +0 -1
- package/dist/chains.js +0 -51
- package/dist/chains.js.map +0 -1
- package/dist/ox/AuthorizationTempo.d.ts +0 -450
- package/dist/ox/AuthorizationTempo.d.ts.map +0 -1
- package/dist/ox/AuthorizationTempo.js +0 -433
- package/dist/ox/AuthorizationTempo.js.map +0 -1
- package/dist/ox/KeyAuthorization.d.ts +0 -356
- package/dist/ox/KeyAuthorization.d.ts.map +0 -1
- package/dist/ox/KeyAuthorization.js +0 -359
- package/dist/ox/KeyAuthorization.js.map +0 -1
- package/dist/ox/Order.d.ts +0 -92
- package/dist/ox/Order.d.ts.map +0 -1
- package/dist/ox/Order.js +0 -88
- package/dist/ox/Order.js.map +0 -1
- package/dist/ox/OrdersFilters.d.ts +0 -72
- package/dist/ox/OrdersFilters.d.ts.map +0 -1
- package/dist/ox/OrdersFilters.js +0 -100
- package/dist/ox/OrdersFilters.js.map +0 -1
- package/dist/ox/Pagination.d.ts +0 -128
- package/dist/ox/Pagination.d.ts.map +0 -1
- package/dist/ox/Pagination.js +0 -78
- package/dist/ox/Pagination.js.map +0 -1
- package/dist/ox/PoolId.d.ts +0 -18
- package/dist/ox/PoolId.d.ts.map +0 -1
- package/dist/ox/PoolId.js +0 -13
- package/dist/ox/PoolId.js.map +0 -1
- package/dist/ox/RpcSchema.d.ts +0 -32
- package/dist/ox/RpcSchema.d.ts.map +0 -1
- package/dist/ox/RpcSchema.js +0 -2
- package/dist/ox/RpcSchema.js.map +0 -1
- package/dist/ox/SignatureEnvelope.d.ts +0 -260
- package/dist/ox/SignatureEnvelope.d.ts.map +0 -1
- package/dist/ox/SignatureEnvelope.js +0 -477
- package/dist/ox/SignatureEnvelope.js.map +0 -1
- package/dist/ox/Tick.d.ts +0 -115
- package/dist/ox/Tick.d.ts.map +0 -1
- package/dist/ox/Tick.js +0 -127
- package/dist/ox/Tick.js.map +0 -1
- package/dist/ox/TokenId.d.ts +0 -25
- package/dist/ox/TokenId.d.ts.map +0 -1
- package/dist/ox/TokenId.js +0 -41
- package/dist/ox/TokenId.js.map +0 -1
- package/dist/ox/TokenRole.d.ts +0 -11
- package/dist/ox/TokenRole.d.ts.map +0 -1
- package/dist/ox/TokenRole.js +0 -22
- package/dist/ox/TokenRole.js.map +0 -1
- package/dist/ox/Transaction.d.ts +0 -201
- package/dist/ox/Transaction.d.ts.map +0 -1
- package/dist/ox/Transaction.js +0 -167
- package/dist/ox/Transaction.js.map +0 -1
- package/dist/ox/TransactionEnvelopeTempo.d.ts +0 -470
- package/dist/ox/TransactionEnvelopeTempo.d.ts.map +0 -1
- package/dist/ox/TransactionEnvelopeTempo.js +0 -547
- package/dist/ox/TransactionEnvelopeTempo.js.map +0 -1
- package/dist/ox/TransactionReceipt.d.ts +0 -155
- package/dist/ox/TransactionReceipt.d.ts.map +0 -1
- package/dist/ox/TransactionReceipt.js +0 -136
- package/dist/ox/TransactionReceipt.js.map +0 -1
- package/dist/ox/TransactionRequest.d.ts +0 -76
- package/dist/ox/TransactionRequest.d.ts.map +0 -1
- package/dist/ox/TransactionRequest.js +0 -93
- package/dist/ox/TransactionRequest.js.map +0 -1
- package/dist/ox/index.d.ts +0 -14
- package/dist/ox/index.d.ts.map +0 -1
- package/dist/ox/index.js +0 -14
- package/dist/ox/index.js.map +0 -1
- package/dist/prool/Instance.d.ts +0 -101
- package/dist/prool/Instance.d.ts.map +0 -1
- package/dist/prool/Instance.js +0 -136
- package/dist/prool/Instance.js.map +0 -1
- package/dist/prool/chain.json +0 -238
- package/dist/prool/index.d.ts +0 -2
- package/dist/prool/index.d.ts.map +0 -1
- package/dist/prool/index.js +0 -2
- package/dist/prool/index.js.map +0 -1
- package/dist/viem/Actions/account.d.ts +0 -40
- package/dist/viem/Actions/account.d.ts.map +0 -1
- package/dist/viem/Actions/account.js +0 -86
- package/dist/viem/Actions/account.js.map +0 -1
- package/dist/viem/Actions/index.d.ts +0 -10
- package/dist/viem/Actions/index.d.ts.map +0 -1
- package/dist/viem/Actions/index.js +0 -10
- package/dist/viem/Actions/index.js.map +0 -1
- package/dist/viem/Decorator.d.ts +0 -2810
- package/dist/viem/Decorator.d.ts.map +0 -1
- package/dist/viem/Decorator.js +0 -138
- package/dist/viem/Decorator.js.map +0 -1
- package/dist/viem/P256.d.ts +0 -2
- package/dist/viem/P256.d.ts.map +0 -1
- package/dist/viem/P256.js +0 -2
- package/dist/viem/P256.js.map +0 -1
- package/dist/viem/Secp256k1.d.ts +0 -2
- package/dist/viem/Secp256k1.d.ts.map +0 -1
- package/dist/viem/Secp256k1.js +0 -2
- package/dist/viem/Secp256k1.js.map +0 -1
- package/dist/viem/TokenIds.d.ts +0 -2
- package/dist/viem/TokenIds.d.ts.map +0 -1
- package/dist/viem/TokenIds.js +0 -2
- package/dist/viem/TokenIds.js.map +0 -1
- package/dist/viem/index.d.ts +0 -17
- package/dist/viem/index.d.ts.map +0 -1
- package/dist/viem/index.js +0 -17
- package/dist/viem/index.js.map +0 -1
- package/src/ox/AuthorizationTempo.test.ts +0 -1256
- package/src/ox/AuthorizationTempo.ts +0 -648
- package/src/ox/KeyAuthorization.test.ts +0 -1332
- package/src/ox/KeyAuthorization.ts +0 -540
- package/src/ox/Order.test.ts +0 -78
- package/src/ox/Order.ts +0 -125
- package/src/ox/OrdersFilters.test.ts +0 -182
- package/src/ox/OrdersFilters.ts +0 -125
- package/src/ox/Pagination.test.ts +0 -162
- package/src/ox/Pagination.ts +0 -164
- package/src/ox/PoolId.test.ts +0 -33
- package/src/ox/PoolId.ts +0 -27
- package/src/ox/RpcSchema.ts +0 -35
- package/src/ox/SignatureEnvelope.test.ts +0 -1876
- package/src/ox/SignatureEnvelope.ts +0 -791
- package/src/ox/Tick.test.ts +0 -281
- package/src/ox/Tick.ts +0 -181
- package/src/ox/TokenId.test.ts +0 -40
- package/src/ox/TokenId.ts +0 -50
- package/src/ox/TokenRole.test.ts +0 -16
- package/src/ox/TokenRole.ts +0 -27
- package/src/ox/Transaction.test.ts +0 -523
- package/src/ox/Transaction.ts +0 -332
- package/src/ox/TransactionEnvelopeTempo.test.ts +0 -1352
- package/src/ox/TransactionEnvelopeTempo.ts +0 -905
- package/src/ox/TransactionReceipt.ts +0 -190
- package/src/ox/TransactionRequest.ts +0 -147
- package/src/ox/e2e.test.ts +0 -1393
- package/src/ox/index.ts +0 -13
- package/src/prool/Instance.test.ts +0 -43
- package/src/prool/Instance.ts +0 -247
- package/src/prool/chain.json +0 -238
- package/src/prool/index.ts +0 -1
- package/src/viem/Actions/__snapshots__/dex.test.ts.snap +0 -850
- package/src/wagmi/Actions/__snapshots__/dex.test.ts.snap +0 -310
- package/src/wagmi/Hooks/__snapshots__/dex.test.ts.snap +0 -457
package/src/ox/Tick.test.ts
DELETED
|
@@ -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
|
-
}
|
package/src/ox/TokenId.test.ts
DELETED
|
@@ -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
|
-
}
|
package/src/ox/TokenRole.test.ts
DELETED
|
@@ -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
|
-
})
|
package/src/ox/TokenRole.ts
DELETED
|
@@ -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
|
-
}
|