@defuse-protocol/intents-sdk 0.81.0 → 0.83.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.
@@ -6,39 +6,28 @@ let _defuse_protocol_internal_utils = require("@defuse-protocol/internal-utils")
6
6
  let valibot = require("valibot");
7
7
  valibot = require_rolldown_runtime.__toESM(valibot);
8
8
  let _omni_bridge_core = require("@omni-bridge/core");
9
- let _omni_bridge_near = require("@omni-bridge/near");
10
9
 
11
10
  //#region src/bridges/omni-bridge/omni-bridge-utils.ts
12
- function createWithdrawIntentsPrimitive(params) {
13
- const { contractId: tokenAccountId, standard } = _defuse_protocol_internal_utils.utils.parseDefuseAssetId(params.assetId);
14
- (0, _defuse_protocol_internal_utils.assert)(standard === "nep141", "Only NEP-141 is supported");
15
- const recipient = (0, _omni_bridge_core.omniAddress)(params.omniChainKind, params.destinationAddress);
16
- let msg = "";
11
+ /**
12
+ * Lays a calculated withdrawal out as intents.
13
+ *
14
+ * It takes the result of `deriveOmniWithdrawIntentParams` rather than the inputs to it, so
15
+ * there is one calculation and no way to hand it a value that was worked out some other way.
16
+ * That matters most for the amount: a UTXO chain has already added its fees to it, and doing
17
+ * that twice would send more than the caller asked for.
18
+ */
19
+ function createWithdrawIntentsPrimitive({ tokenAccountId, recipient, msg, externalId, storageDepositAccountId, amount, nativeFee, storageDepositAmount }) {
17
20
  const ftWithdrawPayload = {
18
21
  recipient,
19
22
  fee: "0",
20
- native_token_fee: params.nativeFee.toString(),
21
- external_id: crypto.randomUUID()
23
+ native_token_fee: nativeFee.toString(),
24
+ external_id: externalId
22
25
  };
23
- if (isUtxoChain(params.omniChainKind)) {
24
- (0, _defuse_protocol_internal_utils.assert)(params.utxoMaxGasFee !== null && params.utxoMaxGasFee > 0n, `Invalid utxo max gas fee: expected > 0, got ${params.utxoMaxGasFee}`);
25
- msg = JSON.stringify({ MaxGasFee: params.utxoMaxGasFee.toString() });
26
- ftWithdrawPayload.msg = msg;
27
- }
26
+ if (msg !== "") ftWithdrawPayload.msg = msg;
28
27
  const intents = [];
29
- if (params.nativeFee > 0n) intents.push({
30
- deposit_for_account_id: (0, _omni_bridge_near.calculateStorageAccountId)({
31
- token: `near:${tokenAccountId}`,
32
- amount: params.amount,
33
- recipient,
34
- fee: {
35
- fee: 0n,
36
- native_fee: params.nativeFee
37
- },
38
- sender: `near:${params.intentsContract}`,
39
- msg
40
- }, ftWithdrawPayload.external_id),
41
- amount: params.nativeFee.toString(),
28
+ if (storageDepositAccountId !== null) intents.push({
29
+ deposit_for_account_id: storageDepositAccountId,
30
+ amount: nativeFee.toString(),
42
31
  contract_id: require_omni_bridge_constants.OMNI_BRIDGE_CONTRACT,
43
32
  intent: "storage_deposit"
44
33
  });
@@ -46,8 +35,8 @@ function createWithdrawIntentsPrimitive(params) {
46
35
  intent: "ft_withdraw",
47
36
  token: tokenAccountId,
48
37
  receiver_id: require_omni_bridge_constants.OMNI_BRIDGE_CONTRACT,
49
- amount: params.amount.toString(),
50
- storage_deposit: params.storageDepositAmount > 0n ? params.storageDepositAmount.toString() : void 0,
38
+ amount: amount.toString(),
39
+ storage_deposit: storageDepositAmount > 0n ? storageDepositAmount.toString() : void 0,
51
40
  msg: JSON.stringify(ftWithdrawPayload),
52
41
  min_gas: require_omni_bridge_constants.MIN_GAS_AMOUNT
53
42
  });
@@ -69,18 +58,12 @@ const CHAIN_MAPPINGS = [
69
58
  [require_caip2.Chains.Fogo, _omni_bridge_core.ChainKind.Fogo],
70
59
  [require_caip2.Chains.Polygon, _omni_bridge_core.ChainKind.Pol],
71
60
  [require_caip2.Chains.Aptos, _omni_bridge_core.ChainKind.Aptos],
72
- [require_caip2.Chains.HyperEvm, _omni_bridge_core.ChainKind.HlEvm]
61
+ [require_caip2.Chains.HyperEvm, _omni_bridge_core.ChainKind.HlEvm],
62
+ [require_caip2.Chains.Zcash, _omni_bridge_core.ChainKind.Zcash]
73
63
  ];
74
- function caip2ToChainKind(network) {
75
- return CHAIN_MAPPINGS.find(([chain]) => chain === network)?.[1] ?? null;
76
- }
77
64
  function chainKindToCaip2(network) {
78
65
  return CHAIN_MAPPINGS.find(([_, kind]) => kind === network)?.[0] ?? null;
79
66
  }
80
- const UTXO_CHAINS = [_omni_bridge_core.ChainKind.Btc];
81
- function isUtxoChain(network) {
82
- return UTXO_CHAINS.includes(network);
83
- }
84
67
  function poaContractIdToChainKind(contractId) {
85
68
  return require_poa_tokens_migrated_to_omni_bridge.POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE[contractId] ?? null;
86
69
  }
@@ -101,7 +84,7 @@ async function getAccountOmniStorageBalance(nearProvider, accountId) {
101
84
  })])
102
85
  });
103
86
  }
104
- const OmniAddressSchema = valibot.custom((input) => typeof input === "string" && (input.startsWith("eth:") || input.startsWith("near:") || input.startsWith("sol:") || input.startsWith("arb:") || input.startsWith("base:") || input.startsWith("btc:") || input.startsWith("bnb:") || input.startsWith("abs:") || input.startsWith("strk:") || input.startsWith("fogo:") || input.startsWith("pol:") || input.startsWith("aptos:") || input.startsWith("hlevm:")), "Must comply with omni address schema");
87
+ const OmniAddressSchema = valibot.custom((input) => typeof input === "string" && (input.startsWith("eth:") || input.startsWith("near:") || input.startsWith("sol:") || input.startsWith("arb:") || input.startsWith("base:") || input.startsWith("btc:") || input.startsWith("bnb:") || input.startsWith("abs:") || input.startsWith("strk:") || input.startsWith("fogo:") || input.startsWith("pol:") || input.startsWith("aptos:") || input.startsWith("hlevm:") || input.startsWith("zcash:")), "Must comply with omni address schema");
105
88
  /**
106
89
  * Converts a token address from one chain to its equivalent on another chain.
107
90
  * @param nearProvider Near provider used for querying the contract
@@ -149,12 +132,11 @@ async function getTokenDecimals(nearProvider, tokenAddress) {
149
132
  }
150
133
 
151
134
  //#endregion
152
- exports.caip2ToChainKind = caip2ToChainKind;
135
+ exports.CHAIN_MAPPINGS = CHAIN_MAPPINGS;
153
136
  exports.chainKindToCaip2 = chainKindToCaip2;
154
137
  exports.createWithdrawIntentsPrimitive = createWithdrawIntentsPrimitive;
155
138
  exports.getAccountOmniStorageBalance = getAccountOmniStorageBalance;
156
139
  exports.getBridgedToken = getBridgedToken;
157
140
  exports.getTokenDecimals = getTokenDecimals;
158
- exports.isUtxoChain = isUtxoChain;
159
141
  exports.poaContractIdToChainKind = poaContractIdToChainKind;
160
142
  exports.validateOmniToken = validateOmniToken;
@@ -1,42 +1,31 @@
1
1
  import { Chains } from "../../lib/caip2.js";
2
2
  import { MIN_GAS_AMOUNT, OMNI_BRIDGE_CONTRACT } from "./omni-bridge-constants.js";
3
3
  import { POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE } from "../../constants/poa-tokens-migrated-to-omni-bridge.js";
4
- import { assert, utils } from "@defuse-protocol/internal-utils";
4
+ import { utils } from "@defuse-protocol/internal-utils";
5
5
  import * as v from "valibot";
6
- import { ChainKind, getChain, isBridgeToken, omniAddress } from "@omni-bridge/core";
7
- import { calculateStorageAccountId } from "@omni-bridge/near";
6
+ import { ChainKind, getChain, isBridgeToken } from "@omni-bridge/core";
8
7
 
9
8
  //#region src/bridges/omni-bridge/omni-bridge-utils.ts
10
- function createWithdrawIntentsPrimitive(params) {
11
- const { contractId: tokenAccountId, standard } = utils.parseDefuseAssetId(params.assetId);
12
- assert(standard === "nep141", "Only NEP-141 is supported");
13
- const recipient = omniAddress(params.omniChainKind, params.destinationAddress);
14
- let msg = "";
9
+ /**
10
+ * Lays a calculated withdrawal out as intents.
11
+ *
12
+ * It takes the result of `deriveOmniWithdrawIntentParams` rather than the inputs to it, so
13
+ * there is one calculation and no way to hand it a value that was worked out some other way.
14
+ * That matters most for the amount: a UTXO chain has already added its fees to it, and doing
15
+ * that twice would send more than the caller asked for.
16
+ */
17
+ function createWithdrawIntentsPrimitive({ tokenAccountId, recipient, msg, externalId, storageDepositAccountId, amount, nativeFee, storageDepositAmount }) {
15
18
  const ftWithdrawPayload = {
16
19
  recipient,
17
20
  fee: "0",
18
- native_token_fee: params.nativeFee.toString(),
19
- external_id: crypto.randomUUID()
21
+ native_token_fee: nativeFee.toString(),
22
+ external_id: externalId
20
23
  };
21
- if (isUtxoChain(params.omniChainKind)) {
22
- assert(params.utxoMaxGasFee !== null && params.utxoMaxGasFee > 0n, `Invalid utxo max gas fee: expected > 0, got ${params.utxoMaxGasFee}`);
23
- msg = JSON.stringify({ MaxGasFee: params.utxoMaxGasFee.toString() });
24
- ftWithdrawPayload.msg = msg;
25
- }
24
+ if (msg !== "") ftWithdrawPayload.msg = msg;
26
25
  const intents = [];
27
- if (params.nativeFee > 0n) intents.push({
28
- deposit_for_account_id: calculateStorageAccountId({
29
- token: `near:${tokenAccountId}`,
30
- amount: params.amount,
31
- recipient,
32
- fee: {
33
- fee: 0n,
34
- native_fee: params.nativeFee
35
- },
36
- sender: `near:${params.intentsContract}`,
37
- msg
38
- }, ftWithdrawPayload.external_id),
39
- amount: params.nativeFee.toString(),
26
+ if (storageDepositAccountId !== null) intents.push({
27
+ deposit_for_account_id: storageDepositAccountId,
28
+ amount: nativeFee.toString(),
40
29
  contract_id: OMNI_BRIDGE_CONTRACT,
41
30
  intent: "storage_deposit"
42
31
  });
@@ -44,8 +33,8 @@ function createWithdrawIntentsPrimitive(params) {
44
33
  intent: "ft_withdraw",
45
34
  token: tokenAccountId,
46
35
  receiver_id: OMNI_BRIDGE_CONTRACT,
47
- amount: params.amount.toString(),
48
- storage_deposit: params.storageDepositAmount > 0n ? params.storageDepositAmount.toString() : void 0,
36
+ amount: amount.toString(),
37
+ storage_deposit: storageDepositAmount > 0n ? storageDepositAmount.toString() : void 0,
49
38
  msg: JSON.stringify(ftWithdrawPayload),
50
39
  min_gas: MIN_GAS_AMOUNT
51
40
  });
@@ -67,18 +56,12 @@ const CHAIN_MAPPINGS = [
67
56
  [Chains.Fogo, ChainKind.Fogo],
68
57
  [Chains.Polygon, ChainKind.Pol],
69
58
  [Chains.Aptos, ChainKind.Aptos],
70
- [Chains.HyperEvm, ChainKind.HlEvm]
59
+ [Chains.HyperEvm, ChainKind.HlEvm],
60
+ [Chains.Zcash, ChainKind.Zcash]
71
61
  ];
72
- function caip2ToChainKind(network) {
73
- return CHAIN_MAPPINGS.find(([chain]) => chain === network)?.[1] ?? null;
74
- }
75
62
  function chainKindToCaip2(network) {
76
63
  return CHAIN_MAPPINGS.find(([_, kind]) => kind === network)?.[0] ?? null;
77
64
  }
78
- const UTXO_CHAINS = [ChainKind.Btc];
79
- function isUtxoChain(network) {
80
- return UTXO_CHAINS.includes(network);
81
- }
82
65
  function poaContractIdToChainKind(contractId) {
83
66
  return POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE[contractId] ?? null;
84
67
  }
@@ -99,7 +82,7 @@ async function getAccountOmniStorageBalance(nearProvider, accountId) {
99
82
  })])
