@defuse-protocol/intents-sdk 0.16.3 → 0.17.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/dist/index.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  assert as assert11,
4
4
  PUBLIC_NEAR_RPC_URLS,
5
5
  RETRY_CONFIGS as RETRY_CONFIGS2,
6
- configsByEnvironment as configsByEnvironment7,
6
+ configsByEnvironment as configsByEnvironment6,
7
7
  nearFailoverRpcProvider,
8
- solverRelay as solverRelay5
8
+ solverRelay as solverRelay3
9
9
  } from "@defuse-protocol/internal-utils";
10
10
  import hotOmniSdk from "@hot-labs/omni-sdk";
11
11
  import { stringify } from "viem";
@@ -13,11 +13,9 @@ import { stringify } from "viem";
13
13
  // src/bridges/aurora-engine-bridge/aurora-engine-bridge.ts
14
14
  import {
15
15
  assert as assert2,
16
- configsByEnvironment,
17
16
  getNearNep141MinStorageBalance,
18
17
  getNearNep141StorageBalance,
19
- solverRelay,
20
- utils as utils2
18
+ utils as utils3
21
19
  } from "@defuse-protocol/internal-utils";
22
20
 
23
21
  // src/constants/route-enum.ts
@@ -72,6 +70,194 @@ function withdrawalParamsInvariant(params) {
72
70
  );
73
71
  }
74
72
 
