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.
- package/README.md +33 -2
- package/dist/chains.d.ts +509 -115
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +18 -9
- package/dist/chains.js.map +1 -1
- package/dist/ox/Order.d.ts +92 -0
- package/dist/ox/Order.d.ts.map +1 -0
- package/dist/ox/Order.js +88 -0
- package/dist/ox/Order.js.map +1 -0
- package/dist/ox/OrdersFilters.d.ts +72 -0
- package/dist/ox/OrdersFilters.d.ts.map +1 -0
- package/dist/ox/OrdersFilters.js +100 -0
- package/dist/ox/OrdersFilters.js.map +1 -0
- package/dist/ox/Pagination.d.ts +128 -0
- package/dist/ox/Pagination.d.ts.map +1 -0
- package/dist/ox/Pagination.js +78 -0
- package/dist/ox/Pagination.js.map +1 -0
- package/dist/ox/PoolId.d.ts +18 -0
- package/dist/ox/PoolId.d.ts.map +1 -0
- package/dist/ox/PoolId.js +13 -0
- package/dist/ox/PoolId.js.map +1 -0
- package/dist/ox/RpcSchema.d.ts +32 -0
- package/dist/ox/RpcSchema.d.ts.map +1 -0
- package/dist/ox/RpcSchema.js +2 -0
- package/dist/ox/RpcSchema.js.map +1 -0
- package/dist/ox/SignatureEnvelope.d.ts +1 -1
- package/dist/ox/SignatureEnvelope.d.ts.map +1 -1
- package/dist/ox/SignatureEnvelope.js.map +1 -1
- package/dist/{viem → ox}/Tick.d.ts +4 -0
- package/dist/ox/Tick.d.ts.map +1 -0
- package/dist/ox/Tick.js.map +1 -0
- package/dist/ox/Transaction.d.ts.map +1 -1
- package/dist/ox/Transaction.js +2 -1
- package/dist/ox/Transaction.js.map +1 -1
- package/dist/ox/TransactionEnvelopeAA.d.ts +6 -6
- package/dist/ox/TransactionEnvelopeAA.d.ts.map +1 -1
- package/dist/ox/TransactionEnvelopeAA.js +4 -2
- package/dist/ox/TransactionEnvelopeAA.js.map +1 -1
- package/dist/ox/TransactionRequest.d.ts +4 -0
- package/dist/ox/TransactionRequest.d.ts.map +1 -1
- package/dist/ox/TransactionRequest.js.map +1 -1
- package/dist/ox/index.d.ts +6 -0
- package/dist/ox/index.d.ts.map +1 -1
- package/dist/ox/index.js +6 -0
- package/dist/ox/index.js.map +1 -1
- package/dist/prool/Instance.d.ts.map +1 -1
- package/dist/prool/Instance.js +20 -4
- package/dist/prool/Instance.js.map +1 -1
- package/dist/viem/Abis.d.ts +1469 -1082
- package/dist/viem/Abis.d.ts.map +1 -1
- package/dist/viem/Abis.js +932 -671
- package/dist/viem/Abis.js.map +1 -1
- package/dist/viem/Account.d.ts +150 -0
- package/dist/viem/Account.d.ts.map +1 -0
- package/dist/viem/Account.js +221 -0
- package/dist/viem/Account.js.map +1 -0
- package/dist/viem/Actions/amm.d.ts +80 -118
- package/dist/viem/Actions/amm.d.ts.map +1 -1
- package/dist/viem/Actions/amm.js +47 -116
- package/dist/viem/Actions/amm.js.map +1 -1
- package/dist/viem/Actions/dex.d.ts +889 -633
- package/dist/viem/Actions/dex.d.ts.map +1 -1
- package/dist/viem/Actions/dex.js +99 -0
- package/dist/viem/Actions/dex.js.map +1 -1
- package/dist/viem/Actions/fee.d.ts +3 -17
- package/dist/viem/Actions/fee.d.ts.map +1 -1
- package/dist/viem/Actions/fee.js.map +1 -1
- package/dist/viem/Actions/index.d.ts +1 -0
- package/dist/viem/Actions/index.d.ts.map +1 -1
- package/dist/viem/Actions/index.js +1 -0
- package/dist/viem/Actions/index.js.map +1 -1
- package/dist/viem/Actions/reward.d.ts +3236 -0
- package/dist/viem/Actions/reward.d.ts.map +1 -0
- package/dist/viem/Actions/reward.js +725 -0
- package/dist/viem/Actions/reward.js.map +1 -0
- package/dist/viem/Actions/token.d.ts +4295 -2646
- package/dist/viem/Actions/token.d.ts.map +1 -1
- package/dist/viem/Actions/token.js +214 -335
- package/dist/viem/Actions/token.js.map +1 -1
- package/dist/viem/Addresses.d.ts +1 -2
- package/dist/viem/Addresses.d.ts.map +1 -1
- package/dist/viem/Addresses.js +1 -2
- package/dist/viem/Addresses.js.map +1 -1
- package/dist/viem/Chain.d.ts +38 -12
- package/dist/viem/Chain.d.ts.map +1 -1
- package/dist/viem/Chain.js +27 -18
- package/dist/viem/Chain.js.map +1 -1
- package/dist/viem/Decorator.d.ts +959 -405
- package/dist/viem/Decorator.d.ts.map +1 -1
- package/dist/viem/Decorator.js +13 -5
- package/dist/viem/Decorator.js.map +1 -1
- package/dist/viem/Formatters.d.ts +8 -1
- package/dist/viem/Formatters.d.ts.map +1 -1
- package/dist/viem/Formatters.js +17 -0
- package/dist/viem/Formatters.js.map +1 -1
- package/dist/viem/P256.d.ts +2 -0
- package/dist/viem/P256.d.ts.map +1 -0
- package/dist/viem/P256.js +2 -0
- package/dist/viem/P256.js.map +1 -0
- package/dist/viem/Secp256k1.d.ts +2 -0
- package/dist/viem/Secp256k1.d.ts.map +1 -0
- package/dist/viem/Secp256k1.js +2 -0
- package/dist/viem/Secp256k1.js.map +1 -0
- package/dist/viem/TokenIds.d.ts +1 -2
- package/dist/viem/TokenIds.d.ts.map +1 -1
- package/dist/viem/TokenIds.js +1 -2
- package/dist/viem/TokenIds.js.map +1 -1
- package/dist/viem/Transaction.d.ts +1 -1
- package/dist/viem/Transaction.d.ts.map +1 -1
- package/dist/viem/Transaction.js +46 -5
- package/dist/viem/Transaction.js.map +1 -1
- package/dist/viem/WebAuthnP256.d.ts +79 -0
- package/dist/viem/WebAuthnP256.d.ts.map +1 -0
- package/dist/viem/WebAuthnP256.js +95 -0
- package/dist/viem/WebAuthnP256.js.map +1 -0
- package/dist/viem/WebCryptoP256.d.ts +2 -0
- package/dist/viem/WebCryptoP256.d.ts.map +1 -0
- package/dist/viem/WebCryptoP256.js +2 -0
- package/dist/viem/WebCryptoP256.js.map +1 -0
- package/dist/viem/index.d.ts +6 -3
- package/dist/viem/index.d.ts.map +1 -1
- package/dist/viem/index.js +6 -3
- package/dist/viem/index.js.map +1 -1
- package/dist/viem/internal/account.d.ts +24 -0
- package/dist/viem/internal/account.d.ts.map +1 -0
- package/dist/viem/internal/account.js +68 -0
- package/dist/viem/internal/account.js.map +1 -0
- package/dist/viem/internal/types.d.ts +10 -0
- package/dist/viem/internal/types.d.ts.map +1 -1
- package/dist/wagmi/Actions/amm.d.ts +428 -0
- package/dist/wagmi/Actions/amm.d.ts.map +1 -0
- package/dist/wagmi/Actions/amm.js +472 -0
- package/dist/wagmi/Actions/amm.js.map +1 -0
- package/dist/wagmi/Actions/dex.d.ts +908 -0
- package/dist/wagmi/Actions/dex.d.ts.map +1 -0
- package/dist/wagmi/Actions/dex.js +1023 -0
- package/dist/wagmi/Actions/dex.js.map +1 -0
- package/dist/wagmi/Actions/fee.d.ts +111 -0
- package/dist/wagmi/Actions/fee.d.ts.map +1 -0
- package/dist/wagmi/Actions/fee.js +126 -0
- package/dist/wagmi/Actions/fee.js.map +1 -0
- package/dist/wagmi/Actions/index.d.ts +6 -0
- package/dist/wagmi/Actions/index.d.ts.map +1 -0
- package/dist/wagmi/Actions/index.js +6 -0
- package/dist/wagmi/Actions/index.js.map +1 -0
- package/dist/wagmi/Actions/reward.d.ts +348 -0
- package/dist/wagmi/Actions/reward.d.ts.map +1 -0
- package/dist/wagmi/Actions/reward.js +388 -0
- package/dist/wagmi/Actions/reward.js.map +1 -0
- package/dist/wagmi/Actions/token.d.ts +1546 -0
- package/dist/wagmi/Actions/token.d.ts.map +1 -0
- package/dist/wagmi/Actions/token.js +1712 -0
- package/dist/wagmi/Actions/token.js.map +1 -0
- package/dist/wagmi/Connector.d.ts +73 -0
- package/dist/wagmi/Connector.d.ts.map +1 -0
- package/dist/wagmi/Connector.js +249 -0
- package/dist/wagmi/Connector.js.map +1 -0
- package/dist/wagmi/Hooks/amm.d.ts +421 -0
- package/dist/wagmi/Hooks/amm.d.ts.map +1 -0
- package/dist/wagmi/Hooks/amm.js +504 -0
- package/dist/wagmi/Hooks/amm.js.map +1 -0
- package/dist/wagmi/Hooks/dex.d.ts +816 -0
- package/dist/wagmi/Hooks/dex.d.ts.map +1 -0
- package/dist/wagmi/Hooks/dex.js +973 -0
- package/dist/wagmi/Hooks/dex.js.map +1 -0
- package/dist/wagmi/Hooks/fee.d.ts +97 -0
- package/dist/wagmi/Hooks/fee.d.ts.map +1 -0
- package/dist/wagmi/Hooks/fee.js +109 -0
- package/dist/wagmi/Hooks/fee.js.map +1 -0
- package/dist/wagmi/Hooks/index.d.ts +6 -0
- package/dist/wagmi/Hooks/index.d.ts.map +1 -0
- package/dist/wagmi/Hooks/index.js +6 -0
- package/dist/wagmi/Hooks/index.js.map +1 -0
- package/dist/wagmi/Hooks/reward.d.ts +307 -0
- package/dist/wagmi/Hooks/reward.d.ts.map +1 -0
- package/dist/wagmi/Hooks/reward.js +349 -0
- package/dist/wagmi/Hooks/reward.js.map +1 -0
- package/dist/wagmi/Hooks/token.d.ts +1388 -0
- package/dist/wagmi/Hooks/token.d.ts.map +1 -0
- package/dist/wagmi/Hooks/token.js +1657 -0
- package/dist/wagmi/Hooks/token.js.map +1 -0
- package/dist/wagmi/index.d.ts +4 -0
- package/dist/wagmi/index.d.ts.map +1 -0
- package/dist/wagmi/index.js +4 -0
- package/dist/wagmi/index.js.map +1 -0
- package/package.json +54 -10
- package/src/chains.ts +19 -9
- package/src/ox/Order.test.ts +78 -0
- package/src/ox/Order.ts +125 -0
- package/src/ox/OrdersFilters.test.ts +182 -0
- package/src/ox/OrdersFilters.ts +125 -0
- package/src/ox/Pagination.test.ts +162 -0
- package/src/ox/Pagination.ts +164 -0
- package/src/ox/PoolId.test.ts +33 -0
- package/src/ox/PoolId.ts +27 -0
- package/src/ox/RpcSchema.ts +35 -0
- package/src/ox/SignatureEnvelope.ts +3 -1
- package/src/{viem → ox}/Tick.test.ts +1 -1
- package/src/{viem → ox}/Tick.ts +5 -0
- package/src/ox/Transaction.test.ts +1 -1
- package/src/ox/Transaction.ts +2 -1
- package/src/ox/TransactionEnvelopeAA.test.ts +239 -96
- package/src/ox/TransactionEnvelopeAA.ts +9 -7
- package/src/ox/TransactionRequest.ts +4 -0
- package/src/ox/index.ts +6 -0
- package/src/prool/Instance.ts +51 -37
- package/src/prool/internal/chain.json +104 -52
- package/src/tsconfig.json +9 -0
- package/src/viem/Abis.ts +972 -710
- package/src/viem/Account.ts +279 -0
- package/src/viem/Actions/__snapshots__/dex.test.ts.snap +850 -0
- package/src/viem/Actions/amm.test.ts +98 -169
- package/src/viem/Actions/amm.ts +68 -155
- package/src/viem/Actions/dex.test.ts +563 -484
- package/src/viem/Actions/dex.ts +173 -0
- package/src/viem/Actions/fee.test.ts +23 -34
- package/src/viem/Actions/fee.ts +7 -0
- package/src/viem/Actions/index.ts +1 -0
- package/src/viem/Actions/policy.test.ts +19 -33
- package/src/viem/Actions/reward.test.ts +457 -0
- package/src/viem/Actions/reward.ts +999 -0
- package/src/viem/Actions/token.test.ts +453 -287
- package/src/viem/Actions/token.ts +452 -540
- package/src/viem/Addresses.ts +1 -2
- package/src/viem/Chain.ts +70 -20
- package/src/viem/Decorator.test.ts +2 -1
- package/src/viem/Decorator.ts +996 -421
- package/src/viem/Formatters.ts +31 -5
- package/src/viem/P256.ts +1 -0
- package/src/viem/Secp256k1.ts +1 -0
- package/src/viem/TokenIds.ts +1 -2
- package/src/viem/Transaction.ts +53 -7
- package/src/viem/WebAuthnP256.ts +140 -0
- package/src/viem/WebCryptoP256.ts +1 -0
- package/src/viem/e2e.test.ts +1126 -297
- package/src/viem/index.ts +6 -3
- package/src/viem/internal/account.ts +107 -0
- package/src/viem/internal/types.ts +9 -0
- package/src/wagmi/Actions/__snapshots__/dex.test.ts.snap +310 -0
- package/src/wagmi/Actions/amm.test.ts +198 -0
- package/src/wagmi/Actions/amm.ts +691 -0
- package/src/wagmi/Actions/dex.test.ts +1507 -0
- package/src/wagmi/Actions/dex.ts +1640 -0
- package/src/wagmi/Actions/fee.test.ts +63 -0
- package/src/wagmi/Actions/fee.ts +208 -0
- package/src/wagmi/Actions/index.ts +5 -0
- package/src/wagmi/Actions/reward.test.ts +210 -0
- package/src/wagmi/Actions/reward.ts +632 -0
- package/src/wagmi/Actions/token.test.ts +1308 -0
- package/src/wagmi/Actions/token.ts +2613 -0
- package/src/wagmi/Connector.test.ts +53 -0
- package/src/wagmi/Connector.ts +367 -0
- package/src/wagmi/Hooks/__snapshots__/dex.test.ts.snap +457 -0
- package/src/wagmi/Hooks/amm.test.ts +424 -0
- package/src/wagmi/Hooks/amm.ts +806 -0
- package/src/wagmi/Hooks/dex.test.ts +1017 -0
- package/src/wagmi/Hooks/dex.ts +1685 -0
- package/src/wagmi/Hooks/fee.test.ts +166 -0
- package/src/wagmi/Hooks/fee.ts +206 -0
- package/src/wagmi/Hooks/index.ts +5 -0
- package/src/wagmi/Hooks/reward.test.ts +219 -0
- package/src/wagmi/Hooks/reward.ts +672 -0
- package/src/wagmi/Hooks/token.test.ts +1670 -0
- package/src/wagmi/Hooks/token.ts +2906 -0
- package/src/wagmi/index.ts +3 -0
- package/src/wagmi/internal/types.ts +16 -0
- package/dist/viem/Client.d.ts +0 -27
- package/dist/viem/Client.d.ts.map +0 -1
- package/dist/viem/Client.js +0 -28
- package/dist/viem/Client.js.map +0 -1
- package/dist/viem/Tick.d.ts.map +0 -1
- package/dist/viem/Tick.js.map +0 -1
- package/src/viem/Client.bench-d.ts +0 -8
- package/src/viem/Client.test.ts +0 -178
- package/src/viem/Client.ts +0 -91
- /package/dist/{viem → ox}/Tick.js +0 -0
|
@@ -1,91 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { describe, expect, test } from 'vitest'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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:
|
|
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:
|
|
103
|
-
maxAmountIn:
|
|
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:
|
|
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:
|
|
135
|
-
maxAmountIn:
|
|
65
|
+
amountOut: parseUnits('100', 6),
|
|
66
|
+
maxAmountIn: parseUnits('50', 6), // Way too low for 1% premium
|
|
136
67
|
}),
|
|
137
|
-
).rejects.
|
|
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:
|
|
164
|
-
maxAmountIn:
|
|
81
|
+
amountOut: parseUnits('100', 6),
|
|
82
|
+
maxAmountIn: parseUnits('150', 6),
|
|
165
83
|
}),
|
|
166
|
-
).rejects.
|
|
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:
|
|
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,
|
|
204
|
-
|
|
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(
|
|
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:
|
|
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 =
|
|
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:
|
|
245
|
-
token:
|
|
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.
|
|
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.
|
|
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,
|
|
304
|
-
|
|
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(
|
|
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:
|
|
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 =
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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:
|
|
298
|
+
amountOut: parseUnits('100', 6),
|
|
431
299
|
}),
|
|
432
|
-
).rejects.
|
|
433
|
-
|
|
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:
|
|
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(
|
|
470
|
-
expect(order.remaining).toBe(
|
|
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:
|
|
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(
|
|
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.
|
|
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:
|
|
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(
|
|
539
|
-
expect(orderBefore.remaining).toBe(
|
|
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:
|
|
546
|
-
maxAmountIn:
|
|
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(
|
|
554
|
-
expect(orderAfter.remaining).toBeLessThan(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
782
|
-
maxAmountIn:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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:
|
|
1059
|
+
amountIn: parseUnits('100', 6),
|
|
866
1060
|
}),
|
|
867
|
-
).rejects.
|
|
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(
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
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(
|
|
1083
|
+
expect(orderId).toBeGreaterThan(0n)
|
|
1084
|
+
expect(token).toBe(base)
|
|
899
1085
|
expect(result).toMatchInlineSnapshot(`
|
|
900
1086
|
{
|
|
901
|
-
"amount":
|
|
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 {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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(
|
|
1107
|
+
expect(orderId2).toBeGreaterThan(0n)
|
|
1108
|
+
expect(token2).toBe(base)
|
|
922
1109
|
expect(result2).toMatchInlineSnapshot(`
|
|
923
1110
|
{
|
|
924
|
-
"amount":
|
|
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:
|
|
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:
|
|
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:
|
|
1156
|
+
amount: parseUnits('10', 6),
|
|
972
1157
|
type: 'buy',
|
|
973
1158
|
tick: Tick.maxTick + 1,
|
|
974
1159
|
}),
|
|
975
|
-
).rejects.
|
|
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:
|
|
1166
|
+
amount: parseUnits('10', 6),
|
|
996
1167
|
type: 'sell',
|
|
997
1168
|
tick: Tick.minTick - 1,
|
|
998
1169
|
}),
|
|
999
|
-
).rejects.
|
|
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 =
|
|
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:
|
|
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:
|
|
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 } =
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
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(
|
|
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":
|
|
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:
|
|
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:
|
|
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.
|
|
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:
|
|
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.
|
|
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:
|
|
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:
|
|
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.
|
|
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:
|
|
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.
|
|
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:
|
|
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:
|
|
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:
|
|
1267
|
-
minAmountOut:
|
|
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:
|
|
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:
|
|
1291
|
-
minAmountOut:
|
|
1395
|
+
amountIn: parseUnits('100', 6),
|
|
1396
|
+
minAmountOut: parseUnits('150', 6), // Way too high
|
|
1292
1397
|
}),
|
|
1293
|
-
).rejects.
|
|
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:
|
|
1320
|
-
minAmountOut:
|
|
1411
|
+
amountIn: parseUnits('100', 6),
|
|
1412
|
+
minAmountOut: parseUnits('50', 6),
|
|
1321
1413
|
}),
|
|
1322
|
-
).rejects.
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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)
|