100
83
  });
101
84
  }
102
- const OmniAddressSchema = v.custom((input) => typeof input === "string" && (input.startsWith("eth:") || input.startsWith("near:") || input.startsWith("sol:") || input.startsWith("arb:") || input.startsWith("base:") || input.startsWith("btc:") || input.startsWith("bnb:") || input.startsWith("abs:") || input.startsWith("strk:") || input.startsWith("fogo:") || input.startsWith("pol:") || input.startsWith("aptos:") || input.startsWith("hlevm:")), "Must comply with omni address schema");
85
+ const OmniAddressSchema = v.custom((input) => typeof input === "string" && (input.startsWith("eth:") || input.startsWith("near:") || input.startsWith("sol:") || input.startsWith("arb:") || input.startsWith("base:") || input.startsWith("btc:") || input.startsWith("bnb:") || input.startsWith("abs:") || input.startsWith("strk:") || input.startsWith("fogo:") || input.startsWith("pol:") || input.startsWith("aptos:") || input.startsWith("hlevm:") || input.startsWith("zcash:")), "Must comply with omni address schema");
103
86
  /**
104
87
  * Converts a token address from one chain to its equivalent on another chain.
105
88
  * @param nearProvider Near provider used for querying the contract
@@ -147,4 +130,4 @@ async function getTokenDecimals(nearProvider, tokenAddress) {
147
130
  }
148
131
 
149
132
  //#endregion
150
- export { caip2ToChainKind, chainKindToCaip2, createWithdrawIntentsPrimitive, getAccountOmniStorageBalance, getBridgedToken, getTokenDecimals, isUtxoChain, poaContractIdToChainKind, validateOmniToken };
133
+ export { CHAIN_MAPPINGS, chainKindToCaip2, createWithdrawIntentsPrimitive, getAccountOmniStorageBalance, getBridgedToken, getTokenDecimals, poaContractIdToChainKind, validateOmniToken };
@@ -1,7 +1,6 @@
1
1
  const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.cjs');
2
2
  const require_errors = require('../../classes/errors.cjs');
3
3
  const require_route_enum = require('../../constants/route-enum.cjs');
4
- const require_caip2 = require('../../lib/caip2.cjs');
5
4
  const require_estimate_fee = require('../../lib/estimate-fee.cjs');
6
5
  const require_parse_defuse_asset_id = require('../../lib/parse-defuse-asset-id.cjs');
7
6
  const require_validateAddress = require('../../lib/validateAddress.cjs');
@@ -11,6 +10,7 @@ const require_error = require('./error.cjs');
11
10
  const require_omni_bridge_constants = require('./omni-bridge-constants.cjs');
12
11
  const require_poa_tokens_migrated_to_omni_bridge = require('../../constants/poa-tokens-migrated-to-omni-bridge.cjs');
13
12
  const require_omni_bridge_utils = require('./omni-bridge-utils.cjs');
13
+ const require_src_bridges_omni_bridge_omni_withdraw_params = require('./omni-withdraw-params.cjs');
14
14
  let _defuse_protocol_internal_utils = require("@defuse-protocol/internal-utils");
15
15
  let lru_cache = require("lru-cache");
16
16
  let _isaacs_ttlcache = require("@isaacs/ttlcache");
@@ -55,7 +55,7 @@ var OmniBridge = class {
55
55
  let omniChainKind = null;
56
56
  let caip2Chain = null;
57
57
  if (this.targetChainSpecified(params.routeConfig)) {
58
- omniChainKind = require_omni_bridge_utils.caip2ToChainKind(params.routeConfig.chain);
58
+ omniChainKind = require_src_bridges_omni_bridge_omni_withdraw_params.caip2ToChainKind(params.routeConfig.chain);
59
59
  if (omniChainKind === null) throw new require_errors.UnsupportedAssetIdError(params.assetId, `Chain ${params.routeConfig.chain} is not supported in Omni Bridge.`);
60
60
  caip2Chain = params.routeConfig.chain;
61
61
  } else {
@@ -89,7 +89,7 @@ var OmniBridge = class {
89
89
  let omniChainKind = null;
90
90
  let blockchain = null;
91
91
  if (this.targetChainSpecified(routeConfig)) {
92
- omniChainKind = require_omni_bridge_utils.caip2ToChainKind(routeConfig.chain);
92
+ omniChainKind = require_src_bridges_omni_bridge_omni_withdraw_params.caip2ToChainKind(routeConfig.chain);
93
93
  blockchain = routeConfig.chain;
94
94
  } else {
95
95
  omniChainKind = this.isPoaTokenMigratedToOmniBridge(parsed.contractId) ? require_omni_bridge_utils.poaContractIdToChainKind(parsed.contractId) : (0, _omni_bridge_core.parseOriginChain)(parsed.contractId);
@@ -106,7 +106,7 @@ var OmniBridge = class {
106
106
  async createWithdrawalIntents(args) {
107
107
  const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
108
108
  (0, _defuse_protocol_internal_utils.assert)(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
109
- const omniChainKind = require_omni_bridge_utils.caip2ToChainKind(assetInfo.blockchain);
109
+ const omniChainKind = require_src_bridges_omni_bridge_omni_withdraw_params.caip2ToChainKind(assetInfo.blockchain);
110
110
  (0, _defuse_protocol_internal_utils.assert)(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
111
111
  const intents = [];
112
112
  if (args.feeEstimation.quote !== null) intents.push({
@@ -117,42 +117,14 @@ var OmniBridge = class {
117
117
  },
118
118
  referral: args.referral
119
119
  });
120
- const relayerFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "relayerFee");
121
- (0, _defuse_protocol_internal_utils.assert)(relayerFee >= 0n, `Invalid Omni bridge relayer fee: expected >= 0, got ${relayerFee}`);
122
- let amount = args.withdrawalParams.amount;
123
- let utxoMaxGasFee = null;
124
- /**
125
- * UTXO withdrawals add protocol + max gas fees to the intent amount since they're paid
126
- * from the withdrawn asset, not wrap.near.
127
- *
128
- * Example with nep141:nbtc.bridge.near (made-up values):
129
- * utxoFees = 50 + 50 = 100, relayerFee = 2 (excluded; paid in wrap.near)
130
- *
131
- * feeInclusive=false:
132
- * - amount = 4000 → intent = 4000 + 100 = 4100 → user receives 4000
133
- *
134
- * feeInclusive=true:
135
- * - amount = 3898 (4000 − 102) → intent = 3898 + 100 = 3998 → user receives 3898
136
- **/
137
- if (require_omni_bridge_utils.isUtxoChain(omniChainKind)) {
138
- utxoMaxGasFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoMaxGasFee");
139
- const utxoProtocolFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoProtocolFee");
140
- (0, _defuse_protocol_internal_utils.assert)(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
141
- (0, _defuse_protocol_internal_utils.assert)(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
142
- amount += utxoMaxGasFee + utxoProtocolFee;
143
- }
144
- let destinationAddress = args.withdrawalParams.destinationAddress;
145
- if (assetInfo.blockchain === require_caip2.Chains.Bitcoin && /^bc1/i.test(destinationAddress)) destinationAddress = destinationAddress.toLowerCase();
146
- intents.push(...require_omni_bridge_utils.createWithdrawIntentsPrimitive({
120
+ intents.push(...require_omni_bridge_utils.createWithdrawIntentsPrimitive(require_src_bridges_omni_bridge_omni_withdraw_params.deriveOmniWithdrawIntentParams({
147
121
  assetId: args.withdrawalParams.assetId,
148
- destinationAddress,
149
- amount,
122
+ destinationAddress: args.withdrawalParams.destinationAddress,
123
+ actualAmount: args.withdrawalParams.amount,
150
124
  omniChainKind,
151
125
  intentsContract: this.envConfig.contractID,
152
- nativeFee: relayerFee,
153
- storageDepositAmount: require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "storageDepositFee"),
154
- utxoMaxGasFee
155
- }));
126
+ feeEstimation: args.feeEstimation
127
+ })));
156
128
  return Promise.resolve(intents);
157
129
  }