73
+ // src/lib/parse-defuse-asset-id.ts
74
+ import { utils as utils2 } from "@defuse-protocol/internal-utils";
75
+
76
+ // src/classes/errors.ts
77
+ import { BaseError } from "@defuse-protocol/internal-utils";
78
+ var FeeExceedsAmountError = class extends BaseError {
79
+ constructor(feeEstimation, amount) {
80
+ super("Amount too small to pay fee.", {
81
+ metaMessages: [
82
+ `Required fee: ${feeEstimation.amount}`,
83
+ `Withdrawal amount: ${amount}`
84
+ ],
85
+ name: "FeeExceedsAmountError"
86
+ });
87
+ this.feeEstimation = feeEstimation;
88
+ this.amount = amount;
89
+ }
90
+ };
91
+ var MinWithdrawalAmountError = class extends BaseError {
92
+ constructor(minAmount, requestedAmount, assetId) {
93
+ super("Withdrawal amount is below minimum required by the bridge.", {
94
+ metaMessages: [
95
+ `Asset ID: ${assetId}`,
96
+ `Minimum amount: ${minAmount}`,
97
+ `Requested amount: ${requestedAmount}`
98
+ ],
99
+ name: "MinWithdrawalAmountError"
100
+ });
101
+ this.minAmount = minAmount;
102
+ this.requestedAmount = requestedAmount;
103
+ this.assetId = assetId;
104
+ }
105
+ };
106
+ var UnsupportedDestinationMemoError = class extends BaseError {
107
+ constructor(blockchain, assetId) {
108
+ super("Destination memo is not supported for this blockchain.", {
109
+ details: "Destination memo is only supported for XRP Ledger withdrawals.",
110
+ metaMessages: [`Blockchain: ${blockchain}`, `Asset ID: ${assetId}`],
111
+ name: "UnsupportedDestinationMemoError"
112
+ });
113
+ this.blockchain = blockchain;
114
+ this.assetId = assetId;
115
+ }
116
+ };
117
+ var TrustlineNotFoundError = class extends BaseError {
118
+ constructor(destinationAddress, assetId, blockchain, tokenAddress) {
119
+ super("Destination address does not have a trustline for this asset.", {
120
+ details: "The destination address must establish a trustline before receiving this asset.",
121
+ metaMessages: [
122
+ `Blockchain: ${blockchain}`,
123
+ `Asset ID: ${assetId}`,
124
+ `Destination address: ${destinationAddress}`,
125
+ `Token address: ${tokenAddress}`
126
+ ],
127
+ name: "TrustlineNotFoundError"
128
+ });
129
+ this.destinationAddress = destinationAddress;
130
+ this.assetId = assetId;
131
+ this.blockchain = blockchain;
132
+ this.tokenAddress = tokenAddress;
133
+ }
134
+ };
135
+ var UnsupportedAssetIdError = class extends BaseError {
136
+ constructor(assetId, details) {
137
+ super("Asset ID is not supported.", {
138
+ details,
139
+ metaMessages: [`Asset ID: ${assetId}`],
140
+ name: "UnsupportedAssetIdError"
141
+ });
142
+ this.assetId = assetId;
143
+ }
144
+ };
145
+
146
+ // src/lib/parse-defuse-asset-id.ts
147
+ function parseDefuseAssetId(assetId) {
148
+ try {
149
+ return utils2.parseDefuseAssetId(assetId);
150
+ } catch {
151
+ throw new UnsupportedAssetIdError(assetId, "Invalid asset id format.");
152
+ }
153
+ }
154
+
155
+ // src/lib/estimate-fee.ts
156
+ import {
157
+ configsByEnvironment as configsByEnvironment2,
158
+ QuoteError,
159
+ solverRelay
160
+ } from "@defuse-protocol/internal-utils";
161
+
162
+ // src/lib/tokensUsdPricesHttpClient/apis.ts
163
+ import { request, configsByEnvironment } from "@defuse-protocol/internal-utils";
164
+ async function tokens(config) {
165
+ const response = await request({
166
+ url: new URL(
167
+ "tokens",
168
+ configsByEnvironment[config.env].managerConsoleBaseURL
169
+ ),
170
+ ...config,
171
+ fetchOptions: {
172
+ ...config.fetchOptions,
173
+ method: "GET"
174
+ }
175
+ });
176
+ return response.json();
177
+ }
178
+
179
+ // src/lib/estimate-fee.ts
180
+ async function getFeeQuote({
181
+ feeAmount,
182
+ feeAssetId,
183
+ tokenAssetId,
184
+ quoteOptions,
185
+ env,
186
+ logger
187
+ }) {
188
+ try {
189
+ return await solverRelay.getQuote({
190
+ quoteParams: {
191
+ defuse_asset_identifier_in: tokenAssetId,
192
+ defuse_asset_identifier_out: feeAssetId,
193
+ exact_amount_out: feeAmount.toString(),
194
+ wait_ms: quoteOptions?.waitMs
195
+ },
196
+ config: {
197
+ baseURL: configsByEnvironment2[env].solverRelayBaseURL,
198
+ logBalanceSufficient: false,
199
+ logger
200
+ }
201
+ });
202
+ } catch (err) {
203
+ if (!(err instanceof QuoteError)) {
204
+ throw err;
205
+ }
206
+ logger?.info(
207
+ "Can't get exact out quote, trying to get exact in quote with x1.2"
208
+ );
209
+ const prices = await tokens({ env });
210
+ const feeAssetPrice = prices.items.find(
211
+ (t) => t.defuse_asset_id === feeAssetId
212
+ );
213
+ const tokenAssetPrice = prices.items.find(
214
+ (t) => t.defuse_asset_id === tokenAssetId
215
+ );
216
+ if (feeAssetPrice == null || tokenAssetPrice == null) {
217
+ throw err;
218
+ }
219
+ const USD_SCALE = 1e6;
220
+ const feePriceScaled = BigInt(Math.round(feeAssetPrice.price * USD_SCALE));
221
+ const tokenPriceScaled = BigInt(
222
+ Math.round(tokenAssetPrice.price * USD_SCALE)
223
+ );
224
+ const feeDecimals = BigInt(feeAssetPrice.decimals);
225
+ const tokenDecimals = BigInt(tokenAssetPrice.decimals);
226
+ const num = feeAmount * feePriceScaled * 12n * 10n ** tokenDecimals;
227
+ const den = tokenPriceScaled * 10n ** feeDecimals * 10n;
228
+ let exactAmountIn = num / den;
229
+ if (num % den !== 0n) exactAmountIn += 1n;
230
+ if (exactAmountIn === 0n) exactAmountIn = 1n;
231
+ const quote = await solverRelay.getQuote({
232
+ quoteParams: {
233
+ defuse_asset_identifier_in: tokenAssetId,
234
+ defuse_asset_identifier_out: feeAssetId,
235
+ exact_amount_in: exactAmountIn.toString(),
236
+ wait_ms: quoteOptions?.waitMs
237
+ },
238
+ config: {
239
+ baseURL: configsByEnvironment2[env].solverRelayBaseURL,
240
+ logBalanceSufficient: false,
241
+ logger
242
+ }
243
+ });
244
+ const RATIO_SCALE = 1000n;
245
+ const actualRatio = BigInt(quote.amount_out) * RATIO_SCALE / feeAmount;
246
+ const actualRatioNumber = Number(actualRatio) / Number(RATIO_SCALE);
247
+ if (actualRatio > 1500n) {
248
+ logger?.warn(
249
+ `Quote amount_out ratio is too high: ${actualRatioNumber.toFixed(2)}x`
250
+ );
251
+ throw err;
252
+ }
253
+ if (BigInt(quote.amount_out) < feeAmount) {
254
+ logger?.warn("Quote amount_out is less than feeAmount");
255
+ throw err;
256
+ }
257
+ return quote;
258
+ }
259
+ }
260
+
75
261
  // src/bridges/aurora-engine-bridge/aurora-engine-bridge.ts
