@paraswap/dex-lib 2.34.0 → 2.35.1
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/build/abi/api3-proxy.json +46 -0
- package/build/abi/api3-server-v1.json +463 -0
- package/build/abi/quick-perps/fast-price-events.json +70 -0
- package/build/abi/quick-perps/fast-price-feed.json +741 -0
- package/build/abi/quick-perps/reader.json +313 -0
- package/build/abi/quick-perps/vault-price-feed.json +323 -0
- package/build/abi/quick-perps/vault.json +1953 -0
- package/build/composed-event-subscriber.js +8 -2
- package/build/composed-event-subscriber.js.map +1 -1
- package/build/config.js +2 -2
- package/build/dex/algebra/algebra.js +0 -12
- package/build/dex/algebra/algebra.js.map +1 -1
- package/build/dex/index.js +2 -0
- package/build/dex/index.js.map +1 -1
- package/build/dex/quick-perps/config.d.ts +11 -0
- package/build/dex/quick-perps/config.js +27 -0
- package/build/dex/quick-perps/config.js.map +1 -0
- package/build/dex/quick-perps/fast-price-feed.d.ts +26 -0
- package/build/dex/quick-perps/fast-price-feed.js +176 -0
- package/build/dex/quick-perps/fast-price-feed.js.map +1 -0
- package/build/dex/quick-perps/pool.d.ts +21 -0
- package/build/dex/quick-perps/pool.js +210 -0
- package/build/dex/quick-perps/pool.js.map +1 -0
- package/build/dex/quick-perps/quick-perps.d.ts +52 -0
- package/build/dex/quick-perps/quick-perps.js +205 -0
- package/build/dex/quick-perps/quick-perps.js.map +1 -0
- package/build/dex/quick-perps/types.d.ts +98 -0
- package/build/dex/quick-perps/types.js +3 -0
- package/build/dex/quick-perps/types.js.map +1 -0
- package/build/dex/quick-perps/usdq.d.ts +15 -0
- package/build/dex/quick-perps/usdq.js +61 -0
- package/build/dex/quick-perps/usdq.js.map +1 -0
- package/build/dex/quick-perps/vault-price-feed.d.ts +43 -0
- package/build/dex/quick-perps/vault-price-feed.js +194 -0
- package/build/dex/quick-perps/vault-price-feed.js.map +1 -0
- package/build/dex/quick-perps/vault-utils.d.ts +8 -0
- package/build/dex/quick-perps/vault-utils.js +41 -0
- package/build/dex/quick-perps/vault-utils.js.map +1 -0
- package/build/dex/quick-perps/vault.d.ts +46 -0
- package/build/dex/quick-perps/vault.js +166 -0
- package/build/dex/quick-perps/vault.js.map +1 -0
- package/build/lib/api3-feed.d.ts +26 -0
- package/build/lib/api3-feed.js +82 -0
- package/build/lib/api3-feed.js.map +1 -0
- package/package.json +1 -1
- package/src/abi/api3-proxy.json +46 -0
- package/src/abi/api3-server-v1.json +463 -0
- package/src/abi/quick-perps/fast-price-events.json +70 -0
- package/src/abi/quick-perps/fast-price-feed.json +741 -0
- package/src/abi/quick-perps/reader.json +313 -0
- package/src/abi/quick-perps/vault-price-feed.json +323 -0
- package/src/abi/quick-perps/vault.json +1953 -0
- package/src/composed-event-subscriber.ts +16 -11
- package/src/config.ts +2 -2
- package/src/dex/algebra/algebra.ts +0 -13
- package/src/dex/index.ts +2 -0
- package/src/dex/quick-perps/config.ts +31 -0
- package/src/dex/quick-perps/fast-price-feed.ts +279 -0
- package/src/dex/quick-perps/pool.ts +372 -0
- package/src/dex/quick-perps/quick-perps-e2e.test.ts +65 -0
- package/src/dex/quick-perps/quick-perps-events.test.ts +101 -0
- package/src/dex/quick-perps/quick-perps-integration.test.ts +153 -0
- package/src/dex/quick-perps/quick-perps.ts +292 -0
- package/src/dex/quick-perps/types.ts +97 -0
- package/src/dex/quick-perps/usdq.ts +83 -0
- package/src/dex/quick-perps/vault-price-feed.ts +322 -0
- package/src/dex/quick-perps/vault-utils.ts +53 -0
- package/src/dex/quick-perps/vault.ts +290 -0
- package/src/lib/api3-feed.ts +140 -0
- package/tests/constants-e2e.ts +29 -0
- package/tests/tenderly-simulation.ts +46 -2
- package/tests/utils-e2e.ts +18 -10
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { DeepReadonly } from 'ts-essentials';
|
|
2
|
+
import { PartialEventSubscriber } from '../composed-event-subscriber';
|
|
3
|
+
import {
|
|
4
|
+
Address,
|
|
5
|
+
BlockHeader,
|
|
6
|
+
Log,
|
|
7
|
+
Logger,
|
|
8
|
+
MultiCallInput,
|
|
9
|
+
MultiCallOutput,
|
|
10
|
+
} from '../types';
|
|
11
|
+
import { Lens } from '../lens';
|
|
12
|
+
import { Interface } from '@ethersproject/abi';
|
|
13
|
+
import ProxyABI from '../abi/api3-proxy.json';
|
|
14
|
+
import Api3ServerV1ABI from '../abi/api3-server-v1.json';
|
|
15
|
+
|
|
16
|
+
export type Api3FeedSubscriberState = {
|
|
17
|
+
value: bigint;
|
|
18
|
+
timestamp: bigint;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export class Api3FeedSubscriber<State> extends PartialEventSubscriber<
|
|
22
|
+
State,
|
|
23
|
+
Api3FeedSubscriberState
|
|
24
|
+
> {
|
|
25
|
+
static readonly proxyInterface = new Interface(ProxyABI);
|
|
26
|
+
static readonly api3ServerV1Iface = new Interface(Api3ServerV1ABI);
|
|
27
|
+
static readonly ANSWER_UPDATED_SIGNED_DATA =
|
|
28
|
+
Api3FeedSubscriber.api3ServerV1Iface.getEventTopic(
|
|
29
|
+
'UpdatedBeaconWithSignedData',
|
|
30
|
+
);
|
|
31
|
+
static readonly ANSWER_UPDATED_BEACON_SET_DATA =
|
|
32
|
+
Api3FeedSubscriber.api3ServerV1Iface.getEventTopic(
|
|
33
|
+
'UpdatedBeaconSetWithBeacons',
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
private proxy: Address,
|
|
38
|
+
api3Server: Address,
|
|
39
|
+
private dataFeedId: string,
|
|
40
|
+
lens: Lens<DeepReadonly<State>, DeepReadonly<Api3FeedSubscriberState>>,
|
|
41
|
+
logger: Logger,
|
|
42
|
+
) {
|
|
43
|
+
super([api3Server], lens, logger);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static getApi3ServerV1MultiCallInput(proxy: Address): MultiCallInput {
|
|
47
|
+
return {
|
|
48
|
+
target: proxy,
|
|
49
|
+
callData:
|
|
50
|
+
Api3FeedSubscriber.proxyInterface.encodeFunctionData('api3ServerV1'),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static getDataFeedId(proxy: Address): MultiCallInput {
|
|
55
|
+
return {
|
|
56
|
+
target: proxy,
|
|
57
|
+
callData:
|
|
58
|
+
Api3FeedSubscriber.proxyInterface.encodeFunctionData('dataFeedId'),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static decodeDataFeedId(multicallOutput: MultiCallOutput) {
|
|
63
|
+
return Api3FeedSubscriber.proxyInterface.decodeFunctionResult(
|
|
64
|
+
'dataFeedId',
|
|
65
|
+
multicallOutput,
|
|
66
|
+
)[0];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static decodeApi3ServerV1Result(multicallOutput: MultiCallOutput): Address {
|
|
70
|
+
return Api3FeedSubscriber.proxyInterface.decodeFunctionResult(
|
|
71
|
+
'api3ServerV1',
|
|
72
|
+
multicallOutput,
|
|
73
|
+
)[0];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public processLog(
|
|
77
|
+
state: DeepReadonly<Api3FeedSubscriberState>,
|
|
78
|
+
log: Readonly<Log>,
|
|
79
|
+
blockHeader: Readonly<BlockHeader>,
|
|
80
|
+
): DeepReadonly<Api3FeedSubscriberState> | null {
|
|
81
|
+
if (log.topics[0] === Api3FeedSubscriber.ANSWER_UPDATED_SIGNED_DATA) {
|
|
82
|
+
const decoded = Api3FeedSubscriber.api3ServerV1Iface.decodeEventLog(
|
|
83
|
+
'UpdatedBeaconWithSignedData',
|
|
84
|
+
log.data,
|
|
85
|
+
log.topics,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (decoded.beaconId !== this.dataFeedId) return null;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
value: BigInt(decoded.value.toString()),
|
|
92
|
+
timestamp: BigInt(decoded.timestamp.toString()),
|
|
93
|
+
};
|
|
94
|
+
} else if (
|
|
95
|
+
log.topics[0] === Api3FeedSubscriber.ANSWER_UPDATED_BEACON_SET_DATA
|
|
96
|
+
) {
|
|
97
|
+
const decoded = Api3FeedSubscriber.api3ServerV1Iface.decodeEventLog(
|
|
98
|
+
'UpdatedBeaconSetWithBeacons',
|
|
99
|
+
log.data,
|
|
100
|
+
log.topics,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
if (decoded.beaconSetId !== this.dataFeedId) return null;
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
value: BigInt(decoded.value.toString()),
|
|
107
|
+
timestamp: BigInt(decoded.timestamp.toString()),
|
|
108
|
+
};
|
|
109
|
+
} else {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public getGenerateStateMultiCallInputs(): MultiCallInput[] {
|
|
115
|
+
return [
|
|
116
|
+
{
|
|
117
|
+
target: this.proxy,
|
|
118
|
+
callData: Api3FeedSubscriber.proxyInterface.encodeFunctionData('read'),
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public generateState(
|
|
124
|
+
multicallOutputs: MultiCallOutput[],
|
|
125
|
+
blockNumber?: number | 'latest',
|
|
126
|
+
): DeepReadonly<Api3FeedSubscriberState> {
|
|
127
|
+
const decoded = Api3FeedSubscriber.proxyInterface.decodeFunctionResult(
|
|
128
|
+
'read',
|
|
129
|
+
multicallOutputs[0],
|
|
130
|
+
);
|
|
131
|
+
return {
|
|
132
|
+
value: BigInt(decoded.value.toString()),
|
|
133
|
+
timestamp: BigInt(decoded.timestamp.toString()),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public getLatestData(state: DeepReadonly<State>): bigint {
|
|
138
|
+
return this.lens.get()(state).value;
|
|
139
|
+
}
|
|
140
|
+
}
|
package/tests/constants-e2e.ts
CHANGED
|
@@ -861,6 +861,28 @@ export const Tokens: {
|
|
|
861
861
|
decimals: 8,
|
|
862
862
|
},
|
|
863
863
|
},
|
|
864
|
+
[Network.ZKEVM]: {
|
|
865
|
+
ETH: {
|
|
866
|
+
address: ETHER_ADDRESS,
|
|
867
|
+
decimals: 18,
|
|
868
|
+
},
|
|
869
|
+
WETH: {
|
|
870
|
+
address: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9',
|
|
871
|
+
decimals: 18,
|
|
872
|
+
},
|
|
873
|
+
MATIC: {
|
|
874
|
+
address: '0xa2036f0538221a77a3937f1379699f44945018d0',
|
|
875
|
+
decimals: 18,
|
|
876
|
+
},
|
|
877
|
+
WBTC: {
|
|
878
|
+
address: '0xea034fb02eb1808c2cc3adbc15f447b93cbe08e1',
|
|
879
|
+
decimals: 8,
|
|
880
|
+
},
|
|
881
|
+
USDC: {
|
|
882
|
+
address: '0xa8ce8aee21bc2a48a5ef670afcc9274c7bbbc035',
|
|
883
|
+
decimals: 6,
|
|
884
|
+
},
|
|
885
|
+
},
|
|
864
886
|
};
|
|
865
887
|
|
|
866
888
|
export const Holders: {
|
|
@@ -1073,6 +1095,13 @@ export const Holders: {
|
|
|
1073
1095
|
rETH: '0x4c2e69e58b14de9afedfb94319519ce34e087283',
|
|
1074
1096
|
WBTC: '0xb9c8f0d3254007ee4b98970b94544e473cd610ec',
|
|
1075
1097
|
},
|
|
1098
|
+
[Network.ZKEVM]: {
|
|
1099
|
+
ETH: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9',
|
|
1100
|
+
WETH: '0xc44ad482f24fd750caeba387d2726d8653f8c4bb',
|
|
1101
|
+
MATIC: '0x8f2a1450c040b3c19efe9676165d8f30d8280019',
|
|
1102
|
+
WBTC: '0x99b31498b0a1dae01fc3433e3cb60f095340935c',
|
|
1103
|
+
USDC: '0x99b31498b0a1dae01fc3433e3cb60f095340935c',
|
|
1104
|
+
},
|
|
1076
1105
|
};
|
|
1077
1106
|
|
|
1078
1107
|
export const SmartTokens = Object.keys(Tokens).reduce((acc, _network) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import axios from 'axios';
|
|
2
3
|
import { Address } from '@paraswap/core';
|
|
4
|
+
import { Provider } from '@ethersproject/providers';
|
|
3
5
|
import { TxObject } from '../src/types';
|
|
4
6
|
import { StateOverrides, StateSimulateApiOverride } from './smart-tokens';
|
|
5
7
|
|
|
@@ -9,7 +11,50 @@ const TENDERLY_PROJECT = process.env.TENDERLY_PROJECT;
|
|
|
9
11
|
const TENDERLY_FORK_ID = process.env.TENDERLY_FORK_ID;
|
|
10
12
|
const TENDERLY_FORK_LAST_TX_ID = process.env.TENDERLY_FORK_LAST_TX_ID;
|
|
11
13
|
|
|
12
|
-
export
|
|
14
|
+
export type SimulationResult = {
|
|
15
|
+
success: boolean;
|
|
16
|
+
gasUsed?: string;
|
|
17
|
+
url?: string;
|
|
18
|
+
transaction?: any;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export interface TransactionSimulator {
|
|
22
|
+
forkId: string;
|
|
23
|
+
setup(): Promise<void>;
|
|
24
|
+
|
|
25
|
+
simulate(
|
|
26
|
+
params: TxObject,
|
|
27
|
+
stateOverrides?: StateOverrides,
|
|
28
|
+
): Promise<SimulationResult>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class EstimateGasSimulation implements TransactionSimulator {
|
|
32
|
+
forkId: string = '0';
|
|
33
|
+
|
|
34
|
+
constructor(private provider: Provider) {}
|
|
35
|
+
|
|
36
|
+
async setup() {}
|
|
37
|
+
|
|
38
|
+
async simulate(
|
|
39
|
+
params: TxObject,
|
|
40
|
+
_: StateOverrides,
|
|
41
|
+
): Promise<SimulationResult> {
|
|
42
|
+
try {
|
|
43
|
+
const result = await this.provider.estimateGas(params);
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
gasUsed: result.toNumber().toString(),
|
|
47
|
+
};
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error(`Estimate gas simulation failed:`, e);
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class TenderlySimulation implements TransactionSimulator {
|
|
13
58
|
lastTx: string = '';
|
|
14
59
|
forkId: string = '';
|
|
15
60
|
maxGasLimit = 80000000;
|
|
@@ -118,7 +163,6 @@ export class TenderlySimulation {
|
|
|
118
163
|
console.error(`TenderlySimulation_simulate:`, e);
|
|
119
164
|
return {
|
|
120
165
|
success: false,
|
|
121
|
-
tenderlyUrl: '',
|
|
122
166
|
};
|
|
123
167
|
}
|
|
124
168
|
}
|
package/tests/utils-e2e.ts
CHANGED
|
@@ -5,7 +5,11 @@ import {
|
|
|
5
5
|
IParaSwapSDK,
|
|
6
6
|
LocalParaswapSDK,
|
|
7
7
|
} from '../src/implementations/local-paraswap-sdk';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
EstimateGasSimulation,
|
|
10
|
+
TenderlySimulation,
|
|
11
|
+
TransactionSimulator,
|
|
12
|
+
} from './tenderly-simulation';
|
|
9
13
|
import {
|
|
10
14
|
SwapSide,
|
|
11
15
|
ETHER_ADDRESS,
|
|
@@ -24,7 +28,7 @@ import {
|
|
|
24
28
|
import Erc20ABI from '../src/abi/erc20.json';
|
|
25
29
|
import AugustusABI from '../src/abi/augustus.json';
|
|
26
30
|
import { generateConfig } from '../src/config';
|
|
27
|
-
import { DummyLimitOrderProvider } from '../src/dex-helper';
|
|
31
|
+
import { DummyDexHelper, DummyLimitOrderProvider } from '../src/dex-helper';
|
|
28
32
|
import { constructSimpleSDK, SimpleFetchSDK } from '@paraswap/sdk';
|
|
29
33
|
import axios from 'axios';
|
|
30
34
|
import { SmartToken, StateOverrides } from './smart-tokens';
|
|
@@ -268,16 +272,20 @@ export async function testE2E(
|
|
|
268
272
|
// Specified in BPS: part of 10000
|
|
269
273
|
slippage?: number,
|
|
270
274
|
sleepMs?: number,
|
|
275
|
+
replaceTenderlyWithEstimateGas?: boolean,
|
|
271
276
|
) {
|
|
272
277
|
const amount = BigInt(_amount);
|
|
273
|
-
|
|
278
|
+
|
|
279
|
+
const ts: TransactionSimulator = replaceTenderlyWithEstimateGas
|
|
280
|
+
? new EstimateGasSimulation(new DummyDexHelper(network).provider)
|
|
281
|
+
: new TenderlySimulation(network);
|
|
274
282
|
await ts.setup();
|
|
275
283
|
|
|
276
284
|
if (srcToken.address.toLowerCase() !== ETHER_ADDRESS.toLowerCase()) {
|
|
277
285
|
const allowanceTx = await ts.simulate(
|
|
278
286
|
allowTokenTransferProxyParams(srcToken.address, senderAddress, network),
|
|
279
287
|
);
|
|
280
|
-
if (!allowanceTx.success) console.log(allowanceTx.
|
|
288
|
+
if (!allowanceTx.success) console.log(allowanceTx.url);
|
|
281
289
|
expect(allowanceTx!.success).toEqual(true);
|
|
282
290
|
}
|
|
283
291
|
|
|
@@ -309,7 +317,7 @@ export async function testE2E(
|
|
|
309
317
|
expect(deployTx.success).toEqual(true);
|
|
310
318
|
|
|
311
319
|
const contractAddress =
|
|
312
|
-
deployTx.transaction
|
|
320
|
+
deployTx.transaction?.transaction_info.contract_address;
|
|
313
321
|
console.log(
|
|
314
322
|
formatDeployMessage(
|
|
315
323
|
'adapter',
|
|
@@ -384,15 +392,15 @@ export async function testE2E(
|
|
|
384
392
|
|
|
385
393
|
const swapTx = await ts.simulate(swapParams);
|
|
386
394
|
// Only log gas estimate if testing against API
|
|
387
|
-
if (useAPI)
|
|
395
|
+
if (useAPI) {
|
|
396
|
+
const gasUsed = swapTx.gasUsed || '0';
|
|
388
397
|
console.log(
|
|
389
398
|
`Gas Estimate API: ${priceRoute.gasCost}, Simulated: ${
|
|
390
399
|
swapTx!.gasUsed
|
|
391
|
-
}, Difference: ${
|
|
392
|
-
parseInt(priceRoute.gasCost) - parseInt(swapTx!.gasUsed)
|
|
393
|
-
}`,
|
|
400
|
+
}, Difference: ${parseInt(priceRoute.gasCost) - parseInt(gasUsed)}`,
|
|
394
401
|
);
|
|
395
|
-
|
|
402
|
+
}
|
|
403
|
+
console.log(`Tenderly URL: ${swapTx!.url}`);
|
|
396
404
|
expect(swapTx!.success).toEqual(true);
|
|
397
405
|
} finally {
|
|
398
406
|
if (paraswap.releaseResources) {
|