@sodax/sdk 2.0.0-rc.10 → 2.0.0-rc.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +411 -131
- package/dist/index.d.cts +222 -95
- package/dist/index.d.ts +222 -95
- package/dist/index.mjs +407 -134
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -3052,9 +3052,9 @@ var spokeChainConfig = {
|
|
|
3052
3052
|
supportedTokens: bitcoinSupportedTokens,
|
|
3053
3053
|
radfi: {
|
|
3054
3054
|
walletMode: "TRADING",
|
|
3055
|
-
apiUrl: "https://api.
|
|
3055
|
+
apiUrl: "https://api.bound.exchange/api",
|
|
3056
3056
|
apiKey: "",
|
|
3057
|
-
umsUrl: "https://ums.
|
|
3057
|
+
umsUrl: "https://api.ums.bound.exchange/api",
|
|
3058
3058
|
accessToken: "",
|
|
3059
3059
|
refreshToken: ""
|
|
3060
3060
|
},
|
|
@@ -3896,6 +3896,9 @@ function detectBitcoinAddressType(address) {
|
|
|
3896
3896
|
return "P2PKH";
|
|
3897
3897
|
throw new Error(`Unknown Bitcoin address type: ${address}`);
|
|
3898
3898
|
}
|
|
3899
|
+
function usesBip322MessageSigning(addressType) {
|
|
3900
|
+
return addressType === "P2WPKH" || addressType === "P2TR";
|
|
3901
|
+
}
|
|
3899
3902
|
var BTC_WALLET_ADDRESS_TYPES = ["taproot", "segwit"];
|
|
3900
3903
|
var BTC_ADDRESS_TYPES = ["P2PKH", "P2SH", "P2WPKH", "P2TR"];
|
|
3901
3904
|
|
|
@@ -4013,7 +4016,7 @@ function isValidWalletProviderForChainKey(chainKey, walletProvider) {
|
|
|
4013
4016
|
}
|
|
4014
4017
|
|
|
4015
4018
|
// ../types/dist/index.js
|
|
4016
|
-
var CONFIG_VERSION =
|
|
4019
|
+
var CONFIG_VERSION = 210;
|
|
4017
4020
|
function isEvmSpokeChainConfig(value) {
|
|
4018
4021
|
return typeof value === "object" && value !== null && value.chain.type === "EVM" && value.chain.key !== HUB_CHAIN_KEY;
|
|
4019
4022
|
}
|
|
@@ -4440,7 +4443,7 @@ async function waitUntilIntentExecuted(payload) {
|
|
|
4440
4443
|
}
|
|
4441
4444
|
async function relayTxAndWaitPacket(params) {
|
|
4442
4445
|
try {
|
|
4443
|
-
const { srcTxHash, data, chainKey, relayerApiEndpoint, timeout = DEFAULT_RELAY_TX_TIMEOUT } = params;
|
|
4446
|
+
const { srcTxHash, data, chainKey, relayerApiEndpoint, timeout = DEFAULT_RELAY_TX_TIMEOUT, pollTxHash } = params;
|
|
4444
4447
|
const intentRelayChainId = getIntentRelayChainId(chainKey).toString();
|
|
4445
4448
|
const isSplitTxChain = isSolanaChainKeyType(chainKey) || isBitcoinChainKeyType(chainKey);
|
|
4446
4449
|
invariant(!isSplitTxChain || data !== void 0, "Data is required for Solana and Bitcoin chain keys");
|
|
@@ -4459,7 +4462,9 @@ async function relayTxAndWaitPacket(params) {
|
|
|
4459
4462
|
if (!submitResult.ok) return submitResult;
|
|
4460
4463
|
return await waitUntilIntentExecuted({
|
|
4461
4464
|
intentRelayChainId,
|
|
4462
|
-
|
|
4465
|
+
// The relay may track the packet under a different id than the submit tx_hash (Bitcoin
|
|
4466
|
+
// on-demand: submit "withdraw", poll the derived `od:<hash>`). Defaults to the submit id.
|
|
4467
|
+
srcTxHash: pollTxHash ?? srcTxHash,
|
|
4463
4468
|
timeout,
|
|
4464
4469
|
apiUrl: relayerApiEndpoint
|
|
4465
4470
|
});
|
|
@@ -13298,11 +13303,43 @@ function mergeSodaxConfig(base2, override) {
|
|
|
13298
13303
|
return merged;
|
|
13299
13304
|
}
|
|
13300
13305
|
|
|
13306
|
+
// src/shared/logger.ts
|
|
13307
|
+
var consoleLogger = {
|
|
13308
|
+
debug: (message, data) => data ? console.debug(message, data) : console.debug(message),
|
|
13309
|
+
info: (message, data) => data ? console.info(message, data) : console.info(message),
|
|
13310
|
+
warn: (message, data) => data ? console.warn(message, data) : console.warn(message),
|
|
13311
|
+
error: (message, error, data) => {
|
|
13312
|
+
if (error !== void 0 && data !== void 0) console.error(message, error, data);
|
|
13313
|
+
else if (error !== void 0) console.error(message, error);
|
|
13314
|
+
else console.error(message);
|
|
13315
|
+
}
|
|
13316
|
+
};
|
|
13317
|
+
var silentLogger = {
|
|
13318
|
+
debug: () => {
|
|
13319
|
+
},
|
|
13320
|
+
info: () => {
|
|
13321
|
+
},
|
|
13322
|
+
warn: () => {
|
|
13323
|
+
},
|
|
13324
|
+
error: () => {
|
|
13325
|
+
}
|
|
13326
|
+
};
|
|
13327
|
+
function resolveLogger(option) {
|
|
13328
|
+
if (option === void 0 || option === "console") return consoleLogger;
|
|
13329
|
+
if (option === "silent") return silentLogger;
|
|
13330
|
+
return option;
|
|
13331
|
+
}
|
|
13332
|
+
|
|
13301
13333
|
// src/shared/config/ConfigService.ts
|
|
13302
13334
|
var ConfigService = class {
|
|
13303
13335
|
sodax;
|
|
13304
13336
|
api;
|
|
13305
13337
|
userConfig;
|
|
13338
|
+
/**
|
|
13339
|
+
* SDK log sink. Resolved once at construction and kept independent of {@link sodax} so that
|
|
13340
|
+
* {@link initialize}'s dynamic-config swap never clobbers it. Read by services via `config.logger`.
|
|
13341
|
+
*/
|
|
13342
|
+
logger;
|
|
13306
13343
|
initialized = false;
|
|
13307
13344
|
// data structures for quick lookup
|
|
13308
13345
|
supportedHubAssetsSet;
|
|
@@ -13314,10 +13351,11 @@ var ConfigService = class {
|
|
|
13314
13351
|
stakedATokenAddressesSet;
|
|
13315
13352
|
chainToSupportedTokenAddressMap;
|
|
13316
13353
|
hubAssetToXTokenMap;
|
|
13317
|
-
constructor({ api, config, userConfig }) {
|
|
13354
|
+
constructor({ api, config, userConfig, logger }) {
|
|
13318
13355
|
this.api = api;
|
|
13319
13356
|
this.sodax = config;
|
|
13320
13357
|
this.userConfig = userConfig;
|
|
13358
|
+
this.logger = logger ?? resolveLogger(void 0);
|
|
13321
13359
|
this.loadSodaxConfigDataStructures(config);
|
|
13322
13360
|
}
|
|
13323
13361
|
async initialize() {
|
|
@@ -13326,7 +13364,7 @@ var ConfigService = class {
|
|
|
13326
13364
|
if (!result.ok) return result;
|
|
13327
13365
|
const response = result.value;
|
|
13328
13366
|
if (!response.version || response.version < CONFIG_VERSION) {
|
|
13329
|
-
|
|
13367
|
+
this.logger.warn(
|
|
13330
13368
|
`Dynamic config version is less than the current version, resorting to the default one. Current version: ${CONFIG_VERSION}, response version: ${response.version}`
|
|
13331
13369
|
);
|
|
13332
13370
|
} else {
|
|
@@ -14484,7 +14522,7 @@ var RadfiProvider = class {
|
|
|
14484
14522
|
}
|
|
14485
14523
|
}
|
|
14486
14524
|
/**
|
|
14487
|
-
* Authenticate with
|
|
14525
|
+
* Authenticate with Bound Exchange: BIP322-sign a login message, then call the Bound Exchange API.
|
|
14488
14526
|
* Returns accessToken, refreshToken, and tradingAddress.
|
|
14489
14527
|
*/
|
|
14490
14528
|
async authenticateWithWallet(walletProvider, cachedPublicKey) {
|
|
@@ -14500,15 +14538,14 @@ var RadfiProvider = class {
|
|
|
14500
14538
|
throw new Error("Failed to retrieve public key from wallet. Please unlock your wallet and try again.");
|
|
14501
14539
|
}
|
|
14502
14540
|
const message = `${Date.now()}`;
|
|
14503
|
-
const
|
|
14504
|
-
const signature = addressType === "P2WPKH" || addressType === "P2TR" ? await walletProvider.signBip322Message(message) : await walletProvider.signEcdsaMessage(message);
|
|
14541
|
+
const signature = usesBip322MessageSigning(detectBitcoinAddressType(address)) ? await walletProvider.signBip322Message(message) : await walletProvider.signEcdsaMessage(message);
|
|
14505
14542
|
const result = await this.authenticate({ message, signature, address, publicKey });
|
|
14506
14543
|
this.setRadfiAccessToken(result.accessToken, result.refreshToken);
|
|
14507
14544
|
return { ...result, publicKey };
|
|
14508
14545
|
}
|
|
14509
14546
|
/**
|
|
14510
|
-
* Ensure a valid
|
|
14511
|
-
* If a token exists, validates it via the
|
|
14547
|
+
* Ensure a valid Bound Exchange access token is set on this provider.
|
|
14548
|
+
* If a token exists, validates it via the Bound Exchange API.
|
|
14512
14549
|
* If invalid, tries refreshing with the refresh token first.
|
|
14513
14550
|
* If refresh also fails, falls back to full re-authentication (BIP322 sign).
|
|
14514
14551
|
*/
|
|
@@ -14541,7 +14578,7 @@ var RadfiProvider = class {
|
|
|
14541
14578
|
});
|
|
14542
14579
|
if (!res.ok) {
|
|
14543
14580
|
const err = await res.json();
|
|
14544
|
-
throw new RadfiApiError(res.status, err, "
|
|
14581
|
+
throw new RadfiApiError(res.status, err, "Bound Exchange authentication failed");
|
|
14545
14582
|
}
|
|
14546
14583
|
return res.json().then((r) => ({
|
|
14547
14584
|
accessToken: r.data?.accessToken ?? "",
|
|
@@ -14633,12 +14670,20 @@ var RadfiProvider = class {
|
|
|
14633
14670
|
}
|
|
14634
14671
|
})
|
|
14635
14672
|
});
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
throw new RadfiApiError(res.status,
|
|
14673
|
+
const body = await res.json();
|
|
14674
|
+
if (!res.ok || !body?.data) {
|
|
14675
|
+
throw new RadfiApiError(res.status, body, "Bound Exchange transaction request failed");
|
|
14639
14676
|
}
|
|
14640
|
-
return
|
|
14677
|
+
return body.data;
|
|
14641
14678
|
}
|
|
14679
|
+
/**
|
|
14680
|
+
* Co-sign and broadcast a `sodax-withdraw` deposit via the Bound Exchange API.
|
|
14681
|
+
*
|
|
14682
|
+
* `relayData` ({ address, payload }) is the same `RelayExtraData` the SDK returns from
|
|
14683
|
+
* `createIntent()` / money-market supply etc. It is optional and non-breaking: when supplied,
|
|
14684
|
+
* the Bound Exchange backend persists it so it can auto-resubmit the intent relay if the relay
|
|
14685
|
+
* gets stuck (otherwise a stuck relay eventually refunds instead of completing the swap).
|
|
14686
|
+
*/
|
|
14642
14687
|
async requestRadfiSignature(params, accessToken) {
|
|
14643
14688
|
const res = await this.request("/sodax/transaction/sign", {
|
|
14644
14689
|
method: "POST",
|
|
@@ -14652,7 +14697,7 @@ var RadfiProvider = class {
|
|
|
14652
14697
|
});
|
|
14653
14698
|
if (!res.ok) {
|
|
14654
14699
|
const err = await res.json();
|
|
14655
|
-
throw new RadfiApiError(res.status, err, "
|
|
14700
|
+
throw new RadfiApiError(res.status, err, "Bound Exchange signature request failed");
|
|
14656
14701
|
}
|
|
14657
14702
|
return res.json().then((r) => r.data.txId);
|
|
14658
14703
|
}
|
|
@@ -14676,7 +14721,7 @@ var RadfiProvider = class {
|
|
|
14676
14721
|
return res.json();
|
|
14677
14722
|
}
|
|
14678
14723
|
/**
|
|
14679
|
-
* Build a renew-utxo transaction via the
|
|
14724
|
+
* Build a renew-utxo transaction via the Bound Exchange API.
|
|
14680
14725
|
* Returns a PSBT that needs to be signed by the user.
|
|
14681
14726
|
*/
|
|
14682
14727
|
async buildRenewUtxoTransaction(params, accessToken) {
|
|
@@ -14700,8 +14745,8 @@ var RadfiProvider = class {
|
|
|
14700
14745
|
return res.json().then((r) => r.data);
|
|
14701
14746
|
}
|
|
14702
14747
|
/**
|
|
14703
|
-
* Sign and broadcast a renew-utxo transaction via the
|
|
14704
|
-
* The user signs the PSBT first, then
|
|
14748
|
+
* Sign and broadcast a renew-utxo transaction via the Bound Exchange API.
|
|
14749
|
+
* The user signs the PSBT first, then Bound Exchange co-signs and broadcasts.
|
|
14705
14750
|
*/
|
|
14706
14751
|
async signAndBroadcastRenewUtxo(params, accessToken) {
|
|
14707
14752
|
const res = await this.request("/transactions/sign", {
|
|
@@ -14742,7 +14787,7 @@ var RadfiProvider = class {
|
|
|
14742
14787
|
return res.json().then((r) => r.data);
|
|
14743
14788
|
}
|
|
14744
14789
|
/**
|
|
14745
|
-
* Sign and broadcast a withdraw transaction via
|
|
14790
|
+
* Sign and broadcast a withdraw transaction via Bound Exchange.
|
|
14746
14791
|
*/
|
|
14747
14792
|
async signAndBroadcastWithdraw(params, accessToken) {
|
|
14748
14793
|
const res = await this.request("/transactions/sign", {
|
|
@@ -14796,7 +14841,20 @@ var RadfiProvider = class {
|
|
|
14796
14841
|
};
|
|
14797
14842
|
|
|
14798
14843
|
// src/shared/entities/btc/btc-utils.ts
|
|
14799
|
-
|
|
14844
|
+
var BITCOIN_FEE_SAFETY_VBYTES = 20;
|
|
14845
|
+
function calcOpReturnOutputVbytes(payloadByteLength) {
|
|
14846
|
+
let scriptSize;
|
|
14847
|
+
if (payloadByteLength <= 75) {
|
|
14848
|
+
scriptSize = 3 + payloadByteLength;
|
|
14849
|
+
} else if (payloadByteLength <= 255) {
|
|
14850
|
+
scriptSize = 4 + payloadByteLength;
|
|
14851
|
+
} else {
|
|
14852
|
+
scriptSize = 5 + payloadByteLength;
|
|
14853
|
+
}
|
|
14854
|
+
const scriptLenVarint = scriptSize <= 252 ? 1 : 3;
|
|
14855
|
+
return 8 + scriptLenVarint + scriptSize;
|
|
14856
|
+
}
|
|
14857
|
+
function estimateBitcoinTxSize(inputCount, outputCount, addressType, opReturnOutputVbytes = 44) {
|
|
14800
14858
|
let inputWeight;
|
|
14801
14859
|
switch (addressType) {
|
|
14802
14860
|
case "P2PKH":
|
|
@@ -14812,7 +14870,9 @@ function estimateBitcoinTxSize(inputCount, outputCount, addressType) {
|
|
|
14812
14870
|
inputWeight = 68;
|
|
14813
14871
|
break;
|
|
14814
14872
|
}
|
|
14815
|
-
return Math.ceil(
|
|
14873
|
+
return Math.ceil(
|
|
14874
|
+
10.5 + opReturnOutputVbytes + BITCOIN_FEE_SAFETY_VBYTES + inputCount * inputWeight + outputCount * 31
|
|
14875
|
+
);
|
|
14816
14876
|
}
|
|
14817
14877
|
function encodeBtcPayloadToBytes(payload) {
|
|
14818
14878
|
return JSON.stringify({
|
|
@@ -14829,6 +14889,10 @@ function normalizePsbtToBase64(signedPsbt) {
|
|
|
14829
14889
|
const isHex = /^[0-9a-fA-F]+$/.test(signedPsbt);
|
|
14830
14890
|
return isHex ? Buffer.from(signedPsbt, "hex").toString("base64") : signedPsbt;
|
|
14831
14891
|
}
|
|
14892
|
+
function normalizeSignatureToBase64(signature) {
|
|
14893
|
+
const isHex = /^[0-9a-fA-F]+$/.test(signature);
|
|
14894
|
+
return isHex ? Buffer.from(signature, "hex").toString("base64") : signature;
|
|
14895
|
+
}
|
|
14832
14896
|
|
|
14833
14897
|
// src/shared/services/spoke/BitcoinSpokeService.ts
|
|
14834
14898
|
bitcoinjsLib.initEccLib(ecc__namespace);
|
|
@@ -14937,7 +15001,7 @@ var BitcoinSpokeService = class {
|
|
|
14937
15001
|
return BigInt(totalBalance);
|
|
14938
15002
|
}
|
|
14939
15003
|
/**
|
|
14940
|
-
* Fund the
|
|
15004
|
+
* Fund the Bound Exchange trading wallet by sending BTC from the user's personal wallet
|
|
14941
15005
|
*
|
|
14942
15006
|
* @param {bigint} amount - Amount in satoshis to send
|
|
14943
15007
|
* @param {BitcoinSpokeProvider} spokeProvider - The Bitcoin spoke provider (must have signing capability)
|
|
@@ -14961,10 +15025,28 @@ var BitcoinSpokeService = class {
|
|
|
14961
15025
|
async sendMessage(params) {
|
|
14962
15026
|
return await this.encodeWithdrawalData(params);
|
|
14963
15027
|
}
|
|
15028
|
+
/**
|
|
15029
|
+
* Build the relay submit/poll identity for an on-demand action (borrow/withdraw).
|
|
15030
|
+
*
|
|
15031
|
+
* Bitcoin borrow/withdraw are on-demand: there is no broadcast transaction — the spoke result is
|
|
15032
|
+
* the signed payload JSON produced by {@link encodeWithdrawalData}/{@link sendMessage}. The relay
|
|
15033
|
+
* accepts the submit under the literal `withdraw` tx_hash with the signed payload (as a JSON object)
|
|
15034
|
+
* in `data`, then tracks the resulting packet under a derived id: `od:` + keccak256 of the ASCII
|
|
15035
|
+
* `payload_hex` string (hash the hex characters, not the decoded bytes). Polling must use that
|
|
15036
|
+
* derived id (`pollTxHash`), not `withdraw`.
|
|
15037
|
+
*
|
|
15038
|
+
* @param tx - The JSON-stringified signed payload returned by `sendMessage` / `encodeWithdrawalData`.
|
|
15039
|
+
*/
|
|
15040
|
+
getOnDemandRelayIdentity(tx) {
|
|
15041
|
+
const data = JSON.parse(tx);
|
|
15042
|
+
const payloadHex = data.payload_hex.startsWith("0x") ? data.payload_hex.slice(2) : data.payload_hex;
|
|
15043
|
+
const pollTxHash = `od:${viem.keccak256(viem.stringToBytes(payloadHex)).slice(2)}`;
|
|
15044
|
+
return { srcTxHash: "withdraw", data, pollTxHash };
|
|
15045
|
+
}
|
|
14964
15046
|
/**
|
|
14965
15047
|
* Build a priority Bitcoin transaction with proper fee calculation
|
|
14966
15048
|
*/
|
|
14967
|
-
async buildBitcoinTransaction(utxos, outputs, changeAddress, chainId, walletProvider, feeRate) {
|
|
15049
|
+
async buildBitcoinTransaction(utxos, outputs, changeAddress, chainId, walletProvider, feeRate, opReturnOutputVbytes) {
|
|
14968
15050
|
const psbt = new bitcoinjsLib.Psbt({ network: this.getBtcNetwork(chainId) });
|
|
14969
15051
|
const effectiveFeeRate = feeRate ?? await this.getFeeRateEstimate();
|
|
14970
15052
|
const walletAddress = await walletProvider.getWalletAddress();
|
|
@@ -15027,7 +15109,7 @@ var BitcoinSpokeService = class {
|
|
|
15027
15109
|
});
|
|
15028
15110
|
}
|
|
15029
15111
|
inputSum += utxo.value;
|
|
15030
|
-
const estimatedSize = estimateBitcoinTxSize(psbt.inputCount, outputs.length, addressType);
|
|
15112
|
+
const estimatedSize = estimateBitcoinTxSize(psbt.inputCount, outputs.length, addressType, opReturnOutputVbytes);
|
|
15031
15113
|
const estimatedFee = Math.ceil(effectiveFeeRate * estimatedSize);
|
|
15032
15114
|
if (inputSum >= outputSum + estimatedFee + DUST_THRESHOLD) {
|
|
15033
15115
|
break;
|
|
@@ -15039,8 +15121,13 @@ var BitcoinSpokeService = class {
|
|
|
15039
15121
|
value: output.value
|
|
15040
15122
|
});
|
|
15041
15123
|
}
|
|
15042
|
-
const sizeWithChange = estimateBitcoinTxSize(
|
|
15043
|
-
|
|
15124
|
+
const sizeWithChange = estimateBitcoinTxSize(
|
|
15125
|
+
psbt.inputCount,
|
|
15126
|
+
outputs.length + 1,
|
|
15127
|
+
addressType,
|
|
15128
|
+
opReturnOutputVbytes
|
|
15129
|
+
);
|
|
15130
|
+
const sizeWithoutChange = estimateBitcoinTxSize(psbt.inputCount, outputs.length, addressType, opReturnOutputVbytes);
|
|
15044
15131
|
const feeWithChange = Math.ceil(effectiveFeeRate * sizeWithChange);
|
|
15045
15132
|
const feeWithoutChange = Math.ceil(effectiveFeeRate * sizeWithoutChange);
|
|
15046
15133
|
let change = inputSum - outputSum - feeWithChange;
|
|
@@ -15109,7 +15196,12 @@ var BitcoinSpokeService = class {
|
|
|
15109
15196
|
return await this.radfi.requestRadfiSignature(
|
|
15110
15197
|
{
|
|
15111
15198
|
userAddress: from,
|
|
15112
|
-
signedBase64Tx
|
|
15199
|
+
signedBase64Tx,
|
|
15200
|
+
// Forward the relay identity ({ hub wallet address, full payload }) so the Bound Exchange
|
|
15201
|
+
// backend can auto-resubmit the intent relay if it gets stuck. `to` is the hub wallet
|
|
15202
|
+
// (relayData.address) and `data` is the full payload (relayData.payload) — the same pair
|
|
15203
|
+
// feature services return as `relayData` from createIntent()/supply().
|
|
15204
|
+
relayData: { address: params.to, payload: data }
|
|
15113
15205
|
},
|
|
15114
15206
|
accessToken
|
|
15115
15207
|
);
|
|
@@ -15119,7 +15211,11 @@ var BitcoinSpokeService = class {
|
|
|
15119
15211
|
"Raw mode is not supported for normal Bitcoin deposits. Use TRADING wallet mode for raw transactions."
|
|
15120
15212
|
);
|
|
15121
15213
|
}
|
|
15122
|
-
const
|
|
15214
|
+
const [allUtxos, mempoolSpent] = await Promise.all([
|
|
15215
|
+
this.fetchUTXOs(from),
|
|
15216
|
+
this.fetchMempoolSpentOutpoints(from)
|
|
15217
|
+
]);
|
|
15218
|
+
const utxos = allUtxos.filter((u) => !mempoolSpent.has(`${u.txid}:${u.vout}`));
|
|
15123
15219
|
if (!utxos?.length) {
|
|
15124
15220
|
throw new Error("No UTXOs available for deposit");
|
|
15125
15221
|
}
|
|
@@ -15134,7 +15230,7 @@ var BitcoinSpokeService = class {
|
|
|
15134
15230
|
);
|
|
15135
15231
|
return await this.signAndBroadcastTransaction(depositPsbt, params.walletProvider);
|
|
15136
15232
|
} catch (error) {
|
|
15137
|
-
|
|
15233
|
+
this.config.logger.error("Error during deposit", error);
|
|
15138
15234
|
throw error;
|
|
15139
15235
|
}
|
|
15140
15236
|
}
|
|
@@ -15142,22 +15238,37 @@ var BitcoinSpokeService = class {
|
|
|
15142
15238
|
* Build deposit PSBT with embedded cross-chain data
|
|
15143
15239
|
*/
|
|
15144
15240
|
async buildDepositPsbt(walletAddress, walletProvider, srcChainKey, token, amount, data, utxos) {
|
|
15145
|
-
const
|
|
15146
|
-
|
|
15241
|
+
const chainConfig = this.config.getChainConfig(srcChainKey);
|
|
15242
|
+
const assetManagerAddress = chainConfig.addresses.assetManager;
|
|
15243
|
+
const normalizedToken = token.toLocaleLowerCase();
|
|
15244
|
+
const nativeBtcTokens = new Set(
|
|
15245
|
+
["btc", chainConfig.nativeToken, chainConfig.supportedTokens.BTC?.address].filter((value) => !!value).map((value) => value.toLocaleLowerCase())
|
|
15246
|
+
);
|
|
15247
|
+
const isNativeBtc = nativeBtcTokens.has(normalizedToken);
|
|
15248
|
+
if (isNativeBtc) {
|
|
15249
|
+
const OP_RETURN = bitcoinjsLib.opcodes.OP_RETURN;
|
|
15250
|
+
const OP_12 = bitcoinjsLib.opcodes.OP_12;
|
|
15251
|
+
if (OP_RETURN === void 0 || OP_12 === void 0) {
|
|
15252
|
+
throw new Error("bitcoinjs-lib opcodes OP_RETURN or OP_12 are undefined");
|
|
15253
|
+
}
|
|
15254
|
+
const OP_RADFI_SODAX_DATA = 49;
|
|
15255
|
+
const payload = Buffer.concat([Buffer.from([OP_RADFI_SODAX_DATA]), Buffer.from(data.slice(2), "hex")]);
|
|
15256
|
+
const opReturnOutputVbytes = calcOpReturnOutputVbytes(payload.length);
|
|
15147
15257
|
const outputs = [
|
|
15148
15258
|
{
|
|
15149
15259
|
address: assetManagerAddress,
|
|
15150
15260
|
value: Number(amount)
|
|
15151
15261
|
}
|
|
15152
15262
|
];
|
|
15153
|
-
const psbt = await this.buildBitcoinTransaction(
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
|
|
15157
|
-
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
|
|
15263
|
+
const psbt = await this.buildBitcoinTransaction(
|
|
15264
|
+
utxos,
|
|
15265
|
+
outputs,
|
|
15266
|
+
walletAddress,
|
|
15267
|
+
srcChainKey,
|
|
15268
|
+
walletProvider,
|
|
15269
|
+
void 0,
|
|
15270
|
+
opReturnOutputVbytes
|
|
15271
|
+
);
|
|
15161
15272
|
const compiledScript = bitcoinjsLib.script.compile([OP_RETURN, OP_12, payload]);
|
|
15162
15273
|
psbt.addOutput({
|
|
15163
15274
|
script: compiledScript,
|
|
@@ -15177,6 +15288,27 @@ var BitcoinSpokeService = class {
|
|
|
15177
15288
|
}
|
|
15178
15289
|
return await response.json();
|
|
15179
15290
|
}
|
|
15291
|
+
/**
|
|
15292
|
+
* Returns the set of "txid:vout" outpoints currently being spent by
|
|
15293
|
+
* unconfirmed transactions in the mempool for the given address.
|
|
15294
|
+
* Used to prevent double-spend when building a new PSBT.
|
|
15295
|
+
*/
|
|
15296
|
+
async fetchMempoolSpentOutpoints(address) {
|
|
15297
|
+
try {
|
|
15298
|
+
const response = await fetch(`${this.rpcUrl}/address/${address}/txs/mempool`);
|
|
15299
|
+
if (!response.ok) return /* @__PURE__ */ new Set();
|
|
15300
|
+
const mempoolTxs = await response.json();
|
|
15301
|
+
const spent = /* @__PURE__ */ new Set();
|
|
15302
|
+
for (const tx of mempoolTxs) {
|
|
15303
|
+
for (const input of tx.vin) {
|
|
15304
|
+
spent.add(`${input.txid}:${input.vout}`);
|
|
15305
|
+
}
|
|
15306
|
+
}
|
|
15307
|
+
return spent;
|
|
15308
|
+
} catch {
|
|
15309
|
+
return /* @__PURE__ */ new Set();
|
|
15310
|
+
}
|
|
15311
|
+
}
|
|
15180
15312
|
/**
|
|
15181
15313
|
* Fetch raw transaction hex
|
|
15182
15314
|
*/
|
|
@@ -15192,7 +15324,7 @@ var BitcoinSpokeService = class {
|
|
|
15192
15324
|
let srcAddress = from;
|
|
15193
15325
|
const addressType = detectBitcoinAddressType(from);
|
|
15194
15326
|
if (walletMode === "TRADING") {
|
|
15195
|
-
srcAddress = await this.radfi.getTradingWallet(srcAddress)
|
|
15327
|
+
srcAddress = (await this.radfi.getTradingWallet(srcAddress)).tradingAddress;
|
|
15196
15328
|
}
|
|
15197
15329
|
const payload = {
|
|
15198
15330
|
src_address: srcAddress,
|
|
@@ -15211,8 +15343,12 @@ var BitcoinSpokeService = class {
|
|
|
15211
15343
|
if (params.raw === true) {
|
|
15212
15344
|
return JSON.stringify(onDemandWithdraw);
|
|
15213
15345
|
}
|
|
15214
|
-
|
|
15215
|
-
|
|
15346
|
+
if (!params.walletProvider.getPublicKey) {
|
|
15347
|
+
throw new Error("Wallet provider does not support getPublicKey");
|
|
15348
|
+
}
|
|
15349
|
+
const rawSignature = usesBip322MessageSigning(addressType) ? await params.walletProvider.signBip322Message(orderedPayload) : await params.walletProvider.signEcdsaMessage(orderedPayload);
|
|
15350
|
+
onDemandWithdraw.signature = normalizeSignatureToBase64(rawSignature);
|
|
15351
|
+
onDemandWithdraw.public_key = await params.walletProvider.getPublicKey();
|
|
15216
15352
|
return JSON.stringify(onDemandWithdraw);
|
|
15217
15353
|
}
|
|
15218
15354
|
/**
|
|
@@ -15220,8 +15356,14 @@ var BitcoinSpokeService = class {
|
|
|
15220
15356
|
*/
|
|
15221
15357
|
async signAndBroadcastTransaction(psbt, walletProvider) {
|
|
15222
15358
|
const psbtBase64 = typeof psbt === "string" ? psbt : psbt.toBase64();
|
|
15223
|
-
const
|
|
15224
|
-
const
|
|
15359
|
+
const signedRaw = await walletProvider.signTransaction(psbtBase64, false);
|
|
15360
|
+
const signedPsbt = bitcoinjsLib.Psbt.fromBase64(normalizePsbtToBase64(signedRaw));
|
|
15361
|
+
try {
|
|
15362
|
+
signedPsbt.finalizeAllInputs();
|
|
15363
|
+
} catch {
|
|
15364
|
+
}
|
|
15365
|
+
const txHex = signedPsbt.extractTransaction().toHex();
|
|
15366
|
+
const txHash = await this.broadcastTransaction(txHex);
|
|
15225
15367
|
return txHash;
|
|
15226
15368
|
}
|
|
15227
15369
|
/**
|
|
@@ -17460,7 +17602,7 @@ function base64Decode(str) {
|
|
|
17460
17602
|
}
|
|
17461
17603
|
var encoder = new TextEncoder();
|
|
17462
17604
|
var decoder = new TextDecoder();
|
|
17463
|
-
function
|
|
17605
|
+
function stringToBytes2(str) {
|
|
17464
17606
|
return encoder.encode(str);
|
|
17465
17607
|
}
|
|
17466
17608
|
function bytesToString(bytes) {
|
|
@@ -20857,7 +20999,7 @@ var JsonRpcProvider = class {
|
|
|
20857
20999
|
};
|
|
20858
21000
|
}
|
|
20859
21001
|
async viewContractState({ contractId, prefix: prefix2, blockQuery = { finality: DEFAULT_FINALITY } }) {
|
|
20860
|
-
const prefixBase64 = base64Encode(
|
|
21002
|
+
const prefixBase64 = base64Encode(stringToBytes2(prefix2 || ""));
|
|
20861
21003
|
let reference;
|
|
20862
21004
|
if ("blockId" in blockQuery) {
|
|
20863
21005
|
reference = { block_id: blockQuery.blockId };
|
|
@@ -20885,7 +21027,7 @@ var JsonRpcProvider = class {
|
|
|
20885
21027
|
}
|
|
20886
21028
|
}
|
|
20887
21029
|
async callFunctionRaw({ contractId, method, args, blockQuery = { finality: DEFAULT_FINALITY } }) {
|
|
20888
|
-
const argsBytes = args instanceof Uint8Array ? args :
|
|
21030
|
+
const argsBytes = args instanceof Uint8Array ? args : stringToBytes2(JSON.stringify(args));
|
|
20889
21031
|
const argsBase64 = base64Encode(argsBytes);
|
|
20890
21032
|
if ("blockId" in blockQuery) {
|
|
20891
21033
|
return this.query({
|
|
@@ -21151,6 +21293,7 @@ var JsonRpcProvider = class {
|
|
|
21151
21293
|
|
|
21152
21294
|
// src/shared/services/spoke/NearSpokeService.ts
|
|
21153
21295
|
var NEAR_DEFAULT_GAS = BigInt("300000000000000");
|
|
21296
|
+
var NEAR_STORAGE_DEPOSIT = BigInt("1250000000000000000000");
|
|
21154
21297
|
var NearSpokeService = class {
|
|
21155
21298
|
config;
|
|
21156
21299
|
rpcProvider;
|
|
@@ -21200,7 +21343,7 @@ var NearSpokeService = class {
|
|
|
21200
21343
|
token: Array.from(Buffer.from(fillData.token, "utf-8"))
|
|
21201
21344
|
};
|
|
21202
21345
|
}
|
|
21203
|
-
async fillIntent(fromInfo, fillData, deposit = BigInt("
|
|
21346
|
+
async fillIntent(fromInfo, fillData, deposit = BigInt("1"), gas = BigInt("300000000000000")) {
|
|
21204
21347
|
const intentFiller = this.config.getChainConfig(fromInfo.srcChainKey).addresses.intentFiller;
|
|
21205
21348
|
if (isNativeToken(fromInfo.srcChainKey, fillData.token)) {
|
|
21206
21349
|
deposit = BigInt(fillData.amount);
|
|
@@ -21274,7 +21417,8 @@ var NearSpokeService = class {
|
|
|
21274
21417
|
data: inputParams.data
|
|
21275
21418
|
})
|
|
21276
21419
|
},
|
|
21277
|
-
|
|
21420
|
+
// NEP-141 requires exactly 1 yoctoNEAR attached to ft_transfer_call.
|
|
21421
|
+
deposit: BigInt("1"),
|
|
21278
21422
|
gas: NEAR_DEFAULT_GAS
|
|
21279
21423
|
}
|
|
21280
21424
|
};
|
|
@@ -21305,6 +21449,52 @@ var NearSpokeService = class {
|
|
|
21305
21449
|
}
|
|
21306
21450
|
return BigInt(bal);
|
|
21307
21451
|
}
|
|
21452
|
+
/**
|
|
21453
|
+
* Whether `accountId` is storage-registered on a NEP-141 `token` contract. NEP-141 requires an
|
|
21454
|
+
* account to pay a one-time storage bond before it can receive (hold a balance of) the token, so
|
|
21455
|
+
* this gates any leg that delivers a token to a user on NEAR (swap output on NEAR, bridge into
|
|
21456
|
+
* NEAR, money-market borrow/withdraw to NEAR).
|
|
21457
|
+
*
|
|
21458
|
+
* Native NEAR is not a NEP-141 token and has no storage registration, so this returns `true` for
|
|
21459
|
+
* the native token. The view goes through {@link queryContract}, i.e. the configurable RPC from
|
|
21460
|
+
* chain config — a custom `rpcUrl` passed to the SDK is honoured.
|
|
21461
|
+
*/
|
|
21462
|
+
async isStorageRegistered(token, accountId) {
|
|
21463
|
+
if (isNativeToken(ChainKeys.NEAR_MAINNET, token)) {
|
|
21464
|
+
return true;
|
|
21465
|
+
}
|
|
21466
|
+
const balance = await this.queryContract(token, "storage_balance_of", { account_id: accountId });
|
|
21467
|
+
return balance != null;
|
|
21468
|
+
}
|
|
21469
|
+
/**
|
|
21470
|
+
* Build (and, unless `raw`, submit) a NEP-141 `storage_deposit` registration for `accountId` on
|
|
21471
|
+
* the `token` contract. Call this when {@link isStorageRegistered} is `false` before a token is
|
|
21472
|
+
* delivered to the account on NEAR.
|
|
21473
|
+
*
|
|
21474
|
+
* Native NEAR has no storage registration — passing the native token throws.
|
|
21475
|
+
*
|
|
21476
|
+
* @param params.deposit Storage bond to attach; defaults to {@link NEAR_STORAGE_DEPOSIT}
|
|
21477
|
+
* (0.00125 NEAR). Override per token if its `storage_balance_bounds.min` differs.
|
|
21478
|
+
*/
|
|
21479
|
+
async registerStorage(params) {
|
|
21480
|
+
if (isNativeToken(ChainKeys.NEAR_MAINNET, params.token)) {
|
|
21481
|
+
throw new Error("[NearSpokeService.registerStorage] Native NEAR has no NEP-141 storage registration.");
|
|
21482
|
+
}
|
|
21483
|
+
const tx = {
|
|
21484
|
+
signerId: params.accountId,
|
|
21485
|
+
params: {
|
|
21486
|
+
contractId: params.token,
|
|
21487
|
+
method: "storage_deposit",
|
|
21488
|
+
args: { account_id: params.accountId, registration_only: true },
|
|
21489
|
+
deposit: params.deposit ?? NEAR_STORAGE_DEPOSIT,
|
|
21490
|
+
gas: NEAR_DEFAULT_GAS
|
|
21491
|
+
}
|
|
21492
|
+
};
|
|
21493
|
+
if (params.raw === true) {
|
|
21494
|
+
return tx;
|
|
21495
|
+
}
|
|
21496
|
+
return params.walletProvider.signAndSubmitTxn(tx);
|
|
21497
|
+
}
|
|
21308
21498
|
/**
|
|
21309
21499
|
* Sends a message to the hub chain.
|
|
21310
21500
|
* @param {SendMessageParams} params - Includes dstChainKey, the chain key of the hub chain.
|
|
@@ -22512,13 +22702,13 @@ var StellarSpokeService = class {
|
|
|
22512
22702
|
);
|
|
22513
22703
|
return `${hash}`;
|
|
22514
22704
|
} catch (error) {
|
|
22515
|
-
|
|
22705
|
+
this.config.logger.error("Error during sendMessage", error);
|
|
22516
22706
|
throw error;
|
|
22517
22707
|
}
|
|
22518
22708
|
}
|
|
22519
22709
|
handleSendTransactionError(response) {
|
|
22520
22710
|
if (response.status === "ERROR") {
|
|
22521
|
-
|
|
22711
|
+
this.config.logger.error(JSON.stringify(response, null, 2));
|
|
22522
22712
|
throw new Error(JSON.stringify(response, null, 2));
|
|
22523
22713
|
}
|
|
22524
22714
|
return response;
|
|
@@ -22629,7 +22819,7 @@ var StellarSpokeService = class {
|
|
|
22629
22819
|
);
|
|
22630
22820
|
return `${hash}`;
|
|
22631
22821
|
} catch (error) {
|
|
22632
|
-
|
|
22822
|
+
this.config.logger.error("Error during deposit", error);
|
|
22633
22823
|
throw error;
|
|
22634
22824
|
}
|
|
22635
22825
|
}
|
|
@@ -22657,7 +22847,7 @@ var StellarSpokeService = class {
|
|
|
22657
22847
|
(balance2) => "limit" in balance2 && "balance" in balance2 && "asset_code" in balance2 && trustlineConfig.assetCode.toLowerCase() === balance2.asset_code?.toLowerCase() && "asset_issuer" in balance2 && trustlineConfig.assetIssuer.toLowerCase() === balance2.asset_issuer?.toLowerCase()
|
|
22658
22848
|
);
|
|
22659
22849
|
if (!tokenBalance) {
|
|
22660
|
-
|
|
22850
|
+
this.config.logger.error(`No token balances found for token: ${token}`);
|
|
22661
22851
|
return false;
|
|
22662
22852
|
}
|
|
22663
22853
|
const limit = parseToStroops(tokenBalance.limit);
|
|
@@ -22706,7 +22896,7 @@ var StellarSpokeService = class {
|
|
|
22706
22896
|
const hash = await this.signAndSendTransaction(walletProvider, transaction);
|
|
22707
22897
|
return `${hash}`;
|
|
22708
22898
|
} catch (error) {
|
|
22709
|
-
|
|
22899
|
+
this.config.logger.error("Error during requestTrustline", error);
|
|
22710
22900
|
throw error;
|
|
22711
22901
|
}
|
|
22712
22902
|
}
|
|
@@ -22940,7 +23130,12 @@ var SolanaSpokeService = class _SolanaSpokeService {
|
|
|
22940
23130
|
}
|
|
22941
23131
|
]).instruction();
|
|
22942
23132
|
} else {
|
|
22943
|
-
const
|
|
23133
|
+
const tokenProgramId = await _SolanaSpokeService.getMintTokenProgramId(this.connection, token);
|
|
23134
|
+
const signerTokenAccount = await _SolanaSpokeService.getAssociatedTokenAddress(
|
|
23135
|
+
token.toBase58(),
|
|
23136
|
+
walletAddress,
|
|
23137
|
+
tokenProgramId
|
|
23138
|
+
);
|
|
22944
23139
|
depositInstruction = await assetManagerProgram.methods.transfer(amountBN, Buffer.from(recipient.slice(2), "hex"), Buffer.from(data.slice(2), "hex")).accountsStrict({
|
|
22945
23140
|
signer: walletPublicKey,
|
|
22946
23141
|
systemProgram: web3_js.SystemProgram.programId,
|
|
@@ -22951,7 +23146,7 @@ var SolanaSpokeService = class _SolanaSpokeService {
|
|
|
22951
23146
|
authority: AssetManagerPDA.authority(assetManagerProgram.programId).pda,
|
|
22952
23147
|
mint: token,
|
|
22953
23148
|
connection: connectionProgram.programId,
|
|
22954
|
-
tokenProgram:
|
|
23149
|
+
tokenProgram: tokenProgramId
|
|
22955
23150
|
}).remainingAccounts([
|
|
22956
23151
|
{
|
|
22957
23152
|
pubkey: ConnectionConfigPDA.config(connectionProgram.programId).pda,
|
|
@@ -23090,8 +23285,22 @@ var SolanaSpokeService = class _SolanaSpokeService {
|
|
|
23090
23285
|
static async getTokenAccountBalance(connection, publicKey) {
|
|
23091
23286
|
return await connection.getTokenAccountBalance(new web3_js.PublicKey(publicKey));
|
|
23092
23287
|
}
|
|
23093
|
-
|
|
23094
|
-
|
|
23288
|
+
/**
|
|
23289
|
+
* Resolves the token program that owns a mint (legacy SPL Token vs Token-2022). Falls back to
|
|
23290
|
+
* the legacy SPL Token program when the mint account can't be read.
|
|
23291
|
+
*/
|
|
23292
|
+
static async getMintTokenProgramId(connection, mint) {
|
|
23293
|
+
const mintAccountInfo = await connection.getAccountInfo(mint);
|
|
23294
|
+
return mintAccountInfo?.owner.equals(splToken.TOKEN_2022_PROGRAM_ID) ? splToken.TOKEN_2022_PROGRAM_ID : splToken.TOKEN_PROGRAM_ID;
|
|
23295
|
+
}
|
|
23296
|
+
static async getAssociatedTokenAddress(mint, walletAddress, tokenProgramId = splToken.TOKEN_PROGRAM_ID) {
|
|
23297
|
+
const ata = await splToken.getAssociatedTokenAddress(
|
|
23298
|
+
new web3_js.PublicKey(mint),
|
|
23299
|
+
new web3_js.PublicKey(walletAddress),
|
|
23300
|
+
true,
|
|
23301
|
+
tokenProgramId
|
|
23302
|
+
);
|
|
23303
|
+
return ata.toBase58();
|
|
23095
23304
|
}
|
|
23096
23305
|
static buildTransactionInstruction(rawInstructions) {
|
|
23097
23306
|
return rawInstructions.map(
|
|
@@ -23546,7 +23755,7 @@ var SpokeService = class _SpokeService {
|
|
|
23546
23755
|
}
|
|
23547
23756
|
default: {
|
|
23548
23757
|
const exhaustiveCheck = chainType;
|
|
23549
|
-
|
|
23758
|
+
this.config.logger.debug("Unhandled exhaustive case", { value: exhaustiveCheck });
|
|
23550
23759
|
throw new Error(`[getSpokeService] Invalid chain type. Valid chain types: ${ChainTypeArr.join(", ")}`);
|
|
23551
23760
|
}
|
|
23552
23761
|
}
|
|
@@ -23719,7 +23928,7 @@ var SpokeService = class _SpokeService {
|
|
|
23719
23928
|
}
|
|
23720
23929
|
default: {
|
|
23721
23930
|
const exhaustiveCheck = chainType;
|
|
23722
|
-
|
|
23931
|
+
this.config.logger.debug("Unhandled exhaustive case", { value: exhaustiveCheck });
|
|
23723
23932
|
return {
|
|
23724
23933
|
ok: false,
|
|
23725
23934
|
error: new Error(`[estimateGas] Invalid chain type. Valid chain types: ${ChainTypeArr.join(", ")}`)
|
|
@@ -23826,17 +24035,17 @@ var SpokeService = class _SpokeService {
|
|
|
23826
24035
|
args: [params.srcChainId, params.srcAddress, params.payload]
|
|
23827
24036
|
})
|
|
23828
24037
|
});
|
|
23829
|
-
|
|
24038
|
+
this.config.logger.warn("simulateRecvMessage did not revert as expected", { result });
|
|
23830
24039
|
return {
|
|
23831
24040
|
ok: false,
|
|
23832
24041
|
error: new Error('Function should have reverted with "Simulation completed"')
|
|
23833
24042
|
};
|
|
23834
24043
|
} catch (error) {
|
|
23835
24044
|
if (error instanceof Error && error.message?.includes("Simulation completed")) {
|
|
23836
|
-
|
|
24045
|
+
this.config.logger.warn("simulateRecvMessage completed successfully with expected revert");
|
|
23837
24046
|
return { ok: true, value: true };
|
|
23838
24047
|
}
|
|
23839
|
-
|
|
24048
|
+
this.config.logger.error("simulateRecvMessage failed with unexpected error", error);
|
|
23840
24049
|
return { ok: false, error };
|
|
23841
24050
|
}
|
|
23842
24051
|
}
|
|
@@ -23921,7 +24130,7 @@ var SpokeService = class _SpokeService {
|
|
|
23921
24130
|
}
|
|
23922
24131
|
default: {
|
|
23923
24132
|
const exhaustiveCheck = chainType;
|
|
23924
|
-
|
|
24133
|
+
this.config.logger.debug("Unhandled exhaustive case", { value: exhaustiveCheck });
|
|
23925
24134
|
return {
|
|
23926
24135
|
ok: false,
|
|
23927
24136
|
error: new Error(`[deposit] Invalid chain type. Valid chain types: ${ChainTypeArr.join(", ")}`)
|
|
@@ -23998,7 +24207,7 @@ var SpokeService = class _SpokeService {
|
|
|
23998
24207
|
}
|
|
23999
24208
|
default: {
|
|
24000
24209
|
const exhaustiveCheck = chainType;
|
|
24001
|
-
|
|
24210
|
+
this.config.logger.debug("Unhandled exhaustive case", { value: exhaustiveCheck });
|
|
24002
24211
|
return {
|
|
24003
24212
|
ok: false,
|
|
24004
24213
|
error: new Error(`[getDeposit] Invalid chain type. Valid chain types: ${ChainTypeArr.join(", ")}`)
|
|
@@ -24107,7 +24316,7 @@ var SpokeService = class _SpokeService {
|
|
|
24107
24316
|
}
|
|
24108
24317
|
default: {
|
|
24109
24318
|
const exhaustiveCheck = chainType;
|
|
24110
|
-
|
|
24319
|
+
this.config.logger.debug("Unhandled exhaustive case", { value: exhaustiveCheck });
|
|
24111
24320
|
return {
|
|
24112
24321
|
ok: false,
|
|
24113
24322
|
error: new Error(`[sendMessage] Invalid chain type. Valid chain types: ${ChainTypeArr.join(", ")}`)
|
|
@@ -24186,10 +24395,10 @@ var SpokeService = class _SpokeService {
|
|
|
24186
24395
|
if (isSolanaChainKeyType(chainKey)) {
|
|
24187
24396
|
const result = await this.solana.waitForTransactionReceipt({ txHash, chainKey });
|
|
24188
24397
|
if (!result.ok || result.value.status !== "success") {
|
|
24189
|
-
|
|
24398
|
+
this.config.logger.warn(
|
|
24190
24399
|
`Solana verifyTxHash failed: ${!result.ok ? result.error : "error" in result.value ? result.value.error : "unknown"}`
|
|
24191
24400
|
);
|
|
24192
|
-
|
|
24401
|
+
this.config.logger.warn("Returning true to assume transaction exists on chain in future ");
|
|
24193
24402
|
return { ok: true, value: true };
|
|
24194
24403
|
}
|
|
24195
24404
|
return { ok: true, value: true };
|
|
@@ -24276,7 +24485,7 @@ var SpokeService = class _SpokeService {
|
|
|
24276
24485
|
}
|
|
24277
24486
|
default: {
|
|
24278
24487
|
const exhaustiveCheck = chainType;
|
|
24279
|
-
|
|
24488
|
+
this.config.logger.debug("Unhandled exhaustive case", { value: exhaustiveCheck });
|
|
24280
24489
|
return { ok: false, error: new Error(`waitForTransactionReceipt not supported for ${params.chainKey}`) };
|
|
24281
24490
|
}
|
|
24282
24491
|
}
|
|
@@ -25327,6 +25536,7 @@ var EvmHubProvider = class {
|
|
|
25327
25536
|
};
|
|
25328
25537
|
|
|
25329
25538
|
// src/swap/SolverApiService.ts
|
|
25539
|
+
var bigintReplacer = (_key, value) => typeof value === "bigint" ? value.toString() : value;
|
|
25330
25540
|
var SolverApiService = class {
|
|
25331
25541
|
constructor() {
|
|
25332
25542
|
}
|
|
@@ -25395,13 +25605,16 @@ var SolverApiService = class {
|
|
|
25395
25605
|
}
|
|
25396
25606
|
};
|
|
25397
25607
|
} catch (e) {
|
|
25398
|
-
|
|
25608
|
+
configService.logger.error(
|
|
25609
|
+
"[SolverApiService.getQuote] failed",
|
|
25610
|
+
e instanceof Error ? e : new Error(JSON.stringify(e, bigintReplacer))
|
|
25611
|
+
);
|
|
25399
25612
|
return {
|
|
25400
25613
|
ok: false,
|
|
25401
25614
|
error: {
|
|
25402
25615
|
detail: {
|
|
25403
25616
|
code: exports.SolverIntentErrorCode.UNKNOWN,
|
|
25404
|
-
message: e ? JSON.stringify(e) : "Unknown error"
|
|
25617
|
+
message: e ? JSON.stringify(e, bigintReplacer) : "Unknown error"
|
|
25405
25618
|
}
|
|
25406
25619
|
}
|
|
25407
25620
|
};
|
|
@@ -25418,7 +25631,7 @@ var SolverApiService = class {
|
|
|
25418
25631
|
* @param config - Solver endpoint configuration.
|
|
25419
25632
|
* @returns A `Result` containing `{ answer: 'OK', intent_hash: Hex }` on success.
|
|
25420
25633
|
*/
|
|
25421
|
-
static async postExecution(request, config) {
|
|
25634
|
+
static async postExecution(request, config, logger = silentLogger) {
|
|
25422
25635
|
try {
|
|
25423
25636
|
const response = await retry(
|
|
25424
25637
|
() => fetch(`${config.solverApiEndpoint}/execute`, {
|
|
@@ -25440,13 +25653,16 @@ var SolverApiService = class {
|
|
|
25440
25653
|
value: await response.json()
|
|
25441
25654
|
};
|
|
25442
25655
|
} catch (e) {
|
|
25443
|
-
|
|
25656
|
+
logger.error(
|
|
25657
|
+
"[SolverApiService.postExecution] failed",
|
|
25658
|
+
e instanceof Error ? e : new Error(JSON.stringify(e, bigintReplacer))
|
|
25659
|
+
);
|
|
25444
25660
|
return {
|
|
25445
25661
|
ok: false,
|
|
25446
25662
|
error: {
|
|
25447
25663
|
detail: {
|
|
25448
25664
|
code: exports.SolverIntentErrorCode.UNKNOWN,
|
|
25449
|
-
message: e ? JSON.stringify(e) : "Unknown error"
|
|
25665
|
+
message: e ? JSON.stringify(e, bigintReplacer) : "Unknown error"
|
|
25450
25666
|
}
|
|
25451
25667
|
}
|
|
25452
25668
|
};
|
|
@@ -25461,7 +25677,7 @@ var SolverApiService = class {
|
|
|
25461
25677
|
* `fill_tx_hash` is set only when `status === SolverIntentStatusCode.SOLVED (3)`.
|
|
25462
25678
|
* @throws Invariant error if `intent_tx_hash` is empty (thrown before the async request).
|
|
25463
25679
|
*/
|
|
25464
|
-
static async getStatus(request, config) {
|
|
25680
|
+
static async getStatus(request, config, logger = silentLogger) {
|
|
25465
25681
|
invariant(request.intent_tx_hash.length > 0, "Empty intent_tx_hash");
|
|
25466
25682
|
try {
|
|
25467
25683
|
const response = await fetch(`${config.solverApiEndpoint}/status`, {
|
|
@@ -25482,13 +25698,16 @@ var SolverApiService = class {
|
|
|
25482
25698
|
value: await response.json()
|
|
25483
25699
|
};
|
|
25484
25700
|
} catch (e) {
|
|
25485
|
-
|
|
25701
|
+
logger.error(
|
|
25702
|
+
"[SolverApiService.getStatus] failed",
|
|
25703
|
+
e instanceof Error ? e : new Error(JSON.stringify(e, bigintReplacer))
|
|
25704
|
+
);
|
|
25486
25705
|
return {
|
|
25487
25706
|
ok: false,
|
|
25488
25707
|
error: {
|
|
25489
25708
|
detail: {
|
|
25490
25709
|
code: exports.SolverIntentErrorCode.UNKNOWN,
|
|
25491
|
-
message: e ? JSON.stringify(e) : "Unknown error"
|
|
25710
|
+
message: e ? JSON.stringify(e, bigintReplacer) : "Unknown error"
|
|
25492
25711
|
}
|
|
25493
25712
|
}
|
|
25494
25713
|
};
|
|
@@ -25608,7 +25827,7 @@ var SwapService = class {
|
|
|
25608
25827
|
* `fill_tx_hash` is populated only when `status === SolverIntentStatusCode.SOLVED (3)`.
|
|
25609
25828
|
*/
|
|
25610
25829
|
async getStatus(request) {
|
|
25611
|
-
return SolverApiService.getStatus(request, this.solver);
|
|
25830
|
+
return SolverApiService.getStatus(request, this.solver, this.config.logger);
|
|
25612
25831
|
}
|
|
25613
25832
|
/**
|
|
25614
25833
|
* Notifies the solver API that an intent has been registered on the hub chain, triggering
|
|
@@ -25631,7 +25850,7 @@ var SwapService = class {
|
|
|
25631
25850
|
*/
|
|
25632
25851
|
async postExecution(request) {
|
|
25633
25852
|
try {
|
|
25634
|
-
const result = await SolverApiService.postExecution(request, this.solver);
|
|
25853
|
+
const result = await SolverApiService.postExecution(request, this.solver, this.config.logger);
|
|
25635
25854
|
if (result.ok) return result;
|
|
25636
25855
|
const detail = result.error?.detail ?? {
|
|
25637
25856
|
code: -999,
|
|
@@ -25904,7 +26123,7 @@ var SwapService = class {
|
|
|
25904
26123
|
* - `raw: false` — broadcasts the transaction; `walletProvider` is required and must match `K`.
|
|
25905
26124
|
*
|
|
25906
26125
|
* Validates tokens and chain keys against the active `ConfigService` before constructing the
|
|
25907
|
-
* intent. Bitcoin source chains require an additional
|
|
26126
|
+
* intent. Bitcoin source chains require an additional Bound Exchange access token step.
|
|
25908
26127
|
*
|
|
25909
26128
|
* @param _params - Intent parameters, source chain key, wallet provider (when `raw: false`),
|
|
25910
26129
|
* and optional `skipSimulation` flag.
|
|
@@ -28385,11 +28604,13 @@ var MigrationService = class {
|
|
|
28385
28604
|
|
|
28386
28605
|
// src/backendApi/BackendApiService.ts
|
|
28387
28606
|
var BackendApiService = class {
|
|
28388
|
-
constructor(config) {
|
|
28607
|
+
constructor(config, logger = consoleLogger) {
|
|
28389
28608
|
this.config = config;
|
|
28390
28609
|
this.headers = { ...config.headers };
|
|
28610
|
+
this.logger = logger;
|
|
28391
28611
|
}
|
|
28392
28612
|
headers;
|
|
28613
|
+
logger;
|
|
28393
28614
|
/**
|
|
28394
28615
|
* Execute a single HTTP request and return the parsed JSON body.
|
|
28395
28616
|
*
|
|
@@ -28428,10 +28649,10 @@ var BackendApiService = class {
|
|
|
28428
28649
|
if (error.name === "AbortError") {
|
|
28429
28650
|
throw new Error("REQUEST_TIMEOUT", { cause: new Error(`Request timeout after ${timeout}ms`) });
|
|
28430
28651
|
}
|
|
28431
|
-
|
|
28652
|
+
this.logger.error("[BackendApiService] Request error", error);
|
|
28432
28653
|
throw error;
|
|
28433
28654
|
}
|
|
28434
|
-
|
|
28655
|
+
this.logger.error("[BackendApiService] Unknown error", error);
|
|
28435
28656
|
throw new Error("UNKNOWN_REQUEST_ERROR", { cause: error });
|
|
28436
28657
|
}
|
|
28437
28658
|
}
|
|
@@ -29101,7 +29322,7 @@ var BridgeService = class {
|
|
|
29101
29322
|
* transaction simulation or batching). When `raw` is `false`, signs and submits the deposit
|
|
29102
29323
|
* transaction via the provided wallet provider.
|
|
29103
29324
|
*
|
|
29104
|
-
* Bitcoin is only supported with `raw: false` because it requires the
|
|
29325
|
+
* Bitcoin is only supported with `raw: false` because it requires the Bound Exchange trading wallet
|
|
29105
29326
|
* derivation flow.
|
|
29106
29327
|
*
|
|
29107
29328
|
* @param _params - Bridge parameters including source/destination chain keys, token addresses,
|
|
@@ -29134,9 +29355,12 @@ var BridgeService = class {
|
|
|
29134
29355
|
{ ...baseCtx, field: "walletProvider" }
|
|
29135
29356
|
);
|
|
29136
29357
|
walletAddress = await this.spoke.bitcoin.getEffectiveWalletAddress(personalAddress);
|
|
29137
|
-
|
|
29358
|
+
if (this.spoke.bitcoin.walletMode === "TRADING") {
|
|
29359
|
+
await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(_params.walletProvider);
|
|
29360
|
+
}
|
|
29138
29361
|
}
|
|
29139
|
-
const hubWallet = await this.hubProvider.getUserHubWalletAddress(
|
|
29362
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(walletAddress, params.srcChainKey);
|
|
29363
|
+
const effectiveSkipSimulation = skipSimulation || isBitcoinChainKeyType(params.srcChainKey) && this.spoke.bitcoin.walletMode === "USER";
|
|
29140
29364
|
const data = this.buildBridgeData(params, srcToken, dstToken, this.config.bridge.partnerFee);
|
|
29141
29365
|
const coreParams = {
|
|
29142
29366
|
srcChainKey: params.srcChainKey,
|
|
@@ -29145,7 +29369,7 @@ var BridgeService = class {
|
|
|
29145
29369
|
token: params.srcToken,
|
|
29146
29370
|
amount: params.amount,
|
|
29147
29371
|
data,
|
|
29148
|
-
skipSimulation
|
|
29372
|
+
skipSimulation: effectiveSkipSimulation
|
|
29149
29373
|
};
|
|
29150
29374
|
const txResult = await this.spoke.deposit(
|
|
29151
29375
|
_params.raw ? {
|
|
@@ -29158,7 +29382,7 @@ var BridgeService = class {
|
|
|
29158
29382
|
}
|
|
29159
29383
|
);
|
|
29160
29384
|
if (!txResult.ok) {
|
|
29161
|
-
|
|
29385
|
+
this.config.logger.error("createBridgeIntent failed", txResult.error);
|
|
29162
29386
|
if (isBridgeCreateIntentError(txResult.error)) return { ok: false, error: txResult.error };
|
|
29163
29387
|
return {
|
|
29164
29388
|
ok: false,
|
|
@@ -29173,7 +29397,7 @@ var BridgeService = class {
|
|
|
29173
29397
|
}
|
|
29174
29398
|
};
|
|
29175
29399
|
} catch (error) {
|
|
29176
|
-
|
|
29400
|
+
this.config.logger.error("createBridgeIntent failed", error);
|
|
29177
29401
|
if (isBridgeCreateIntentError(error)) return { ok: false, error };
|
|
29178
29402
|
return {
|
|
29179
29403
|
ok: false,
|
|
@@ -29343,7 +29567,7 @@ var BridgeService = class {
|
|
|
29343
29567
|
value: availableDepositNormalised.isLessThan(assetManagerBalanceNormalised) ? { amount: availableDeposit, decimals: fromTokenInfo.decimals, type: "DEPOSIT_LIMIT" } : { amount: assetManagerBalance, decimals: toTokenInfo.decimals, type: "WITHDRAWAL_LIMIT" }
|
|
29344
29568
|
};
|
|
29345
29569
|
} catch (error) {
|
|
29346
|
-
|
|
29570
|
+
this.config.logger.error("getBridgeableAmount failed", error);
|
|
29347
29571
|
if (isBridgeLookupError(error)) return { ok: false, error };
|
|
29348
29572
|
return {
|
|
29349
29573
|
ok: false,
|
|
@@ -29390,7 +29614,7 @@ var BridgeService = class {
|
|
|
29390
29614
|
});
|
|
29391
29615
|
return srcToken.vault.toLowerCase() === dstToken.vault.toLowerCase();
|
|
29392
29616
|
} catch (error) {
|
|
29393
|
-
|
|
29617
|
+
this.config.logger.error("isBridgeable check failed", error);
|
|
29394
29618
|
return false;
|
|
29395
29619
|
}
|
|
29396
29620
|
}
|
|
@@ -31780,7 +32004,7 @@ var ClService = class _ClService {
|
|
|
31780
32004
|
};
|
|
31781
32005
|
const txResult = await this.spoke.sendMessage(sendMessageParams);
|
|
31782
32006
|
if (!txResult.ok) {
|
|
31783
|
-
|
|
32007
|
+
this.config.logger.error("executeSupplyLiquidity error", txResult.error);
|
|
31784
32008
|
return {
|
|
31785
32009
|
ok: false,
|
|
31786
32010
|
error: txResult.error
|
|
@@ -31794,7 +32018,7 @@ var ClService = class _ClService {
|
|
|
31794
32018
|
}
|
|
31795
32019
|
};
|
|
31796
32020
|
} catch (error) {
|
|
31797
|
-
|
|
32021
|
+
this.config.logger.error("executeSupplyLiquidity error", error);
|
|
31798
32022
|
return {
|
|
31799
32023
|
ok: false,
|
|
31800
32024
|
error
|
|
@@ -32067,7 +32291,7 @@ var ClService = class _ClService {
|
|
|
32067
32291
|
}
|
|
32068
32292
|
return { ok: true, value: { srcChainTxHash: txResult.value.tx, dstChainTxHash: hubTxHash } };
|
|
32069
32293
|
} catch (error) {
|
|
32070
|
-
|
|
32294
|
+
this.config.logger.error("supplyLiquidity error", error);
|
|
32071
32295
|
return {
|
|
32072
32296
|
ok: false,
|
|
32073
32297
|
error
|
|
@@ -32211,7 +32435,7 @@ var ClService = class _ClService {
|
|
|
32211
32435
|
}
|
|
32212
32436
|
};
|
|
32213
32437
|
} catch (error) {
|
|
32214
|
-
|
|
32438
|
+
this.config.logger.error("getPoolRewardConfig error", error);
|
|
32215
32439
|
return {
|
|
32216
32440
|
ok: false,
|
|
32217
32441
|
error: lookupFailed("dex", "getPoolRewardConfig", error)
|
|
@@ -32272,7 +32496,7 @@ var ClService = class _ClService {
|
|
|
32272
32496
|
};
|
|
32273
32497
|
const txResult = await this.spoke.sendMessage(sendMessageParams);
|
|
32274
32498
|
if (!txResult.ok) {
|
|
32275
|
-
|
|
32499
|
+
this.config.logger.error("executeClaimRewards error", txResult.error);
|
|
32276
32500
|
return {
|
|
32277
32501
|
ok: false,
|
|
32278
32502
|
error: txResult.error
|
|
@@ -32286,7 +32510,7 @@ var ClService = class _ClService {
|
|
|
32286
32510
|
}
|
|
32287
32511
|
};
|
|
32288
32512
|
} catch (error) {
|
|
32289
|
-
|
|
32513
|
+
this.config.logger.error("executeClaimRewards error", error);
|
|
32290
32514
|
return {
|
|
32291
32515
|
ok: false,
|
|
32292
32516
|
error
|
|
@@ -32328,7 +32552,7 @@ var ClService = class _ClService {
|
|
|
32328
32552
|
}
|
|
32329
32553
|
return { ok: true, value: { srcChainTxHash: txResult.value.tx, dstChainTxHash: hubTxHash } };
|
|
32330
32554
|
} catch (error) {
|
|
32331
|
-
|
|
32555
|
+
this.config.logger.error("claimRewards error", error);
|
|
32332
32556
|
return {
|
|
32333
32557
|
ok: false,
|
|
32334
32558
|
error
|
|
@@ -32376,7 +32600,7 @@ var ClService = class _ClService {
|
|
|
32376
32600
|
address: tokenAddress
|
|
32377
32601
|
};
|
|
32378
32602
|
} catch (error) {
|
|
32379
|
-
|
|
32603
|
+
this.config.logger.error(`Failed to fetch token info for ${tokenAddress}`, error);
|
|
32380
32604
|
return {
|
|
32381
32605
|
symbol: "UNKNOWN",
|
|
32382
32606
|
name: "Unknown Token",
|
|
@@ -32401,12 +32625,12 @@ var ClService = class _ClService {
|
|
|
32401
32625
|
const oneShare = BigInt(10 ** 18);
|
|
32402
32626
|
const result = await Erc4626Service.convertToAssets(statATokenAddress, oneShare, this.hubProvider.publicClient);
|
|
32403
32627
|
if (!result.ok) {
|
|
32404
|
-
|
|
32628
|
+
this.config.logger.error("[getStatATokenConversionRate] Failed to get conversion rate", result.error);
|
|
32405
32629
|
return oneShare;
|
|
32406
32630
|
}
|
|
32407
32631
|
return result.value;
|
|
32408
32632
|
} catch (error) {
|
|
32409
|
-
|
|
32633
|
+
this.config.logger.error("[getStatATokenConversionRate] Error", error);
|
|
32410
32634
|
return BigInt(10 ** 18);
|
|
32411
32635
|
}
|
|
32412
32636
|
}
|
|
@@ -32443,7 +32667,7 @@ var ClService = class _ClService {
|
|
|
32443
32667
|
underlyingToken
|
|
32444
32668
|
};
|
|
32445
32669
|
} catch (error) {
|
|
32446
|
-
|
|
32670
|
+
this.config.logger.error(`[getTokenEnrichmentData] Failed to enrich token ${token.address}`, error);
|
|
32447
32671
|
return {
|
|
32448
32672
|
token,
|
|
32449
32673
|
isStatAToken: true
|
|
@@ -32513,7 +32737,7 @@ var ClService = class _ClService {
|
|
|
32513
32737
|
rewardConfig = rewardConfigResult.value;
|
|
32514
32738
|
}
|
|
32515
32739
|
} catch (error) {
|
|
32516
|
-
|
|
32740
|
+
this.config.logger.warn("Failed to fetch reward config for pool", { error });
|
|
32517
32741
|
}
|
|
32518
32742
|
}
|
|
32519
32743
|
return {
|
|
@@ -32549,7 +32773,7 @@ var ClService = class _ClService {
|
|
|
32549
32773
|
}
|
|
32550
32774
|
};
|
|
32551
32775
|
} catch (error) {
|
|
32552
|
-
|
|
32776
|
+
this.config.logger.error("Failed to fetch pool data", error);
|
|
32553
32777
|
return {
|
|
32554
32778
|
ok: false,
|
|
32555
32779
|
error: lookupFailed("dex", "getPoolData", error)
|
|
@@ -35333,14 +35557,25 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35333
35557
|
);
|
|
35334
35558
|
const dstChainKey = params.dstChainKey ?? srcChainKey;
|
|
35335
35559
|
const dstAddress = params.dstAddress ?? params.srcAddress;
|
|
35336
|
-
const
|
|
35337
|
-
|
|
35338
|
-
|
|
35339
|
-
|
|
35560
|
+
const isBitcoinSrc = isBitcoinChainKeyType(srcChainKey);
|
|
35561
|
+
if (isBitcoinSrc && !_params.raw) {
|
|
35562
|
+
mmInvariant(
|
|
35563
|
+
walletProvider !== void 0 && isBitcoinWalletProviderType(walletProvider),
|
|
35564
|
+
`Invalid wallet provider for chain key: ${srcChainKey}. Expected bitcoin wallet provider.`,
|
|
35565
|
+
{ ...baseCtx, field: "walletProvider" }
|
|
35566
|
+
);
|
|
35567
|
+
await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(walletProvider);
|
|
35568
|
+
}
|
|
35569
|
+
const srcEffectiveAddress = isBitcoinSrc ? await this.spoke.bitcoin.getEffectiveWalletAddress(params.srcAddress) : params.srcAddress;
|
|
35570
|
+
const fromHubWallet = await this.hubProvider.getUserHubWalletAddress(srcEffectiveAddress, srcChainKey);
|
|
35571
|
+
const toHubWallet = dstChainKey === srcChainKey && dstAddress === params.srcAddress ? fromHubWallet : await this.hubProvider.getUserHubWalletAddress(
|
|
35572
|
+
isBitcoinChainKeyType(dstChainKey) ? await this.spoke.bitcoin.getEffectiveWalletAddress(dstAddress) : dstAddress,
|
|
35573
|
+
dstChainKey
|
|
35574
|
+
);
|
|
35340
35575
|
const data = this.buildSupplyData(srcChainKey, params.token, params.amount, toHubWallet);
|
|
35341
35576
|
const coreParams = {
|
|
35342
35577
|
srcChainKey,
|
|
35343
|
-
srcAddress:
|
|
35578
|
+
srcAddress: srcEffectiveAddress,
|
|
35344
35579
|
to: fromHubWallet,
|
|
35345
35580
|
token: params.token,
|
|
35346
35581
|
amount: params.amount,
|
|
@@ -35380,6 +35615,17 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35380
35615
|
}
|
|
35381
35616
|
}
|
|
35382
35617
|
// ==== borrow ==========================================================================
|
|
35618
|
+
/**
|
|
35619
|
+
* Build the relay submit/poll identity for a money-market borrow/withdraw.
|
|
35620
|
+
*
|
|
35621
|
+
* Bitcoin borrow/withdraw are on-demand: the spoke result is a signed payload JSON that the relay
|
|
35622
|
+
* submits under the literal "withdraw" tx_hash and tracks under a derived `od:<hash>` poll id
|
|
35623
|
+
* (see {@link BitcoinSpokeService.getOnDemandRelayIdentity}). Every other chain relays and polls by
|
|
35624
|
+
* its real spoke tx hash, so `pollTxHash` is undefined and `srcChainTxHash` stays the spoke tx.
|
|
35625
|
+
*/
|
|
35626
|
+
buildRelayIdentity(srcChainKey, tx, relayData) {
|
|
35627
|
+
return isBitcoinChainKeyType(srcChainKey) ? this.spoke.bitcoin.getOnDemandRelayIdentity(tx) : { srcTxHash: tx, data: relayData, pollTxHash: void 0 };
|
|
35628
|
+
}
|
|
35383
35629
|
/**
|
|
35384
35630
|
* Borrow tokens from the money market lending pool and wait for the cross-chain relay to
|
|
35385
35631
|
* deliver the funds to the destination address.
|
|
@@ -35415,9 +35661,9 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35415
35661
|
value: { srcChainTxHash: txResult.value.tx, dstChainTxHash: txResult.value.tx }
|
|
35416
35662
|
};
|
|
35417
35663
|
}
|
|
35664
|
+
const relayIdentity = this.buildRelayIdentity(srcChainKey, txResult.value.tx, txResult.value.relayData);
|
|
35418
35665
|
const packet = await relayTxAndWaitPacket({
|
|
35419
|
-
|
|
35420
|
-
data: txResult.value.relayData,
|
|
35666
|
+
...relayIdentity,
|
|
35421
35667
|
chainKey: srcChainKey,
|
|
35422
35668
|
relayerApiEndpoint: this.relayerApiEndpoint,
|
|
35423
35669
|
timeout
|
|
@@ -35432,7 +35678,13 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35432
35678
|
dstChainKey: baseCtx.dstChainKey
|
|
35433
35679
|
})
|
|
35434
35680
|
};
|
|
35435
|
-
return {
|
|
35681
|
+
return {
|
|
35682
|
+
ok: true,
|
|
35683
|
+
value: {
|
|
35684
|
+
srcChainTxHash: relayIdentity.pollTxHash ?? txResult.value.tx,
|
|
35685
|
+
dstChainTxHash: packet.value.dst_tx_hash
|
|
35686
|
+
}
|
|
35687
|
+
};
|
|
35436
35688
|
} catch (error) {
|
|
35437
35689
|
if (isMoneyMarketOrchestrationError(error)) return { ok: false, error };
|
|
35438
35690
|
return {
|
|
@@ -35474,7 +35726,8 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35474
35726
|
field: "token"
|
|
35475
35727
|
});
|
|
35476
35728
|
const encodedDstAddress = encodeAddress(dstChainKey, dstAddress);
|
|
35477
|
-
const
|
|
35729
|
+
const srcEffectiveAddress = isBitcoinChainKeyType(srcChainKey) ? await this.spoke.bitcoin.getEffectiveWalletAddress(params.srcAddress) : params.srcAddress;
|
|
35730
|
+
const fromHubWallet = await this.hubProvider.getUserHubWalletAddress(srcEffectiveAddress, srcChainKey);
|
|
35478
35731
|
const payload = this.buildBorrowData(
|
|
35479
35732
|
fromHubWallet,
|
|
35480
35733
|
encodedDstAddress,
|
|
@@ -35558,9 +35811,9 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35558
35811
|
value: { srcChainTxHash: txResult.value.tx, dstChainTxHash: txResult.value.tx }
|
|
35559
35812
|
};
|
|
35560
35813
|
}
|
|
35814
|
+
const relayIdentity = this.buildRelayIdentity(srcChainKey, txResult.value.tx, txResult.value.relayData);
|
|
35561
35815
|
const packet = await relayTxAndWaitPacket({
|
|
35562
|
-
|
|
35563
|
-
data: txResult.value.relayData,
|
|
35816
|
+
...relayIdentity,
|
|
35564
35817
|
chainKey: srcChainKey,
|
|
35565
35818
|
relayerApiEndpoint: this.relayerApiEndpoint,
|
|
35566
35819
|
timeout
|
|
@@ -35575,7 +35828,13 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35575
35828
|
dstChainKey: baseCtx.dstChainKey
|
|
35576
35829
|
})
|
|
35577
35830
|
};
|
|
35578
|
-
return {
|
|
35831
|
+
return {
|
|
35832
|
+
ok: true,
|
|
35833
|
+
value: {
|
|
35834
|
+
srcChainTxHash: relayIdentity.pollTxHash ?? txResult.value.tx,
|
|
35835
|
+
dstChainTxHash: packet.value.dst_tx_hash
|
|
35836
|
+
}
|
|
35837
|
+
};
|
|
35579
35838
|
} catch (error) {
|
|
35580
35839
|
if (isMoneyMarketOrchestrationError(error)) return { ok: false, error };
|
|
35581
35840
|
return {
|
|
@@ -35617,7 +35876,8 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35617
35876
|
{ ...baseCtx, field: "token" }
|
|
35618
35877
|
);
|
|
35619
35878
|
const encodedDstAddress = encodeAddress(dstChainKey, dstAddress);
|
|
35620
|
-
const
|
|
35879
|
+
const srcEffectiveAddress = isBitcoinChainKeyType(srcChainKey) ? await this.spoke.bitcoin.getEffectiveWalletAddress(params.srcAddress) : params.srcAddress;
|
|
35880
|
+
const fromHubWallet = await this.hubProvider.getUserHubWalletAddress(srcEffectiveAddress, srcChainKey);
|
|
35621
35881
|
const payload = this.buildWithdrawData(
|
|
35622
35882
|
fromHubWallet,
|
|
35623
35883
|
encodedDstAddress,
|
|
@@ -35754,14 +36014,25 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
35754
36014
|
);
|
|
35755
36015
|
const dstChainKey = params.dstChainKey ?? srcChainKey;
|
|
35756
36016
|
const dstAddress = params.dstAddress ?? params.srcAddress;
|
|
35757
|
-
const
|
|
35758
|
-
|
|
35759
|
-
|
|
35760
|
-
|
|
36017
|
+
const isBitcoinSrc = isBitcoinChainKeyType(srcChainKey);
|
|
36018
|
+
if (isBitcoinSrc && !_params.raw) {
|
|
36019
|
+
mmInvariant(
|
|
36020
|
+
walletProvider !== void 0 && isBitcoinWalletProviderType(walletProvider),
|
|
36021
|
+
`Invalid wallet provider for chain key: ${srcChainKey}. Expected bitcoin wallet provider.`,
|
|
36022
|
+
{ ...baseCtx, field: "walletProvider" }
|
|
36023
|
+
);
|
|
36024
|
+
await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(walletProvider);
|
|
36025
|
+
}
|
|
36026
|
+
const srcEffectiveAddress = isBitcoinSrc ? await this.spoke.bitcoin.getEffectiveWalletAddress(params.srcAddress) : params.srcAddress;
|
|
36027
|
+
const fromHubWallet = await this.hubProvider.getUserHubWalletAddress(srcEffectiveAddress, srcChainKey);
|
|
36028
|
+
const toHubWallet = dstChainKey === srcChainKey && dstAddress === params.srcAddress ? fromHubWallet : await this.hubProvider.getUserHubWalletAddress(
|
|
36029
|
+
isBitcoinChainKeyType(dstChainKey) ? await this.spoke.bitcoin.getEffectiveWalletAddress(dstAddress) : dstAddress,
|
|
36030
|
+
dstChainKey
|
|
36031
|
+
);
|
|
35761
36032
|
const data = this.buildRepayData(srcChainKey, params.token, params.amount, toHubWallet);
|
|
35762
36033
|
const coreParams = {
|
|
35763
36034
|
srcChainKey,
|
|
35764
|
-
srcAddress:
|
|
36035
|
+
srcAddress: srcEffectiveAddress,
|
|
35765
36036
|
to: fromHubWallet,
|
|
35766
36037
|
token: params.token,
|
|
35767
36038
|
amount: params.amount,
|
|
@@ -36322,9 +36593,9 @@ var PartnerFeeClaimService = class {
|
|
|
36322
36593
|
if (typeof balanceResult === "bigint") {
|
|
36323
36594
|
balance = balanceResult;
|
|
36324
36595
|
} else {
|
|
36325
|
-
|
|
36326
|
-
`[PartnerFeeClaimService] Unexpected balance result format for ${entry.hubAsset.symbol} (${entry.assetAddress})
|
|
36327
|
-
balanceResult
|
|
36596
|
+
this.config.logger.warn(
|
|
36597
|
+
`[PartnerFeeClaimService] Unexpected balance result format for ${entry.hubAsset.symbol} (${entry.assetAddress})`,
|
|
36598
|
+
{ balanceResult }
|
|
36328
36599
|
);
|
|
36329
36600
|
balance = 0n;
|
|
36330
36601
|
}
|
|
@@ -36660,7 +36931,8 @@ var PartnerFeeClaimService = class {
|
|
|
36660
36931
|
}
|
|
36661
36932
|
const solverExecutionResponse = await SolverApiService.postExecution(
|
|
36662
36933
|
{ intent_tx_hash: intentTxHash },
|
|
36663
|
-
this.config.solver
|
|
36934
|
+
this.config.solver,
|
|
36935
|
+
this.config.logger
|
|
36664
36936
|
);
|
|
36665
36937
|
if (!solverExecutionResponse.ok) {
|
|
36666
36938
|
return solverExecutionResponse;
|
|
@@ -36871,9 +37143,10 @@ var Sodax = class {
|
|
|
36871
37143
|
spoke;
|
|
36872
37144
|
// spoke service enabling spoke chain operations
|
|
36873
37145
|
constructor(config) {
|
|
37146
|
+
const logger = resolveLogger(config?.logger);
|
|
36874
37147
|
this.instanceConfig = config ? mergeSodaxConfig(sodaxConfig, config) : sodaxConfig;
|
|
36875
|
-
this.backendApi = new BackendApiService(this.instanceConfig.api);
|
|
36876
|
-
this.config = new ConfigService({ api: this.backendApi, config: this.instanceConfig, userConfig: config });
|
|
37148
|
+
this.backendApi = new BackendApiService(this.instanceConfig.api, logger);
|
|
37149
|
+
this.config = new ConfigService({ api: this.backendApi, config: this.instanceConfig, userConfig: config, logger });
|
|
36877
37150
|
this.hubProvider = new EvmHubProvider({ config: this.config });
|
|
36878
37151
|
this.spoke = new SpokeService({ config: this.config, hubProvider: this.hubProvider });
|
|
36879
37152
|
this.swaps = new SwapService({
|
|
@@ -37026,6 +37299,7 @@ exports.MoneyMarketService = MoneyMarketService;
|
|
|
37026
37299
|
exports.NEAR_CHAIN_KEYS = NEAR_CHAIN_KEYS;
|
|
37027
37300
|
exports.NEAR_CHAIN_KEYS_SET = NEAR_CHAIN_KEYS_SET;
|
|
37028
37301
|
exports.NEAR_DEFAULT_GAS = NEAR_DEFAULT_GAS;
|
|
37302
|
+
exports.NEAR_STORAGE_DEPOSIT = NEAR_STORAGE_DEPOSIT;
|
|
37029
37303
|
exports.NearSpokeService = NearSpokeService;
|
|
37030
37304
|
exports.PartnerFeeClaimService = PartnerFeeClaimService;
|
|
37031
37305
|
exports.PartnerService = PartnerService;
|
|
@@ -37089,6 +37363,7 @@ exports.bnUSDLegacyTokens = bnUSDLegacyTokens;
|
|
|
37089
37363
|
exports.bridgeConfig = bridgeConfig;
|
|
37090
37364
|
exports.bridgeInvariant = bridgeInvariant;
|
|
37091
37365
|
exports.bscSupportedTokens = bscSupportedTokens;
|
|
37366
|
+
exports.calcOpReturnOutputVbytes = calcOpReturnOutputVbytes;
|
|
37092
37367
|
exports.calculateAllReserveIncentives = calculateAllReserveIncentives;
|
|
37093
37368
|
exports.calculateAllUserIncentives = calculateAllUserIncentives;
|
|
37094
37369
|
exports.calculateAvailableBorrowsMarketReferenceCurrency = calculateAvailableBorrowsMarketReferenceCurrency;
|
|
@@ -37107,6 +37382,7 @@ exports.clRouterAbi = clRouterAbi;
|
|
|
37107
37382
|
exports.clTickLensAbi = clTickLensAbi;
|
|
37108
37383
|
exports.concentratedLiquidityConfig = concentratedLiquidityConfig;
|
|
37109
37384
|
exports.connectionAbi = connectionAbi;
|
|
37385
|
+
exports.consoleLogger = consoleLogger;
|
|
37110
37386
|
exports.convertTransactionInstructionToRaw = convertTransactionInstructionToRaw;
|
|
37111
37387
|
exports.createInvariant = createInvariant;
|
|
37112
37388
|
exports.deepMerge = deepMerge;
|
|
@@ -37283,6 +37559,7 @@ exports.newbnUSDSpokeChainIds = newbnUSDSpokeChainIds;
|
|
|
37283
37559
|
exports.normalize = normalize;
|
|
37284
37560
|
exports.normalizeBN = normalizeBN;
|
|
37285
37561
|
exports.normalizePsbtToBase64 = normalizePsbtToBase64;
|
|
37562
|
+
exports.normalizeSignatureToBase64 = normalizeSignatureToBase64;
|
|
37286
37563
|
exports.normalizedToUsd = normalizedToUsd;
|
|
37287
37564
|
exports.optimismSupportedTokens = optimismSupportedTokens;
|
|
37288
37565
|
exports.pancakeSwapInfinityDefaultHookAbi = pancakeSwapInfinityDefaultHookAbi;
|
|
@@ -37307,9 +37584,11 @@ exports.relayTxAndWaitPacket = relayTxAndWaitPacket;
|
|
|
37307
37584
|
exports.requestAddress = requestAddress;
|
|
37308
37585
|
exports.requestJsonRpc = requestJsonRpc;
|
|
37309
37586
|
exports.requestSigning = requestSigning;
|
|
37587
|
+
exports.resolveLogger = resolveLogger;
|
|
37310
37588
|
exports.retry = retry;
|
|
37311
37589
|
exports.reverseEncodeAddress = reverseEncodeAddress;
|
|
37312
37590
|
exports.serializeAddressData = serializeAddressData;
|
|
37591
|
+
exports.silentLogger = silentLogger;
|
|
37313
37592
|
exports.sleep = sleep;
|
|
37314
37593
|
exports.sodaxConfig = sodaxConfig;
|
|
37315
37594
|
exports.sodaxInvariant = sodaxInvariant;
|
|
@@ -37337,6 +37616,7 @@ exports.swapsConfig = swapsConfig;
|
|
|
37337
37616
|
exports.uiPoolDataAbi = uiPoolDataAbi;
|
|
37338
37617
|
exports.universalRouterAbi = universalRouterAbi;
|
|
37339
37618
|
exports.unknownFailed = unknownFailed;
|
|
37619
|
+
exports.usesBip322MessageSigning = usesBip322MessageSigning;
|
|
37340
37620
|
exports.valueToBigNumber = valueToBigNumber;
|
|
37341
37621
|
exports.valueToZDBigNumber = valueToZDBigNumber;
|
|
37342
37622
|
exports.variableDebtTokenAbi = variableDebtTokenAbi;
|