76
262
  var AuroraEngineBridge = class {
77
263
  constructor({
@@ -84,11 +270,19 @@ var AuroraEngineBridge = class {
84
270
  is(routeConfig) {
85
271
  return routeConfig.route === RouteEnum.VirtualChain;
86
272
  }
87
- supports(params) {
88
- if ("routeConfig" in params && params.routeConfig != null) {
89
- return this.is(params.routeConfig);
273
+ async supports(params) {
274
+ if (params.routeConfig == null || !this.is(params.routeConfig)) {
275
+ return false;
90
276
  }
91
- return false;
277
+ const assetInfo = parseDefuseAssetId(params.assetId);
278
+ const isValid = assetInfo.standard === "nep141";
279
+ if (!isValid) {
280
+ throw new UnsupportedAssetIdError(
281
+ params.assetId,
282
+ "`assetId` does not match `routeConfig`."
283
+ );
284
+ }
285
+ return isValid;
92
286
  }
93
287
  parseAssetId() {
94
288
  return null;
@@ -125,7 +319,7 @@ var AuroraEngineBridge = class {
125
319
  }
126
320
  async estimateWithdrawalFee(args) {
127
321
  withdrawalParamsInvariant(args.withdrawalParams);
128
- const { contractId: tokenAccountId, standard } = utils2.parseDefuseAssetId(
322
+ const { contractId: tokenAccountId, standard } = utils3.parseDefuseAssetId(
129
323
  args.withdrawalParams.assetId
130
324
  );
131
325
  assert2(standard === "nep141", "Only NEP-141 is supported");
@@ -148,18 +342,13 @@ var AuroraEngineBridge = class {
148
342
  }
149
343
  const feeAssetId = NEAR_NATIVE_ASSET_ID;
150
344
  const feeAmount = minStorageBalance - userStorageBalance;
151
- const feeQuote = args.withdrawalParams.assetId === feeAssetId ? null : await solverRelay.getQuote({
152
- quoteParams: {
153
- defuse_asset_identifier_in: args.withdrawalParams.assetId,
154
- defuse_asset_identifier_out: feeAssetId,
155
- exact_amount_out: feeAmount.toString(),
156
- wait_ms: args.quoteOptions?.waitMs
157
- },
158
- config: {
159
- baseURL: configsByEnvironment[this.env].solverRelayBaseURL,
160
- logBalanceSufficient: false,
161
- logger: args.logger
162
- }
345
+ const feeQuote = args.withdrawalParams.assetId === feeAssetId ? null : await getFeeQuote({
346
+ feeAmount,
347
+ feeAssetId,
348
+ tokenAssetId: args.withdrawalParams.assetId,
349
+ logger: args.logger,
350
+ env: this.env,
351
+ quoteOptions: args.quoteOptions
163
352
  });
164
353
  return {
165
354
  amount: feeQuote ? BigInt(feeQuote.amount_in) : feeAmount,
@@ -174,11 +363,9 @@ var AuroraEngineBridge = class {
174
363
  // src/bridges/direct-bridge/direct-bridge.ts
175
364
  import {
176
365
  assert as assert5,
177
- configsByEnvironment as configsByEnvironment2,
178
366
  getNearNep141MinStorageBalance as getNearNep141MinStorageBalance2,
179
367
  getNearNep141StorageBalance as getNearNep141StorageBalance2,
180
- solverRelay as solverRelay2,
181
- utils as utils4
368
+ utils as utils5
182
369
  } from "@defuse-protocol/internal-utils";
183
370
 
184
371
  // src/constants/bridge-name-enum.ts
@@ -227,7 +414,7 @@ function getEIP155ChainId(chain) {
227
414
  var NEAR_NATIVE_ASSET_ID2 = "nep141:wrap.near";
228
415
 
229
416
  // src/bridges/direct-bridge/direct-bridge-utils.ts
230
- import { assert as assert4, utils as utils3 } from "@defuse-protocol/internal-utils";
417
+ import { assert as assert4, utils as utils4 } from "@defuse-protocol/internal-utils";
231
418
  function createWithdrawIntentPrimitive2(params) {
232
419
  if (params.assetId === NEAR_NATIVE_ASSET_ID2 && // Ensure `msg` is not passed, because `native_withdraw` intent doesn't support `msg`
233
420
  params.msg === void 0) {
@@ -237,7 +424,7 @@ function createWithdrawIntentPrimitive2(params) {
237
424
  amount: params.amount.toString()
238
425
  };
239
426
  }
240
- const { contractId: tokenAccountId, standard } = utils3.parseDefuseAssetId(
427
+ const { contractId: tokenAccountId, standard } = utils4.parseDefuseAssetId(
241
428
  params.assetId
242
429
  );
243
430
  assert4(standard === "nep141", "Only NEP-141 is supported");
@@ -269,19 +456,22 @@ var DirectBridge = class {
269
456
  is(routeConfig) {
270
457
  return routeConfig.route === RouteEnum.NearWithdrawal;
271
458
  }
272
- supports(params) {
273
- let result = true;
274
- if ("routeConfig" in params && params.routeConfig != null) {
275
- result && (result = this.is(params.routeConfig));
276
- }
277
- try {
278
- return result && this.parseAssetId(params.assetId) != null;
279
- } catch {
459
+ async supports(params) {
460
+ if (params.routeConfig != null && !this.is(params.routeConfig)) {
280
461
  return false;
281
462
  }
463
+ const assetInfo = this.parseAssetId(params.assetId);
464
+ const isValid = assetInfo != null;
465
+ if (!isValid && params.routeConfig != null) {
466
+ throw new UnsupportedAssetIdError(
467
+ params.assetId,
468
+ "`assetId` does not match `routeConfig`."
469
+ );
470
+ }
471
+ return isValid;
282
472
  }
283
473
  parseAssetId(assetId) {
284
- const parsed = utils4.parseDefuseAssetId(assetId);
474
+ const parsed = parseDefuseAssetId(assetId);
285
475
  if (parsed.standard === "nep141") {
286
476
  return Object.assign(parsed, {
287
477
  blockchain: Chains.Near,
@@ -322,7 +512,7 @@ var DirectBridge = class {
322
512
  }
323
513
  async estimateWithdrawalFee(args) {
324
514
  withdrawalParamsInvariant2(args.withdrawalParams);
325
- const { contractId: tokenAccountId, standard } = utils4.parseDefuseAssetId(
515
+ const { contractId: tokenAccountId, standard } = utils5.parseDefuseAssetId(
326
516
  args.withdrawalParams.assetId
327
517
  );
328
518
  assert5(standard === "nep141", "Only NEP-141 is supported");
@@ -354,18 +544,13 @@ var DirectBridge = class {
354
544
  }
355
545
  const feeAssetId = NEAR_NATIVE_ASSET_ID2;
356
546
  const feeAmount = minStorageBalance - userStorageBalance;
357
- const feeQuote = args.withdrawalParams.assetId === feeAssetId ? null : await solverRelay2.getQuote({
358
- quoteParams: {
359
- defuse_asset_identifier_in: args.withdrawalParams.assetId,
360
- defuse_asset_identifier_out: feeAssetId,
361
- exact_amount_out: feeAmount.toString(),
362
- wait_ms: args.quoteOptions?.waitMs
363
- },
364
- config: {
365
- baseURL: configsByEnvironment2[this.env].solverRelayBaseURL,
366
- logBalanceSufficient: false,
367
- logger: args.logger
368
- }
547
+ const feeQuote = args.withdrawalParams.assetId === feeAssetId ? null : await getFeeQuote({
548
+ feeAmount,
549
+ feeAssetId,
550
+ tokenAssetId: args.withdrawalParams.assetId,
551
+ logger: args.logger,
552
+ env: this.env,
553
+ quoteOptions: args.quoteOptions
369
554
  });
370
555
  return {
371
556
  amount: feeQuote ? BigInt(feeQuote.amount_in) : feeAmount,
@@ -380,74 +565,11 @@ var DirectBridge = class {
380
565
  // src/bridges/hot-bridge/hot-bridge.ts
381
566
  import {
382
567
  assert as assert7,
383
- RETRY_CONFIGS,
384
- configsByEnvironment as configsByEnvironment3,
385
- utils as internalUtils,
386
- solverRelay as solverRelay3
568
+ RETRY_CONFIGS
387
569
  } from "@defuse-protocol/internal-utils";
388
- import { utils as utils5 } from "@hot-labs/omni-sdk";
570
+ import { utils as utils6 } from "@hot-labs/omni-sdk";
389
571
  import { retry } from "@lifeomic/attempt";
390
572
 
391
- // src/classes/errors.ts
392
- import { BaseError } from "@defuse-protocol/internal-utils";
393
- var FeeExceedsAmountError = class extends BaseError {
394
- constructor(feeEstimation, amount) {
395
- super("Amount too small to pay fee.", {
396
- metaMessages: [
397
- `Required fee: ${feeEstimation.amount}`,
398
- `Withdrawal amount: ${amount}`
399
- ],
400
- name: "FeeExceedsAmountError"
401
- });
402
- this.feeEstimation = feeEstimation;
403
- this.amount = amount;
404
- }
405
- };
406
- var MinWithdrawalAmountError = class extends BaseError {
407
- constructor(minAmount, requestedAmount, assetId) {
408
- super("Withdrawal amount is below minimum required by the bridge.", {
409
- metaMessages: [
410
- `Asset ID: ${assetId}`,
411
- `Minimum amount: ${minAmount}`,
412
- `Requested amount: ${requestedAmount}`
413
- ],
414
- name: "MinWithdrawalAmountError"
415
- });
416
- this.minAmount = minAmount;
417
- this.requestedAmount = requestedAmount;
418
- this.assetId = assetId;
419
- }
420
- };
421
- var UnsupportedDestinationMemoError = class extends BaseError {
422
- constructor(blockchain, assetId) {
423
- super("Destination memo is not supported for this blockchain.", {
424
- details: "Destination memo is only supported for XRP Ledger withdrawals.",
425
- metaMessages: [`Blockchain: ${blockchain}`, `Asset ID: ${assetId}`],
426
- name: "UnsupportedDestinationMemoError"
427
- });
428
- this.blockchain = blockchain;
429
- this.assetId = assetId;
430
- }
431
- };
432
- var TrustlineNotFoundError = class extends BaseError {
433
- constructor(destinationAddress, assetId, blockchain, tokenAddress) {
434
- super("Destination address does not have a trustline for this asset.", {
435
- details: "The destination address must establish a trustline before receiving this asset.",
436
- metaMessages: [
437
- `Blockchain: ${blockchain}`,
438
- `Asset ID: ${assetId}`,
439
- `Destination address: ${destinationAddress}`,
440
- `Token address: ${tokenAddress}`
441
- ],
442
- name: "TrustlineNotFoundError"
443
- });
444
- this.destinationAddress = destinationAddress;
445
- this.assetId = assetId;
446
- this.blockchain = blockchain;
447
- this.tokenAddress = tokenAddress;
448
- }
449
- };
450
-
451
573
  // src/bridges/hot-bridge/error.ts
452
574
  import { BaseError as BaseError2 } from "@defuse-protocol/internal-utils";
453
575
  var HotWithdrawalPendingError = class extends BaseError2 {
@@ -557,37 +679,56 @@ var HotBridge = class {
557
679
  is(routeConfig) {
558
680
  return routeConfig.route === RouteEnum.HotBridge;
559
681
  }
560
- supports(params) {
561
- let result = true;
562
- if ("routeConfig" in params && params.routeConfig != null) {
563
- result && (result = this.is(params.routeConfig));
564
- }
565
- try {
566
- return result && this.parseAssetId(params.assetId) != null;
567
- } catch {
682
+ async supports(params) {
683
+ if (params.routeConfig != null && !this.is(params.routeConfig)) {
568
684
  return false;
569
685
  }
686
+ const assetInfo = this.parseAssetId(params.assetId);
687
+ const isValid = assetInfo != null;
688
+ if (!isValid && params.routeConfig != null) {
689
+ throw new UnsupportedAssetIdError(
690
+ params.assetId,
691
+ "`assetId` does not match `routeConfig`."
692
+ );
693
+ }
694
+ return isValid;
570
695
  }
571
696
  parseAssetId(assetId) {
572
- const parsed = internalUtils.parseDefuseAssetId(assetId);
573
- if (parsed.contractId === utils5.OMNI_HOT_V2) {
574
- assert7(
575
- parsed.standard === "nep245",
576
- "NEP-245 is supported only for HOT bridge"
697
+ const parsed = parseDefuseAssetId(assetId);
698
+ const contractIdSatisfies = parsed.contractId === utils6.OMNI_HOT_V2;
699
+ if (!contractIdSatisfies) {
700
+ return null;
701
+ }
702
+ if (parsed.standard !== "nep245") {
703
+ throw new UnsupportedAssetIdError(
704
+ assetId,
705
+ 'Should start with "nep245:".'
577
706
  );
578
- const [chainId, address] = utils5.fromOmni(parsed.tokenId).split(":");
579
- assert7(chainId != null, "Chain ID is not found");
580
- assert7(address != null, "Address is not found");
581
- return Object.assign(
582
- parsed,
583
- {
584
- blockchain: hotNetworkIdToCAIP2(chainId),
585
- bridgeName: BridgeNameEnum.Hot
586
- },
587
- address === "native" ? { native: true } : { address }
707
+ }
708
+ const [chainId, address] = utils6.fromOmni(parsed.tokenId).split(":");
709
+ if (chainId == null || address == null) {
710
+ throw new UnsupportedAssetIdError(
711
+ assetId,
712
+ "Asset has invalid token id format."
588
713
  );
589
714
  }
590
- return null;
715
+ let blockchain;
716
+ try {
717
+ blockchain = hotNetworkIdToCAIP2(chainId);
718
+ } catch {
719
+ throw new UnsupportedAssetIdError(
720
+ assetId,
721
+ "Asset belongs to unknown blockchain."
722
+ );
723
+ }
724
+ return Object.assign(
725
+ parsed,
726
+ {
727
+ blockchain,
728
+ bridgeName: BridgeNameEnum.Hot
729
+ },
730
+ address === "native" ? { native: true } : { address }
731
+ );
591
732
  }
592
733
  async createWithdrawalIntents(args) {
593
734
  const assetInfo = this.parseAssetId(args.withdrawalParams.assetId);
@@ -669,18 +810,13 @@ var HotBridge = class {
669
810
  args.withdrawalParams.destinationAddress
670
811
  );
671
812
  const feeAssetId = getFeeAssetIdForChain(assetInfo.blockchain);
672
- const feeQuote = args.withdrawalParams.assetId === feeAssetId || feeAmount === 0n ? null : await solverRelay3.getQuote({
673
- quoteParams: {
674
- defuse_asset_identifier_in: args.withdrawalParams.assetId,
675
- defuse_asset_identifier_out: feeAssetId,
676
- exact_amount_out: feeAmount.toString(),
677
- wait_ms: args.quoteOptions?.waitMs
678
- },
679
- config: {
680
- baseURL: configsByEnvironment3[this.env].solverRelayBaseURL,
681
- logBalanceSufficient: false,
682
- logger: args.logger
683
- }
813
+ const feeQuote = args.withdrawalParams.assetId === feeAssetId || feeAmount === 0n ? null : await getFeeQuote({
814
+ feeAmount,
815
+ feeAssetId,
816
+ tokenAssetId: args.withdrawalParams.assetId,
817
+ logger: args.logger,
818
+ env: this.env,
819
+ quoteOptions: args.quoteOptions
684
820
  });
685
821
  return {
686
822
  amount: feeQuote ? BigInt(feeQuote.amount_in) : feeAmount,
@@ -734,7 +870,7 @@ var IntentsBridge = class {
734
870
  is(routeConfig) {
735
871
  return routeConfig.route === RouteEnum.InternalTransfer;
736
872
  }
737
- supports(params) {
873
+ async supports(params) {
738
874
  if ("routeConfig" in params && params.routeConfig != null) {
739
875
  return this.is(params.routeConfig);
740
876
  }
@@ -775,16 +911,16 @@ var IntentsBridge = class {
775
911
  // src/bridges/poa-bridge/poa-bridge.ts
776
912
  import {
777
913
  assert as assert8,
778
- configsByEnvironment as configsByEnvironment4,
914
+ configsByEnvironment as configsByEnvironment3,
779
915
  poaBridge,
780
- utils as utils7
916
+ utils as utils8
781
917
  } from "@defuse-protocol/internal-utils";
782
918
  import TTLCache from "@isaacs/ttlcache";
783
919
 
784
920
  // src/bridges/poa-bridge/poa-bridge-utils.ts
785
- import { utils as utils6 } from "@defuse-protocol/internal-utils";
921
+ import { utils as utils7 } from "@defuse-protocol/internal-utils";
786
922
  function createWithdrawIntentPrimitive3(params) {
787
- const { contractId: tokenAccountId } = utils6.parseDefuseAssetId(
923
+ const { contractId: tokenAccountId } = utils7.parseDefuseAssetId(
788
924
  params.assetId
789
925
  );
790
926
  return {
@@ -865,30 +1001,43 @@ var PoaBridge = class {
865
1001
  is(routeConfig) {
866
1002
  return routeConfig.route === RouteEnum.PoaBridge;
867
1003
  }
868
- supports(params) {
869
- let result = true;
870
- if ("routeConfig" in params && params.routeConfig != null) {
871
- result && (result = this.is(params.routeConfig));
872
- }
873
- try {
874
- return result && this.parseAssetId(params.assetId) != null;
875
- } catch {
1004
+ async supports(params) {
1005
+ if (params.routeConfig != null && !this.is(params.routeConfig)) {
876
1006
  return false;
877
1007
  }
1008
+ const assetInfo = this.parseAssetId(params.assetId);
1009
+ const isValid = assetInfo != null;
1010
+ if (!isValid && params.routeConfig != null) {
1011
+ throw new UnsupportedAssetIdError(
1012
+ params.assetId,
1013
+ "`assetId` does not match `routeConfig`."
1014
+ );
1015
+ }
1016
+ return isValid;
878
1017
  }
879
1018
  parseAssetId(assetId) {
880
- const parsed = utils7.parseDefuseAssetId(assetId);
881
- if (parsed.contractId.endsWith(
882
- `.${configsByEnvironment4[this.env].poaTokenFactoryContractID}`
883
- )) {
884
- return Object.assign(parsed, {
885
- blockchain: contractIdToCaip2(parsed.contractId),
886
- bridgeName: BridgeNameEnum.Poa,
887
- address: ""
888
- // todo: derive address (or native)
889
- });
1019
+ const parsed = parseDefuseAssetId(assetId);
1020
+ const contractIdSatisfies = parsed.contractId.endsWith(
1021
+ `.${configsByEnvironment3[this.env].poaTokenFactoryContractID}`
1022
+ );
1023
+ if (!contractIdSatisfies) {
1024
+ return null;
890
1025
  }
891
- return null;
1026
+ let blockchain;
1027
+ try {
1028
+ blockchain = contractIdToCaip2(parsed.contractId);
1029
+ } catch {
1030
+ throw new UnsupportedAssetIdError(
1031
+ assetId,
1032
+ "Asset belongs to unknown blockchain."
1033
+ );
1034
+ }
1035
+ return Object.assign(parsed, {
1036
+ blockchain,
1037
+ bridgeName: BridgeNameEnum.Poa,
1038
+ address: ""
1039
+ // todo: derive address (or native)
1040
+ });
892
1041
  }
893
1042
  createWithdrawalIntents(args) {
894
1043
  const intent = createWithdrawIntentPrimitive3({
@@ -907,11 +1056,11 @@ var PoaBridge = class {
907
1056
  async validateWithdrawal(args) {
908
1057
  const assetInfo = this.parseAssetId(args.assetId);
909
1058
  assert8(assetInfo != null, "Asset is not supported");
910
- const { tokens } = await this.getCachedSupportedTokens(
1059
+ const { tokens: tokens2 } = await this.getCachedSupportedTokens(
911
1060
  [toPoaNetwork(assetInfo.blockchain)],
912
1061
  args.logger
913
1062
  );
914
- const tokenInfo = tokens.find(
1063
+ const tokenInfo = tokens2.find(
915
1064
  (token) => token.intents_token_id === args.assetId
916
1065
  );
917
1066
  if (tokenInfo != null) {
@@ -930,13 +1079,13 @@ var PoaBridge = class {
930
1079
  assert8(assetInfo != null, "Asset is not supported");
931
1080
  const estimation = await poaBridge.httpClient.getWithdrawalEstimate(
932
1081
  {
933
- token: utils7.getTokenAccountId(args.withdrawalParams.assetId),
1082
+ token: utils8.getTokenAccountId(args.withdrawalParams.assetId),
934
1083
  address: args.withdrawalParams.destinationAddress,
935
1084
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
936
1085
  chain: toPoaNetwork(assetInfo.blockchain)
937
1086
  },
938
1087
  {
939
- baseURL: configsByEnvironment4[this.env].poaBridgeBaseURL,
1088
+ baseURL: configsByEnvironment3[this.env].poaBridgeBaseURL,
940
1089
  logger: args.logger
941
1090
  }
942
1091
  );
@@ -951,7 +1100,7 @@ var PoaBridge = class {
951
1100
  index: args.index,
952
1101
  signal: args.signal ?? new AbortController().signal,
953
1102
  retryOptions: args.retryOptions,
954
- baseURL: configsByEnvironment4[this.env].poaBridgeBaseURL,
1103
+ baseURL: configsByEnvironment3[this.env].poaBridgeBaseURL,
955
1104
  logger: args.logger
956
1105
  });
957
1106
  return { hash: withdrawalStatus.destinationTxHash };
@@ -969,7 +1118,7 @@ var PoaBridge = class {
969
1118
  const data = await poaBridge.httpClient.getSupportedTokens(
970
1119
  { chains },
971
1120
  {
972
- baseURL: configsByEnvironment4[this.env].poaBridgeBaseURL,
1121
+ baseURL: configsByEnvironment3[this.env].poaBridgeBaseURL,
973
1122
  logger
974
1123
  }
975
1124
  );
@@ -992,7 +1141,7 @@ var PUBLIC_STELLAR_RPC_URLS = {
992
1141
 
993
1142
  // src/intents/intent-executer-impl/intent-executer.ts
994
1143
  import {
995
- configsByEnvironment as configsByEnvironment5
1144
+ configsByEnvironment as configsByEnvironment4
996
1145
  } from "@defuse-protocol/internal-utils";
997
1146
 
998
1147
  // ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/_u64.js
@@ -1374,7 +1523,7 @@ var IntentExecuter = class {
1374
1523
  relayParams: relayParamsFactory,
1375
1524
  ...intentParams
1376
1525
  }) {
1377
- const verifyingContract = configsByEnvironment5[this.env].contractID;
1526
+ const verifyingContract = configsByEnvironment4[this.env].contractID;
1378
1527
  let intentPayload = defaultIntentPayloadFactory({
1379
1528
  verifying_contract: verifyingContract,
1380
1529
  ...intentParams
@@ -1425,8 +1574,8 @@ async function mergeIntentPayloads(basePayload, intentPayloadFactory) {
1425
1574
 
1426
1575
  // src/intents/intent-relayer-impl/intent-relayer-public.ts
1427
1576
  import {
1428
- configsByEnvironment as configsByEnvironment6,
1429
- solverRelay as solverRelay4
1577
+ configsByEnvironment as configsByEnvironment5,
1578
+ solverRelay as solverRelay2
1430
1579
  } from "@defuse-protocol/internal-utils";
1431
1580
  var IntentRelayerPublic = class {
1432
1581
  constructor({ env }) {
@@ -1449,13 +1598,13 @@ var IntentRelayerPublic = class {
1449
1598
  multiPayloads,
1450
1599
  quoteHashes
1451
1600
  }, ctx = {}) {
1452
- const a = await solverRelay4.publishIntents(
1601
+ const a = await solverRelay2.publishIntents(
1453
1602
  {
1454
1603
  quote_hashes: quoteHashes,
1455
1604
  signed_datas: multiPayloads
1456
1605
  },
1457
1606
  {
1458
- baseURL: configsByEnvironment6[this.env].solverRelayBaseURL,
1607
+ baseURL: configsByEnvironment5[this.env].solverRelayBaseURL,
1459
1608
  logger: ctx.logger
1460
1609
  }
1461
1610
  );
@@ -1465,10 +1614,10 @@ var IntentRelayerPublic = class {
1465
1614
  throw a.unwrapErr();
1466
1615
  }
1467
1616
  async waitForSettlement(ticket, ctx = {}) {
1468
- const result = await solverRelay4.waitForIntentSettlement({
1617
+ const result = await solverRelay2.waitForIntentSettlement({
1469
1618
  intentHash: ticket,
1470
1619
  signal: new AbortController().signal,
1471
- baseURL: configsByEnvironment6[this.env].solverRelayBaseURL,
1620
+ baseURL: configsByEnvironment5[this.env].solverRelayBaseURL,
1472
1621
  logger: ctx.logger
1473
1622
  });
1474
1623
  return {
@@ -1476,7 +1625,7 @@ var IntentRelayerPublic = class {
1476
1625
  hash: result.txHash,
1477
1626
  // Usually relayer's account id is the verifying contract (`intents.near`),
1478
1627
  // but it is not set in stone and may change in the future.
1479
- accountId: configsByEnvironment6[this.env].contractID
1628
+ accountId: configsByEnvironment5[this.env].contractID
1480
1629
  }
1481
1630
  };
1482
1631
  }
@@ -1547,7 +1696,7 @@ function createInternalTransferRoute() {
1547
1696
  function createNearWithdrawalRoute(msg) {
1548
1697
  return { route: RouteEnum.NearWithdrawal, msg };
1549
1698
  }
1550
- function createOmniWithdrawalRoute() {
1699
+ function createOmniBridgeRoute() {
1551
1700
  return { route: RouteEnum.OmniBridge };
1552
1701
  }
1553
1702
  function createVirtualChainRoute(auroraEngineContractId, proxyTokenContractId) {
@@ -1581,17 +1730,11 @@ function determineRouteConfig(sdk, withdrawalParams) {
1581
1730
  const bridgeName = parseAssetId.bridgeName;
1582
1731
  switch (bridgeName) {
1583
1732
  case BridgeNameEnum.Hot:
1584
- return {
1585
- route: RouteEnum.HotBridge,
1586
- chain: parseAssetId.blockchain
1587
- };
1733
+ return createHotBridgeRoute(parseAssetId.blockchain);
1588
1734
  case BridgeNameEnum.Poa:
1589
- return {
1590
- route: RouteEnum.PoaBridge,
1591
- chain: parseAssetId.blockchain
1592
- };
1735
+ return createPoaBridgeRoute(parseAssetId.blockchain);
1593
1736
  case BridgeNameEnum.Omni:
1594
- return createOmniWithdrawalRoute();
1737
+ return createOmniBridgeRoute();
1595
1738
  case BridgeNameEnum.None:
1596
1739
  return createNearWithdrawalRoute();
1597
1740
  default:
@@ -1656,7 +1799,7 @@ var IntentsSDK = class {
1656
1799
  }
1657
1800
  async createWithdrawalIntents(args) {
1658
1801
  for (const bridge of this.bridges) {
1659
- if (bridge.supports(args.withdrawalParams)) {
1802
+ if (await bridge.supports(args.withdrawalParams)) {
1660
1803
  const actualAmount = args.withdrawalParams.feeInclusive ? args.withdrawalParams.amount - args.feeEstimation.amount : args.withdrawalParams.amount;
1661
1804
  await bridge.validateWithdrawal({
1662
1805
  assetId: args.withdrawalParams.assetId,
@@ -1698,7 +1841,7 @@ var IntentsSDK = class {
1698
1841
  }
1699
1842
  async _estimateWithdrawalFee(args) {
1700
1843
  for (const bridge of this.bridges) {
1701
- if (bridge.supports(args.withdrawalParams)) {
1844
+ if (await bridge.supports(args.withdrawalParams)) {
1702
1845
  const fee = await bridge.estimateWithdrawalFee({
1703
1846
  withdrawalParams: args.withdrawalParams,
1704
1847
  quoteOptions: args.quoteOptions,
@@ -1850,12 +1993,12 @@ var IntentsSDK = class {
1850
1993
  intentHash,
1851
1994
  logger
1852
1995
  }) {
1853
- return solverRelay5.getStatus(
1996
+ return solverRelay3.getStatus(
1854
1997
  {
1855
1998
  intent_hash: intentHash
1856
1999
  },
1857
2000
  {
1858
- baseURL: configsByEnvironment7[this.env].solverRelayBaseURL,
2001
+ baseURL: configsByEnvironment6[this.env].solverRelayBaseURL,
1859
2002
  logger
1860
2003
  }
1861
2004
  );
@@ -1965,14 +2108,14 @@ var IntentSignerNearKeypair = class extends IntentSignerNEP413 {
1965
2108
  };
1966
2109
 
1967
2110
  // src/intents/intent-signer-impl/intent-signer-viem.ts
1968
- import { utils as utils8 } from "@defuse-protocol/internal-utils";
2111
+ import { utils as utils9 } from "@defuse-protocol/internal-utils";
1969
2112
  var IntentSignerViem = class {
1970
2113
  constructor(account) {
1971
2114
  this.account = account;
1972
2115
  }
1973
2116
  async signIntent(intent) {
1974
2117
  const payload = JSON.stringify({
1975
- signer_id: intent.signer_id ?? utils8.authHandleToIntentsUserId({
2118
+ signer_id: intent.signer_id ?? utils9.authHandleToIntentsUserId({
1976
2119
  identifier: this.account.address,
1977
2120
  method: "evm"
1978
2121
  }),
@@ -1990,7 +2133,7 @@ var IntentSignerViem = class {
1990
2133
  return {
1991
2134
  standard: "erc191",
1992
2135
  payload,
1993
- signature: utils8.transformERC191Signature(signature)
2136
+ signature: utils9.transformERC191Signature(signature)
1994
2137
  };
1995
2138
  }
1996
2139
  };
@@ -2072,7 +2215,7 @@ import {
2072
2215
  AssertionError
2073
2216
  } from "@defuse-protocol/internal-utils";
2074
2217
  import {
2075
- QuoteError,
2218
+ QuoteError as QuoteError2,
2076
2219
  IntentSettlementError,
2077
2220
  RelayPublishError
2078
2221
  } from "@defuse-protocol/internal-utils";
@@ -2094,7 +2237,7 @@ export {
2094
2237
  PoaWithdrawalInvariantError,
2095
2238
  PoaWithdrawalNotFoundError,
2096
2239
  PoaWithdrawalPendingError,
2097
- QuoteError,
2240
+ QuoteError2 as QuoteError,
2098
2241
  RelayPublishError,
2099
2242
  RouteEnum,
2100
2243
  RpcRequestError,
@@ -2102,6 +2245,7 @@ export {
2102
2245
  TokenNotFoundInDestinationChainError,
2103
2246
  TokenNotSupportedByOmniRelayerError,
2104
2247
  TrustlineNotFoundError,
2248
+ UnsupportedAssetIdError,
2105
2249
  UnsupportedDestinationMemoError,
2106
2250
  createDefaultRoute,
2107
2251
  createHotBridgeRoute,
@@ -2110,7 +2254,7 @@ export {
2110
2254
  createIntentSignerViem,
2111
2255
  createInternalTransferRoute,
2112
2256
  createNearWithdrawalRoute,
2113
- createOmniWithdrawalRoute,
2257
+ createOmniBridgeRoute,
2114
2258
  createPoaBridgeRoute,
2115
2259
  createVirtualChainRoute
2116
2260
  };