@augustdigital/sdk 8.3.2 → 8.6.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 +207 -117
- package/lib/abis/ERC20_Bytes32.d.ts +4 -0
- package/lib/abis/ERC20_Bytes32.js +4 -0
- package/lib/abis/ERC4626.d.ts +1 -0
- package/lib/abis/ERC4626.js +1 -0
- package/lib/abis/ERC721.d.ts +1 -0
- package/lib/abis/ERC721.js +1 -0
- package/lib/abis/FeeOracle.js +1 -0
- package/lib/abis/LendingPool.js +1 -0
- package/lib/abis/LendingPoolV2.js +1 -0
- package/lib/abis/Multicall3.js +3 -0
- package/lib/abis/OFT.d.ts +20 -0
- package/lib/abis/OFT.js +20 -0
- package/lib/abis/SmartAccount.d.ts +1 -0
- package/lib/abis/SmartAccount.js +3 -0
- package/lib/abis/SwapRouter.d.ts +1 -0
- package/lib/abis/SwapRouter.js +1 -0
- package/lib/abis/UniversalSignatureValidator.js +3 -0
- package/lib/abis/index.d.ts +5 -0
- package/lib/abis/index.js +5 -0
- package/lib/adapters/evm/getters.d.ts +17 -2
- package/lib/adapters/evm/getters.js +35 -3
- package/lib/adapters/evm/index.d.ts +266 -4
- package/lib/adapters/evm/index.js +270 -1
- package/lib/adapters/evm/utils.d.ts +6 -0
- package/lib/adapters/evm/utils.js +7 -0
- package/lib/adapters/solana/constants.d.ts +1 -1
- package/lib/adapters/solana/constants.js +4 -1
- package/lib/adapters/solana/getters.d.ts +9 -1
- package/lib/adapters/solana/getters.js +21 -0
- package/lib/adapters/solana/idl/vault-idl.js +9 -0
- package/lib/adapters/solana/index.d.ts +59 -4
- package/lib/adapters/solana/index.js +61 -0
- package/lib/adapters/solana/types.d.ts +1 -1
- package/lib/adapters/solana/utils.d.ts +31 -3
- package/lib/adapters/solana/utils.js +79 -4
- package/lib/adapters/solana/vault.actions.d.ts +23 -4
- package/lib/adapters/solana/vault.actions.js +47 -3
- package/lib/adapters/stellar/actions.d.ts +26 -1
- package/lib/adapters/stellar/actions.js +33 -0
- package/lib/adapters/stellar/constants.d.ts +26 -0
- package/lib/adapters/stellar/constants.js +29 -0
- package/lib/adapters/stellar/getters.d.ts +56 -0
- package/lib/adapters/stellar/getters.js +81 -0
- package/lib/adapters/stellar/index.d.ts +70 -0
- package/lib/adapters/stellar/index.js +71 -0
- package/lib/adapters/stellar/soroban.d.ts +21 -1
- package/lib/adapters/stellar/soroban.js +47 -1
- package/lib/adapters/stellar/submit.d.ts +29 -0
- package/lib/adapters/stellar/submit.js +90 -5
- package/lib/adapters/stellar/types.d.ts +27 -0
- package/lib/adapters/stellar/types.js +3 -0
- package/lib/adapters/stellar/utils.d.ts +10 -0
- package/lib/adapters/stellar/utils.js +10 -0
- package/lib/adapters/sui/getters.d.ts +7 -1
- package/lib/adapters/sui/getters.js +6 -0
- package/lib/adapters/sui/index.d.ts +16 -1
- package/lib/adapters/sui/index.js +17 -0
- package/lib/adapters/sui/transformer.d.ts +8 -2
- package/lib/adapters/sui/transformer.js +7 -0
- package/lib/adapters/sui/types.d.ts +1 -1
- package/lib/adapters/sui/utils.d.ts +6 -0
- package/lib/adapters/sui/utils.js +6 -0
- package/lib/core/analytics/chain-name.d.ts +8 -0
- package/lib/core/analytics/chain-name.js +8 -0
- package/lib/core/analytics/constants.d.ts +4 -0
- package/lib/core/analytics/constants.js +4 -0
- package/lib/core/analytics/env.d.ts +25 -0
- package/lib/core/analytics/env.js +26 -0
- package/lib/core/analytics/index.d.ts +26 -0
- package/lib/core/analytics/index.js +35 -0
- package/lib/core/analytics/instrumentation.d.ts +26 -0
- package/lib/core/analytics/instrumentation.js +66 -2
- package/lib/core/analytics/method-taxonomy.d.ts +16 -0
- package/lib/core/analytics/method-taxonomy.js +18 -0
- package/lib/core/analytics/metrics.d.ts +23 -0
- package/lib/core/analytics/metrics.js +40 -0
- package/lib/core/analytics/sanitize.d.ts +38 -0
- package/lib/core/analytics/sanitize.js +46 -0
- package/lib/core/analytics/sentry-runtime.d.ts +11 -0
- package/lib/core/analytics/sentry-runtime.js +20 -1
- package/lib/core/analytics/sentry.d.ts +47 -2
- package/lib/core/analytics/sentry.js +115 -2
- package/lib/core/analytics/types.d.ts +28 -1
- package/lib/core/analytics/user-identity.d.ts +36 -2
- package/lib/core/analytics/user-identity.js +43 -1
- package/lib/core/analytics/version.d.ts +6 -1
- package/lib/core/analytics/version.js +6 -1
- package/lib/core/auth/verify.js +5 -0
- package/lib/core/base.class.d.ts +78 -3
- package/lib/core/base.class.js +66 -4
- package/lib/core/cache.d.ts +5 -0
- package/lib/core/cache.js +6 -0
- package/lib/core/constants/adapters.d.ts +16 -1
- package/lib/core/constants/adapters.js +28 -8
- package/lib/core/constants/core.d.ts +14 -1
- package/lib/core/constants/core.js +18 -0
- package/lib/core/constants/swap-router.d.ts +83 -1
- package/lib/core/constants/swap-router.js +91 -1
- package/lib/core/constants/vaults.d.ts +57 -1
- package/lib/core/constants/vaults.js +66 -1
- package/lib/core/constants/web3.d.ts +4 -1
- package/lib/core/constants/web3.js +15 -5
- package/lib/core/errors/index.d.ts +38 -2
- package/lib/core/errors/index.js +38 -0
- package/lib/core/fetcher.d.ts +136 -2
- package/lib/core/fetcher.js +229 -25
- package/lib/core/helpers/adapters.d.ts +10 -1
- package/lib/core/helpers/adapters.js +11 -0
- package/lib/core/helpers/chain-address.d.ts +10 -0
- package/lib/core/helpers/chain-address.js +11 -0
- package/lib/core/helpers/core.d.ts +49 -4
- package/lib/core/helpers/core.js +74 -7
- package/lib/core/helpers/explorer-link.d.ts +15 -1
- package/lib/core/helpers/explorer-link.js +14 -0
- package/lib/core/helpers/signer.d.ts +27 -1
- package/lib/core/helpers/signer.js +39 -0
- package/lib/core/helpers/swap-router.d.ts +33 -1
- package/lib/core/helpers/swap-router.js +32 -0
- package/lib/core/helpers/vault-version.d.ts +2 -1
- package/lib/core/helpers/vault-version.js +2 -0
- package/lib/core/helpers/vaults.d.ts +9 -1
- package/lib/core/helpers/vaults.js +22 -8
- package/lib/core/helpers/web3.d.ts +154 -2
- package/lib/core/helpers/web3.js +192 -15
- package/lib/core/logger/index.d.ts +55 -0
- package/lib/core/logger/index.js +19 -0
- package/lib/core/logger/slack.d.ts +3 -0
- package/lib/core/logger/slack.js +3 -0
- package/lib/core/vault-metadata.d.ts +7 -1
- package/lib/core/vault-metadata.js +6 -0
- package/lib/core/version-check.d.ts +52 -0
- package/lib/core/version-check.js +82 -1
- package/lib/evm/methods/crossChainVault.d.ts +90 -0
- package/lib/evm/methods/crossChainVault.js +187 -2
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +240 -0
- package/lib/evm/methods/index.d.ts +1 -0
- package/lib/evm/methods/index.js +1 -0
- package/lib/evm/types/crossChain.d.ts +202 -0
- package/lib/evm/types/crossChain.js +12 -1
- package/lib/index.d.ts +16 -0
- package/lib/index.js +19 -0
- package/lib/main.d.ts +289 -6
- package/lib/main.js +312 -0
- package/lib/modules/api/index.d.ts +1 -0
- package/lib/modules/api/index.js +6 -0
- package/lib/modules/api/main.d.ts +52 -0
- package/lib/modules/api/main.js +130 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +17 -2
- package/lib/modules/sub-accounts/fetcher.js +15 -0
- package/lib/modules/sub-accounts/main.d.ts +35 -2
- package/lib/modules/sub-accounts/main.js +39 -1
- package/lib/modules/sub-accounts/utils.d.ts +4 -1
- package/lib/modules/sub-accounts/utils.js +3 -0
- package/lib/modules/vaults/adapter.helpers.d.ts +21 -3
- package/lib/modules/vaults/adapter.helpers.js +34 -0
- package/lib/modules/vaults/fetcher.d.ts +45 -0
- package/lib/modules/vaults/fetcher.js +91 -4
- package/lib/modules/vaults/getters.d.ts +295 -0
- package/lib/modules/vaults/getters.js +567 -26
- package/lib/modules/vaults/index.d.ts +12 -0
- package/lib/modules/vaults/index.js +12 -0
- package/lib/modules/vaults/main.d.ts +292 -4
- package/lib/modules/vaults/main.js +382 -8
- package/lib/modules/vaults/read.actions.d.ts +170 -2
- package/lib/modules/vaults/read.actions.js +143 -0
- package/lib/modules/vaults/types.d.ts +34 -0
- package/lib/modules/vaults/utils/call-data-decoder.d.ts +48 -1
- package/lib/modules/vaults/utils/call-data-decoder.js +56 -0
- package/lib/modules/vaults/utils/date-utils.d.ts +39 -0
- package/lib/modules/vaults/utils/date-utils.js +47 -1
- package/lib/modules/vaults/utils.d.ts +85 -0
- package/lib/modules/vaults/utils.js +139 -7
- package/lib/modules/vaults/write.actions.d.ts +363 -3
- package/lib/modules/vaults/write.actions.js +399 -3
- package/lib/polyfills.js +4 -2
- package/lib/sdk.d.ts +23847 -0
- package/lib/services/coingecko/fetcher.d.ts +15 -1
- package/lib/services/coingecko/fetcher.js +30 -9
- package/lib/services/debank/fetcher.d.ts +15 -1
- package/lib/services/debank/fetcher.js +12 -0
- package/lib/services/debank/utils.d.ts +1 -1
- package/lib/services/debank/utils.js +18 -1
- package/lib/services/layerzero/deposits.d.ts +12 -1
- package/lib/services/layerzero/deposits.js +34 -11
- package/lib/services/layerzero/redeems.d.ts +11 -1
- package/lib/services/layerzero/redeems.js +13 -0
- package/lib/services/layerzero/utils.d.ts +8 -0
- package/lib/services/layerzero/utils.js +11 -0
- package/lib/services/octavfi/fetcher.d.ts +8 -1
- package/lib/services/octavfi/fetcher.js +25 -0
- package/lib/services/octavfi/types.d.ts +1 -1
- package/lib/services/octavfi/utils.d.ts +14 -2
- package/lib/services/octavfi/utils.js +44 -10
- package/lib/services/subgraph/fetcher.js +4 -2
- package/lib/services/subgraph/vaults.d.ts +12 -0
- package/lib/services/subgraph/vaults.js +119 -2
- package/lib/services/swap-quotes/index.d.ts +80 -0
- package/lib/services/swap-quotes/index.js +27 -1
- package/lib/services/swap-quotes/paraswap.d.ts +25 -0
- package/lib/services/swap-quotes/paraswap.js +22 -0
- package/lib/types/pools.d.ts +5 -2
- package/lib/types/staking.d.ts +1 -1
- package/lib/types/sub-accounts.d.ts +1 -1
- package/lib/types/subgraph.d.ts +10 -1
- package/lib/types/typed-contract.d.ts +64 -0
- package/lib/types/vaults.d.ts +163 -2
- package/lib/types/vaults.js +10 -0
- package/lib/types/web3.d.ts +9 -1
- package/lib/types/web3.js +1 -0
- package/lib/types/webserver.d.ts +47 -2
- package/package.json +6 -5
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.transformOctavfiToDebank = transformOctavfiToDebank;
|
|
4
4
|
exports.transformOctavfiPortfoliosToDebank = transformOctavfiPortfoliosToDebank;
|
|
5
|
+
/**
|
|
6
|
+
* Transforms Octavfi portfolio response to DeBank-compatible format.
|
|
7
|
+
* This allows Solana addresses to use Octavfi data while maintaining
|
|
8
|
+
* compatibility with existing DeBank parsing functions.
|
|
9
|
+
*
|
|
10
|
+
* @param octavfiPortfolio - Octavfi portfolio response
|
|
11
|
+
* @returns DeBank-compatible response structure
|
|
12
|
+
*/
|
|
5
13
|
function transformOctavfiToDebank(octavfiPortfolio) {
|
|
6
14
|
if (!octavfiPortfolio) {
|
|
7
15
|
return {
|
|
@@ -13,20 +21,25 @@ function transformOctavfiToDebank(octavfiPortfolio) {
|
|
|
13
21
|
}
|
|
14
22
|
const positions = [];
|
|
15
23
|
const tokens = [];
|
|
24
|
+
// Transform protocols (assetByProtocols) into DeBank positions format
|
|
16
25
|
const assetByProtocols = octavfiPortfolio.assetByProtocols || {};
|
|
17
26
|
Object.entries(assetByProtocols).forEach(([protocolKey, protocol]) => {
|
|
27
|
+
// Skip wallet protocol - we'll handle it separately in tokens
|
|
18
28
|
if (protocolKey === 'wallet') {
|
|
19
29
|
return;
|
|
20
30
|
}
|
|
31
|
+
// Extract all assets from nested structure: chains -> protocolPositions -> assets
|
|
21
32
|
const allAssets = [];
|
|
22
33
|
if (protocol.chains) {
|
|
23
34
|
Object.values(protocol.chains).forEach((chain) => {
|
|
24
35
|
if (chain.protocolPositions) {
|
|
25
36
|
Object.values(chain.protocolPositions).forEach((protocolPosition) => {
|
|
37
|
+
// Direct assets
|
|
26
38
|
if (protocolPosition.assets &&
|
|
27
39
|
Array.isArray(protocolPosition.assets)) {
|
|
28
40
|
allAssets.push(...protocolPosition.assets);
|
|
29
41
|
}
|
|
42
|
+
// Nested protocolPositions (like in Kamino)
|
|
30
43
|
if (protocolPosition.protocolPositions &&
|
|
31
44
|
Array.isArray(protocolPosition.protocolPositions)) {
|
|
32
45
|
protocolPosition.protocolPositions.forEach((nestedPos) => {
|
|
@@ -39,33 +52,36 @@ function transformOctavfiToDebank(octavfiPortfolio) {
|
|
|
39
52
|
}
|
|
40
53
|
});
|
|
41
54
|
}
|
|
55
|
+
// Create position structure matching DeBank format
|
|
42
56
|
const position = {
|
|
43
57
|
id: protocolKey,
|
|
44
58
|
chain: getChainFromProtocol(protocol, octavfiPortfolio),
|
|
45
59
|
name: protocol.name || protocolKey,
|
|
46
|
-
logo_url: '',
|
|
47
|
-
site_url: '',
|
|
60
|
+
logo_url: '', // Octavfi doesn't provide protocol logos
|
|
61
|
+
site_url: '', // Octavfi doesn't provide protocol URLs
|
|
48
62
|
portfolio_item_list: [
|
|
49
63
|
{
|
|
50
64
|
name: protocol.name || protocolKey,
|
|
51
65
|
stats: {
|
|
52
66
|
asset_usd_value: parseFloat(protocol.value || '0') || 0,
|
|
53
|
-
debt_usd_value: 0,
|
|
67
|
+
debt_usd_value: 0, // Octavfi doesn't distinguish debt, default to 0
|
|
54
68
|
net_usd_value: parseFloat(protocol.value || '0') || 0,
|
|
55
69
|
},
|
|
56
70
|
detail: {
|
|
57
71
|
supply_token_list: allAssets
|
|
58
72
|
.map((asset) => transformAssetToDebankToken(asset, 'supply'))
|
|
59
73
|
.filter((token) => token !== null),
|
|
60
|
-
borrow_token_list: [],
|
|
74
|
+
borrow_token_list: [], // Octavfi doesn't provide borrow data
|
|
61
75
|
},
|
|
62
76
|
},
|
|
63
77
|
],
|
|
64
78
|
};
|
|
65
79
|
positions.push(position);
|
|
66
80
|
});
|
|
81
|
+
// Transform wallet assets to tokens array
|
|
67
82
|
const walletProtocol = assetByProtocols['wallet'];
|
|
68
83
|
if (walletProtocol && walletProtocol.chains) {
|
|
84
|
+
// Extract assets from nested structure: chains -> protocolPositions -> assets
|
|
69
85
|
Object.values(walletProtocol.chains).forEach((chain) => {
|
|
70
86
|
if (chain.protocolPositions) {
|
|
71
87
|
Object.values(chain.protocolPositions).forEach((protocolPosition) => {
|
|
@@ -75,7 +91,7 @@ function transformOctavfiToDebank(octavfiPortfolio) {
|
|
|
75
91
|
tokens.push({
|
|
76
92
|
...transformAssetToDebankToken(asset, 'wallet'),
|
|
77
93
|
is_wallet: true,
|
|
78
|
-
is_core: true,
|
|
94
|
+
is_core: true, // Assume wallet tokens are core tokens
|
|
79
95
|
});
|
|
80
96
|
});
|
|
81
97
|
}
|
|
@@ -83,28 +99,33 @@ function transformOctavfiToDebank(octavfiPortfolio) {
|
|
|
83
99
|
}
|
|
84
100
|
});
|
|
85
101
|
}
|
|
102
|
+
// Also add protocol assets as tokens (non-wallet)
|
|
86
103
|
Object.entries(assetByProtocols).forEach(([protocolKey, protocol]) => {
|
|
87
104
|
if (protocolKey === 'wallet')
|
|
88
105
|
return;
|
|
89
106
|
if (!protocol || !protocol.chains)
|
|
90
107
|
return;
|
|
108
|
+
// Extract assets from nested structure
|
|
91
109
|
Object.values(protocol.chains).forEach((chain) => {
|
|
92
110
|
if (chain.protocolPositions) {
|
|
93
111
|
Object.values(chain.protocolPositions).forEach((protocolPosition) => {
|
|
112
|
+
// Direct assets
|
|
94
113
|
if (protocolPosition.assets &&
|
|
95
114
|
Array.isArray(protocolPosition.assets)) {
|
|
96
115
|
protocolPosition.assets.forEach((asset) => {
|
|
116
|
+
// Check if token already exists (from wallet)
|
|
97
117
|
const existingToken = tokens.find((t) => t.symbol === asset.symbol &&
|
|
98
118
|
t.chain === (asset.chainKey || asset.chain));
|
|
99
119
|
if (!existingToken) {
|
|
100
120
|
tokens.push({
|
|
101
121
|
...transformAssetToDebankToken(asset, 'supply'),
|
|
102
122
|
is_wallet: false,
|
|
103
|
-
is_core: true,
|
|
123
|
+
is_core: true, // Assume protocol tokens are core
|
|
104
124
|
});
|
|
105
125
|
}
|
|
106
126
|
});
|
|
107
127
|
}
|
|
128
|
+
// Nested protocolPositions (like in Kamino)
|
|
108
129
|
if (protocolPosition.protocolPositions &&
|
|
109
130
|
Array.isArray(protocolPosition.protocolPositions)) {
|
|
110
131
|
protocolPosition.protocolPositions.forEach((nestedPos) => {
|
|
@@ -134,7 +155,11 @@ function transformOctavfiToDebank(octavfiPortfolio) {
|
|
|
134
155
|
},
|
|
135
156
|
};
|
|
136
157
|
}
|
|
137
|
-
|
|
158
|
+
/**
|
|
159
|
+
* Transforms Octavfi asset to DeBank token format
|
|
160
|
+
*/
|
|
161
|
+
function transformAssetToDebankToken(asset, // Using any since the actual structure differs from IOctavfiAsset
|
|
162
|
+
exposureType) {
|
|
138
163
|
if (!asset) {
|
|
139
164
|
return null;
|
|
140
165
|
}
|
|
@@ -145,26 +170,31 @@ function transformAssetToDebankToken(asset, exposureType) {
|
|
|
145
170
|
const contract = asset.contract || asset.chainContract || asset.contractAddress;
|
|
146
171
|
const decimals = parseInt(asset.decimal || asset.decimals || '18', 10);
|
|
147
172
|
return {
|
|
148
|
-
id: contract || asset.symbol || 'unknown',
|
|
173
|
+
id: contract || asset.symbol || 'unknown', // Use contract address if available, fallback to symbol
|
|
149
174
|
chain: chain,
|
|
150
175
|
name: asset.name || asset.symbol || 'Unknown',
|
|
151
176
|
symbol: asset.symbol || 'UNKNOWN',
|
|
152
177
|
optimized_symbol: asset.symbol || 'UNKNOWN',
|
|
153
178
|
decimals: decimals,
|
|
154
|
-
logo_url: '',
|
|
179
|
+
logo_url: '', // Octavfi doesn't provide token logos
|
|
155
180
|
amount,
|
|
156
181
|
price,
|
|
157
|
-
protocol_id: '',
|
|
182
|
+
protocol_id: '', // Will be set by the calling context
|
|
158
183
|
supplying_exposure: exposureType === 'supply' ? 'true' : undefined,
|
|
159
184
|
};
|
|
160
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Determines the chain from protocol data or portfolio chains
|
|
188
|
+
*/
|
|
161
189
|
function getChainFromProtocol(protocol, portfolio) {
|
|
190
|
+
// Try to get chain from protocol.chains structure
|
|
162
191
|
if (protocol.chains) {
|
|
163
192
|
const chainKeys = Object.keys(protocol.chains);
|
|
164
193
|
if (chainKeys.length > 0) {
|
|
165
194
|
return chainKeys[0];
|
|
166
195
|
}
|
|
167
196
|
}
|
|
197
|
+
// Fallback to first chain in portfolio
|
|
168
198
|
const chains = portfolio.chains || {};
|
|
169
199
|
const chainKeys = Object.keys(chains);
|
|
170
200
|
if (chainKeys.length > 0) {
|
|
@@ -172,6 +202,10 @@ function getChainFromProtocol(protocol, portfolio) {
|
|
|
172
202
|
}
|
|
173
203
|
return 'unknown';
|
|
174
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Transforms multiple Octavfi portfolios to DeBank format.
|
|
207
|
+
* Used when fetching multiple addresses.
|
|
208
|
+
*/
|
|
175
209
|
function transformOctavfiPortfoliosToDebank(portfolios) {
|
|
176
210
|
return portfolios.map(transformOctavfiToDebank);
|
|
177
211
|
}
|
|
@@ -14,7 +14,7 @@ async function fetchSubgraphWithRetry(graphUrl, query, apiKey, maxRetries = 3, b
|
|
|
14
14
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
15
15
|
try {
|
|
16
16
|
const controller = new AbortController();
|
|
17
|
-
const timeoutId = setTimeout(() => controller.abort(), core_1.REQUEST_TIMEOUT_MS / 3);
|
|
17
|
+
const timeoutId = setTimeout(() => controller.abort(), core_1.REQUEST_TIMEOUT_MS / 3); // 30 second timeout
|
|
18
18
|
try {
|
|
19
19
|
const headers = {
|
|
20
20
|
'Content-Type': 'application/json',
|
|
@@ -40,17 +40,19 @@ async function fetchSubgraphWithRetry(graphUrl, query, apiKey, maxRetries = 3, b
|
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
42
42
|
lastError = error;
|
|
43
|
+
// If it's a timeout error, abort error, or network error and we have retries left
|
|
43
44
|
if (attempt < maxRetries &&
|
|
44
45
|
((error instanceof TypeError &&
|
|
45
46
|
error.message.includes('fetch failed')) ||
|
|
46
47
|
error.name === 'AbortError' ||
|
|
47
48
|
error.message.includes('ETIMEDOUT') ||
|
|
48
49
|
error.message.includes('timeout'))) {
|
|
49
|
-
const delay = baseDelay *
|
|
50
|
+
const delay = baseDelay * 2 ** attempt; // Exponential backoff
|
|
50
51
|
core_1.Logger.log.warn(`fetchSubgraph`, `${graphUrl?.includes('/subgraphs') ? graphUrl?.split('/subgraphs/')?.[1]?.split('/')?.[0] : graphUrl}: Attempt ${attempt + 1} failed, retrying in ${delay}ms`);
|
|
51
52
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
52
53
|
continue;
|
|
53
54
|
}
|
|
55
|
+
// If it's not a retryable error or we're out of retries, throw
|
|
54
56
|
throw error;
|
|
55
57
|
}
|
|
56
58
|
}
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import type { IAddress, IContractRunner, ISubgraphTransfer, ISubgraphUserHistoryItem, ISubgraphWithdrawProccessed, ISubgraphWithdrawRequest } from '../../types';
|
|
2
2
|
export declare function isOldSubgraphSchema(vaultSymbol: string): boolean;
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param pool
|
|
6
|
+
* @param provider
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
3
9
|
export declare function getSubgraphWithdrawRequests(pool: IAddress, provider: IContractRunner, slackWebookUrl?: string): Promise<ISubgraphWithdrawRequest[]>;
|
|
4
10
|
export declare function getSubgraphWithdrawProccessed(pool: IAddress, provider: IContractRunner, slackWebookUrl?: string): Promise<ISubgraphWithdrawProccessed[]>;
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param pool
|
|
14
|
+
* @param provider
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
5
17
|
export declare function getSubgraphAllWithdrawals(pool: IAddress, provider: IContractRunner, slackWebookUrl?: string): Promise<{
|
|
6
18
|
withdrawalRequesteds: ISubgraphWithdrawRequest[];
|
|
7
19
|
withdrawalProcesseds: ISubgraphWithdrawProccessed[];
|
|
@@ -11,11 +11,20 @@ const slack_1 = require("../../core/logger/slack");
|
|
|
11
11
|
const fetcher_1 = require("./fetcher");
|
|
12
12
|
const core_1 = require("../../core");
|
|
13
13
|
const fetcher_2 = require("../../modules/vaults/fetcher");
|
|
14
|
+
/**
|
|
15
|
+
* Utils
|
|
16
|
+
*/
|
|
14
17
|
const GOLDSKY_API_KEY = 'cmd0lz6qf35lg01ty7u20aijy';
|
|
18
|
+
/**
|
|
19
|
+
* earnAUSD exists on both Ethereum and Monad, so it needs a _monad suffix
|
|
20
|
+
* to distinguish its Monad subgraph from the Ethereum one.
|
|
21
|
+
* Other Monad-native vaults (sausd, supermon, etc.) don't need this.
|
|
22
|
+
*/
|
|
15
23
|
function needsMonadSuffix(chainId, symbol) {
|
|
16
24
|
return chainId === 143 && symbol.toLowerCase() === 'earnausd';
|
|
17
25
|
}
|
|
18
26
|
function transformUserHistory(data, chainId, decimals, poolAddress) {
|
|
27
|
+
//ok to return dupes even though withdraws will return dupe because we parse out duplicate txn hash on the FE
|
|
19
28
|
return [
|
|
20
29
|
...(data.withdraws?.map((item) => ({
|
|
21
30
|
...item,
|
|
@@ -69,6 +78,7 @@ function sortUserHistory(data, chainId, decimals, poolAddress) {
|
|
|
69
78
|
return [];
|
|
70
79
|
return transformUserHistory(data, chainId, decimals, poolAddress).sort((a, b) => Number(a.timestamp_) - Number(b.timestamp_));
|
|
71
80
|
}
|
|
81
|
+
// queries
|
|
72
82
|
const WITHDRAWALS_REQUESTED_QUERY_PROPS = `
|
|
73
83
|
id
|
|
74
84
|
day
|
|
@@ -155,10 +165,15 @@ const EVM_V2_DEPOSIT_QUERY_PROPS = `
|
|
|
155
165
|
senderAddr
|
|
156
166
|
receiverAddr
|
|
157
167
|
`;
|
|
168
|
+
// New deployment process uses a different subgraph schema (no trailing underscores).
|
|
169
|
+
// Vaults in SUBGRAPH_VAULT_URLS use the old schema; everything else uses the new schema.
|
|
170
|
+
// GraphQL aliases map new-schema fields to what the SDK expects internally.
|
|
158
171
|
function isOldSubgraphSchema(vaultSymbol) {
|
|
159
172
|
return (vaultSymbol?.toLowerCase() in
|
|
160
173
|
core_1.SUBGRAPH_VAULT_URLS);
|
|
161
174
|
}
|
|
175
|
+
// New schema query props (shared across evm-1 and evm-2 — the new subgraph schema
|
|
176
|
+
// normalized field names, so no per-version variants are needed)
|
|
162
177
|
const NEW_DEPOSIT_QUERY_PROPS = `
|
|
163
178
|
id
|
|
164
179
|
assetIn
|
|
@@ -196,6 +211,7 @@ const NEW_WITHDRAWALS_QUERY_PROPS = `
|
|
|
196
211
|
shares
|
|
197
212
|
owner
|
|
198
213
|
`;
|
|
214
|
+
// New schema: transfer query props
|
|
199
215
|
const NEW_TRANSFER_QUERY_PROPS = `
|
|
200
216
|
id
|
|
201
217
|
from
|
|
@@ -215,7 +231,14 @@ const TRANSFER_QUERY_PROPS = `
|
|
|
215
231
|
block_number
|
|
216
232
|
contractId_
|
|
217
233
|
`;
|
|
234
|
+
/**
|
|
235
|
+
*
|
|
236
|
+
* @param pool
|
|
237
|
+
* @param provider
|
|
238
|
+
* @returns
|
|
239
|
+
*/
|
|
218
240
|
async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = slack_1.DEFAULT_SLACK_WEBHOOK_URL) {
|
|
241
|
+
// setup
|
|
219
242
|
let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
|
|
220
243
|
if (vaultSymbol === undefined) {
|
|
221
244
|
core_1.Logger.log.warn('getSubgraphWithdrawRequests', `cannot find vault symbol for pool: ${pool}`);
|
|
@@ -226,6 +249,7 @@ async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = slac
|
|
|
226
249
|
if (needsMonadSuffix(network, vaultSymbol)) {
|
|
227
250
|
vaultSymbol = vaultSymbol.concat('_monad');
|
|
228
251
|
}
|
|
252
|
+
// sanitize
|
|
229
253
|
if (vaultSymbol === 'testWETHTSA') {
|
|
230
254
|
return [];
|
|
231
255
|
}
|
|
@@ -275,6 +299,7 @@ async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = slac
|
|
|
275
299
|
}
|
|
276
300
|
async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = slack_1.DEFAULT_SLACK_WEBHOOK_URL) {
|
|
277
301
|
try {
|
|
302
|
+
// setup
|
|
278
303
|
let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
|
|
279
304
|
if (vaultSymbol === undefined) {
|
|
280
305
|
core_1.Logger.log.warn('getSubgraphWithdrawProccessed', `cannot find vault symbol for pool: ${pool}`);
|
|
@@ -286,6 +311,7 @@ async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = sl
|
|
|
286
311
|
vaultSymbol = vaultSymbol.concat('_monad');
|
|
287
312
|
}
|
|
288
313
|
const noWithdrawalProcessed = vaultSymbol === 'agETH';
|
|
314
|
+
// sanitize
|
|
289
315
|
if (vaultSymbol === 'testWETHTSA' || noWithdrawalProcessed) {
|
|
290
316
|
return [];
|
|
291
317
|
}
|
|
@@ -338,9 +364,16 @@ async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = sl
|
|
|
338
364
|
return [];
|
|
339
365
|
}
|
|
340
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
*
|
|
369
|
+
* @param pool
|
|
370
|
+
* @param provider
|
|
371
|
+
* @returns
|
|
372
|
+
*/
|
|
341
373
|
async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = slack_1.DEFAULT_SLACK_WEBHOOK_URL) {
|
|
342
374
|
let query = '';
|
|
343
375
|
try {
|
|
376
|
+
// setup
|
|
344
377
|
const errorReturnObj = {
|
|
345
378
|
withdrawalRequesteds: [],
|
|
346
379
|
withdrawalProcesseds: [],
|
|
@@ -356,6 +389,7 @@ async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = slack_
|
|
|
356
389
|
vaultSymbol = vaultSymbol.concat('_monad');
|
|
357
390
|
}
|
|
358
391
|
const noWithdrawalProcessed = vaultSymbol === 'agETH';
|
|
392
|
+
// sanitize
|
|
359
393
|
if (vaultSymbol === 'testWETHTSA') {
|
|
360
394
|
return errorReturnObj;
|
|
361
395
|
}
|
|
@@ -429,8 +463,85 @@ async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = slack_
|
|
|
429
463
|
};
|
|
430
464
|
}
|
|
431
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* Fetch a user's deposit/withdraw history for an archived vault from the backend
|
|
468
|
+
* Mongo snapshot (`/upshift/vault_history`) instead of its retired subgraph.
|
|
469
|
+
*
|
|
470
|
+
* Returns the same {@link ISubgraphUserHistoryItem} shape as the subgraph path,
|
|
471
|
+
* so the caller's downstream transform/normalization is unchanged. `amount` is
|
|
472
|
+
* the raw deposited-asset amount (base units); `decimals` is attached so the
|
|
473
|
+
* caller can normalize, mirroring the subgraph path.
|
|
474
|
+
*
|
|
475
|
+
* Pre-deposit vaults accept multiple deposit assets with differing decimals
|
|
476
|
+
* (e.g. USDS at 18, USDC at 6). When the backend supplies `asset_address` per
|
|
477
|
+
* row, it is propagated as {@link ISubgraphUserHistoryItem.assetIn} (and, when
|
|
478
|
+
* present, `asset_decimals` is used for that row's `decimals`) so lifetime PnL
|
|
479
|
+
* resolves each deposit against its own token rather than the vault decimals —
|
|
480
|
+
* without it, an 18-decimal deposit normalized at the vault's 6 decimals
|
|
481
|
+
* inflates the cost basis by ~1e12. This mirrors the subgraph path, whose
|
|
482
|
+
* deposit rows already carry `assetIn`.
|
|
483
|
+
*
|
|
484
|
+
* Side effects: one RPC read (`getDecimals`) and one HTTP GET to the public API.
|
|
485
|
+
*
|
|
486
|
+
* @param user - The wallet whose history to fetch.
|
|
487
|
+
* @param provider - Contract runner, used to read the vault's decimals.
|
|
488
|
+
* @param pool - The (archived) vault contract address.
|
|
489
|
+
* @returns The user's deposits and settled withdrawals. Empty on a non-200
|
|
490
|
+
* response.
|
|
491
|
+
*/
|
|
492
|
+
async function getArchivedVaultUserHistory(user, provider, pool) {
|
|
493
|
+
const decimals = await (0, core_1.getDecimals)(provider, pool);
|
|
494
|
+
const response = await (0, core_1.fetchAugustPublic)(core_1.WEBSERVER_ENDPOINTS.public.tokenizedVault.userHistory(pool, user));
|
|
495
|
+
if (response.status !== 200) {
|
|
496
|
+
core_1.Logger.log.error('getArchivedVaultUserHistory', `non-200 from vault_history for ${pool}: ${response.status}`);
|
|
497
|
+
return [];
|
|
498
|
+
}
|
|
499
|
+
const rows = (await response.json());
|
|
500
|
+
// The backend already stores final ISubgraphUserHistoryItem.type values, so
|
|
501
|
+
// no translation is needed. Two row-level guards before mapping, since both
|
|
502
|
+
// bad shapes propagate destructively downstream:
|
|
503
|
+
// - amount_raw must be a non-negative integer: the caller does
|
|
504
|
+
// BigInt(amount) outside a try/catch, and one bad row would throw and
|
|
505
|
+
// wipe the user's entire (all-vault) history.
|
|
506
|
+
// - timestamp must parse to a real time: a malformed value makes getTime()
|
|
507
|
+
// return NaN, which stringifies to "NaN" and then sorts/normalizes
|
|
508
|
+
// incorrectly downstream. Drop the row rather than emit a "NaN" stamp.
|
|
509
|
+
return (rows
|
|
510
|
+
.filter((row) => /^\d+$/.test(row.amount_raw) &&
|
|
511
|
+
!Number.isNaN(new Date(row.timestamp).getTime()))
|
|
512
|
+
.map((row) => ({
|
|
513
|
+
id: row.transaction_hash,
|
|
514
|
+
contractId_: pool,
|
|
515
|
+
timestamp_: String(Math.floor(new Date(row.timestamp).getTime() / 1000)),
|
|
516
|
+
transactionHash_: row.transaction_hash,
|
|
517
|
+
block_number: row.block_number != null ? String(row.block_number) : '0',
|
|
518
|
+
address: row.wallet,
|
|
519
|
+
amount: row.amount_raw,
|
|
520
|
+
type: row.type,
|
|
521
|
+
// Per-asset decimals when known, else the vault's. PnL re-resolves
|
|
522
|
+
// decimals from `assetIn` anyway; this keeps display/normalization
|
|
523
|
+
// correct for any consumer that reads the row's `decimals` directly.
|
|
524
|
+
decimals: row.asset_decimals ?? decimals,
|
|
525
|
+
// Carry the deposit asset through so mixed-decimal deposits normalize
|
|
526
|
+
// against their own token, not the vault's. Omitted when unknown.
|
|
527
|
+
...(row.asset_address ? { assetIn: row.asset_address } : {}),
|
|
528
|
+
}))
|
|
529
|
+
// Match the subgraph path's ordering contract: sortUserHistory sorts
|
|
530
|
+
// ascending by unix timestamp_, and downstream consumers rely on that
|
|
531
|
+
// chronology. The backend returns rows in arbitrary order, so re-sort here.
|
|
532
|
+
.sort((a, b) => Number(a.timestamp_) - Number(b.timestamp_)));
|
|
533
|
+
}
|
|
432
534
|
async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = slack_1.DEFAULT_SLACK_WEBHOOK_URL) {
|
|
433
535
|
try {
|
|
536
|
+
// Archived vaults: serve history from the backend Mongo snapshot instead of
|
|
537
|
+
// the (retired) subgraph. The archived set is fetched from the backend (the
|
|
538
|
+
// routing source of truth) so a vault is only rerouted once its history is
|
|
539
|
+
// backfilled. Same return shape keeps downstream unchanged.
|
|
540
|
+
const archivedVaults = await (0, fetcher_2.fetchArchivedVaults)();
|
|
541
|
+
if (archivedVaults.has(pool.toLowerCase())) {
|
|
542
|
+
return await getArchivedVaultUserHistory(user, provider, pool);
|
|
543
|
+
}
|
|
544
|
+
// setup
|
|
434
545
|
const chainId = await (0, core_1.getChainId)(provider);
|
|
435
546
|
const requests = [];
|
|
436
547
|
let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
|
|
@@ -444,6 +555,7 @@ async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = sla
|
|
|
444
555
|
vaultSymbol = vaultSymbol.concat('_monad');
|
|
445
556
|
}
|
|
446
557
|
const noWithdrawalProcessed = vaultSymbol === 'agETH';
|
|
558
|
+
// sanitize
|
|
447
559
|
if (vaultSymbol === 'testWETHTSA') {
|
|
448
560
|
return requests;
|
|
449
561
|
}
|
|
@@ -541,6 +653,7 @@ async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = sla
|
|
|
541
653
|
return requests;
|
|
542
654
|
}
|
|
543
655
|
const json = (await result.json());
|
|
656
|
+
// Format data
|
|
544
657
|
const decimals = await (0, core_1.getDecimals)(provider, pool);
|
|
545
658
|
const formattedRequests = sortUserHistory(json.data, chainId, decimals, pool);
|
|
546
659
|
return formattedRequests;
|
|
@@ -552,6 +665,7 @@ async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = sla
|
|
|
552
665
|
}
|
|
553
666
|
async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.DEFAULT_SLACK_WEBHOOK_URL) {
|
|
554
667
|
try {
|
|
668
|
+
// setup
|
|
555
669
|
const requests = [];
|
|
556
670
|
let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
|
|
557
671
|
if (vaultSymbol === undefined) {
|
|
@@ -562,7 +676,7 @@ async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
|
|
|
562
676
|
const network = Number(networkValue.chainId);
|
|
563
677
|
if (needsMonadSuffix(network, vaultSymbol)) {
|
|
564
678
|
vaultSymbol = vaultSymbol.concat('_monad');
|
|
565
|
-
}
|
|
679
|
+
} // sanitize
|
|
566
680
|
if (vaultSymbol === 'testWETHTSA') {
|
|
567
681
|
return requests;
|
|
568
682
|
}
|
|
@@ -642,6 +756,7 @@ async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
|
|
|
642
756
|
return requests;
|
|
643
757
|
}
|
|
644
758
|
const json = (await result.json());
|
|
759
|
+
// Format data
|
|
645
760
|
const chainId = await (0, core_1.getChainId)(provider);
|
|
646
761
|
const decimals = await (0, core_1.getDecimals)(provider, pool);
|
|
647
762
|
const formattedRequests = sortUserHistory(json.data, chainId, decimals, pool);
|
|
@@ -654,6 +769,7 @@ async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
|
|
|
654
769
|
}
|
|
655
770
|
async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = slack_1.DEFAULT_SLACK_WEBHOOK_URL) {
|
|
656
771
|
try {
|
|
772
|
+
// setup
|
|
657
773
|
let amountOfTransfers = 0;
|
|
658
774
|
let userTransfers = [];
|
|
659
775
|
let hasNoData = false;
|
|
@@ -669,7 +785,7 @@ async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = s
|
|
|
669
785
|
const network = Number(networkValue.chainId);
|
|
670
786
|
if (needsMonadSuffix(network, vaultSymbol)) {
|
|
671
787
|
vaultSymbol = vaultSymbol.concat('_monad');
|
|
672
|
-
}
|
|
788
|
+
} // sanitize
|
|
673
789
|
if (vaultSymbol === 'testWETHTSA') {
|
|
674
790
|
return userTransfers;
|
|
675
791
|
}
|
|
@@ -696,6 +812,7 @@ async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = s
|
|
|
696
812
|
? TRANSFER_QUERY_PROPS
|
|
697
813
|
: NEW_TRANSFER_QUERY_PROPS;
|
|
698
814
|
do {
|
|
815
|
+
// get all the transfers, includes redeem requests and deposits, excludes stake and withdraw events
|
|
699
816
|
const where = `
|
|
700
817
|
where: {
|
|
701
818
|
and: [
|
|
@@ -1,25 +1,105 @@
|
|
|
1
|
+
/** @module core/services/swap-quotes */
|
|
1
2
|
import type { IAddress } from '../../types';
|
|
3
|
+
/** Quote-provider discriminant. Will widen as new providers are added. */
|
|
2
4
|
export type ISwapQuoteProvider = 'paraswap';
|
|
5
|
+
/**
|
|
6
|
+
* Input to {@link fetchSwapQuote}.
|
|
7
|
+
*/
|
|
3
8
|
export interface ISwapQuoteRequest {
|
|
9
|
+
/** EVM chain ID where the swap will execute. */
|
|
4
10
|
chainId: number;
|
|
11
|
+
/** ERC-20 the user holds. */
|
|
5
12
|
srcToken: IAddress;
|
|
13
|
+
/** `srcToken.decimals()`. */
|
|
6
14
|
srcDecimals: number;
|
|
15
|
+
/** ERC-20 the SwapRouter should produce — typically the vault's `referenceAsset`. */
|
|
7
16
|
destToken: IAddress;
|
|
17
|
+
/** `destToken.decimals()`. */
|
|
8
18
|
destDecimals: number;
|
|
19
|
+
/** Input amount in `srcToken`'s smallest unit. */
|
|
9
20
|
amount: bigint;
|
|
21
|
+
/**
|
|
22
|
+
* Address that will execute the resulting calldata. For SwapRouter use,
|
|
23
|
+
* pass the SwapRouter's address — the aggregator's calldata is bound to
|
|
24
|
+
* this address, so it must hold the tokens at swap time.
|
|
25
|
+
*/
|
|
10
26
|
receiver: IAddress;
|
|
27
|
+
/**
|
|
28
|
+
* Slippage tolerance in bps (1 bp = 0.01%). Defaults to 100 (1%). Must be
|
|
29
|
+
* in `[0, 10_000)` — 10_000 disables protection entirely and is rejected.
|
|
30
|
+
*/
|
|
11
31
|
slippageBps?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Optional aggregator contract-method filter. When set, the aggregator is
|
|
34
|
+
* constrained to this single method (ParaSwap's `/prices`
|
|
35
|
+
* `includeContractMethods`), so the returned calldata's leading 4-byte
|
|
36
|
+
* selector is deterministic — required when the on-chain SwapRouter only
|
|
37
|
+
* authorizes one selector per router. When omitted, the aggregator picks the
|
|
38
|
+
* optimal method freely and the selector may vary between quotes.
|
|
39
|
+
*/
|
|
40
|
+
contractMethod?: string;
|
|
41
|
+
/** Aggregator partner key. Defaults to `'august'`. */
|
|
12
42
|
partner?: string;
|
|
43
|
+
/** Aggregator partner-fee receiver. Defaults to the August partner address. */
|
|
13
44
|
partnerAddress?: IAddress;
|
|
45
|
+
/**
|
|
46
|
+
* `fetch`-compatible function override. Defaults to `globalThis.fetch`.
|
|
47
|
+
* Exposed so callers in Node environments lacking a global `fetch` can
|
|
48
|
+
* inject one, and so tests can mock without touching the global.
|
|
49
|
+
*/
|
|
14
50
|
fetchImpl?: typeof fetch;
|
|
51
|
+
/** Optional AbortSignal to cancel the in-flight Paraswap requests. */
|
|
15
52
|
signal?: AbortSignal;
|
|
16
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Output of {@link fetchSwapQuote}. The `router` + `payload` pair maps
|
|
56
|
+
* directly into one entry of an `ISwapParams[]` passed to
|
|
57
|
+
* `SwapRouter.swapAndDeposit`.
|
|
58
|
+
*
|
|
59
|
+
* Modeled as a discriminated union on `provider` so adding 1inch/0x is an
|
|
60
|
+
* additive change rather than a breaking widening.
|
|
61
|
+
*/
|
|
17
62
|
export type ISwapQuoteResult = {
|
|
63
|
+
/** Quote provider that produced this calldata. */
|
|
18
64
|
provider: 'paraswap';
|
|
65
|
+
/** DEX router that will execute the swap (the contract `payload` is calldata for). */
|
|
19
66
|
router: IAddress;
|
|
67
|
+
/** ABI-encoded calldata for `router`. */
|
|
20
68
|
payload: `0x${string}`;
|
|
69
|
+
/** Expected output in `destToken` units before slippage. */
|
|
21
70
|
expectedAmountOut: bigint;
|
|
71
|
+
/** Slippage-adjusted minimum output. Below this the on-chain call reverts. */
|
|
22
72
|
minAmountOut: bigint;
|
|
73
|
+
/**
|
|
74
|
+
* Epoch ms when the quote was fetched. Callers that prefetch a quote
|
|
75
|
+
* before submitting should re-fetch when this is older than ~60s — DEX
|
|
76
|
+
* pool state moves and a stale `minAmountOut` may have been computed
|
|
77
|
+
* against a price that no longer holds.
|
|
78
|
+
*/
|
|
23
79
|
fetchedAt: number;
|
|
24
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Fetch a swap quote and the calldata required for the on-chain SwapRouter
|
|
83
|
+
* to execute it.
|
|
84
|
+
*
|
|
85
|
+
* @throws {@link AugustValidationError} on invalid input (slippage out of
|
|
86
|
+
* range, zero amount, src===dst).
|
|
87
|
+
* @throws {@link AugustNetworkError} on transport failure.
|
|
88
|
+
* @throws {@link AugustServerError} on aggregator-side errors.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const quote = await fetchSwapQuote({
|
|
93
|
+
* chainId: 1,
|
|
94
|
+
* srcToken: WBTC,
|
|
95
|
+
* srcDecimals: 8,
|
|
96
|
+
* destToken: USDC,
|
|
97
|
+
* destDecimals: 6,
|
|
98
|
+
* amount: 100_000_000n,
|
|
99
|
+
* receiver: SWAP_ROUTER_ADDRESSES[1]!,
|
|
100
|
+
* });
|
|
101
|
+
* // quote.router -> Paraswap augustor
|
|
102
|
+
* // quote.payload -> calldata
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
25
105
|
export declare function fetchSwapQuote(request: ISwapQuoteRequest): Promise<ISwapQuoteResult>;
|
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/** @module core/services/swap-quotes */
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.fetchSwapQuote = fetchSwapQuote;
|
|
4
5
|
const errors_1 = require("../../core/errors");
|
|
5
6
|
const paraswap_1 = require("./paraswap");
|
|
6
7
|
const DEFAULT_SLIPPAGE_BPS = 100;
|
|
7
8
|
const BPS_DENOMINATOR = 10000n;
|
|
9
|
+
/**
|
|
10
|
+
* Fetch a swap quote and the calldata required for the on-chain SwapRouter
|
|
11
|
+
* to execute it.
|
|
12
|
+
*
|
|
13
|
+
* @throws {@link AugustValidationError} on invalid input (slippage out of
|
|
14
|
+
* range, zero amount, src===dst).
|
|
15
|
+
* @throws {@link AugustNetworkError} on transport failure.
|
|
16
|
+
* @throws {@link AugustServerError} on aggregator-side errors.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const quote = await fetchSwapQuote({
|
|
21
|
+
* chainId: 1,
|
|
22
|
+
* srcToken: WBTC,
|
|
23
|
+
* srcDecimals: 8,
|
|
24
|
+
* destToken: USDC,
|
|
25
|
+
* destDecimals: 6,
|
|
26
|
+
* amount: 100_000_000n,
|
|
27
|
+
* receiver: SWAP_ROUTER_ADDRESSES[1]!,
|
|
28
|
+
* });
|
|
29
|
+
* // quote.router -> Paraswap augustor
|
|
30
|
+
* // quote.payload -> calldata
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
8
33
|
async function fetchSwapQuote(request) {
|
|
9
34
|
validateRequest(request);
|
|
10
35
|
const slippageBps = request.slippageBps ?? DEFAULT_SLIPPAGE_BPS;
|
|
@@ -20,6 +45,7 @@ async function fetchSwapQuote(request) {
|
|
|
20
45
|
slippageBps,
|
|
21
46
|
partner: request.partner ?? paraswap_1.PARASWAP_DEFAULTS.partner,
|
|
22
47
|
partnerAddress: request.partnerAddress ?? paraswap_1.PARASWAP_DEFAULTS.partnerAddress,
|
|
48
|
+
contractMethod: request.contractMethod,
|
|
23
49
|
fetchImpl,
|
|
24
50
|
signal: request.signal,
|
|
25
51
|
});
|
|
@@ -35,7 +61,7 @@ async function fetchSwapQuote(request) {
|
|
|
35
61
|
}
|
|
36
62
|
function validateRequest(req) {
|
|
37
63
|
if (req.slippageBps !== undefined &&
|
|
38
|
-
(req.slippageBps < 0 || req.slippageBps >=
|
|
64
|
+
(req.slippageBps < 0 || req.slippageBps >= 10_000)) {
|
|
39
65
|
throw new errors_1.AugustValidationError('INVALID_INPUT', `fetchSwapQuote: slippageBps must be in [0, 10000), got ${req.slippageBps}. 10000 bps = 100% slippage and disables protection entirely; use a tighter bound.`);
|
|
40
66
|
}
|
|
41
67
|
if (req.amount === 0n) {
|