@xswap-link/sdk 0.8.5 → 0.8.7
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/.github/workflows/pr_agent.yml +22 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.global.js +116 -116
- package/dist/index.js +10 -10
- package/dist/index.mjs +9 -9
- package/package.json +1 -1
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/ChainItem/index.tsx +5 -7
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/index.tsx +18 -2
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/index.tsx +1 -24
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/QuickPickTokenItem/index.tsx +2 -11
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +1 -1
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +13 -6
- package/src/components/Swap/SwapView/SwapPanel/index.tsx +5 -1
- package/src/constants/index.ts +1 -1
- package/src/context/SwapProvider.tsx +66 -41
- package/src/utils/validation.ts +199 -180
- package/tailwind.config.js +1 -1
package/src/utils/validation.ts
CHANGED
|
@@ -70,9 +70,13 @@ const getDefaultBridgeTokenForChain = ({
|
|
|
70
70
|
chain,
|
|
71
71
|
bridgeTokensDictionary,
|
|
72
72
|
}: {
|
|
73
|
-
chain: Chain;
|
|
73
|
+
chain: Chain | undefined;
|
|
74
74
|
bridgeTokensDictionary: BridgeTokensDictionary;
|
|
75
75
|
}) => {
|
|
76
|
+
if (!chain) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
76
80
|
const xswapToken = chain.tokens.find((token) => token.tokenId === "XSWAP");
|
|
77
81
|
|
|
78
82
|
if (xswapToken) {
|
|
@@ -108,7 +112,8 @@ const isSwapTargetChainValid = ({
|
|
|
108
112
|
);
|
|
109
113
|
};
|
|
110
114
|
|
|
111
|
-
const isBridgeSourceValid = (sourceChain: Chain) =>
|
|
115
|
+
const isBridgeSourceValid = (sourceChain: Chain | undefined) =>
|
|
116
|
+
!sourceChain || sourceChain.bridgeSupported;
|
|
112
117
|
|
|
113
118
|
const isBridgeTargetValid = ({
|
|
114
119
|
sourceChain,
|
|
@@ -116,71 +121,55 @@ const isBridgeTargetValid = ({
|
|
|
116
121
|
sourceToken,
|
|
117
122
|
}: {
|
|
118
123
|
sourceChain: Chain | undefined;
|
|
119
|
-
targetChain: Chain;
|
|
124
|
+
targetChain: Chain | undefined;
|
|
120
125
|
sourceToken: Token | undefined;
|
|
121
126
|
}) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
// We set it to a valid state initially.
|
|
128
|
+
let isSameToken = true;
|
|
129
|
+
let isSameChain = false;
|
|
125
130
|
|
|
126
|
-
if (
|
|
127
|
-
sourceToken &&
|
|
128
|
-
!targetChain.tokens.find((token) => token.tokenId === sourceToken!.tokenId)
|
|
129
|
-
) {
|
|
131
|
+
if (sourceToken && targetChain) {
|
|
130
132
|
// Bridge target chain is invalid when it doesn't have the same token available as selected in the source.
|
|
131
|
-
|
|
133
|
+
isSameToken = !!targetChain.tokens.find(
|
|
134
|
+
(token) => token.tokenId === sourceToken.tokenId,
|
|
135
|
+
);
|
|
132
136
|
}
|
|
133
137
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
//
|
|
137
|
-
sourceChain.chainId
|
|
138
|
-
|
|
138
|
+
if (sourceChain && targetChain) {
|
|
139
|
+
// @TODO use bridge_tokens collection
|
|
140
|
+
// See: https://github.com/xswap-link/xswap-sdk/pull/200#discussion_r1905586346
|
|
141
|
+
isSameChain = sourceChain.chainId === targetChain.chainId;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return isSameToken && !isSameChain;
|
|
139
145
|
};
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
// If provided data is valid, it returns the same.
|
|
143
|
-
// If data is not valid, it returns other available chain/token.
|
|
144
|
-
export const mapToValidPath = ({
|
|
145
|
-
source,
|
|
146
|
-
target,
|
|
147
|
-
type,
|
|
148
|
-
supportedChains,
|
|
149
|
-
bridgeTokensDictionary,
|
|
150
|
-
}: {
|
|
147
|
+
type MapToValidPathParams = {
|
|
151
148
|
source: { chain: Chain | undefined; token: Token | undefined };
|
|
152
149
|
target: { chain: Chain | undefined; token: Token | undefined };
|
|
153
150
|
type: "SWAP" | "BRIDGE";
|
|
154
151
|
supportedChains: Chain[];
|
|
155
152
|
bridgeTokensDictionary: BridgeTokensDictionary;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const mapToValidPathSwap = ({
|
|
156
|
+
source,
|
|
157
|
+
target,
|
|
158
|
+
supportedChains,
|
|
159
|
+
}: Omit<MapToValidPathParams, "type">) => {
|
|
160
160
|
let newSourceChain: Chain | undefined =
|
|
161
161
|
source.chain || getDefaultSourceChain({ supportedChains });
|
|
162
162
|
let newTargetChain: Chain | undefined =
|
|
163
163
|
target.chain || getDefaultDestinationChain({ supportedChains });
|
|
164
164
|
let newSourceToken: Token | undefined =
|
|
165
|
-
source.token ||
|
|
166
|
-
(type === "SWAP"
|
|
167
|
-
? getDefaultSwapTokenForChain(newSourceChain)
|
|
168
|
-
: getDefaultBridgeTokenForChain({
|
|
169
|
-
chain: newSourceChain,
|
|
170
|
-
bridgeTokensDictionary,
|
|
171
|
-
}));
|
|
165
|
+
source.token || getDefaultSwapTokenForChain(newSourceChain);
|
|
172
166
|
let newTargetToken: Token | undefined =
|
|
173
167
|
target.token ||
|
|
174
|
-
(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
)
|
|
180
|
-
: getDefaultBridgeTokenForChain({
|
|
181
|
-
chain: newTargetChain,
|
|
182
|
-
bridgeTokensDictionary,
|
|
183
|
-
}));
|
|
168
|
+
getDefaultSwapTokenForChain(
|
|
169
|
+
newTargetChain,
|
|
170
|
+
newSourceChain.chainId === newTargetChain.chainId,
|
|
171
|
+
newSourceToken?.tokenId,
|
|
172
|
+
);
|
|
184
173
|
|
|
185
174
|
if (
|
|
186
175
|
!newSourceChain ||
|
|
@@ -195,28 +184,36 @@ export const mapToValidPath = ({
|
|
|
195
184
|
};
|
|
196
185
|
}
|
|
197
186
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// We can't have dangling token from a different chain.
|
|
203
|
-
newSourceToken = undefined;
|
|
187
|
+
if (!isSwapSourceValid(newSourceChain)) {
|
|
188
|
+
newSourceChain = getDefaultSourceChain({ supportedChains });
|
|
189
|
+
// We can't have dangling token from a different chain.
|
|
190
|
+
newSourceToken = undefined;
|
|
204
191
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
192
|
+
if (!isSwapSourceValid(newSourceChain)) {
|
|
193
|
+
// This should never occur if our app is configured properly.
|
|
194
|
+
console.error("[WRONG CONFIG] default swap source chain is invalid.");
|
|
208
195
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
196
|
+
// Find any chain that is valid.
|
|
197
|
+
newSourceChain = supportedChains.find((chain) =>
|
|
198
|
+
isSwapSourceValid(chain),
|
|
199
|
+
);
|
|
200
|
+
if (!newSourceChain) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
"mapToValidSwap > None of the chains supports swap. Couldn't set source chain.",
|
|
212
203
|
);
|
|
213
|
-
if (!newSourceChain) {
|
|
214
|
-
throw new Error(
|
|
215
|
-
"mapToValidSwap > None of the chains supports swap. Couldn't set source chain.",
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
204
|
}
|
|
219
205
|
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (
|
|
209
|
+
!isSwapTargetChainValid({
|
|
210
|
+
sourceChain: newSourceChain,
|
|
211
|
+
targetChain: newTargetChain,
|
|
212
|
+
})
|
|
213
|
+
) {
|
|
214
|
+
newTargetChain = getDefaultDestinationChain({ supportedChains });
|
|
215
|
+
// We can't have dangling token from a different chain.
|
|
216
|
+
newTargetToken = undefined;
|
|
220
217
|
|
|
221
218
|
if (
|
|
222
219
|
!isSwapTargetChainValid({
|
|
@@ -224,54 +221,85 @@ export const mapToValidPath = ({
|
|
|
224
221
|
targetChain: newTargetChain,
|
|
225
222
|
})
|
|
226
223
|
) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
newTargetToken = undefined;
|
|
224
|
+
// This should never occur if our app is configured properly.
|
|
225
|
+
console.error("[WRONG CONFIG] default swap target chain is invalid.");
|
|
230
226
|
|
|
231
|
-
|
|
232
|
-
|
|
227
|
+
// Find any chain that is valid.
|
|
228
|
+
newTargetChain = supportedChains.find((chain) =>
|
|
229
|
+
isSwapTargetChainValid({
|
|
233
230
|
sourceChain: newSourceChain,
|
|
234
|
-
targetChain:
|
|
235
|
-
})
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
// Find any chain that is valid.
|
|
241
|
-
newTargetChain = supportedChains.find((chain) =>
|
|
242
|
-
isSwapTargetChainValid({
|
|
243
|
-
sourceChain: newSourceChain,
|
|
244
|
-
targetChain: chain,
|
|
245
|
-
}),
|
|
231
|
+
targetChain: chain,
|
|
232
|
+
}),
|
|
233
|
+
);
|
|
234
|
+
if (!newTargetChain) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
"mapToValidSwap > None of the chains supports swap. Couldn't set target chain.",
|
|
246
237
|
);
|
|
247
|
-
if (!newTargetChain) {
|
|
248
|
-
throw new Error(
|
|
249
|
-
"mapToValidSwap > None of the chains supports swap. Couldn't set target chain.",
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
238
|
}
|
|
253
239
|
}
|
|
254
|
-
}
|
|
255
|
-
if (!isBridgeSourceValid(newSourceChain)) {
|
|
256
|
-
newSourceChain = getDefaultSourceChain({ supportedChains });
|
|
257
|
-
// We can't have dangling token from a different chain.
|
|
258
|
-
newSourceToken = undefined;
|
|
240
|
+
}
|
|
259
241
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
242
|
+
// Setting tokens
|
|
243
|
+
|
|
244
|
+
if (!newSourceToken) {
|
|
245
|
+
newSourceToken = getDefaultSwapTokenForChain(newSourceChain);
|
|
246
|
+
}
|
|
247
|
+
if (!newTargetToken) {
|
|
248
|
+
newTargetToken = getDefaultSwapTokenForChain(
|
|
249
|
+
newTargetChain,
|
|
250
|
+
newSourceChain.chainId === newTargetChain.chainId,
|
|
251
|
+
newSourceToken?.tokenId,
|
|
252
|
+
);
|
|
253
|
+
}
|
|
263
254
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
255
|
+
return {
|
|
256
|
+
source: { chain: newSourceChain, token: newSourceToken },
|
|
257
|
+
target: { chain: newTargetChain, token: newTargetToken },
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const mapToValidPathBridge = ({
|
|
262
|
+
source,
|
|
263
|
+
target,
|
|
264
|
+
supportedChains,
|
|
265
|
+
bridgeTokensDictionary,
|
|
266
|
+
}: Omit<MapToValidPathParams, "type">) => {
|
|
267
|
+
let newSourceChain = source.chain;
|
|
268
|
+
let newTargetChain = target.chain;
|
|
269
|
+
let newSourceToken = source.token;
|
|
270
|
+
let newTargetToken = target.token;
|
|
271
|
+
|
|
272
|
+
if (!isBridgeSourceValid(newSourceChain)) {
|
|
273
|
+
newSourceChain = getDefaultSourceChain({ supportedChains });
|
|
274
|
+
// We can't have dangling token from a different chain.
|
|
275
|
+
newSourceToken = undefined;
|
|
276
|
+
|
|
277
|
+
if (!isBridgeSourceValid(newSourceChain)) {
|
|
278
|
+
// This should never occur if our app is configured properly.
|
|
279
|
+
console.error("[WRONG CONFIG] default bridge source chain is invalid.");
|
|
280
|
+
|
|
281
|
+
// Find any chain that is valid.
|
|
282
|
+
newSourceChain = supportedChains.find((chain) =>
|
|
283
|
+
isBridgeSourceValid(chain),
|
|
284
|
+
);
|
|
285
|
+
if (!newSourceChain) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
"mapToValidSwap > None of the chains supports bridge. Couldn't set source chain.",
|
|
267
288
|
);
|
|
268
|
-
if (!newSourceChain) {
|
|
269
|
-
throw new Error(
|
|
270
|
-
"mapToValidSwap > None of the chains supports bridge. Couldn't set source chain.",
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
289
|
}
|
|
274
290
|
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (
|
|
294
|
+
!isBridgeTargetValid({
|
|
295
|
+
sourceChain: newSourceChain,
|
|
296
|
+
targetChain: newTargetChain,
|
|
297
|
+
sourceToken: newSourceToken,
|
|
298
|
+
})
|
|
299
|
+
) {
|
|
300
|
+
newTargetChain = getDefaultDestinationChain({ supportedChains });
|
|
301
|
+
// We can't have dangling token from a different chain.
|
|
302
|
+
newTargetToken = undefined;
|
|
275
303
|
|
|
276
304
|
if (
|
|
277
305
|
!isBridgeTargetValid({
|
|
@@ -280,99 +308,73 @@ export const mapToValidPath = ({
|
|
|
280
308
|
sourceToken: newSourceToken,
|
|
281
309
|
})
|
|
282
310
|
) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
newTargetToken = undefined;
|
|
311
|
+
// This should never occur if our app is configured properly.
|
|
312
|
+
console.error("[WRONG CONFIG] default bridge target chain is invalid.");
|
|
286
313
|
|
|
287
|
-
|
|
288
|
-
|
|
314
|
+
// Find any chain that is valid.
|
|
315
|
+
newTargetChain = supportedChains.find((chain) =>
|
|
316
|
+
isBridgeTargetValid({
|
|
289
317
|
sourceChain: newSourceChain,
|
|
290
|
-
targetChain:
|
|
318
|
+
targetChain: chain,
|
|
291
319
|
sourceToken: newSourceToken,
|
|
292
|
-
})
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
// Find any chain that is valid.
|
|
298
|
-
newTargetChain = supportedChains.find((chain) =>
|
|
299
|
-
isBridgeTargetValid({
|
|
300
|
-
sourceChain: newSourceChain,
|
|
301
|
-
targetChain: chain,
|
|
302
|
-
sourceToken: newSourceToken,
|
|
303
|
-
}),
|
|
320
|
+
}),
|
|
321
|
+
);
|
|
322
|
+
if (!newTargetChain) {
|
|
323
|
+
throw new Error(
|
|
324
|
+
"mapToValidSwap > None of the chains supports bridge. Couldn't set target chain.",
|
|
304
325
|
);
|
|
305
|
-
if (!newTargetChain) {
|
|
306
|
-
throw new Error(
|
|
307
|
-
"mapToValidSwap > None of the chains supports swap. Couldn't set target chain.",
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
326
|
}
|
|
311
327
|
}
|
|
312
328
|
}
|
|
313
329
|
|
|
314
330
|
// Setting tokens
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
bridgeTokensDictionary,
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
if (defaultToken) {
|
|
334
|
-
const isDefaultTokenBridgeable =
|
|
335
|
-
!!bridgeTokensDictionary[newSourceChain.chainId]?.[
|
|
336
|
-
defaultToken.address.toLowerCase()
|
|
337
|
-
]?.[newTargetChain.chainId];
|
|
338
|
-
|
|
339
|
-
if (isDefaultTokenBridgeable) {
|
|
340
|
-
newSourceToken = defaultToken;
|
|
341
|
-
} else {
|
|
342
|
-
// This should never occur if our app is configured properly.
|
|
343
|
-
console.error(
|
|
344
|
-
"[WRONG CONFIG] default bridge source token is invalid.",
|
|
345
|
-
);
|
|
346
|
-
// Default is invalid, so let's keep it unset.
|
|
347
|
-
newSourceToken = undefined;
|
|
348
|
-
}
|
|
331
|
+
|
|
332
|
+
if (!newSourceToken) {
|
|
333
|
+
const defaultToken = getDefaultBridgeTokenForChain({
|
|
334
|
+
chain: newSourceChain,
|
|
335
|
+
bridgeTokensDictionary,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (defaultToken && newSourceChain && newTargetChain) {
|
|
339
|
+
const isDefaultTokenBridgeable =
|
|
340
|
+
!!bridgeTokensDictionary[newSourceChain.chainId]?.[
|
|
341
|
+
defaultToken.address.toLowerCase()
|
|
342
|
+
]?.[newTargetChain.chainId];
|
|
343
|
+
|
|
344
|
+
if (isDefaultTokenBridgeable) {
|
|
345
|
+
newSourceToken = defaultToken;
|
|
349
346
|
} else {
|
|
350
|
-
//
|
|
347
|
+
// This should never occur if our app is configured properly.
|
|
348
|
+
console.error("[WRONG CONFIG] default bridge source token is invalid.");
|
|
349
|
+
// Default is invalid, so let's keep it unset.
|
|
351
350
|
newSourceToken = undefined;
|
|
352
351
|
}
|
|
352
|
+
} else {
|
|
353
|
+
// Default was not found, so let's keep it unset.
|
|
354
|
+
newSourceToken = undefined;
|
|
353
355
|
}
|
|
356
|
+
}
|
|
354
357
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
+
if (newSourceToken?.tokenId !== newTargetToken?.tokenId) {
|
|
359
|
+
newTargetToken = undefined;
|
|
360
|
+
}
|
|
358
361
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
362
|
+
if (!newTargetToken) {
|
|
363
|
+
if (newSourceToken && newSourceChain && newTargetChain) {
|
|
364
|
+
const correspondingTokenAddress =
|
|
365
|
+
bridgeTokensDictionary[newSourceChain.chainId]?.[
|
|
366
|
+
newSourceToken.address.toLowerCase()
|
|
367
|
+
]?.[newTargetChain.chainId];
|
|
368
|
+
|
|
369
|
+
const correspondingToken = newTargetChain.tokens.find(
|
|
370
|
+
(token) =>
|
|
371
|
+
token.address.toLowerCase() ===
|
|
372
|
+
correspondingTokenAddress?.toLowerCase(),
|
|
373
|
+
);
|
|
374
|
+
newTargetToken = correspondingToken;
|
|
375
|
+
} else {
|
|
376
|
+
// If source token is not defined, destination token can't be defined as well.
|
|
377
|
+
newTargetToken = undefined;
|
|
376
378
|
}
|
|
377
379
|
}
|
|
378
380
|
|
|
@@ -381,3 +383,20 @@ export const mapToValidPath = ({
|
|
|
381
383
|
target: { chain: newTargetChain, token: newTargetToken },
|
|
382
384
|
};
|
|
383
385
|
};
|
|
386
|
+
|
|
387
|
+
// It takes chain and token for source and target and returns them.
|
|
388
|
+
// If provided data is valid, it returns the same.
|
|
389
|
+
// If data is not valid, it returns other available chain/token.
|
|
390
|
+
export const mapToValidPath = ({
|
|
391
|
+
type,
|
|
392
|
+
...params
|
|
393
|
+
}: MapToValidPathParams): {
|
|
394
|
+
source: { chain: Chain | undefined; token: Token | undefined };
|
|
395
|
+
target: { chain: Chain | undefined; token: Token | undefined };
|
|
396
|
+
} => {
|
|
397
|
+
if (type === "SWAP") {
|
|
398
|
+
return mapToValidPathSwap(params);
|
|
399
|
+
} else {
|
|
400
|
+
return mapToValidPathBridge(params);
|
|
401
|
+
}
|
|
402
|
+
};
|