lampamazaza-new-intents-sdk 0.47.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1083 -0
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/index.cjs +124 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +19 -0
- package/dist/src/bridges/aurora-engine-bridge/aurora-engine-bridge-constants.cjs +10 -0
- package/dist/src/bridges/aurora-engine-bridge/aurora-engine-bridge-constants.js +7 -0
- package/dist/src/bridges/aurora-engine-bridge/aurora-engine-bridge-utils.cjs +44 -0
- package/dist/src/bridges/aurora-engine-bridge/aurora-engine-bridge-utils.js +42 -0
- package/dist/src/bridges/aurora-engine-bridge/aurora-engine-bridge.cjs +111 -0
- package/dist/src/bridges/aurora-engine-bridge/aurora-engine-bridge.js +110 -0
- package/dist/src/bridges/direct-bridge/direct-bridge-constants.cjs +8 -0
- package/dist/src/bridges/direct-bridge/direct-bridge-constants.js +6 -0
- package/dist/src/bridges/direct-bridge/direct-bridge-utils.cjs +47 -0
- package/dist/src/bridges/direct-bridge/direct-bridge-utils.js +44 -0
- package/dist/src/bridges/direct-bridge/direct-bridge.cjs +155 -0
- package/dist/src/bridges/direct-bridge/direct-bridge.js +154 -0
- package/dist/src/bridges/direct-bridge/error.cjs +16 -0
- package/dist/src/bridges/direct-bridge/error.d.cts +12 -0
- package/dist/src/bridges/direct-bridge/error.d.ts +12 -0
- package/dist/src/bridges/direct-bridge/error.js +15 -0
- package/dist/src/bridges/hot-bridge/error.cjs +23 -0
- package/dist/src/bridges/hot-bridge/error.d.cts +19 -0
- package/dist/src/bridges/hot-bridge/error.d.ts +19 -0
- package/dist/src/bridges/hot-bridge/error.js +21 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-chains.cjs +21 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-chains.d.cts +6 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-chains.d.ts +6 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-chains.js +20 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-constants.cjs +11 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-constants.js +9 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-utils.cjs +66 -0
- package/dist/src/bridges/hot-bridge/hot-bridge-utils.js +61 -0
- package/dist/src/bridges/hot-bridge/hot-bridge.cjs +241 -0
- package/dist/src/bridges/hot-bridge/hot-bridge.js +239 -0
- package/dist/src/bridges/intents-bridge/intents-bridge.cjs +59 -0
- package/dist/src/bridges/intents-bridge/intents-bridge.js +59 -0
- package/dist/src/bridges/omni-bridge/error.cjs +54 -0
- package/dist/src/bridges/omni-bridge/error.d.cts +41 -0
- package/dist/src/bridges/omni-bridge/error.d.ts +41 -0
- package/dist/src/bridges/omni-bridge/error.js +49 -0
- package/dist/src/bridges/omni-bridge/omni-bridge-constants.cjs +12 -0
- package/dist/src/bridges/omni-bridge/omni-bridge-constants.js +8 -0
- package/dist/src/bridges/omni-bridge/omni-bridge-utils.cjs +153 -0
- package/dist/src/bridges/omni-bridge/omni-bridge-utils.js +143 -0
- package/dist/src/bridges/omni-bridge/omni-bridge.cjs +316 -0
- package/dist/src/bridges/omni-bridge/omni-bridge.js +314 -0
- package/dist/src/bridges/poa-bridge/poa-bridge-utils.cjs +76 -0
- package/dist/src/bridges/poa-bridge/poa-bridge-utils.js +73 -0
- package/dist/src/bridges/poa-bridge/poa-bridge.cjs +175 -0
- package/dist/src/bridges/poa-bridge/poa-bridge.js +173 -0
- package/dist/src/bridges/poa-bridge/poa-constants.cjs +6 -0
- package/dist/src/bridges/poa-bridge/poa-constants.js +5 -0
- package/dist/src/classes/errors.cjs +87 -0
- package/dist/src/classes/errors.d.cts +48 -0
- package/dist/src/classes/errors.d.ts +48 -0
- package/dist/src/classes/errors.js +81 -0
- package/dist/src/constants/bridge-name-enum.cjs +11 -0
- package/dist/src/constants/bridge-name-enum.d.cts +11 -0
- package/dist/src/constants/bridge-name-enum.d.ts +11 -0
- package/dist/src/constants/bridge-name-enum.js +10 -0
- package/dist/src/constants/poa-tokens-routable-through-omni-bridge.cjs +17 -0
- package/dist/src/constants/poa-tokens-routable-through-omni-bridge.d.cts +12 -0
- package/dist/src/constants/poa-tokens-routable-through-omni-bridge.d.ts +12 -0
- package/dist/src/constants/poa-tokens-routable-through-omni-bridge.js +16 -0
- package/dist/src/constants/public-rpc-urls.cjs +25 -0
- package/dist/src/constants/public-rpc-urls.js +24 -0
- package/dist/src/constants/route-enum.cjs +13 -0
- package/dist/src/constants/route-enum.d.cts +13 -0
- package/dist/src/constants/route-enum.d.ts +13 -0
- package/dist/src/constants/route-enum.js +12 -0
- package/dist/src/constants/withdrawal-timing.cjs +68 -0
- package/dist/src/constants/withdrawal-timing.js +68 -0
- package/dist/src/core/withdrawal-watcher.cjs +86 -0
- package/dist/src/core/withdrawal-watcher.d.cts +18 -0
- package/dist/src/core/withdrawal-watcher.d.ts +19 -0
- package/dist/src/core/withdrawal-watcher.js +82 -0
- package/dist/src/intents/expirable-nonce.cjs +90 -0
- package/dist/src/intents/expirable-nonce.d.cts +44 -0
- package/dist/src/intents/expirable-nonce.d.ts +45 -0
- package/dist/src/intents/expirable-nonce.js +82 -0
- package/dist/src/intents/intent-executer-impl/intent-executer.cjs +85 -0
- package/dist/src/intents/intent-executer-impl/intent-executer.d.cts +20 -0
- package/dist/src/intents/intent-executer-impl/intent-executer.d.ts +24 -0
- package/dist/src/intents/intent-executer-impl/intent-executer.js +85 -0
- package/dist/src/intents/intent-hash.cjs +48 -0
- package/dist/src/intents/intent-hash.d.cts +8 -0
- package/dist/src/intents/intent-hash.d.ts +8 -0
- package/dist/src/intents/intent-hash.js +47 -0
- package/dist/src/intents/intent-hashes/erc191.cjs +38 -0
- package/dist/src/intents/intent-hashes/erc191.js +37 -0
- package/dist/src/intents/intent-hashes/nep413.cjs +23 -0
- package/dist/src/intents/intent-hashes/nep413.js +22 -0
- package/dist/src/intents/intent-hashes/raw-ed25519.cjs +26 -0
- package/dist/src/intents/intent-hashes/raw-ed25519.js +25 -0
- package/dist/src/intents/intent-hashes/sep53.cjs +36 -0
- package/dist/src/intents/intent-hashes/sep53.js +35 -0
- package/dist/src/intents/intent-hashes/tip191.cjs +39 -0
- package/dist/src/intents/intent-hashes/tip191.js +38 -0
- package/dist/src/intents/intent-hashes/ton-connect.cjs +105 -0
- package/dist/src/intents/intent-hashes/ton-connect.js +104 -0
- package/dist/src/intents/intent-hashes/webauthn.cjs +26 -0
- package/dist/src/intents/intent-hashes/webauthn.js +25 -0
- package/dist/src/intents/intent-payload-builder.cjs +208 -0
- package/dist/src/intents/intent-payload-builder.d.cts +161 -0
- package/dist/src/intents/intent-payload-builder.d.ts +161 -0
- package/dist/src/intents/intent-payload-builder.js +207 -0
- package/dist/src/intents/intent-payload-factory.cjs +23 -0
- package/dist/src/intents/intent-payload-factory.js +21 -0
- package/dist/src/intents/intent-relayer-impl/intent-relayer-public.cjs +43 -0
- package/dist/src/intents/intent-relayer-impl/intent-relayer-public.js +42 -0
- package/dist/src/intents/intent-signer-impl/factories.cjs +19 -0
- package/dist/src/intents/intent-signer-impl/factories.d.cts +11 -0
- package/dist/src/intents/intent-signer-impl/factories.d.ts +11 -0
- package/dist/src/intents/intent-signer-impl/factories.js +17 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-near-keypair.cjs +22 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-near-keypair.d.cts +15 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-near-keypair.d.ts +16 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-near-keypair.js +21 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-nep413.cjs +37 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-nep413.d.cts +14 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-nep413.d.ts +14 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-nep413.js +36 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-noop.cjs +8 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-noop.js +7 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-viem.cjs +31 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-viem.d.cts +17 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-viem.d.ts +17 -0
- package/dist/src/intents/intent-signer-impl/intent-signer-viem.js +30 -0
- package/dist/src/intents/interfaces/intent-executer.d.ts +2 -0
- package/dist/src/intents/interfaces/intent-relayer.d.cts +43 -0
- package/dist/src/intents/interfaces/intent-relayer.d.ts +43 -0
- package/dist/src/intents/interfaces/intent-signer.d.cts +8 -0
- package/dist/src/intents/interfaces/intent-signer.d.ts +8 -0
- package/dist/src/intents/interfaces/salt-manager.d.cts +9 -0
- package/dist/src/intents/interfaces/salt-manager.d.ts +9 -0
- package/dist/src/intents/salt-manager.cjs +74 -0
- package/dist/src/intents/salt-manager.js +72 -0
- package/dist/src/intents/shared-types.d.cts +20 -0
- package/dist/src/intents/shared-types.d.ts +20 -0
- package/dist/src/lib/array.cjs +11 -0
- package/dist/src/lib/array.js +10 -0
- package/dist/src/lib/caip2.cjs +50 -0
- package/dist/src/lib/caip2.d.cts +38 -0
- package/dist/src/lib/caip2.d.ts +38 -0
- package/dist/src/lib/caip2.js +48 -0
- package/dist/src/lib/configure-rpc-config.cjs +20 -0
- package/dist/src/lib/configure-rpc-config.js +18 -0
- package/dist/src/lib/estimate-fee.cjs +96 -0
- package/dist/src/lib/estimate-fee.js +94 -0
- package/dist/src/lib/hex.cjs +11 -0
- package/dist/src/lib/hex.js +10 -0
- package/dist/src/lib/nep413.cjs +42 -0
- package/dist/src/lib/nep413.d.cts +14 -0
- package/dist/src/lib/nep413.d.ts +14 -0
- package/dist/src/lib/nep413.js +41 -0
- package/dist/src/lib/object.cjs +10 -0
- package/dist/src/lib/object.js +9 -0
- package/dist/src/lib/parse-defuse-asset-id.cjs +15 -0
- package/dist/src/lib/parse-defuse-asset-id.js +14 -0
- package/dist/src/lib/route-config-factory.cjs +43 -0
- package/dist/src/lib/route-config-factory.d.cts +13 -0
- package/dist/src/lib/route-config-factory.d.ts +13 -0
- package/dist/src/lib/route-config-factory.js +37 -0
- package/dist/src/lib/tokensUsdPricesHttpClient/apis.cjs +17 -0
- package/dist/src/lib/tokensUsdPricesHttpClient/apis.js +16 -0
- package/dist/src/lib/validateAddress.cjs +271 -0
- package/dist/src/lib/validateAddress.d.cts +14 -0
- package/dist/src/lib/validateAddress.d.ts +14 -0
- package/dist/src/lib/validateAddress.js +270 -0
- package/dist/src/sdk.cjs +435 -0
- package/dist/src/sdk.d.cts +231 -0
- package/dist/src/sdk.d.ts +231 -0
- package/dist/src/sdk.js +433 -0
- package/dist/src/shared-types.d.cts +378 -0
- package/dist/src/shared-types.d.ts +378 -0
- package/package.json +62 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_errors = require('../../classes/errors.cjs');
|
|
3
|
+
const require_route_enum = require('../../constants/route-enum.cjs');
|
|
4
|
+
const require_estimate_fee = require('../../lib/estimate-fee.cjs');
|
|
5
|
+
const require_parse_defuse_asset_id = require('../../lib/parse-defuse-asset-id.cjs');
|
|
6
|
+
const require_validateAddress = require('../../lib/validateAddress.cjs');
|
|
7
|
+
const require_bridge_name_enum = require('../../constants/bridge-name-enum.cjs');
|
|
8
|
+
const require_error = require('./error.cjs');
|
|
9
|
+
const require_omni_bridge_constants = require('./omni-bridge-constants.cjs');
|
|
10
|
+
const require_poa_tokens_routable_through_omni_bridge = require('../../constants/poa-tokens-routable-through-omni-bridge.cjs');
|
|
11
|
+
const require_omni_bridge_utils = require('./omni-bridge-utils.cjs');
|
|
12
|
+
let lampamazaza_internal_utils = require("lampamazaza-internal-utils");
|
|
13
|
+
let lru_cache = require("lru-cache");
|
|
14
|
+
let _isaacs_ttlcache = require("@isaacs/ttlcache");
|
|
15
|
+
_isaacs_ttlcache = require_rolldown_runtime.__toESM(_isaacs_ttlcache);
|
|
16
|
+
let _omni_bridge_core = require("@omni-bridge/core");
|
|
17
|
+
|
|
18
|
+
//#region src/bridges/omni-bridge/omni-bridge.ts
|
|
19
|
+
var OmniBridge = class {
|
|
20
|
+
constructor({ envConfig, nearProvider, solverRelayApiKey, routeMigratedPoaTokensThroughOmniBridge }) {
|
|
21
|
+
this.route = require_route_enum.RouteEnum.OmniBridge;
|
|
22
|
+
this.storageDepositCache = new lru_cache.LRUCache({
|
|
23
|
+
max: 100,
|
|
24
|
+
ttl: 36e5
|
|
25
|
+
});
|
|
26
|
+
this.destinationChainAddressCache = new _isaacs_ttlcache.default({ ttl: 36e5 });
|
|
27
|
+
this.tokenDecimalsCache = new _isaacs_ttlcache.default({ ttl: 36e5 });
|
|
28
|
+
this.envConfig = envConfig;
|
|
29
|
+
this.nearProvider = nearProvider;
|
|
30
|
+
this.omniBridgeAPI = new _omni_bridge_core.BridgeAPI("mainnet");
|
|
31
|
+
this.solverRelayApiKey = solverRelayApiKey;
|
|
32
|
+
this.routeMigratedPoaTokensThroughOmniBridge = routeMigratedPoaTokensThroughOmniBridge ?? false;
|
|
33
|
+
}
|
|
34
|
+
is(routeConfig) {
|
|
35
|
+
return routeConfig.route === require_route_enum.RouteEnum.OmniBridge;
|
|
36
|
+
}
|
|
37
|
+
async supports(params) {
|
|
38
|
+
if (params.routeConfig && !this.is(params.routeConfig)) return false;
|
|
39
|
+
const parsed = require_parse_defuse_asset_id.parseDefuseAssetId(params.assetId);
|
|
40
|
+
const omniBridgeSetWithNoChain = Boolean(params.routeConfig && params.routeConfig.route === require_route_enum.RouteEnum.OmniBridge && params.routeConfig.chain === void 0);
|
|
41
|
+
const targetChainSpecified = this.targetChainSpecified(params.routeConfig);
|
|
42
|
+
const nonValidStandard = parsed.standard !== "nep141";
|
|
43
|
+
if (nonValidStandard && (omniBridgeSetWithNoChain || targetChainSpecified)) throw new require_errors.UnsupportedAssetIdError(params.assetId, `Only NEP-141 tokens are supported by Omni Bridge.`);
|
|
44
|
+
if (nonValidStandard) return false;
|
|
45
|
+
const poaTokenRoutedThroughOmniBridge = this.isPoaTokenRoutedThroughOmniBridge(parsed.contractId);
|
|
46
|
+
const nonValidToken = !poaTokenRoutedThroughOmniBridge && require_omni_bridge_utils.validateOmniToken(parsed.contractId) === false;
|
|
47
|
+
if (nonValidToken && omniBridgeSetWithNoChain) throw new require_errors.UnsupportedAssetIdError(params.assetId, `Non valid omni contract id ${parsed.contractId}`);
|
|
48
|
+
if (!targetChainSpecified && nonValidToken) return false;
|
|
49
|
+
let omniChainKind = null;
|
|
50
|
+
let caip2Chain = null;
|
|
51
|
+
if (this.targetChainSpecified(params.routeConfig)) {
|
|
52
|
+
omniChainKind = require_omni_bridge_utils.caip2ToChainKind(params.routeConfig.chain);
|
|
53
|
+
if (omniChainKind === null) throw new require_errors.UnsupportedAssetIdError(params.assetId, `Chain ${params.routeConfig.chain} is not supported in Omni Bridge.`);
|
|
54
|
+
caip2Chain = params.routeConfig.chain;
|
|
55
|
+
} else {
|
|
56
|
+
omniChainKind = poaTokenRoutedThroughOmniBridge ? require_omni_bridge_utils.poaContractIdToChainKind(parsed.contractId) : (0, _omni_bridge_core.parseOriginChain)(parsed.contractId);
|
|
57
|
+
if (omniChainKind === null) throw new require_errors.UnsupportedAssetIdError(params.assetId, `Withdrawal of ${parsed.contractId} to its origin chain is not supported in Omni Bridge.`);
|
|
58
|
+
caip2Chain = require_omni_bridge_utils.chainKindToCaip2(omniChainKind);
|
|
59
|
+
if (caip2Chain === null) throw new require_errors.UnsupportedAssetIdError(params.assetId, `Withdrawal of ${parsed.contractId} to its origin chain is not supported in Omni Bridge.`);
|
|
60
|
+
}
|
|
61
|
+
if (await this.getCachedDestinationTokenAddress(parsed.contractId, omniChainKind) === null) throw new require_error.TokenNotFoundInDestinationChainError(params.assetId, caip2Chain);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
targetChainSpecified(routeConfig) {
|
|
65
|
+
return Boolean(routeConfig?.route && routeConfig.route === require_route_enum.RouteEnum.OmniBridge && routeConfig.chain);
|
|
66
|
+
}
|
|
67
|
+
parseAssetId(assetId) {
|
|
68
|
+
const parsed = require_parse_defuse_asset_id.parseDefuseAssetId(assetId);
|
|
69
|
+
if (parsed.standard !== "nep141") return null;
|
|
70
|
+
const omniChainKind = this.isPoaTokenRoutedThroughOmniBridge(parsed.contractId) ? require_omni_bridge_utils.poaContractIdToChainKind(parsed.contractId) : (0, _omni_bridge_core.parseOriginChain)(parsed.contractId);
|
|
71
|
+
if (omniChainKind === null) return null;
|
|
72
|
+
const blockchain = require_omni_bridge_utils.chainKindToCaip2(omniChainKind);
|
|
73
|
+
if (blockchain === null) return null;
|
|
74
|
+
return Object.assign(parsed, {
|
|
75
|
+
blockchain,
|
|
76
|
+
bridgeName: require_bridge_name_enum.BridgeNameEnum.Omni,
|
|
77
|
+
address: parsed.contractId
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
makeAssetInfo(assetId, routeConfig) {
|
|
81
|
+
const parsed = require_parse_defuse_asset_id.parseDefuseAssetId(assetId);
|
|
82
|
+
if (parsed.standard !== "nep141") return null;
|
|
83
|
+
let omniChainKind = null;
|
|
84
|
+
let blockchain = null;
|
|
85
|
+
if (this.targetChainSpecified(routeConfig)) {
|
|
86
|
+
omniChainKind = require_omni_bridge_utils.caip2ToChainKind(routeConfig.chain);
|
|
87
|
+
blockchain = routeConfig.chain;
|
|
88
|
+
} else {
|
|
89
|
+
omniChainKind = this.isPoaTokenRoutedThroughOmniBridge(parsed.contractId) ? require_omni_bridge_utils.poaContractIdToChainKind(parsed.contractId) : (0, _omni_bridge_core.parseOriginChain)(parsed.contractId);
|
|
90
|
+
if (omniChainKind === null) return null;
|
|
91
|
+
blockchain = require_omni_bridge_utils.chainKindToCaip2(omniChainKind);
|
|
92
|
+
}
|
|
93
|
+
if (omniChainKind === null || blockchain === null) return null;
|
|
94
|
+
return Object.assign(parsed, {
|
|
95
|
+
blockchain,
|
|
96
|
+
bridgeName: require_bridge_name_enum.BridgeNameEnum.Omni,
|
|
97
|
+
address: parsed.contractId
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async createWithdrawalIntents(args) {
|
|
101
|
+
const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
|
|
102
|
+
(0, lampamazaza_internal_utils.assert)(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
|
|
103
|
+
const omniChainKind = require_omni_bridge_utils.caip2ToChainKind(assetInfo.blockchain);
|
|
104
|
+
(0, lampamazaza_internal_utils.assert)(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
|
|
105
|
+
const intents = [];
|
|
106
|
+
if (args.feeEstimation.quote !== null) intents.push({
|
|
107
|
+
intent: "token_diff",
|
|
108
|
+
diff: {
|
|
109
|
+
[args.feeEstimation.quote.defuse_asset_identifier_in]: `-${args.feeEstimation.quote.amount_in}`,
|
|
110
|
+
[args.feeEstimation.quote.defuse_asset_identifier_out]: args.feeEstimation.quote.amount_out
|
|
111
|
+
},
|
|
112
|
+
referral: args.referral
|
|
113
|
+
});
|
|
114
|
+
const relayerFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "relayerFee");
|
|
115
|
+
(0, lampamazaza_internal_utils.assert)(relayerFee >= 0n, `Invalid Omni bridge relayer fee: expected >= 0, got ${relayerFee}`);
|
|
116
|
+
let amount = args.withdrawalParams.amount;
|
|
117
|
+
let utxoMaxGasFee = null;
|
|
118
|
+
/**
|
|
119
|
+
* UTXO withdrawals add protocol + max gas fees to the intent amount since they're paid
|
|
120
|
+
* from the withdrawn asset, not wrap.near.
|
|
121
|
+
*
|
|
122
|
+
* Example with nep141:nbtc.bridge.near (made-up values):
|
|
123
|
+
* utxoFees = 50 + 50 = 100, relayerFee = 2 (excluded; paid in wrap.near)
|
|
124
|
+
*
|
|
125
|
+
* feeInclusive=false:
|
|
126
|
+
* - amount = 4000 → intent = 4000 + 100 = 4100 → user receives 4000
|
|
127
|
+
*
|
|
128
|
+
* feeInclusive=true:
|
|
129
|
+
* - amount = 3898 (4000 − 102) → intent = 3898 + 100 = 3998 → user receives 3898
|
|
130
|
+
**/
|
|
131
|
+
if (require_omni_bridge_utils.isUtxoChain(omniChainKind)) {
|
|
132
|
+
utxoMaxGasFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoMaxGasFee");
|
|
133
|
+
const utxoProtocolFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoProtocolFee");
|
|
134
|
+
(0, lampamazaza_internal_utils.assert)(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
|
|
135
|
+
(0, lampamazaza_internal_utils.assert)(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
|
|
136
|
+
amount += utxoMaxGasFee + utxoProtocolFee;
|
|
137
|
+
}
|
|
138
|
+
intents.push(...require_omni_bridge_utils.createWithdrawIntentsPrimitive({
|
|
139
|
+
assetId: args.withdrawalParams.assetId,
|
|
140
|
+
destinationAddress: args.withdrawalParams.destinationAddress,
|
|
141
|
+
amount,
|
|
142
|
+
omniChainKind,
|
|
143
|
+
intentsContract: this.envConfig.contractID,
|
|
144
|
+
nativeFee: relayerFee,
|
|
145
|
+
storageDepositAmount: require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "storageDepositFee"),
|
|
146
|
+
utxoMaxGasFee
|
|
147
|
+
}));
|
|
148
|
+
return Promise.resolve(intents);
|
|
149
|
+
}
|
|
150
|
+
async validateWithdrawal(args) {
|
|
151
|
+
(0, lampamazaza_internal_utils.assert)(args.feeEstimation.amount > 0n, `Invalid Omni Bridge fee: expected > 0, got ${args.feeEstimation.amount}`);
|
|
152
|
+
const assetInfo = this.makeAssetInfo(args.assetId, args.routeConfig);
|
|
153
|
+
(0, lampamazaza_internal_utils.assert)(assetInfo !== null, `Asset ${args.assetId} is not supported by Omni Bridge`);
|
|
154
|
+
if (require_validateAddress.validateAddress(args.destinationAddress, assetInfo.blockchain) === false) throw new require_errors.InvalidDestinationAddressForWithdrawalError(args.destinationAddress, assetInfo.blockchain);
|
|
155
|
+
const omniChainKind = require_omni_bridge_utils.caip2ToChainKind(assetInfo.blockchain);
|
|
156
|
+
(0, lampamazaza_internal_utils.assert)(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
|
|
157
|
+
const destTokenAddress = await this.getCachedDestinationTokenAddress(assetInfo.contractId, omniChainKind);
|
|
158
|
+
if (destTokenAddress === null) throw new require_error.TokenNotFoundInDestinationChainError(args.assetId, assetInfo.blockchain);
|
|
159
|
+
const decimals = await this.getCachedTokenDecimals(destTokenAddress);
|
|
160
|
+
(0, lampamazaza_internal_utils.assert)(decimals !== null, `Failed to retrieve token decimals for address ${destTokenAddress} via OmniBridge contract.
|
|
161
|
+
Ensure the token is supported and the address is correct.`);
|
|
162
|
+
if ((0, _omni_bridge_core.verifyTransferAmount)(args.amount, 0n, decimals.origin_decimals, decimals.decimals) === false) throw new require_errors.MinWithdrawalAmountError((0, _omni_bridge_core.getMinimumTransferableAmount)(decimals.origin_decimals, decimals.decimals), args.amount, args.assetId);
|
|
163
|
+
const storageBalance = await require_omni_bridge_utils.getAccountOmniStorageBalance(this.nearProvider, this.envConfig.contractID);
|
|
164
|
+
const intentsNearStorageBalance = storageBalance === null ? 0n : BigInt(storageBalance.available);
|
|
165
|
+
if (intentsNearStorageBalance <= require_omni_bridge_constants.MIN_ALLOWED_STORAGE_BALANCE_FOR_INTENTS_NEAR) throw new require_error.IntentsNearOmniAvailableBalanceTooLowError(intentsNearStorageBalance.toString());
|
|
166
|
+
const utxoChainWithdrawal = require_omni_bridge_utils.isUtxoChain(omniChainKind);
|
|
167
|
+
if (utxoChainWithdrawal === false) {
|
|
168
|
+
const relayerFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "relayerFee");
|
|
169
|
+
(0, lampamazaza_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}`);
|
|
170
|
+
}
|
|
171
|
+
if (utxoChainWithdrawal) {
|
|
172
|
+
const fee = await (0, lampamazaza_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.destinationAddress), (0, _omni_bridge_core.omniAddress)(_omni_bridge_core.ChainKind.Near, assetInfo.contractId), args.amount), {
|
|
173
|
+
timeout: typeof window !== "undefined" ? 1e4 : 3e3,
|
|
174
|
+
errorInstance: new require_error.OmniWithdrawalApiFeeRequestTimeoutError()
|
|
175
|
+
});
|
|
176
|
+
if (fee.insufficient_utxo) throw new require_error.InsufficientUtxoForOmniBridgeWithdrawalError(assetInfo.blockchain);
|
|
177
|
+
(0, lampamazaza_internal_utils.assert)(fee.min_amount !== null && fee.min_amount !== void 0 && BigInt(fee.min_amount) > 0n, `Invalid min amount value for a UTXO chain withdrawal: expected > 0, got ${fee.min_amount}`);
|
|
178
|
+
const minAmount = BigInt(fee.min_amount);
|
|
179
|
+
const utxoMaxGasFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoMaxGasFee");
|
|
180
|
+
const utxoProtocolFee = require_estimate_fee.getUnderlyingFee(args.feeEstimation, require_route_enum.RouteEnum.OmniBridge, "utxoProtocolFee");
|
|
181
|
+
(0, lampamazaza_internal_utils.assert)(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
|
|
182
|
+
(0, lampamazaza_internal_utils.assert)(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
|
|
183
|
+
const actualAmountWithFee = args.amount + utxoMaxGasFee + utxoProtocolFee;
|
|
184
|
+
if (actualAmountWithFee < minAmount) throw new require_errors.MinWithdrawalAmountError(minAmount, actualAmountWithFee, args.assetId);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async estimateWithdrawalFee(args) {
|
|
188
|
+
const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
|
|
189
|
+
(0, lampamazaza_internal_utils.assert)(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
|
|
190
|
+
const omniChainKind = require_omni_bridge_utils.caip2ToChainKind(assetInfo.blockchain);
|
|
191
|
+
(0, lampamazaza_internal_utils.assert)(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
|
|
192
|
+
const fee = await (0, lampamazaza_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), {
|
|
193
|
+
timeout: typeof window !== "undefined" ? 1e4 : 3e3,
|
|
194
|
+
errorInstance: new require_error.OmniWithdrawalApiFeeRequestTimeoutError()
|
|
195
|
+
});
|
|
196
|
+
if (fee.native_token_fee === null || fee.native_token_fee < 0n) throw new require_error.InvalidFeeValueError(args.withdrawalParams.assetId, fee.native_token_fee);
|
|
197
|
+
const underlyingFees = {
|
|
198
|
+
relayerFee: fee.native_token_fee,
|
|
199
|
+
storageDepositFee: 0n
|
|
200
|
+
};
|
|
201
|
+
let totalAmountToQuote = fee.native_token_fee;
|
|
202
|
+
const [minStorageBalance, currentStorageBalance] = await this.getCachedStorageDepositValue(assetInfo.contractId);
|
|
203
|
+
const storageDepositFee = minStorageBalance - currentStorageBalance;
|
|
204
|
+
if (storageDepositFee > 0n) {
|
|
205
|
+
totalAmountToQuote += storageDepositFee;
|
|
206
|
+
underlyingFees.storageDepositFee = storageDepositFee;
|
|
207
|
+
}
|
|
208
|
+
if (args.withdrawalParams.assetId === require_omni_bridge_constants.NEAR_NATIVE_ASSET_ID) return {
|
|
209
|
+
amount: totalAmountToQuote,
|
|
210
|
+
quote: null,
|
|
211
|
+
underlyingFees: { [require_route_enum.RouteEnum.OmniBridge]: underlyingFees }
|
|
212
|
+
};
|
|
213
|
+
let amount = 0n;
|
|
214
|
+
let quote = null;
|
|
215
|
+
if (totalAmountToQuote > 0n) {
|
|
216
|
+
quote = await require_estimate_fee.getFeeQuote({
|
|
217
|
+
feeAmount: totalAmountToQuote,
|
|
218
|
+
feeAssetId: require_omni_bridge_constants.NEAR_NATIVE_ASSET_ID,
|
|
219
|
+
tokenAssetId: args.withdrawalParams.assetId,
|
|
220
|
+
logger: args.logger,
|
|
221
|
+
envConfig: this.envConfig,
|
|
222
|
+
quoteOptions: args.quoteOptions,
|
|
223
|
+
solverRelayApiKey: this.solverRelayApiKey
|
|
224
|
+
});
|
|
225
|
+
amount += BigInt(quote.amount_in);
|
|
226
|
+
}
|
|
227
|
+
if (require_omni_bridge_utils.isUtxoChain(omniChainKind)) {
|
|
228
|
+
(0, lampamazaza_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}`);
|
|
229
|
+
(0, lampamazaza_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}`);
|
|
230
|
+
amount += fee.gas_fee + fee.protocol_fee;
|
|
231
|
+
underlyingFees.utxoMaxGasFee = fee.gas_fee;
|
|
232
|
+
underlyingFees.utxoProtocolFee = fee.protocol_fee;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
amount,
|
|
236
|
+
quote,
|
|
237
|
+
underlyingFees: { [require_route_enum.RouteEnum.OmniBridge]: underlyingFees }
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
createWithdrawalIdentifier(args) {
|
|
241
|
+
const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
|
|
242
|
+
(0, lampamazaza_internal_utils.assert)(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
|
|
243
|
+
return {
|
|
244
|
+
landingChain: args.withdrawalParams.routeConfig != null && "chain" in args.withdrawalParams.routeConfig && args.withdrawalParams.routeConfig.chain !== void 0 ? args.withdrawalParams.routeConfig.chain : assetInfo.blockchain,
|
|
245
|
+
index: args.index,
|
|
246
|
+
withdrawalParams: args.withdrawalParams,
|
|
247
|
+
tx: args.tx
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async describeWithdrawal(args) {
|
|
251
|
+
const transfer = (await this.omniBridgeAPI.getTransfer({ transactionHash: args.tx.hash }))[args.index];
|
|
252
|
+
if (transfer == null || transfer.transfer_message == null) return { status: "pending" };
|
|
253
|
+
const destinationChain = (0, _omni_bridge_core.getChain)(transfer.transfer_message.recipient);
|
|
254
|
+
let txHash = null;
|
|
255
|
+
if ((0, _omni_bridge_core.isEvmChain)(destinationChain)) txHash = transfer.finalised?.EVMLog?.transaction_hash;
|
|
256
|
+
else if (destinationChain === _omni_bridge_core.ChainKind.Sol) txHash = transfer.finalised?.Solana?.signature;
|
|
257
|
+
else if (destinationChain === _omni_bridge_core.ChainKind.Btc) txHash = typeof window !== "undefined" ? transfer.utxo_transfer?.btc_pending_id : transfer.finalised?.UtxoLog?.transaction_hash;
|
|
258
|
+
else return {
|
|
259
|
+
status: "completed",
|
|
260
|
+
txHash: null
|
|
261
|
+
};
|
|
262
|
+
if (!txHash) return { status: "pending" };
|
|
263
|
+
return {
|
|
264
|
+
status: "completed",
|
|
265
|
+
txHash
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Gets storage deposit for a token to avoid frequent RPC calls.
|
|
270
|
+
*/
|
|
271
|
+
async getCachedStorageDepositValue(contractId) {
|
|
272
|
+
const cached = this.storageDepositCache.get(contractId);
|
|
273
|
+
if (cached !== void 0) return cached;
|
|
274
|
+
const result = await Promise.all([(0, lampamazaza_internal_utils.getNearNep141MinStorageBalance)({
|
|
275
|
+
contractId,
|
|
276
|
+
nearProvider: this.nearProvider
|
|
277
|
+
}), (0, lampamazaza_internal_utils.getNearNep141StorageBalance)({
|
|
278
|
+
contractId,
|
|
279
|
+
accountId: require_omni_bridge_constants.OMNI_BRIDGE_CONTRACT,
|
|
280
|
+
nearProvider: this.nearProvider
|
|
281
|
+
})]);
|
|
282
|
+
if (result[1] >= result[0]) this.storageDepositCache.set(contractId, result);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Gets cached token address on destination chain.
|
|
287
|
+
*/
|
|
288
|
+
async getCachedDestinationTokenAddress(contractId, omniChainKind) {
|
|
289
|
+
const key = `${omniChainKind}:${contractId}`;
|
|
290
|
+
const cached = this.destinationChainAddressCache.get(key);
|
|
291
|
+
if (cached !== void 0) return cached;
|
|
292
|
+
const tokenOnDestinationNetwork = await require_omni_bridge_utils.getBridgedToken(this.nearProvider, (0, _omni_bridge_core.omniAddress)(_omni_bridge_core.ChainKind.Near, contractId), omniChainKind);
|
|
293
|
+
if (tokenOnDestinationNetwork !== null) this.destinationChainAddressCache.set(key, tokenOnDestinationNetwork);
|
|
294
|
+
return tokenOnDestinationNetwork;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Gets cached token decimals on destination chain and on near.
|
|
298
|
+
*/
|
|
299
|
+
async getCachedTokenDecimals(omniAddress$1) {
|
|
300
|
+
const cached = this.tokenDecimalsCache.get(omniAddress$1);
|
|
301
|
+
if (cached !== void 0) return cached;
|
|
302
|
+
const tokenDecimals = await require_omni_bridge_utils.getTokenDecimals(this.nearProvider, omniAddress$1);
|
|
303
|
+
if (tokenDecimals !== null) this.tokenDecimalsCache.set(omniAddress$1, tokenDecimals);
|
|
304
|
+
return tokenDecimals;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Checks if passed token contract id is an allowlisted PoA token that should be routed via OmniBridge.
|
|
308
|
+
* Always return false when feature flag routeMigratedPoaTokensThroughOmniBridge = false.
|
|
309
|
+
*/
|
|
310
|
+
isPoaTokenRoutedThroughOmniBridge(nearAddress) {
|
|
311
|
+
return this.routeMigratedPoaTokensThroughOmniBridge ? require_poa_tokens_routable_through_omni_bridge.POA_TOKENS_ROUTABLE_THROUGH_OMNI_BRIDGE[nearAddress] !== void 0 : false;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
//#endregion
|
|
316
|
+
exports.OmniBridge = OmniBridge;
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { InvalidDestinationAddressForWithdrawalError, MinWithdrawalAmountError, UnsupportedAssetIdError } from "../../classes/errors.js";
|
|
2
|
+
import { RouteEnum } from "../../constants/route-enum.js";
|
|
3
|
+
import { getFeeQuote, getUnderlyingFee } from "../../lib/estimate-fee.js";
|
|
4
|
+
import { parseDefuseAssetId } from "../../lib/parse-defuse-asset-id.js";
|
|
5
|
+
import { validateAddress } from "../../lib/validateAddress.js";
|
|
6
|
+
import { BridgeNameEnum } from "../../constants/bridge-name-enum.js";
|
|
7
|
+
import { InsufficientUtxoForOmniBridgeWithdrawalError, IntentsNearOmniAvailableBalanceTooLowError, InvalidFeeValueError, OmniWithdrawalApiFeeRequestTimeoutError, TokenNotFoundInDestinationChainError } from "./error.js";
|
|
8
|
+
import { MIN_ALLOWED_STORAGE_BALANCE_FOR_INTENTS_NEAR, NEAR_NATIVE_ASSET_ID, OMNI_BRIDGE_CONTRACT } from "./omni-bridge-constants.js";
|
|
9
|
+
import { POA_TOKENS_ROUTABLE_THROUGH_OMNI_BRIDGE } from "../../constants/poa-tokens-routable-through-omni-bridge.js";
|
|
10
|
+
import { caip2ToChainKind, chainKindToCaip2, createWithdrawIntentsPrimitive, getAccountOmniStorageBalance, getBridgedToken, getTokenDecimals, isUtxoChain, poaContractIdToChainKind, validateOmniToken } from "./omni-bridge-utils.js";
|
|
11
|
+
import { assert, getNearNep141MinStorageBalance, getNearNep141StorageBalance, withTimeout } from "lampamazaza-internal-utils";
|
|
12
|
+
import { LRUCache } from "lru-cache";
|
|
13
|
+
import TTLCache from "@isaacs/ttlcache";
|
|
14
|
+
import { BridgeAPI, ChainKind, getChain, getMinimumTransferableAmount, isEvmChain, omniAddress, parseOriginChain, verifyTransferAmount } from "@omni-bridge/core";
|
|
15
|
+
|
|
16
|
+
//#region src/bridges/omni-bridge/omni-bridge.ts
|
|
17
|
+
var OmniBridge = class {
|
|
18
|
+
constructor({ envConfig, nearProvider, solverRelayApiKey, routeMigratedPoaTokensThroughOmniBridge }) {
|
|
19
|
+
this.route = RouteEnum.OmniBridge;
|
|
20
|
+
this.storageDepositCache = new LRUCache({
|
|
21
|
+
max: 100,
|
|
22
|
+
ttl: 36e5
|
|
23
|
+
});
|
|
24
|
+
this.destinationChainAddressCache = new TTLCache({ ttl: 36e5 });
|
|
25
|
+
this.tokenDecimalsCache = new TTLCache({ ttl: 36e5 });
|
|
26
|
+
this.envConfig = envConfig;
|
|
27
|
+
this.nearProvider = nearProvider;
|
|
28
|
+
this.omniBridgeAPI = new BridgeAPI("mainnet");
|
|
29
|
+
this.solverRelayApiKey = solverRelayApiKey;
|
|
30
|
+
this.routeMigratedPoaTokensThroughOmniBridge = routeMigratedPoaTokensThroughOmniBridge ?? false;
|
|
31
|
+
}
|
|
32
|
+
is(routeConfig) {
|
|
33
|
+
return routeConfig.route === RouteEnum.OmniBridge;
|
|
34
|
+
}
|
|
35
|
+
async supports(params) {
|
|
36
|
+
if (params.routeConfig && !this.is(params.routeConfig)) return false;
|
|
37
|
+
const parsed = parseDefuseAssetId(params.assetId);
|
|
38
|
+
const omniBridgeSetWithNoChain = Boolean(params.routeConfig && params.routeConfig.route === RouteEnum.OmniBridge && params.routeConfig.chain === void 0);
|
|
39
|
+
const targetChainSpecified = this.targetChainSpecified(params.routeConfig);
|
|
40
|
+
const nonValidStandard = parsed.standard !== "nep141";
|
|
41
|
+
if (nonValidStandard && (omniBridgeSetWithNoChain || targetChainSpecified)) throw new UnsupportedAssetIdError(params.assetId, `Only NEP-141 tokens are supported by Omni Bridge.`);
|
|
42
|
+
if (nonValidStandard) return false;
|
|
43
|
+
const poaTokenRoutedThroughOmniBridge = this.isPoaTokenRoutedThroughOmniBridge(parsed.contractId);
|
|
44
|
+
const nonValidToken = !poaTokenRoutedThroughOmniBridge && validateOmniToken(parsed.contractId) === false;
|
|
45
|
+
if (nonValidToken && omniBridgeSetWithNoChain) throw new UnsupportedAssetIdError(params.assetId, `Non valid omni contract id ${parsed.contractId}`);
|
|
46
|
+
if (!targetChainSpecified && nonValidToken) return false;
|
|
47
|
+
let omniChainKind = null;
|
|
48
|
+
let caip2Chain = null;
|
|
49
|
+
if (this.targetChainSpecified(params.routeConfig)) {
|
|
50
|
+
omniChainKind = caip2ToChainKind(params.routeConfig.chain);
|
|
51
|
+
if (omniChainKind === null) throw new UnsupportedAssetIdError(params.assetId, `Chain ${params.routeConfig.chain} is not supported in Omni Bridge.`);
|
|
52
|
+
caip2Chain = params.routeConfig.chain;
|
|
53
|
+
} else {
|
|
54
|
+
omniChainKind = poaTokenRoutedThroughOmniBridge ? poaContractIdToChainKind(parsed.contractId) : parseOriginChain(parsed.contractId);
|
|
55
|
+
if (omniChainKind === null) throw new UnsupportedAssetIdError(params.assetId, `Withdrawal of ${parsed.contractId} to its origin chain is not supported in Omni Bridge.`);
|
|
56
|
+
caip2Chain = chainKindToCaip2(omniChainKind);
|
|
57
|
+
if (caip2Chain === null) throw new UnsupportedAssetIdError(params.assetId, `Withdrawal of ${parsed.contractId} to its origin chain is not supported in Omni Bridge.`);
|
|
58
|
+
}
|
|
59
|
+
if (await this.getCachedDestinationTokenAddress(parsed.contractId, omniChainKind) === null) throw new TokenNotFoundInDestinationChainError(params.assetId, caip2Chain);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
targetChainSpecified(routeConfig) {
|
|
63
|
+
return Boolean(routeConfig?.route && routeConfig.route === RouteEnum.OmniBridge && routeConfig.chain);
|
|
64
|
+
}
|
|
65
|
+
parseAssetId(assetId) {
|
|
66
|
+
const parsed = parseDefuseAssetId(assetId);
|
|
67
|
+
if (parsed.standard !== "nep141") return null;
|
|
68
|
+
const omniChainKind = this.isPoaTokenRoutedThroughOmniBridge(parsed.contractId) ? poaContractIdToChainKind(parsed.contractId) : parseOriginChain(parsed.contractId);
|
|
69
|
+
if (omniChainKind === null) return null;
|
|
70
|
+
const blockchain = chainKindToCaip2(omniChainKind);
|
|
71
|
+
if (blockchain === null) return null;
|
|
72
|
+
return Object.assign(parsed, {
|
|
73
|
+
blockchain,
|
|
74
|
+
bridgeName: BridgeNameEnum.Omni,
|
|
75
|
+
address: parsed.contractId
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
makeAssetInfo(assetId, routeConfig) {
|
|
79
|
+
const parsed = parseDefuseAssetId(assetId);
|
|
80
|
+
if (parsed.standard !== "nep141") return null;
|
|
81
|
+
let omniChainKind = null;
|
|
82
|
+
let blockchain = null;
|
|
83
|
+
if (this.targetChainSpecified(routeConfig)) {
|
|
84
|
+
omniChainKind = caip2ToChainKind(routeConfig.chain);
|
|
85
|
+
blockchain = routeConfig.chain;
|
|
86
|
+
} else {
|
|
87
|
+
omniChainKind = this.isPoaTokenRoutedThroughOmniBridge(parsed.contractId) ? poaContractIdToChainKind(parsed.contractId) : parseOriginChain(parsed.contractId);
|
|
88
|
+
if (omniChainKind === null) return null;
|
|
89
|
+
blockchain = chainKindToCaip2(omniChainKind);
|
|
90
|
+
}
|
|
91
|
+
if (omniChainKind === null || blockchain === null) return null;
|
|
92
|
+
return Object.assign(parsed, {
|
|
93
|
+
blockchain,
|
|
94
|
+
bridgeName: BridgeNameEnum.Omni,
|
|
95
|
+
address: parsed.contractId
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async createWithdrawalIntents(args) {
|
|
99
|
+
const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
|
|
100
|
+
assert(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
|
|
101
|
+
const omniChainKind = caip2ToChainKind(assetInfo.blockchain);
|
|
102
|
+
assert(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
|
|
103
|
+
const intents = [];
|
|
104
|
+
if (args.feeEstimation.quote !== null) intents.push({
|
|
105
|
+
intent: "token_diff",
|
|
106
|
+
diff: {
|
|
107
|
+
[args.feeEstimation.quote.defuse_asset_identifier_in]: `-${args.feeEstimation.quote.amount_in}`,
|
|
108
|
+
[args.feeEstimation.quote.defuse_asset_identifier_out]: args.feeEstimation.quote.amount_out
|
|
109
|
+
},
|
|
110
|
+
referral: args.referral
|
|
111
|
+
});
|
|
112
|
+
const relayerFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "relayerFee");
|
|
113
|
+
assert(relayerFee >= 0n, `Invalid Omni bridge relayer fee: expected >= 0, got ${relayerFee}`);
|
|
114
|
+
let amount = args.withdrawalParams.amount;
|
|
115
|
+
let utxoMaxGasFee = null;
|
|
116
|
+
/**
|
|
117
|
+
* UTXO withdrawals add protocol + max gas fees to the intent amount since they're paid
|
|
118
|
+
* from the withdrawn asset, not wrap.near.
|
|
119
|
+
*
|
|
120
|
+
* Example with nep141:nbtc.bridge.near (made-up values):
|
|
121
|
+
* utxoFees = 50 + 50 = 100, relayerFee = 2 (excluded; paid in wrap.near)
|
|
122
|
+
*
|
|
123
|
+
* feeInclusive=false:
|
|
124
|
+
* - amount = 4000 → intent = 4000 + 100 = 4100 → user receives 4000
|
|
125
|
+
*
|
|
126
|
+
* feeInclusive=true:
|
|
127
|
+
* - amount = 3898 (4000 − 102) → intent = 3898 + 100 = 3998 → user receives 3898
|
|
128
|
+
**/
|
|
129
|
+
if (isUtxoChain(omniChainKind)) {
|
|
130
|
+
utxoMaxGasFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "utxoMaxGasFee");
|
|
131
|
+
const utxoProtocolFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "utxoProtocolFee");
|
|
132
|
+
assert(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
|
|
133
|
+
assert(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
|
|
134
|
+
amount += utxoMaxGasFee + utxoProtocolFee;
|
|
135
|
+
}
|
|
136
|
+
intents.push(...createWithdrawIntentsPrimitive({
|
|
137
|
+
assetId: args.withdrawalParams.assetId,
|
|
138
|
+
destinationAddress: args.withdrawalParams.destinationAddress,
|
|
139
|
+
amount,
|
|
140
|
+
omniChainKind,
|
|
141
|
+
intentsContract: this.envConfig.contractID,
|
|
142
|
+
nativeFee: relayerFee,
|
|
143
|
+
storageDepositAmount: getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "storageDepositFee"),
|
|
144
|
+
utxoMaxGasFee
|
|
145
|
+
}));
|
|
146
|
+
return Promise.resolve(intents);
|
|
147
|
+
}
|
|
148
|
+
async validateWithdrawal(args) {
|
|
149
|
+
assert(args.feeEstimation.amount > 0n, `Invalid Omni Bridge fee: expected > 0, got ${args.feeEstimation.amount}`);
|
|
150
|
+
const assetInfo = this.makeAssetInfo(args.assetId, args.routeConfig);
|
|
151
|
+
assert(assetInfo !== null, `Asset ${args.assetId} is not supported by Omni Bridge`);
|
|
152
|
+
if (validateAddress(args.destinationAddress, assetInfo.blockchain) === false) throw new InvalidDestinationAddressForWithdrawalError(args.destinationAddress, assetInfo.blockchain);
|
|
153
|
+
const omniChainKind = caip2ToChainKind(assetInfo.blockchain);
|
|
154
|
+
assert(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
|
|
155
|
+
const destTokenAddress = await this.getCachedDestinationTokenAddress(assetInfo.contractId, omniChainKind);
|
|
156
|
+
if (destTokenAddress === null) throw new TokenNotFoundInDestinationChainError(args.assetId, assetInfo.blockchain);
|
|
157
|
+
const decimals = await this.getCachedTokenDecimals(destTokenAddress);
|
|
158
|
+
assert(decimals !== null, `Failed to retrieve token decimals for address ${destTokenAddress} via OmniBridge contract.
|
|
159
|
+
Ensure the token is supported and the address is correct.`);
|
|
160
|
+
if (verifyTransferAmount(args.amount, 0n, decimals.origin_decimals, decimals.decimals) === false) throw new MinWithdrawalAmountError(getMinimumTransferableAmount(decimals.origin_decimals, decimals.decimals), args.amount, args.assetId);
|
|
161
|
+
const storageBalance = await getAccountOmniStorageBalance(this.nearProvider, this.envConfig.contractID);
|
|
162
|
+
const intentsNearStorageBalance = storageBalance === null ? 0n : BigInt(storageBalance.available);
|
|
163
|
+
if (intentsNearStorageBalance <= MIN_ALLOWED_STORAGE_BALANCE_FOR_INTENTS_NEAR) throw new IntentsNearOmniAvailableBalanceTooLowError(intentsNearStorageBalance.toString());
|
|
164
|
+
const utxoChainWithdrawal = isUtxoChain(omniChainKind);
|
|
165
|
+
if (utxoChainWithdrawal === false) {
|
|
166
|
+
const relayerFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "relayerFee");
|
|
167
|
+
assert(getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "relayerFee") > 0n, `Invalid Omni Bridge relayer fee for non UTXO chain withdrawal: expected > 0, got ${relayerFee}`);
|
|
168
|
+
}
|
|
169
|
+
if (utxoChainWithdrawal) {
|
|
170
|
+
const fee = await withTimeout(() => this.omniBridgeAPI.getFee(omniAddress(ChainKind.Near, this.envConfig.contractID), omniAddress(omniChainKind, args.destinationAddress), omniAddress(ChainKind.Near, assetInfo.contractId), args.amount), {
|
|
171
|
+
timeout: typeof window !== "undefined" ? 1e4 : 3e3,
|
|
172
|
+
errorInstance: new OmniWithdrawalApiFeeRequestTimeoutError()
|
|
173
|
+
});
|
|
174
|
+
if (fee.insufficient_utxo) throw new InsufficientUtxoForOmniBridgeWithdrawalError(assetInfo.blockchain);
|
|
175
|
+
assert(fee.min_amount !== null && fee.min_amount !== void 0 && BigInt(fee.min_amount) > 0n, `Invalid min amount value for a UTXO chain withdrawal: expected > 0, got ${fee.min_amount}`);
|
|
176
|
+
const minAmount = BigInt(fee.min_amount);
|
|
177
|
+
const utxoMaxGasFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "utxoMaxGasFee");
|
|
178
|
+
const utxoProtocolFee = getUnderlyingFee(args.feeEstimation, RouteEnum.OmniBridge, "utxoProtocolFee");
|
|
179
|
+
assert(utxoMaxGasFee !== void 0 && utxoMaxGasFee > 0n, `Invalid Omni Bridge utxo max gas fee: expected > 0, got ${utxoMaxGasFee}`);
|
|
180
|
+
assert(utxoProtocolFee !== void 0 && utxoProtocolFee > 0n, `Invalid Omni Bridge utxo protocol fee: expected > 0, got ${utxoProtocolFee}`);
|
|
181
|
+
const actualAmountWithFee = args.amount + utxoMaxGasFee + utxoProtocolFee;
|
|
182
|
+
if (actualAmountWithFee < minAmount) throw new MinWithdrawalAmountError(minAmount, actualAmountWithFee, args.assetId);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async estimateWithdrawalFee(args) {
|
|
186
|
+
const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
|
|
187
|
+
assert(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
|
|
188
|
+
const omniChainKind = caip2ToChainKind(assetInfo.blockchain);
|
|
189
|
+
assert(omniChainKind !== null, `Chain ${assetInfo.blockchain} is not supported by Omni Bridge`);
|
|
190
|
+
const fee = await withTimeout(() => this.omniBridgeAPI.getFee(omniAddress(ChainKind.Near, this.envConfig.contractID), omniAddress(omniChainKind, args.withdrawalParams.destinationAddress), omniAddress(ChainKind.Near, assetInfo.contractId), args.withdrawalParams.amount), {
|
|
191
|
+
timeout: typeof window !== "undefined" ? 1e4 : 3e3,
|
|
192
|
+
errorInstance: new OmniWithdrawalApiFeeRequestTimeoutError()
|
|
193
|
+
});
|
|
194
|
+
if (fee.native_token_fee === null || fee.native_token_fee < 0n) throw new InvalidFeeValueError(args.withdrawalParams.assetId, fee.native_token_fee);
|
|
195
|
+
const underlyingFees = {
|
|
196
|
+
relayerFee: fee.native_token_fee,
|
|
197
|
+
storageDepositFee: 0n
|
|
198
|
+
};
|
|
199
|
+
let totalAmountToQuote = fee.native_token_fee;
|
|
200
|
+
const [minStorageBalance, currentStorageBalance] = await this.getCachedStorageDepositValue(assetInfo.contractId);
|
|
201
|
+
const storageDepositFee = minStorageBalance - currentStorageBalance;
|
|
202
|
+
if (storageDepositFee > 0n) {
|
|
203
|
+
totalAmountToQuote += storageDepositFee;
|
|
204
|
+
underlyingFees.storageDepositFee = storageDepositFee;
|
|
205
|
+
}
|
|
206
|
+
if (args.withdrawalParams.assetId === NEAR_NATIVE_ASSET_ID) return {
|
|
207
|
+
amount: totalAmountToQuote,
|
|
208
|
+
quote: null,
|
|
209
|
+
underlyingFees: { [RouteEnum.OmniBridge]: underlyingFees }
|
|
210
|
+
};
|
|
211
|
+
let amount = 0n;
|
|
212
|
+
let quote = null;
|
|
213
|
+
if (totalAmountToQuote > 0n) {
|
|
214
|
+
quote = await getFeeQuote({
|
|
215
|
+
feeAmount: totalAmountToQuote,
|
|
216
|
+
feeAssetId: NEAR_NATIVE_ASSET_ID,
|
|
217
|
+
tokenAssetId: args.withdrawalParams.assetId,
|
|
218
|
+
logger: args.logger,
|
|
219
|
+
envConfig: this.envConfig,
|
|
220
|
+
quoteOptions: args.quoteOptions,
|
|
221
|
+
solverRelayApiKey: this.solverRelayApiKey
|
|
222
|
+
});
|
|
223
|
+
amount += BigInt(quote.amount_in);
|
|
224
|
+
}
|
|
225
|
+
if (isUtxoChain(omniChainKind)) {
|
|
226
|
+
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}`);
|
|
227
|
+
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}`);
|
|
228
|
+
amount += fee.gas_fee + fee.protocol_fee;
|
|
229
|
+
underlyingFees.utxoMaxGasFee = fee.gas_fee;
|
|
230
|
+
underlyingFees.utxoProtocolFee = fee.protocol_fee;
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
amount,
|
|
234
|
+
quote,
|
|
235
|
+
underlyingFees: { [RouteEnum.OmniBridge]: underlyingFees }
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
createWithdrawalIdentifier(args) {
|
|
239
|
+
const assetInfo = this.makeAssetInfo(args.withdrawalParams.assetId, args.withdrawalParams.routeConfig);
|
|
240
|
+
assert(assetInfo !== null, `Asset ${args.withdrawalParams.assetId} is not supported by Omni Bridge`);
|
|
241
|
+
return {
|
|
242
|
+
landingChain: args.withdrawalParams.routeConfig != null && "chain" in args.withdrawalParams.routeConfig && args.withdrawalParams.routeConfig.chain !== void 0 ? args.withdrawalParams.routeConfig.chain : assetInfo.blockchain,
|
|
243
|
+
index: args.index,
|
|
244
|
+
withdrawalParams: args.withdrawalParams,
|
|
245
|
+
tx: args.tx
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async describeWithdrawal(args) {
|
|
249
|
+
const transfer = (await this.omniBridgeAPI.getTransfer({ transactionHash: args.tx.hash }))[args.index];
|
|
250
|
+
if (transfer == null || transfer.transfer_message == null) return { status: "pending" };
|
|
251
|
+
const destinationChain = getChain(transfer.transfer_message.recipient);
|
|
252
|
+
let txHash = null;
|
|
253
|
+
if (isEvmChain(destinationChain)) txHash = transfer.finalised?.EVMLog?.transaction_hash;
|
|
254
|
+
else if (destinationChain === ChainKind.Sol) txHash = transfer.finalised?.Solana?.signature;
|
|
255
|
+
else if (destinationChain === ChainKind.Btc) txHash = typeof window !== "undefined" ? transfer.utxo_transfer?.btc_pending_id : transfer.finalised?.UtxoLog?.transaction_hash;
|
|
256
|
+
else return {
|
|
257
|
+
status: "completed",
|
|
258
|
+
txHash: null
|
|
259
|
+
};
|
|
260
|
+
if (!txHash) return { status: "pending" };
|
|
261
|
+
return {
|
|
262
|
+
status: "completed",
|
|
263
|
+
txHash
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Gets storage deposit for a token to avoid frequent RPC calls.
|
|
268
|
+
*/
|
|
269
|
+
async getCachedStorageDepositValue(contractId) {
|
|
270
|
+
const cached = this.storageDepositCache.get(contractId);
|
|
271
|
+
if (cached !== void 0) return cached;
|
|
272
|
+
const result = await Promise.all([getNearNep141MinStorageBalance({
|
|
273
|
+
contractId,
|
|
274
|
+
nearProvider: this.nearProvider
|
|
275
|
+
}), getNearNep141StorageBalance({
|
|
276
|
+
contractId,
|
|
277
|
+
accountId: OMNI_BRIDGE_CONTRACT,
|
|
278
|
+
nearProvider: this.nearProvider
|
|
279
|
+
})]);
|
|
280
|
+
if (result[1] >= result[0]) this.storageDepositCache.set(contractId, result);
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Gets cached token address on destination chain.
|
|
285
|
+
*/
|
|
286
|
+
async getCachedDestinationTokenAddress(contractId, omniChainKind) {
|
|
287
|
+
const key = `${omniChainKind}:${contractId}`;
|
|
288
|
+
const cached = this.destinationChainAddressCache.get(key);
|
|
289
|
+
if (cached !== void 0) return cached;
|
|
290
|
+
const tokenOnDestinationNetwork = await getBridgedToken(this.nearProvider, omniAddress(ChainKind.Near, contractId), omniChainKind);
|
|
291
|
+
if (tokenOnDestinationNetwork !== null) this.destinationChainAddressCache.set(key, tokenOnDestinationNetwork);
|
|
292
|
+
return tokenOnDestinationNetwork;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Gets cached token decimals on destination chain and on near.
|
|
296
|
+
*/
|
|
297
|
+
async getCachedTokenDecimals(omniAddress$1) {
|
|
298
|
+
const cached = this.tokenDecimalsCache.get(omniAddress$1);
|
|
299
|
+
if (cached !== void 0) return cached;
|
|
300
|
+
const tokenDecimals = await getTokenDecimals(this.nearProvider, omniAddress$1);
|
|
301
|
+
if (tokenDecimals !== null) this.tokenDecimalsCache.set(omniAddress$1, tokenDecimals);
|
|
302
|
+
return tokenDecimals;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Checks if passed token contract id is an allowlisted PoA token that should be routed via OmniBridge.
|
|
306
|
+
* Always return false when feature flag routeMigratedPoaTokensThroughOmniBridge = false.
|
|
307
|
+
*/
|
|
308
|
+
isPoaTokenRoutedThroughOmniBridge(nearAddress) {
|
|
309
|
+
return this.routeMigratedPoaTokensThroughOmniBridge ? POA_TOKENS_ROUTABLE_THROUGH_OMNI_BRIDGE[nearAddress] !== void 0 : false;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
//#endregion
|
|
314
|
+
export { OmniBridge };
|