158
130
  async validateWithdrawal(args) {
@@ -162,7 +134,7 @@ var OmniBridge = class {
162
134
  const assetInfo = this.makeAssetInfo(args.assetId, args.routeConfig);
163
135
  (0, _defuse_protocol_internal_utils.assert)(assetInfo !== null, `Asset ${args.assetId} is not supported by Omni Bridge`);
164
136
  if (require_validateAddress.validateAddress(args.destinationAddress, assetInfo.blockchain) === false) throw new require_errors.InvalidDestinationAddressForWithdrawalError(args.destinationAddress, assetInfo.blockchain);
165
- const omniChainKind = require_omni_bridge_utils.caip2ToChainKind(assetInfo.blockchain);
137
+ const omniChainKind = require_src_bridges_omni_bridge_omni_withdraw_params.caip2ToChainKind(assetInfo.blockchain);
166
138
  (0, _defuse_protocol_internal_utils.assert)(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
167
139
  const destTokenOmniAddress = await this.getCachedDestinationTokenAddress(assetInfo.contractId, omniChainKind);
168
140
  if (destTokenOmniAddress === null) throw new require_error.TokenNotFoundInDestinationChainError(args.assetId, assetInfo.blockchain);
@@ -176,7 +148,7 @@ var OmniBridge = class {
176
148
  }
177
149
  const intentsStorageBalance = await this.getCachedIntentsStorageBalance();
178
150
  if (intentsStorageBalance <= require_omni_bridge_constants.MIN_STORAGE_BALANCE_FOR_INTENTS_NEAR) throw new require_error.IntentsNearOmniAvailableBalanceTooLowError(intentsStorageBalance.toString());
179
- const utxoChainWithdrawal = require_omni_bridge_utils.isUtxoChain(omniChainKind);
151
+ const utxoChainWithdrawal = require_src_bridges_omni_bridge_omni_withdraw_params.isUtxoChain(omniChainKind);
180
152
  if (!utxoChainWithdrawal && !isFeeSubsidized) {
181
153
  const relayerFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "relayerFee");
182
154
  (0, _defuse_protocol_internal_utils.assert)(require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "relayerFee") > 0n, `Invalid Omni Bridge relayer fee for non UTXO chain withdrawal: expected > 0, got ${relayerFee}`);
@@ -202,7 +174,7 @@ var OmniBridge = class {
202
174
  async estimateWithdrawalFee(args) {
203
175
  const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
204
176
  (0, _defuse_protocol_internal_utils.assert)(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
205
- const omniChainKind = require_omni_bridge_utils.caip2ToChainKind(assetInfo.blockchain);
177
+ const omniChainKind = require_src_bridges_omni_bridge_omni_withdraw_params.caip2ToChainKind(assetInfo.blockchain);
206
178
  (0, _defuse_protocol_internal_utils.assert)(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
207
179
  const fee = await (0, _defuse_protocol_internal_utils.withTimeout)(() => this.omniBridgeAPI.getFee((0, _omni_bridge_core.omniAddress)(_omni_bridge_core.ChainKind.Near, this.envConfig.contractID), (0, _omni_bridge_core.omniAddress)(omniChainKind, args.withdrawalParams.destinationAddress), (0, _omni_bridge_core.omniAddress)(_omni_bridge_core.ChainKind.Near, assetInfo.contractId), args.withdrawalParams.amount), {
208
180
  timeout: typeof window !== "undefined" ? 1e4 : 3e3,
@@ -240,7 +212,7 @@ var OmniBridge = class {
240
212
  });
241
213
  amount += BigInt(quote.amount_in);
242
214
  }
243
- if (require_omni_bridge_utils.isUtxoChain(omniChainKind)) {
215
+ if (require_src_bridges_omni_bridge_omni_withdraw_params.isUtxoChain(omniChainKind)) {
244
216
  (0, _defuse_protocol_internal_utils.assert)(fee.gas_fee !== null && fee.gas_fee !== void 0 && fee.gas_fee > 0n, `Invalid Omni Bridge utxo gas fee: expected > 0, got ${fee.gas_fee}`);
245
217
  (0, _defuse_protocol_internal_utils.assert)(fee.protocol_fee !== null && fee.protocol_fee !== void 0 && fee.protocol_fee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${fee.protocol_fee}`);
246
218
  amount += fee.gas_fee + fee.protocol_fee;
@@ -269,7 +241,7 @@ var OmniBridge = class {
269
241
  const destinationChain = (0, _omni_bridge_core.getChain)(transfer.recipient);
270
242
  let txHash = null;
271
243
  if ((0, _omni_bridge_core.isEvmChain)(destinationChain) || destinationChain === _omni_bridge_core.ChainKind.Sol || destinationChain === _omni_bridge_core.ChainKind.Fogo || destinationChain === _omni_bridge_core.ChainKind.Strk || destinationChain === _omni_bridge_core.ChainKind.Aptos) txHash = transfer.finalised?.transaction_hash;
272
- else if (require_omni_bridge_utils.isUtxoChain(destinationChain)) txHash = typeof window !== "undefined" ? transfer.utxo_meta?.pending_sign_id : transfer.finalised?.transaction_hash;
244
+ else if (require_src_bridges_omni_bridge_omni_withdraw_params.isUtxoChain(destinationChain)) txHash = typeof window !== "undefined" ? transfer.utxo_meta?.pending_sign_id : transfer.finalised?.transaction_hash;
273
245
  else return {
274
246
  status: "completed",
275
247
  txHash: null
@@ -1,6 +1,5 @@
1
1
  import { DestinationAddressMatchesTokenAddressError, InvalidDestinationAddressForWithdrawalError, MinWithdrawalAmountError, UnsupportedAssetIdError } from "../../classes/errors.js";
2
2
  import { RouteEnum } from "../../constants/route-enum.js";
3
- import { Chains } from "../../lib/caip2.js";
4
3
  import { getFeeQuote, getUnderlyingFee } from "../../lib/estimate-fee.js";
5
4
  import { parseDefuseAssetId } from "../../lib/parse-defuse-asset-id.js";
6
5
  import { validateAddress } from "../../lib/validateAddress.js";
@@ -9,7 +8,8 @@ import { compareAddresses } from "../../lib/compareAddresses.js";
9
8
  import { InsufficientUtxoForOmniBridgeWithdrawalError, IntentsNearOmniAvailableBalanceTooLowError, InvalidFeeValueError, OmniWithdrawalApiFeeRequestTimeoutError, TokenNotFoundInDestinationChainError } from "./error.js";
10
9
  import { FEE_SUBSIDIZED_TOKENS, INTENTS_STORAGE_BALANCE_CACHE_KEY, MIN_AMOUNT_SOL_OMNI_WITHDRAWAL, MIN_STORAGE_BALANCE_FOR_INTENTS_NEAR, NEAR_NATIVE_ASSET_ID, OMNI_BRIDGE_CONTRACT, SOL_OMNI_CONTRACT_ID } from "./omni-bridge-constants.js";
11
10
  import { POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE } from "../../constants/poa-tokens-migrated-to-omni-bridge.js";
12
- import { caip2ToChainKind, chainKindToCaip2, createWithdrawIntentsPrimitive, getAccountOmniStorageBalance, getBridgedToken, getTokenDecimals, isUtxoChain, poaContractIdToChainKind, validateOmniToken } from "./omni-bridge-utils.js";
11
+ import { chainKindToCaip2, createWithdrawIntentsPrimitive, getAccountOmniStorageBalance, getBridgedToken, getTokenDecimals, poaContractIdToChainKind, validateOmniToken } from "./omni-bridge-utils.js";
12
+ import { caip2ToChainKind, deriveOmniWithdrawIntentParams, isUtxoChain } from "./omni-withdraw-params.js";
13
13
  import { assert, getNearNep141MinStorageBalance, getNearNep141StorageBalance, withTimeout } from "@defuse-protocol/internal-utils";
14
14
  import { LRUCache } from "lru-cache";
15
15
  import TTLCache from "@isaacs/ttlcache";
@@ -115,42 +115,14 @@ var OmniBridge = class {
115
115
  },
116
116
  referral: args.referral
117
117
  });
118
- const relayerFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "relayerFee");
119
- assert(relayerFee >= 0n, `Invalid Omni bridge relayer fee: expected >= 0, got ${relayerFee}`);
120
- let amount = args.withdrawalParams.amount;
121
- let utxoMaxGasFee = null;
122
- /**
123
- * UTXO withdrawals add protocol + max gas fees to the intent amount since they're paid
124
- * from the withdrawn asset, not wrap.near.
125
- *
126
- * Example with nep141:nbtc.bridge.near (made-up values):
127
- * utxoFees = 50 + 50 = 100, relayerFee = 2 (excluded; paid in wrap.near)
128
- *
129
- * feeInclusive=false:
130
- * - amount = 4000 → intent = 4000 + 100 = 4100 → user receives 4000
131
- *
132
- * feeInclusive=true:
133
- * - amount = 3898 (4000 − 102) → intent = 3898 + 100 = 3998 → user receives 3898
134
- **/
135
- if (isUtxoChain(omniChainKind)) {
136
- utxoMaxGasFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "utxoMaxGasFee");
137
- const utxoProtocolFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "utxoProtocolFee");
138
- assert(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
139
- assert(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
140
- amount += utxoMaxGasFee + utxoProtocolFee;
141
- }
142
- let destinationAddress = args.withdrawalParams.destinationAddress;
143
- if (assetInfo.blockchain === Chains.Bitcoin && /^bc1/i.test(destinationAddress)) destinationAddress = destinationAddress.toLowerCase();
144
- intents.push(...createWithdrawIntentsPrimitive({
118
+ intents.push(...createWithdrawIntentsPrimitive(deriveOmniWithdrawIntentParams({
145
119
  assetId: args.withdrawalParams.assetId,
146
- destinationAddress,
147
- amount,
120
+ destinationAddress: args.withdrawalParams.destinationAddress,
121
+ actualAmount: args.withdrawalParams.amount,
148
122
  omniChainKind,
149
123
  intentsContract: this.envConfig.contractID,
150
- nativeFee: relayerFee,
151
- storageDepositAmount: getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "storageDepositFee"),
152
- utxoMaxGasFee
153
- }));
124
+ feeEstimation: args.feeEstimation
125
+ })));
154
126
  return Promise.resolve(intents);
155
127
  }
156
128
  async validateWithdrawal(args) {
@@ -0,0 +1,72 @@
1
+ const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.cjs');
2
+ const require_route_enum = require('../../constants/route-enum.cjs');
3
+ const require_estimate_fee = require('../../lib/estimate-fee.cjs');
4
+ const require_omni_bridge_utils = require('./omni-bridge-utils.cjs');
5
+ let _defuse_protocol_internal_utils = require("@defuse-protocol/internal-utils");
6
+ let _omni_bridge_core = require("@omni-bridge/core");
7
+ let _omni_bridge_near = require("@omni-bridge/near");
8
+
9
+ //#region src/bridges/omni-bridge/omni-withdraw-params.ts
10
+ /**
11
+ * Computes the values of an Omni withdrawal without building the intents. `OmniBridge` calls
12
+ * it too, so a caller that signs the payload elsewhere gets the same numbers.
13
+ * @param params.actualAmount Net of `feeEstimation.amount`. `IntentsSDK` subtracts it for a
14
+ * fee-inclusive withdrawal, so a caller that builds the payload itself has to do the same
15
+ * @param params.feeEstimation Read for every fee of the route, one of which raises the amount
16
+ * @param params.externalId Supply one to repeat an earlier call.
17
+ * `calculateStorageAccountId` throws above 64 UTF-8 bytes. Omit it and the function draws a
18
+ * random one
19
+ * @returns The values the `ft_withdraw` carries
20
+ */
21
+ function deriveOmniWithdrawIntentParams(params) {
22
+ const { contractId: tokenAccountId, standard } = _defuse_protocol_internal_utils.utils.parseDefuseAssetId(params.assetId);
23
+ (0, _defuse_protocol_internal_utils.assert)(standard === "nep141", "Only NEP-141 is supported");
24
+ const nativeFee = require_estimate_fee.getUnderlyingFee(params.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "relayerFee");
25
+ (0, _defuse_protocol_internal_utils.assert)(nativeFee >= 0n, `Invalid Omni bridge relayer fee: expected >= 0, got ${nativeFee}`);
26
+ const storageDepositAmount = require_estimate_fee.getUnderlyingFee(params.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "storageDepositFee");
27
+ let amount = params.actualAmount;
28
+ let msg = "";
29
+ if (isUtxoChain(params.omniChainKind)) {
30
+ const utxoMaxGasFee = require_estimate_fee.getUnderlyingFee(params.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoMaxGasFee");
31
+ const utxoProtocolFee = require_estimate_fee.getUnderlyingFee(params.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoProtocolFee");
32
+ (0, _defuse_protocol_internal_utils.assert)(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
33
+ (0, _defuse_protocol_internal_utils.assert)(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
34
+ amount += utxoMaxGasFee + utxoProtocolFee;
35
+ msg = JSON.stringify({ MaxGasFee: utxoMaxGasFee.toString() });
36
+ }
37
+ const destinationAddress = params.omniChainKind === _omni_bridge_core.ChainKind.Btc && /^bc1/i.test(params.destinationAddress) ? params.destinationAddress.toLowerCase() : params.destinationAddress;
38
+ const recipient = (0, _omni_bridge_core.omniAddress)(params.omniChainKind, destinationAddress);
39
+ const externalId = params.externalId ?? crypto.randomUUID();
40
+ return {
41
+ tokenAccountId,
42
+ recipient,
43
+ msg,
44
+ externalId,
45
+ amount,
46
+ nativeFee,
47
+ storageDepositAmount,
48
+ storageDepositAccountId: nativeFee > 0n ? (0, _omni_bridge_near.calculateStorageAccountId)({
49
+ token: `near:${tokenAccountId}`,
50
+ amount,
51
+ recipient,
52
+ fee: {
53
+ fee: 0n,
54
+ native_fee: nativeFee
55
+ },
56
+ sender: `near:${params.intentsContract}`,
57
+ msg
58
+ }, externalId) : null
59
+ };
60
+ }
61
+ function caip2ToChainKind(network) {
62
+ return require_omni_bridge_utils.CHAIN_MAPPINGS.find(([chain]) => chain === network)?.[1] ?? null;
63
+ }
64
+ const UTXO_CHAINS = [_omni_bridge_core.ChainKind.Btc, _omni_bridge_core.ChainKind.Zcash];
65
+ function isUtxoChain(network) {
66
+ return UTXO_CHAINS.includes(network);
67
+ }
68
+
69
+ //#endregion
70
+ exports.caip2ToChainKind = caip2ToChainKind;
71
+ exports.deriveOmniWithdrawIntentParams = deriveOmniWithdrawIntentParams;
72
+ exports.isUtxoChain = isUtxoChain;
@@ -0,0 +1,60 @@
1
+ import { Chain } from "../../lib/caip2.cjs";
2
+ import { FeeEstimation } from "../../shared-types.cjs";
3
+ import { ChainKind, OmniAddress } from "@omni-bridge/core";
4
+
5
+ //#region src/bridges/omni-bridge/omni-withdraw-params.d.ts
6
+
7
+ /**
8
+ * The values an Omni withdrawal computes before it builds the intents.
9
+ *
10
+ * `storageDepositAccountId` is derived from `externalId`, and letter case takes part in that
11
+ * derivation, so recomputing any of these sends the native fee to a different account.
12
+ */
13
+ type OmniWithdrawIntentParams = {
14
+ /** The NEP-141 account of the asset. */
15
+ tokenAccountId: string;
16
+ recipient: OmniAddress;
17
+ /** Empty, except for a UTXO chain. Then it contains `MaxGasFee`. */
18
+ msg: string;
19
+ /**
20
+ * This value makes the storage account unique. The hash covers the rest of the transfer,
21
+ * so two withdrawals that match on every field would otherwise land on one account.
22
+ * `calculateStorageAccountId` throws above 64 UTF-8 bytes.
23
+ */
24
+ externalId: string;
25
+ /** The account that gets the native fee. Null if there is no native fee. */
26
+ storageDepositAccountId: string | null;
27
+ /**
28
+ * The amount the `ft_withdraw` carries. A UTXO chain adds its own fees to the amount the
29
+ * caller asked for, because they are paid from the asset and not from wrap.near.
30
+ */
31
+ amount: bigint;
32
+ /** The relayer fee. It goes in `native_token_fee`, and the storage deposit transfers it. */
33
+ nativeFee: bigint;
34
+ /** The `storage_deposit` of the `ft_withdraw`. Zero leaves the field out. */
35
+ storageDepositAmount: bigint;
36
+ };
37
+ /**
38
+ * Computes the values of an Omni withdrawal without building the intents. `OmniBridge` calls
39
+ * it too, so a caller that signs the payload elsewhere gets the same numbers.
40
+ * @param params.actualAmount Net of `feeEstimation.amount`. `IntentsSDK` subtracts it for a
41
+ * fee-inclusive withdrawal, so a caller that builds the payload itself has to do the same
42
+ * @param params.feeEstimation Read for every fee of the route, one of which raises the amount
43
+ * @param params.externalId Supply one to repeat an earlier call.
44
+ * `calculateStorageAccountId` throws above 64 UTF-8 bytes. Omit it and the function draws a
45
+ * random one
46
+ * @returns The values the `ft_withdraw` carries
47
+ */
48
+ declare function deriveOmniWithdrawIntentParams(params: {
49
+ assetId: string;
50
+ destinationAddress: string;
51
+ actualAmount: bigint;
52
+ omniChainKind: ChainKind;
53
+ intentsContract: string;
54
+ feeEstimation: FeeEstimation;
55
+ externalId?: string;
56
+ }): OmniWithdrawIntentParams;
57
+ declare function caip2ToChainKind(network: Chain): ChainKind | null;
58
+ declare function isUtxoChain(network: ChainKind): boolean;
59
+ //#endregion
60
+ export { OmniWithdrawIntentParams, caip2ToChainKind, deriveOmniWithdrawIntentParams, isUtxoChain };
@@ -0,0 +1,60 @@
1
+ import { Chain } from "../../lib/caip2.js";
2
+ import { FeeEstimation } from "../../shared-types.js";
3
+ import { ChainKind, OmniAddress } from "@omni-bridge/core";
4
+
5
+ //#region src/bridges/omni-bridge/omni-withdraw-params.d.ts
6
+
7
+ /**
8
+ * The values an Omni withdrawal computes before it builds the intents.
9
+ *
10
+ * `storageDepositAccountId` is derived from `externalId`, and letter case takes part in that
11
+ * derivation, so recomputing any of these sends the native fee to a different account.
12
+ */
13
+ type OmniWithdrawIntentParams = {
14
+ /** The NEP-141 account of the asset. */
15
+ tokenAccountId: string;
16
+ recipient: OmniAddress;
17
+ /** Empty, except for a UTXO chain. Then it contains `MaxGasFee`. */
18
+ msg: string;
19
+ /**
20
+ * This value makes the storage account unique. The hash covers the rest of the transfer,
21
+ * so two withdrawals that match on every field would otherwise land on one account.
22
+ * `calculateStorageAccountId` throws above 64 UTF-8 bytes.
23
+ */
24
+ externalId: string;
25
+ /** The account that gets the native fee. Null if there is no native fee. */
26
+ storageDepositAccountId: string | null;
27
+ /**
28
+ * The amount the `ft_withdraw` carries. A UTXO chain adds its own fees to the amount the
29
+ * caller asked for, because they are paid from the asset and not from wrap.near.
30
+ */
31
+ amount: bigint;
32
+ /** The relayer fee. It goes in `native_token_fee`, and the storage deposit transfers it. */
33
+ nativeFee: bigint;
34
+ /** The `storage_deposit` of the `ft_withdraw`. Zero leaves the field out. */
35
+ storageDepositAmount: bigint;
36
+ };
37
+ /**
38
+ * Computes the values of an Omni withdrawal without building the intents. `OmniBridge` calls
39
+ * it too, so a caller that signs the payload elsewhere gets the same numbers.
40
+ * @param params.actualAmount Net of `feeEstimation.amount`. `IntentsSDK` subtracts it for a
41
+ * fee-inclusive withdrawal, so a caller that builds the payload itself has to do the same
42
+ * @param params.feeEstimation Read for every fee of the route, one of which raises the amount
43
+ * @param params.externalId Supply one to repeat an earlier call.
44
+ * `calculateStorageAccountId` throws above 64 UTF-8 bytes. Omit it and the function draws a
45
+ * random one
46
+ * @returns The values the `ft_withdraw` carries
47
+ */
48
+ declare function deriveOmniWithdrawIntentParams(params: {
49
+ assetId: string;
50
+ destinationAddress: string;
51
+ actualAmount: bigint;
52
+ omniChainKind: ChainKind;
53
+ intentsContract: string;
54
+ feeEstimation: FeeEstimation;
55
+ externalId?: string;
56
+ }): OmniWithdrawIntentParams;
57
+ declare function caip2ToChainKind(network: Chain): ChainKind | null;
58
+ declare function isUtxoChain(network: ChainKind): boolean;
59
+ //#endregion
60
+ export { OmniWithdrawIntentParams, caip2ToChainKind, deriveOmniWithdrawIntentParams, isUtxoChain };
@@ -0,0 +1,69 @@
1
+ import { RouteEnum } from "../../constants/route-enum.js";
2
+ import { getUnderlyingFee } from "../../lib/estimate-fee.js";
3
+ import { CHAIN_MAPPINGS } from "./omni-bridge-utils.js";
4
+ import { assert, utils } from "@defuse-protocol/internal-utils";
5
+ import { ChainKind, omniAddress } from "@omni-bridge/core";
6
+ import { calculateStorageAccountId } from "@omni-bridge/near";
7
+
8
+ //#region src/bridges/omni-bridge/omni-withdraw-params.ts
9
+ /**
10
+ * Computes the values of an Omni withdrawal without building the intents. `OmniBridge` calls
11
+ * it too, so a caller that signs the payload elsewhere gets the same numbers.
12
+ * @param params.actualAmount Net of `feeEstimation.amount`. `IntentsSDK` subtracts it for a
13
+ * fee-inclusive withdrawal, so a caller that builds the payload itself has to do the same
14
+ * @param params.feeEstimation Read for every fee of the route, one of which raises the amount
15
+ * @param params.externalId Supply one to repeat an earlier call.
16
+ * `calculateStorageAccountId` throws above 64 UTF-8 bytes. Omit it and the function draws a
17
+ * random one
18
+ * @returns The values the `ft_withdraw` carries
19
+ */
20
+ function deriveOmniWithdrawIntentParams(params) {
21
+ const { contractId: tokenAccountId, standard } = utils.parseDefuseAssetId(params.assetId);
22
+ assert(standard === "nep141", "Only NEP-141 is supported");
23
+ const nativeFee = getUnderlyingFee(params.feeEstimation, RouteEnum.OmniBridge, "relayerFee");
24
+ assert(nativeFee >= 0n, `Invalid Omni bridge relayer fee: expected >= 0, got ${nativeFee}`);
25
+ const storageDepositAmount = getUnderlyingFee(params.feeEstimation, RouteEnum.OmniBridge, "storageDepositFee");
26
+ let amount = params.actualAmount;
27
+ let msg = "";
28
+ if (isUtxoChain(params.omniChainKind)) {
29
+ const utxoMaxGasFee = getUnderlyingFee(params.feeEstimation, RouteEnum.OmniBridge, "utxoMaxGasFee");
30
+ const utxoProtocolFee = getUnderlyingFee(params.feeEstimation, RouteEnum.OmniBridge, "utxoProtocolFee");
31
+ assert(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
32
+ assert(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
33
+ amount += utxoMaxGasFee + utxoProtocolFee;
34
+ msg = JSON.stringify({ MaxGasFee: utxoMaxGasFee.toString() });
35
+ }
36
+ const destinationAddress = params.omniChainKind === ChainKind.Btc && /^bc1/i.test(params.destinationAddress) ? params.destinationAddress.toLowerCase() : params.destinationAddress;
37
+ const recipient = omniAddress(params.omniChainKind, destinationAddress);
38
+ const externalId = params.externalId ?? crypto.randomUUID();
39
+ return {
40
+ tokenAccountId,
41
+ recipient,
42
+ msg,
43
+ externalId,
44
+ amount,
45
+ nativeFee,
46
+ storageDepositAmount,
47
+ storageDepositAccountId: nativeFee > 0n ? calculateStorageAccountId({
48
+ token: `near:${tokenAccountId}`,
49
+ amount,
50
+ recipient,
51
+ fee: {
52
+ fee: 0n,
53
+ native_fee: nativeFee
54
+ },
55
+ sender: `near:${params.intentsContract}`,
56
+ msg
57
+ }, externalId) : null
58
+ };
59
+ }
60
+ function caip2ToChainKind(network) {
61
+ return CHAIN_MAPPINGS.find(([chain]) => chain === network)?.[1] ?? null;
62
+ }
63
+ const UTXO_CHAINS = [ChainKind.Btc, ChainKind.Zcash];
64
+ function isUtxoChain(network) {
65
+ return UTXO_CHAINS.includes(network);
66
+ }
67
+
68
+ //#endregion
69
+ export { caip2ToChainKind, deriveOmniWithdrawIntentParams, isUtxoChain };
@@ -31,7 +31,6 @@ const caip2Mapping = {
31
31
  [require_caip2.Chains.BitcoinCash]: "bch:mainnet",
32
32
  [require_caip2.Chains.Dogecoin]: "doge:mainnet",
33
33
  [require_caip2.Chains.XRPL]: "xrp:mainnet",
34
- [require_caip2.Chains.Zcash]: "zec:mainnet",
35
34
  [require_caip2.Chains.Gnosis]: "eth:100",
36
35
  [require_caip2.Chains.Berachain]: "eth:80094",
37
36
  [require_caip2.Chains.Tron]: "tron:mainnet",
@@ -56,7 +55,6 @@ const tokenPrefixMapping = {
56
55
  bch: require_caip2.Chains.BitcoinCash,
57
56
  doge: require_caip2.Chains.Dogecoin,
58
57
  xrp: require_caip2.Chains.XRPL,
59
- zec: require_caip2.Chains.Zcash,
60
58
  gnosis: require_caip2.Chains.Gnosis,
61
59
  bera: require_caip2.Chains.Berachain,
62
60
  tron: require_caip2.Chains.Tron,
@@ -30,7 +30,6 @@ const caip2Mapping = {
30
30
  [Chains.BitcoinCash]: "bch:mainnet",
31
31
  [Chains.Dogecoin]: "doge:mainnet",
32
32
  [Chains.XRPL]: "xrp:mainnet",
33
- [Chains.Zcash]: "zec:mainnet",
34
33
  [Chains.Gnosis]: "eth:100",
35
34
  [Chains.Berachain]: "eth:80094",
36
35
  [Chains.Tron]: "tron:mainnet",
@@ -55,7 +54,6 @@ const tokenPrefixMapping = {
55
54
  bch: Chains.BitcoinCash,
56
55
  doge: Chains.Dogecoin,
57
56
  xrp: Chains.XRPL,
58
- zec: Chains.Zcash,
59
57
  gnosis: Chains.Gnosis,
60
58
  bera: Chains.Berachain,
61
59
  tron: Chains.Tron,
@@ -3,7 +3,8 @@ let _omni_bridge_core = require("@omni-bridge/core");
3
3
 
4
4
  //#region src/constants/poa-tokens-migrated-to-omni-bridge.ts
5
5
  /**
6
- * These tokens originaly have been PoA Bridge tokens but have been migrated to Omni bridge.
6
+ * These tokens originally were PoA Bridge tokens but have since been migrated to Omni Bridge.
7
+ * Every migrated token must be listed here, otherwise the PoA bridge class (supports, parseAssetId methods) will keep treating it as a PoA token.
7
8
  */
8
9
  const POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE = {
9
10
  "sol-57d087fd8c460f612f8701f5499ad8b2eec5ab68.omft.near": _omni_bridge_core.ChainKind.Sol,
@@ -21,7 +22,8 @@ const POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE = {
21
22
  "aptos.omft.near": _omni_bridge_core.ChainKind.Aptos,
22
23
  "aptos-34ee497f210c5a511e8d5b53bc56d75b63612bb5.omft.near": _omni_bridge_core.ChainKind.Aptos,
23
24
  "aptos-88cb7619440a914fe6400149a12b443c3ac21d59.omft.near": _omni_bridge_core.ChainKind.Aptos,
24
- "starknet.omft.near": _omni_bridge_core.ChainKind.Strk
25
+ "starknet.omft.near": _omni_bridge_core.ChainKind.Strk,
26
+ "zec.omft.near": _omni_bridge_core.ChainKind.Zcash
25
27
  };
26
28
 
27
29
  //#endregion
@@ -3,7 +3,8 @@ import { ChainKind } from "@omni-bridge/core";
3
3
  //#region src/constants/poa-tokens-migrated-to-omni-bridge.d.ts
4
4
 
5
5
  /**
6
- * These tokens originaly have been PoA Bridge tokens but have been migrated to Omni bridge.
6
+ * These tokens originally were PoA Bridge tokens but have since been migrated to Omni Bridge.
7
+ * Every migrated token must be listed here, otherwise the PoA bridge class (supports, parseAssetId methods) will keep treating it as a PoA token.
7
8
  */
8
9
  declare const POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE: Record<string, ChainKind>;
9
10
  //#endregion
@@ -3,7 +3,8 @@ import { ChainKind } from "@omni-bridge/core";
3
3
  //#region src/constants/poa-tokens-migrated-to-omni-bridge.d.ts
4
4
 
5
5
  /**
6
- * These tokens originaly have been PoA Bridge tokens but have been migrated to Omni bridge.
6
+ * These tokens originally were PoA Bridge tokens but have since been migrated to Omni Bridge.
7
+ * Every migrated token must be listed here, otherwise the PoA bridge class (supports, parseAssetId methods) will keep treating it as a PoA token.
7
8
  */
8
9
  declare const POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE: Record<string, ChainKind>;
9
10
  //#endregion
@@ -2,7 +2,8 @@ import { ChainKind } from "@omni-bridge/core";
2
2
 
3
3
  //#region src/constants/poa-tokens-migrated-to-omni-bridge.ts
4
4
  /**
5
- * These tokens originaly have been PoA Bridge tokens but have been migrated to Omni bridge.
5
+ * These tokens originally were PoA Bridge tokens but have since been migrated to Omni Bridge.
6
+ * Every migrated token must be listed here, otherwise the PoA bridge class (supports, parseAssetId methods) will keep treating it as a PoA token.
6
7
  */
7
8
  const POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE = {
8
9
  "sol-57d087fd8c460f612f8701f5499ad8b2eec5ab68.omft.near": ChainKind.Sol,
@@ -20,7 +21,8 @@ const POA_TOKENS_MIGRATED_TO_OMNI_BRIDGE = {
20
21
  "aptos.omft.near": ChainKind.Aptos,
21
22
  "aptos-34ee497f210c5a511e8d5b53bc56d75b63612bb5.omft.near": ChainKind.Aptos,
22
23
  "aptos-88cb7619440a914fe6400149a12b443c3ac21d59.omft.near": ChainKind.Aptos,
23
- "starknet.omft.near": ChainKind.Strk
24
+ "starknet.omft.near": ChainKind.Strk,
25
+ "zec.omft.near": ChainKind.Zcash
24
26
  };
25
27
 
26
28
  //#endregion
@@ -1,6 +1,7 @@
1
1
  const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
2
  const require_caip2 = require('./caip2.cjs');
3
3
  const require_ton_address = require('./ton-address.cjs');
4
+ const require_zcash_unified_address = require('./zcash-unified-address.cjs');
4
5
  let _defuse_protocol_internal_utils = require("@defuse-protocol/internal-utils");
5
6
  let viem = require("viem");
6
7
  let _noble_hashes_sha2 = require("@noble/hashes/sha2");
@@ -199,6 +200,7 @@ function validateXrpAddress(address) {
199
200
  * Supports:
200
201
  * - Transparent addresses (t1, t3)
201
202
  * - TEX addresses (tex1)
203
+ * - Unified Orchard / Unified Addresses (UA)
202
204
  */
203
205
  function validateZcashAddress(address) {
204
206
  if (address.startsWith("t1") || address.startsWith("t3")) return /^t[13][a-km-zA-HJ-NP-Z1-9]{33}$/.test(address);
@@ -210,12 +212,7 @@ function validateZcashAddress(address) {
210
212
  } catch {
211
213
  return false;
212
214
  }
213
- const uaHrp = "u";
214
- if (address.startsWith(`${uaHrp}1`)) try {
215
- return _scure_base.bech32m.decodeToBytes(address).prefix === uaHrp;
216
- } catch {
217
- return false;
218
- }
215
+ if (address.startsWith("u1")) return require_zcash_unified_address.validateZcashUnifiedAddress(address);
219
216
  return false;
220
217
  }
221
218
  /**
@@ -1,5 +1,6 @@
1
1
  import { Chains } from "./caip2.js";
2
2
  import { TON_ADDRESS_TAG_BOUNCEABLE_MAINNET, TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET, TON_WORKCHAIN_BASECHAIN, TON_WORKCHAIN_MASTERCHAIN, tryParseTonAddress } from "./ton-address.js";
3
+ import { validateZcashUnifiedAddress } from "./zcash-unified-address.js";
3
4
  import { utils } from "@defuse-protocol/internal-utils";
4
5
  import { isAddress } from "viem";
5
6
  import { sha256 } from "@noble/hashes/sha2";
@@ -198,6 +199,7 @@ function validateXrpAddress(address) {
198
199
  * Supports:
199
200
  * - Transparent addresses (t1, t3)
200
201
  * - TEX addresses (tex1)
202
+ * - Unified Orchard / Unified Addresses (UA)
201
203
  */
202
204
  function validateZcashAddress(address) {
203
205
  if (address.startsWith("t1") || address.startsWith("t3")) return /^t[13][a-km-zA-HJ-NP-Z1-9]{33}$/.test(address);
@@ -209,12 +211,7 @@ function validateZcashAddress(address) {
209
211
  } catch {
210
212
  return false;
211
213
  }
212
- const uaHrp = "u";
213
- if (address.startsWith(`${uaHrp}1`)) try {
214
- return bech32m.decodeToBytes(address).prefix === uaHrp;
215
- } catch {
216
- return false;
217
- }
214
+ if (address.startsWith("u1")) return validateZcashUnifiedAddress(address);
218
215
  return false;
219
216
  }
220
217
  /**
@@ -0,0 +1,192 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ let _scure_base = require("@scure/base");
3
+ let _noble_hashes_blake2 = require("@noble/hashes/blake2");
4
+
5
+ //#region src/lib/zcash-unified-address.ts
6
+ /**
7
+ * Zcash Unified Address (ZIP 316) validation.
8
+ *
9
+ * Reference implementation used to cross-check this code:
10
+ * - crate: `zcash_address` https://crates.io/crates/zcash_address
11
+ * - crate: `f4jumble` https://crates.io/crates/f4jumble
12
+ * - source: https://github.com/zcash/librustzcash/tree/main/components/zcash_address
13
+ * https://github.com/zcash/librustzcash/tree/main/components/f4jumble
14
+ *
15
+ * Spec: https://zips.z.cash/zip-0316
16
+ */
17
+ const ZCASH_UA_MAINNET_HRP = "u";
18
+ const F4_MIN_LEN = 48;
19
+ const F4_MAX_LEN = 4194368;
20
+ const F4_BLAKE2B_LEN = 64;
21
+ const G_PREFIX = asciiBytes("UA_F4Jumble_G");
22
+ const H_PREFIX = asciiBytes("UA_F4Jumble_H");
23
+ const RECEIVER_TYPECODE = {
24
+ P2PKH: 0,
25
+ P2SH: 1,
26
+ SAPLING: 2,
27
+ ORCHARD: 3
28
+ };
29
+ const MAX_TYPECODE_OR_LENGTH = 33554432;
30
+ const MUST_UNDERSTAND_METADATA_MIN = 224;
31
+ const MUST_UNDERSTAND_METADATA_MAX = 252;
32
+ const KNOWN_RECEIVER_LENGTH = {
33
+ [RECEIVER_TYPECODE.P2PKH]: 20,
34
+ [RECEIVER_TYPECODE.P2SH]: 20,
35
+ [RECEIVER_TYPECODE.SAPLING]: 43,
36
+ [RECEIVER_TYPECODE.ORCHARD]: 43
37
+ };
38
+ /**
39
+ * Validates a Zcash Unified Address (ZIP 316) and requires that it contains
40
+ * at least one Orchard, P2PKH, or P2SH receiver. Sapling-only UAs are rejected.
41
+ *
42
+ * The parse pipeline (bech32m → F4Jumble⁻¹ → padding check → receiver list)
43
+ * mirrors `Encoding::parse_items` in
44
+ * https://github.com/zcash/librustzcash/blob/main/components/zcash_address/src/kind/unified.rs
45
+ */
46
+ function validateZcashUnifiedAddress(address) {
47
+ try {
48
+ const decoded = _scure_base.bech32m.decodeToBytes(address);
49
+ if (decoded.prefix !== ZCASH_UA_MAINNET_HRP) return false;
50
+ const payload = decoded.bytes;
51
+ if (payload.length < F4_MIN_LEN || payload.length > F4_MAX_LEN) return false;
52
+ const unjumbled = f4JumbleInverse(payload);
53
+ const paddingLen = 16;
54
+ if (unjumbled.length <= paddingLen) return false;
55
+ const paddingStart = unjumbled.length - paddingLen;
56
+ if (unjumbled[paddingStart] !== ZCASH_UA_MAINNET_HRP.charCodeAt(0)) return false;
57
+ for (let i = paddingStart + 1; i < unjumbled.length; i++) if (unjumbled[i] !== 0) return false;
58
+ let offset = 0;
59
+ let lastTypecode = -1;
60
+ let hasOrchardOrTransparent = false;
61
+ let hasP2pkh = false;
62
+ let hasP2sh = false;
63
+ while (offset < paddingStart) {
64
+ const typeRead = readCompactSize(unjumbled, offset, paddingStart);
65
+ if (typeRead === null) return false;
66
+ const typecode = typeRead.value;
67
+ offset = typeRead.next;
68
+ if (typecode > MAX_TYPECODE_OR_LENGTH) return false;
69
+ if (typecode <= lastTypecode) return false;
70
+ lastTypecode = typecode;
71
+ const lenRead = readCompactSize(unjumbled, offset, paddingStart);
72
+ if (lenRead === null) return false;
73
+ const len = lenRead.value;
74
+ offset = lenRead.next;
75
+ if (len === 0 || len > MAX_TYPECODE_OR_LENGTH) return false;
76
+ if (offset + len > paddingStart) return false;
77
+ const expectedLen = KNOWN_RECEIVER_LENGTH[typecode];
78
+ if (expectedLen !== void 0 && len !== expectedLen) return false;
79
+ if (expectedLen === void 0 && typecode >= MUST_UNDERSTAND_METADATA_MIN && typecode <= MUST_UNDERSTAND_METADATA_MAX) return false;
80
+ if (typecode === RECEIVER_TYPECODE.P2PKH) hasP2pkh = true;
81
+ if (typecode === RECEIVER_TYPECODE.P2SH) hasP2sh = true;
82
+ if (typecode === RECEIVER_TYPECODE.P2PKH || typecode === RECEIVER_TYPECODE.P2SH || typecode === RECEIVER_TYPECODE.ORCHARD) hasOrchardOrTransparent = true;
83
+ offset += len;
84
+ }
85
+ if (offset !== paddingStart) return false;
86
+ if (hasP2pkh && hasP2sh) return false;
87
+ return hasOrchardOrTransparent;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ /**
93
+ * Bitcoin-style CompactSize decoder, canonical form only.
94
+ * Reference: `CompactSize::read` in
95
+ * https://github.com/zcash/librustzcash/blob/main/components/zcash_encoding/src/lib.rs
96
+ */
97
+ function readCompactSize(buf, offset, end) {
98
+ if (offset >= end) return null;
99
+ const first = buf[offset];
100
+ if (first === void 0) return null;
101
+ if (first < 253) return {
102
+ value: first,
103
+ next: offset + 1
104
+ };
105
+ if (first === 253) {
106
+ if (offset + 3 > end) return null;
107
+ const b1 = buf[offset + 1];
108
+ const b2 = buf[offset + 2];
109
+ if (b1 === void 0 || b2 === void 0) return null;
110
+ const value = b1 | b2 << 8;
111
+ if (value < 253) return null;
112
+ return {
113
+ value,
114
+ next: offset + 3
115
+ };
116
+ }
117
+ if (first === 254) {
118
+ if (offset + 5 > end) return null;
119
+ const b1 = buf[offset + 1];
120
+ const b2 = buf[offset + 2];
121
+ const b3 = buf[offset + 3];
122
+ const b4 = buf[offset + 4];
123
+ if (b1 === void 0 || b2 === void 0 || b3 === void 0 || b4 === void 0) return null;
124
+ const value = (b1 | b2 << 8 | b3 << 16 | b4 << 24) >>> 0;
125
+ if (value <= 65535) return null;
126
+ return {
127
+ value,
128
+ next: offset + 5
129
+ };
130
+ }
131
+ return null;
132
+ }
133
+ /**
134
+ * Inverse of ZIP 316 F4Jumble: a 4-round unkeyed Feistel over BLAKE2b.
135
+ * Forward: x = b ⊕ G_0(a); y = a ⊕ H_0(x); d = x ⊕ G_1(y); c = y ⊕ H_1(d)
136
+ * Inverse undoes each XOR in reverse order.
137
+ *
138
+ * Reference: `State::apply_f4jumble_inv` in
139
+ * https://github.com/zcash/librustzcash/blob/main/components/f4jumble/src/lib.rs
140
+ */
141
+ function f4JumbleInverse(msg) {
142
+ const len = msg.length;
143
+ const lLen = Math.min(F4_BLAKE2B_LEN, Math.floor(len / 2));
144
+ const rLen = len - lLen;
145
+ const left = msg.slice(0, lLen);
146
+ const right = msg.slice(lLen);
147
+ xorInto(left, hI(1, right, lLen));
148
+ xorInto(right, gI(1, left, rLen));
149
+ xorInto(left, hI(0, right, lLen));
150
+ xorInto(right, gI(0, left, rLen));
151
+ const out = new Uint8Array(len);
152
+ out.set(left, 0);
153
+ out.set(right, lLen);
154
+ return out;
155
+ }
156
+ function hI(i, u, lLen) {
157
+ return (0, _noble_hashes_blake2.blake2b)(u, {
158
+ personalization: buildPersonalization(H_PREFIX, i, 0),
159
+ dkLen: lLen
160
+ });
161
+ }
162
+ function gI(i, u, rLen) {
163
+ const chunks = Math.ceil(rLen / F4_BLAKE2B_LEN);
164
+ const out = new Uint8Array(chunks * F4_BLAKE2B_LEN);
165
+ for (let j = 0; j < chunks; j++) {
166
+ const digest = (0, _noble_hashes_blake2.blake2b)(u, {
167
+ personalization: buildPersonalization(G_PREFIX, i, j),
168
+ dkLen: F4_BLAKE2B_LEN
169
+ });
170
+ out.set(digest, j * F4_BLAKE2B_LEN);
171
+ }
172
+ return out.subarray(0, rLen);
173
+ }
174
+ function buildPersonalization(prefix, i, j) {
175
+ const p = new Uint8Array(16);
176
+ p.set(prefix, 0);
177
+ p[13] = i & 255;
178
+ p[14] = j & 255;
179
+ p[15] = j >> 8 & 255;
180
+ return p;
181
+ }
182
+ function asciiBytes(s) {
183
+ const out = new Uint8Array(s.length);
184
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
185
+ return out;
186
+ }
187
+ function xorInto(target, other) {
188
+ for (let i = 0; i < target.length; i++) target[i] = target[i] ^ other[i];
189
+ }
190
+
191
+ //#endregion
192
+ exports.validateZcashUnifiedAddress = validateZcashUnifiedAddress;
@@ -0,0 +1,191 @@
1
+ import { bech32m } from "@scure/base";
2
+ import { blake2b } from "@noble/hashes/blake2";
3
+
4
+ //#region src/lib/zcash-unified-address.ts
5
+ /**
6
+ * Zcash Unified Address (ZIP 316) validation.
7
+ *
8
+ * Reference implementation used to cross-check this code:
9
+ * - crate: `zcash_address` https://crates.io/crates/zcash_address
10
+ * - crate: `f4jumble` https://crates.io/crates/f4jumble
11
+ * - source: https://github.com/zcash/librustzcash/tree/main/components/zcash_address
12
+ * https://github.com/zcash/librustzcash/tree/main/components/f4jumble
13
+ *
14
+ * Spec: https://zips.z.cash/zip-0316
15
+ */
16
+ const ZCASH_UA_MAINNET_HRP = "u";
17
+ const F4_MIN_LEN = 48;
18
+ const F4_MAX_LEN = 4194368;
19
+ const F4_BLAKE2B_LEN = 64;
20
+ const G_PREFIX = asciiBytes("UA_F4Jumble_G");
21
+ const H_PREFIX = asciiBytes("UA_F4Jumble_H");
22
+ const RECEIVER_TYPECODE = {
23
+ P2PKH: 0,
24
+ P2SH: 1,
25
+ SAPLING: 2,
26
+ ORCHARD: 3
27
+ };
28
+ const MAX_TYPECODE_OR_LENGTH = 33554432;
29
+ const MUST_UNDERSTAND_METADATA_MIN = 224;
30
+ const MUST_UNDERSTAND_METADATA_MAX = 252;
31
+ const KNOWN_RECEIVER_LENGTH = {
32
+ [RECEIVER_TYPECODE.P2PKH]: 20,
33
+ [RECEIVER_TYPECODE.P2SH]: 20,
34
+ [RECEIVER_TYPECODE.SAPLING]: 43,
35
+ [RECEIVER_TYPECODE.ORCHARD]: 43
36
+ };
37
+ /**
38
+ * Validates a Zcash Unified Address (ZIP 316) and requires that it contains
39
+ * at least one Orchard, P2PKH, or P2SH receiver. Sapling-only UAs are rejected.
40
+ *
41
+ * The parse pipeline (bech32m → F4Jumble⁻¹ → padding check → receiver list)
42
+ * mirrors `Encoding::parse_items` in
43
+ * https://github.com/zcash/librustzcash/blob/main/components/zcash_address/src/kind/unified.rs
44
+ */
45
+ function validateZcashUnifiedAddress(address) {
46
+ try {
47
+ const decoded = bech32m.decodeToBytes(address);
48
+ if (decoded.prefix !== ZCASH_UA_MAINNET_HRP) return false;
49
+ const payload = decoded.bytes;
50
+ if (payload.length < F4_MIN_LEN || payload.length > F4_MAX_LEN) return false;
51
+ const unjumbled = f4JumbleInverse(payload);
52
+ const paddingLen = 16;
53
+ if (unjumbled.length <= paddingLen) return false;
54
+ const paddingStart = unjumbled.length - paddingLen;
55
+ if (unjumbled[paddingStart] !== ZCASH_UA_MAINNET_HRP.charCodeAt(0)) return false;
56
+ for (let i = paddingStart + 1; i < unjumbled.length; i++) if (unjumbled[i] !== 0) return false;
57
+ let offset = 0;
58
+ let lastTypecode = -1;
59
+ let hasOrchardOrTransparent = false;
60
+ let hasP2pkh = false;
61
+ let hasP2sh = false;
62
+ while (offset < paddingStart) {
63
+ const typeRead = readCompactSize(unjumbled, offset, paddingStart);
64
+ if (typeRead === null) return false;
65
+ const typecode = typeRead.value;
66
+ offset = typeRead.next;
67
+ if (typecode > MAX_TYPECODE_OR_LENGTH) return false;
68
+ if (typecode <= lastTypecode) return false;
69
+ lastTypecode = typecode;
70
+ const lenRead = readCompactSize(unjumbled, offset, paddingStart);
71
+ if (lenRead === null) return false;
72
+ const len = lenRead.value;
73
+ offset = lenRead.next;
74
+ if (len === 0 || len > MAX_TYPECODE_OR_LENGTH) return false;
75
+ if (offset + len > paddingStart) return false;
76
+ const expectedLen = KNOWN_RECEIVER_LENGTH[typecode];
77
+ if (expectedLen !== void 0 && len !== expectedLen) return false;
78
+ if (expectedLen === void 0 && typecode >= MUST_UNDERSTAND_METADATA_MIN && typecode <= MUST_UNDERSTAND_METADATA_MAX) return false;
79
+ if (typecode === RECEIVER_TYPECODE.P2PKH) hasP2pkh = true;
80
+ if (typecode === RECEIVER_TYPECODE.P2SH) hasP2sh = true;
81
+ if (typecode === RECEIVER_TYPECODE.P2PKH || typecode === RECEIVER_TYPECODE.P2SH || typecode === RECEIVER_TYPECODE.ORCHARD) hasOrchardOrTransparent = true;
82
+ offset += len;
83
+ }
84
+ if (offset !== paddingStart) return false;
85
+ if (hasP2pkh && hasP2sh) return false;
86
+ return hasOrchardOrTransparent;
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+ /**
92
+ * Bitcoin-style CompactSize decoder, canonical form only.
93
+ * Reference: `CompactSize::read` in
94
+ * https://github.com/zcash/librustzcash/blob/main/components/zcash_encoding/src/lib.rs
95
+ */
96
+ function readCompactSize(buf, offset, end) {
97
+ if (offset >= end) return null;
98
+ const first = buf[offset];
99
+ if (first === void 0) return null;
100
+ if (first < 253) return {
101
+ value: first,
102
+ next: offset + 1
103
+ };
104
+ if (first === 253) {
105
+ if (offset + 3 > end) return null;
106
+ const b1 = buf[offset + 1];
107
+ const b2 = buf[offset + 2];
108
+ if (b1 === void 0 || b2 === void 0) return null;
109
+ const value = b1 | b2 << 8;
110
+ if (value < 253) return null;
111
+ return {
112
+ value,
113
+ next: offset + 3
114
+ };
115
+ }
116
+ if (first === 254) {
117
+ if (offset + 5 > end) return null;
118
+ const b1 = buf[offset + 1];
119
+ const b2 = buf[offset + 2];
120
+ const b3 = buf[offset + 3];
121
+ const b4 = buf[offset + 4];
122
+ if (b1 === void 0 || b2 === void 0 || b3 === void 0 || b4 === void 0) return null;
123
+ const value = (b1 | b2 << 8 | b3 << 16 | b4 << 24) >>> 0;
124
+ if (value <= 65535) return null;
125
+ return {
126
+ value,
127
+ next: offset + 5
128
+ };
129
+ }
130
+ return null;
131
+ }
132
+ /**
133
+ * Inverse of ZIP 316 F4Jumble: a 4-round unkeyed Feistel over BLAKE2b.
134
+ * Forward: x = b ⊕ G_0(a); y = a ⊕ H_0(x); d = x ⊕ G_1(y); c = y ⊕ H_1(d)
135
+ * Inverse undoes each XOR in reverse order.
136
+ *
137
+ * Reference: `State::apply_f4jumble_inv` in
138
+ * https://github.com/zcash/librustzcash/blob/main/components/f4jumble/src/lib.rs
139
+ */
140
+ function f4JumbleInverse(msg) {
141
+ const len = msg.length;
142
+ const lLen = Math.min(F4_BLAKE2B_LEN, Math.floor(len / 2));
143
+ const rLen = len - lLen;
144
+ const left = msg.slice(0, lLen);
145
+ const right = msg.slice(lLen);
146
+ xorInto(left, hI(1, right, lLen));
147
+ xorInto(right, gI(1, left, rLen));
148
+ xorInto(left, hI(0, right, lLen));
149
+ xorInto(right, gI(0, left, rLen));
150
+ const out = new Uint8Array(len);
151
+ out.set(left, 0);
152
+ out.set(right, lLen);
153
+ return out;
154
+ }
155
+ function hI(i, u, lLen) {
156
+ return blake2b(u, {
157
+ personalization: buildPersonalization(H_PREFIX, i, 0),
158
+ dkLen: lLen
159
+ });
160
+ }
161
+ function gI(i, u, rLen) {
162
+ const chunks = Math.ceil(rLen / F4_BLAKE2B_LEN);
163
+ const out = new Uint8Array(chunks * F4_BLAKE2B_LEN);
164
+ for (let j = 0; j < chunks; j++) {
165
+ const digest = blake2b(u, {
166
+ personalization: buildPersonalization(G_PREFIX, i, j),
167
+ dkLen: F4_BLAKE2B_LEN
168
+ });
169
+ out.set(digest, j * F4_BLAKE2B_LEN);
170
+ }
171
+ return out.subarray(0, rLen);
172
+ }
173
+ function buildPersonalization(prefix, i, j) {
174
+ const p = new Uint8Array(16);
175
+ p.set(prefix, 0);
176
+ p[13] = i & 255;
177
+ p[14] = j & 255;
178
+ p[15] = j >> 8 & 255;
179
+ return p;
180
+ }
181
+ function asciiBytes(s) {
182
+ const out = new Uint8Array(s.length);
183
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
184
+ return out;
185
+ }
186
+ function xorInto(target, other) {
187
+ for (let i = 0; i < target.length; i++) target[i] = target[i] ^ other[i];
188
+ }
189
+
190
+ //#endregion
191
+ export { validateZcashUnifiedAddress };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defuse-protocol/intents-sdk",
3
- "version": "0.81.0",
3
+ "version": "0.83.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "repository": {
@@ -26,6 +26,16 @@
26
26
  "types": "./dist/index.d.cts",
27
27
  "default": "./dist/index.cjs"
28
28
  }
29
+ },
30
+ "./omni-bridge": {
31
+ "import": {
32
+ "types": "./dist/src/bridges/omni-bridge/omni-withdraw-params.d.ts",
33
+ "default": "./dist/src/bridges/omni-bridge/omni-withdraw-params.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/src/bridges/omni-bridge/omni-withdraw-params.d.cts",
37
+ "default": "./dist/src/bridges/omni-bridge/omni-withdraw-params.cjs"
38
+ }
29
39
  }
30
40
  },
31
41
  "files": [
@@ -38,8 +48,8 @@
38
48
  "@hot-labs/omni-sdk": "2.25.5",
39
49
  "@isaacs/ttlcache": "^1.0.0",
40
50
  "@lifeomic/attempt": "^3.0.0",
41
- "@omni-bridge/core": "0.18.0",
42
- "@omni-bridge/near": "0.18.0",
51
+ "@omni-bridge/core": "0.19.0",
52
+ "@omni-bridge/near": "0.19.0",
43
53
  "@noble/hashes": "^1.7.1",
44
54
  "@scure/base": "^1.0.0",
45
55
  "borsher": "^4.0.0",