@mycelium-sdk/core 1.0.0-alpha.0 → 1.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -348,9 +348,9 @@ var DefaultSmartWallet = class extends SmartWallet {
348
348
  * @param amount Human-readable amount string
349
349
  * @returns Transaction result for the deposit
350
350
  */
351
- async earn(amount) {
351
+ async earn(vaultInfo, amount) {
352
352
  this.chainManager.getSupportedChain();
353
- const depositTransactionResult = this.protocolProvider.deposit(amount, this);
353
+ const depositTransactionResult = this.protocolProvider.deposit(vaultInfo, amount, this);
354
354
  return depositTransactionResult;
355
355
  }
356
356
  /**
@@ -361,13 +361,9 @@ var DefaultSmartWallet = class extends SmartWallet {
361
361
  * @category Earn
362
362
  * @returns Vault balance or `null` if nothing deposited
363
363
  */
364
- async getEarnBalance() {
365
- const depositedVault = await this.protocolProvider.fetchDepositedVaults(this);
366
- if (!depositedVault) {
367
- return null;
368
- }
364
+ async getEarnBalances() {
369
365
  const userAddress = await this.getAddress();
370
- return this.protocolProvider.getBalance(depositedVault, userAddress);
366
+ return this.protocolProvider.getBalances(userAddress);
371
367
  }
372
368
  /**
373
369
  * Withdraws from the selected protocol’s vault
@@ -378,8 +374,8 @@ var DefaultSmartWallet = class extends SmartWallet {
378
374
  * @throws Error if the withdrawal fails
379
375
  * @throws Error a user didn't deposit anything
380
376
  */
381
- async withdraw(amount) {
382
- const withdrawTransactionResult = await this.protocolProvider.withdraw(amount, this);
377
+ async withdraw(vaultInfo, amount) {
378
+ const withdrawTransactionResult = await this.protocolProvider.withdraw(vaultInfo, amount, this);
383
379
  return withdrawTransactionResult;
384
380
  }
385
381
  /**
@@ -416,7 +412,7 @@ var DefaultSmartWallet = class extends SmartWallet {
416
412
  return hash;
417
413
  } catch (error) {
418
414
  throw new Error(
419
- `Failed to send transaction: ${error instanceof Error ? error.message : "Unknown error"}`
415
+ `Failed to send transaction: ${error instanceof Error ? error.message.toString().slice(0, 100) : "Unknown error"}`
420
416
  );
421
417
  }
422
418
  }
@@ -639,127 +635,6 @@ var chainById = Object.values(viemChains).reduce(
639
635
  {}
640
636
  );
641
637
 
642
- // src/types/logger.ts
643
- var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
644
- LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
645
- LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
646
- LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
647
- LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
648
- return LogLevel2;
649
- })(LogLevel || {});
650
-
651
- // src/tools/Logger.ts
652
- var Logger = class _Logger {
653
- /**
654
- * Create a new logger instance
655
- * @param logLevel Initial log level, defaults to DEBUG
656
- */
657
- constructor(logLevel = 0 /* DEBUG */) {
658
- this.logs = [];
659
- this.maxLogs = 1e3;
660
- this.logLevel = logLevel;
661
- }
662
- /**
663
- * Get singleton instance of the logger
664
- * @param logLevel Optional log level to initialize if instance not yet created
665
- * @returns Logger instance
666
- */
667
- static getInstance(logLevel) {
668
- if (!_Logger.instance) {
669
- _Logger.instance = new _Logger(logLevel);
670
- }
671
- return _Logger.instance;
672
- }
673
- /** Set the log level */
674
- setLogLevel(level) {
675
- this.logLevel = level;
676
- }
677
- /** Get the current log level */
678
- getLogLevel() {
679
- return this.logLevel;
680
- }
681
- /** Internal check if a message should be logged */
682
- shouldLog(level) {
683
- return level >= this.logLevel;
684
- }
685
- /** Format log message into a readable string */
686
- formatMessage(level, message, data, context) {
687
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
688
- const levelName = LogLevel[level];
689
- const contextStr = context ? `[${context}]` : "";
690
- return `${timestamp} ${levelName}${contextStr}: ${message}`;
691
- }
692
- /** Add a log entry and output to console */
693
- addLog(level, message, data, context) {
694
- if (!this.shouldLog(level)) {
695
- return;
696
- }
697
- const logEntry = {
698
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
699
- level,
700
- message,
701
- data,
702
- context
703
- };
704
- this.logs.push(logEntry);
705
- if (this.logs.length > this.maxLogs) {
706
- this.logs = this.logs.slice(-this.maxLogs);
707
- }
708
- const formattedMessage = this.formatMessage(level, message, data, context);
709
- switch (level) {
710
- case 0 /* DEBUG */:
711
- console.debug(`\u{1F50D} ${formattedMessage}`, data || "");
712
- break;
713
- case 1 /* INFO */:
714
- console.info(`\u2139\uFE0F ${formattedMessage}`, data || "");
715
- break;
716
- case 2 /* WARN */:
717
- console.warn(`\u26A0\uFE0F ${formattedMessage}`, data || "");
718
- break;
719
- case 3 /* ERROR */:
720
- console.error(`\u274C ${formattedMessage}`, data || "");
721
- break;
722
- }
723
- }
724
- /** Log a debug message */
725
- debug(message, data, context) {
726
- this.addLog(0 /* DEBUG */, message, data, context);
727
- }
728
- /** Log an info message */
729
- info(message, data, context) {
730
- this.addLog(1 /* INFO */, message, data, context);
731
- }
732
- /** Log a warning message */
733
- warn(message, data, context) {
734
- this.addLog(2 /* WARN */, message, data, context);
735
- }
736
- /** Log an error message */
737
- error(message, data, context) {
738
- this.addLog(3 /* ERROR */, message, data, context);
739
- }
740
- /** Get all logs */
741
- getLogs() {
742
- return [...this.logs];
743
- }
744
- /** Get logs by level */
745
- getLogsByLevel(level) {
746
- return this.logs.filter((log) => log.level === level);
747
- }
748
- /** Clear all logs */
749
- clearLogs() {
750
- this.logs = [];
751
- }
752
- /** Export logs as a JSON string */
753
- exportLogs() {
754
- return JSON.stringify(this.logs, null, 2);
755
- }
756
- /** Set maximum number of logs to retain in memory */
757
- setMaxLogs(max) {
758
- this.maxLogs = max;
759
- }
760
- };
761
- var logger = Logger.getInstance();
762
-
763
638
  // src/tools/ChainManager.ts
764
639
  var ChainManager = class {
765
640
  /**
@@ -815,7 +690,6 @@ var ChainManager = class {
815
690
  if (!bundlerUrl) {
816
691
  throw new Error(`No bundler URL configured for chain ID: ${chainId}`);
817
692
  }
818
- logger.info("Public client setup:", { bundlerUrl, chainId }, "ChainManager");
819
693
  const client = createPublicClient({
820
694
  chain: this.getChain(chainId),
821
695
  transport: http(rpcUrl)
@@ -1048,7 +922,7 @@ var DefaultSmartWalletProvider = class extends SmartWalletProvider {
1048
922
  constructor(chainManager, protocol, coinbaseCDP) {
1049
923
  super();
1050
924
  this.chainManager = chainManager;
1051
- this.protocolProvider = protocol.instance;
925
+ this.protocolProvider = protocol;
1052
926
  this.coinbaseCDP = coinbaseCDP;
1053
927
  }
1054
928
  /**
@@ -1311,8 +1185,7 @@ var WalletProvider = class {
1311
1185
  throw new Error(
1312
1186
  "Either walletAddress or deploymentOwners array must be provided to locate the smart wallet"
1313
1187
  );
1314
- } catch (error) {
1315
- logger.error("Error getting smart wallet", error, "WalletProvider");
1188
+ } catch {
1316
1189
  throw new Error(
1317
1190
  "Either walletAddress or deploymentOwners array must be provided to locate the smart wallet"
1318
1191
  );
@@ -1358,6 +1231,127 @@ var EmbeddedWallet = class {
1358
1231
  }
1359
1232
  };
1360
1233
 
1234
+ // src/types/logger.ts
1235
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
1236
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
1237
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
1238
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
1239
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
1240
+ return LogLevel2;
1241
+ })(LogLevel || {});
1242
+
1243
+ // src/tools/Logger.ts
1244
+ var Logger = class _Logger {
1245
+ /**
1246
+ * Create a new logger instance
1247
+ * @param logLevel Initial log level, defaults to DEBUG
1248
+ */
1249
+ constructor(logLevel = 0 /* DEBUG */) {
1250
+ this.logs = [];
1251
+ this.maxLogs = 1e3;
1252
+ this.logLevel = logLevel;
1253
+ }
1254
+ /**
1255
+ * Get singleton instance of the logger
1256
+ * @param logLevel Optional log level to initialize if instance not yet created
1257
+ * @returns Logger instance
1258
+ */
1259
+ static getInstance(logLevel) {
1260
+ if (!_Logger.instance) {
1261
+ _Logger.instance = new _Logger(logLevel);
1262
+ }
1263
+ return _Logger.instance;
1264
+ }
1265
+ /** Set the log level */
1266
+ setLogLevel(level) {
1267
+ this.logLevel = level;
1268
+ }
1269
+ /** Get the current log level */
1270
+ getLogLevel() {
1271
+ return this.logLevel;
1272
+ }
1273
+ /** Internal check if a message should be logged */
1274
+ shouldLog(level) {
1275
+ return level >= this.logLevel;
1276
+ }
1277
+ /** Format log message into a readable string */
1278
+ formatMessage(level, message, data, context) {
1279
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
1280
+ const levelName = LogLevel[level];
1281
+ const contextStr = context ? `[${context}]` : "";
1282
+ return `${timestamp} ${levelName}${contextStr}: ${message}`;
1283
+ }
1284
+ /** Add a log entry and output to console */
1285
+ addLog(level, message, data, context) {
1286
+ if (!this.shouldLog(level)) {
1287
+ return;
1288
+ }
1289
+ const logEntry = {
1290
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1291
+ level,
1292
+ message,
1293
+ data,
1294
+ context
1295
+ };
1296
+ this.logs.push(logEntry);
1297
+ if (this.logs.length > this.maxLogs) {
1298
+ this.logs = this.logs.slice(-this.maxLogs);
1299
+ }
1300
+ const formattedMessage = this.formatMessage(level, message, data, context);
1301
+ switch (level) {
1302
+ case 0 /* DEBUG */:
1303
+ console.debug(`\u{1F50D} ${formattedMessage}`, data || "");
1304
+ break;
1305
+ case 1 /* INFO */:
1306
+ console.info(`\u2139\uFE0F ${formattedMessage}`, data || "");
1307
+ break;
1308
+ case 2 /* WARN */:
1309
+ console.warn(`\u26A0\uFE0F ${formattedMessage}`, data || "");
1310
+ break;
1311
+ case 3 /* ERROR */:
1312
+ console.error(`\u274C ${formattedMessage}`, data || "");
1313
+ break;
1314
+ }
1315
+ }
1316
+ /** Log a debug message */
1317
+ debug(message, data, context) {
1318
+ this.addLog(0 /* DEBUG */, message, data, context);
1319
+ }
1320
+ /** Log an info message */
1321
+ info(message, data, context) {
1322
+ this.addLog(1 /* INFO */, message, data, context);
1323
+ }
1324
+ /** Log a warning message */
1325
+ warn(message, data, context) {
1326
+ this.addLog(2 /* WARN */, message, data, context);
1327
+ }
1328
+ /** Log an error message */
1329
+ error(message, data, context) {
1330
+ this.addLog(3 /* ERROR */, message, data, context);
1331
+ }
1332
+ /** Get all logs */
1333
+ getLogs() {
1334
+ return [...this.logs];
1335
+ }
1336
+ /** Get logs by level */
1337
+ getLogsByLevel(level) {
1338
+ return this.logs.filter((log) => log.level === level);
1339
+ }
1340
+ /** Clear all logs */
1341
+ clearLogs() {
1342
+ this.logs = [];
1343
+ }
1344
+ /** Export logs as a JSON string */
1345
+ exportLogs() {
1346
+ return JSON.stringify(this.logs, null, 2);
1347
+ }
1348
+ /** Set maximum number of logs to retain in memory */
1349
+ setMaxLogs(max) {
1350
+ this.maxLogs = max;
1351
+ }
1352
+ };
1353
+ var logger = Logger.getInstance();
1354
+
1361
1355
  // src/wallet/PrivyWallet.ts
1362
1356
  var PrivyWallet = class extends EmbeddedWallet {
1363
1357
  /**
@@ -1681,12 +1675,7 @@ var BaseProtocol = class {
1681
1675
  };
1682
1676
 
1683
1677
  // src/protocols/implementations/SparkProtocol.ts
1684
- import {
1685
- encodeFunctionData as encodeFunctionData2,
1686
- erc20Abi as erc20Abi4,
1687
- formatUnits as formatUnits2,
1688
- parseUnits as parseUnits2
1689
- } from "viem";
1678
+ import { encodeFunctionData as encodeFunctionData2, erc20Abi as erc20Abi4, formatUnits as formatUnits2, parseUnits as parseUnits2 } from "viem";
1690
1679
 
1691
1680
  // src/abis/protocols/spark.ts
1692
1681
  var SPARK_VAULT_ABI = [
@@ -1748,14 +1737,14 @@ var SPARK_SSR_ORACLE_ADDRESS = "0x65d946e533748A998B1f0E430803e39A6388f7a1";
1748
1737
  var SPARK_VAULT = [
1749
1738
  {
1750
1739
  id: "sUSDC",
1740
+ protocolId: "spark",
1741
+ name: "sUSDC",
1742
+ type: "stable",
1751
1743
  chain: "base",
1752
1744
  vaultAddress: "0x3128a0f7f0ea68e7b7c9b00afa7e41045828e858",
1753
- depositTokenAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
1754
- depositTokenDecimals: 6,
1755
- depositTokenSymbol: "USDC",
1756
- earnTokenAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
1757
- earnTokenDecimals: 18,
1758
- earnTokenSymbol: "sUSDC",
1745
+ tokenAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
1746
+ tokenDecimals: 6,
1747
+ tokenSymbol: "USDC",
1759
1748
  metadata: {}
1760
1749
  }
1761
1750
  ];
@@ -1766,6 +1755,7 @@ var RAY = BigInt("1000000000000000000000000000");
1766
1755
  var SparkProtocol = class extends BaseProtocol {
1767
1756
  constructor() {
1768
1757
  super(...arguments);
1758
+ /** All Spark vaults */
1769
1759
  this.allVaults = [];
1770
1760
  }
1771
1761
  /**
@@ -1776,7 +1766,7 @@ var SparkProtocol = class extends BaseProtocol {
1776
1766
  this.chainManager = chainManager;
1777
1767
  this.selectedChainId = chainManager.getSupportedChain();
1778
1768
  this.publicClient = chainManager.getPublicClient(this.selectedChainId);
1779
- this.allVaults = this.getVaults();
1769
+ this.allVaults = SPARK_VAULT;
1780
1770
  }
1781
1771
  /**
1782
1772
  * Get the SSR (Sky Saving Rate) of the Spark protocol
@@ -1806,88 +1796,54 @@ var SparkProtocol = class extends BaseProtocol {
1806
1796
  async getAPY() {
1807
1797
  const ssr = await this.getSSR();
1808
1798
  const apy = Math.exp(Math.log(ssr) * SECONDS_PER_YEAR) - 1;
1809
- return Number((apy * 100).toFixed(2));
1810
- }
1811
- /**
1812
- *
1813
- * Get all vault info from a Spark protocol
1814
- * @returns The list of vaults
1815
- */
1816
- getVaults() {
1817
- return SPARK_VAULT;
1799
+ return apy;
1818
1800
  }
1819
1801
  /**
1820
- * Get the best available Spark vault
1821
- * @returns The top-ranked Spark vault
1802
+ * Get the best available Spark vaults
1803
+ * @remarks Currently, the vault is only one and relates to sUSDC. Currently return only one stable vault
1804
+ * @returns Best Spark vaults in 2 groups: stable and non-stable
1822
1805
  * @throws Error if no vaults found
1823
1806
  */
1824
- async getBestVault() {
1807
+ async getBestVaults() {
1825
1808
  if (this.allVaults.length === 0) {
1826
1809
  throw new Error("No vaults found");
1827
1810
  }
1828
1811
  const selectedVault = this.allVaults[0];
1829
1812
  selectedVault.metadata.apy = await this.getAPY();
1830
- return selectedVault;
1831
- }
1832
- /**
1833
- * Fetch a vault where the user previously deposited funds
1834
- * @param smartWallet Smart wallet to inspect
1835
- * @returns The vault with user deposits, or null if none found
1836
- */
1837
- async fetchDepositedVaults(smartWallet) {
1838
- let depositedVault = void 0;
1839
- const userAddress = await smartWallet.getAddress();
1840
- for (const vault of this.allVaults) {
1841
- const balance = await this.getBalance(vault, userAddress);
1842
- if (parseInt(balance.depositedAmount) > 0) {
1843
- depositedVault = vault;
1844
- }
1845
- }
1846
- if (depositedVault) {
1847
- depositedVault.metadata.apy = await this.getAPY();
1848
- }
1849
- logger.info("Deposited vaults:", { depositedVault }, "SparkProtocol");
1850
- return depositedVault || null;
1813
+ return {
1814
+ stable: [selectedVault],
1815
+ nonStable: []
1816
+ };
1851
1817
  }
1852
1818
  /**
1853
1819
  * Deposit funds into a Spark vault
1820
+ * @param vaultInfo Vault information
1854
1821
  * @param amount Amount to deposit (human-readable)
1855
1822
  * @param smartWallet Smart wallet instance to use
1856
1823
  * @returns Transaction result with hash
1857
1824
  */
1858
- async deposit(amount, smartWallet) {
1859
- const depositedVault = await this.fetchDepositedVaults(smartWallet);
1860
- let vaultInfoToDeposit;
1861
- logger.info("Previously deposited vault:", { depositedVault }, "SparkProtocol");
1862
- if (depositedVault) {
1863
- vaultInfoToDeposit = depositedVault;
1864
- } else {
1865
- vaultInfoToDeposit = await this.getBestVault();
1866
- logger.info("Best vault that found:", { bestVault: vaultInfoToDeposit }, "SparkProtocol");
1867
- }
1825
+ async deposit(vaultInfo, amount, smartWallet) {
1868
1826
  const owner = await smartWallet.getAddress();
1869
- const assets = parseUnits2(amount, vaultInfoToDeposit.depositTokenDecimals);
1870
- logger.info("Raw deposit amount:", { amount, assets }, "SparkProtocol");
1827
+ const assets = parseUnits2(amount, vaultInfo.tokenDecimals);
1871
1828
  const allowance = await this.checkAllowance(
1872
- vaultInfoToDeposit.depositTokenAddress,
1873
- vaultInfoToDeposit.vaultAddress,
1829
+ vaultInfo.tokenAddress,
1830
+ vaultInfo.vaultAddress,
1874
1831
  owner,
1875
1832
  this.selectedChainId
1876
1833
  );
1877
- logger.info("Current vault contract allowance:", { allowance }, "SparkProtocol");
1878
1834
  const ops = [];
1879
1835
  if (allowance < assets) {
1880
1836
  ops.push({
1881
- to: vaultInfoToDeposit.depositTokenAddress,
1837
+ to: vaultInfo.tokenAddress,
1882
1838
  data: encodeFunctionData2({
1883
1839
  abi: erc20Abi4,
1884
1840
  functionName: "approve",
1885
- args: [vaultInfoToDeposit.vaultAddress, assets]
1841
+ args: [vaultInfo.vaultAddress, assets]
1886
1842
  })
1887
1843
  });
1888
1844
  }
1889
1845
  ops.push({
1890
- to: vaultInfoToDeposit.vaultAddress,
1846
+ to: vaultInfo.vaultAddress,
1891
1847
  data: encodeFunctionData2({
1892
1848
  abi: SPARK_VAULT_ABI,
1893
1849
  functionName: "deposit",
@@ -1899,23 +1855,19 @@ var SparkProtocol = class extends BaseProtocol {
1899
1855
  }
1900
1856
  /**
1901
1857
  * Withdraw funds from a Spark vault
1902
- * @param amountInUnderlying Amount in base token units (or undefined to withdraw all)
1858
+ * @param vaultInfo Vault information
1859
+ * @param amount Amount in base token units (or undefined to withdraw all)
1903
1860
  * @param smartWallet Smart wallet instance to withdraw from
1904
1861
  * @returns Transaction result with hash
1905
1862
  * @throws Error if no deposited vault found
1906
1863
  */
1907
- async withdraw(amountInUnderlying, smartWallet) {
1908
- const depositedVault = await this.fetchDepositedVaults(smartWallet);
1909
- if (!depositedVault) {
1910
- throw new Error("No vault found to withdraw from");
1911
- }
1864
+ async withdraw(vaultInfo, amount, smartWallet) {
1912
1865
  const owner = await smartWallet.getAddress();
1913
1866
  let withdrawData;
1914
- if (amountInUnderlying) {
1915
- const assets = parseUnits2(amountInUnderlying, depositedVault.depositTokenDecimals);
1916
- logger.info("Withdraw amount:", { amountInUnderlying, assets }, "SparkProtocol");
1867
+ if (amount) {
1868
+ const assets = parseUnits2(amount, vaultInfo.tokenDecimals);
1917
1869
  withdrawData = {
1918
- to: depositedVault.vaultAddress,
1870
+ to: vaultInfo.vaultAddress,
1919
1871
  data: encodeFunctionData2({
1920
1872
  abi: SPARK_VAULT_ABI,
1921
1873
  functionName: "withdraw",
@@ -1923,10 +1875,9 @@ var SparkProtocol = class extends BaseProtocol {
1923
1875
  })
1924
1876
  };
1925
1877
  } else {
1926
- const maxShares = await this.getMaxRedeemableShares(depositedVault, owner);
1927
- logger.info("Withdrawing all funds:", { maxShares }, "SparkProtocol");
1878
+ const maxShares = await this.getMaxRedeemableShares(vaultInfo, owner);
1928
1879
  withdrawData = {
1929
- to: depositedVault.vaultAddress,
1880
+ to: vaultInfo.vaultAddress,
1930
1881
  data: encodeFunctionData2({
1931
1882
  abi: SPARK_VAULT_ABI,
1932
1883
  functionName: "redeem",
@@ -1935,7 +1886,6 @@ var SparkProtocol = class extends BaseProtocol {
1935
1886
  };
1936
1887
  }
1937
1888
  const hash = await smartWallet.send(withdrawData, this.selectedChainId);
1938
- logger.info("Withdraw transaction sent:", { hash }, "SparkProtocol");
1939
1889
  return { success: true, hash };
1940
1890
  }
1941
1891
  /**
@@ -1958,14 +1908,15 @@ var SparkProtocol = class extends BaseProtocol {
1958
1908
  }
1959
1909
  /**
1960
1910
  * Get amount that a wallet has deposited in a vault
1961
- * @param vaultInfo Vault information
1962
1911
  * @param walletAddress Wallet address to check
1963
- * @returns Object containing shares and deposited amount
1912
+ * @returns Array of vault balances with vaults info
1964
1913
  */
1965
- async getBalance(vaultInfo, walletAddress) {
1914
+ async getBalances(walletAddress) {
1966
1915
  if (!this.publicClient) {
1967
1916
  throw new Error("Public client not initialized");
1968
1917
  }
1918
+ const vaultInfo = SPARK_VAULT[0];
1919
+ vaultInfo.metadata.apy = await this.getAPY();
1969
1920
  const shares = await this.publicClient.readContract({
1970
1921
  address: vaultInfo.vaultAddress,
1971
1922
  abi: SPARK_VAULT_ABI,
@@ -1973,7 +1924,7 @@ var SparkProtocol = class extends BaseProtocol {
1973
1924
  args: [walletAddress]
1974
1925
  });
1975
1926
  if (shares === 0n) {
1976
- return { shares: "0", depositedAmount: "0", vaultInfo };
1927
+ return [{ balance: null, vaultInfo }];
1977
1928
  }
1978
1929
  const assets = await this.publicClient.readContract({
1979
1930
  address: vaultInfo.vaultAddress,
@@ -1981,11 +1932,12 @@ var SparkProtocol = class extends BaseProtocol {
1981
1932
  functionName: "convertToAssets",
1982
1933
  args: [shares]
1983
1934
  });
1984
- return {
1985
- shares: formatUnits2(shares, vaultInfo.earnTokenDecimals),
1986
- depositedAmount: formatUnits2(assets, vaultInfo.depositTokenDecimals),
1987
- vaultInfo
1988
- };
1935
+ return [
1936
+ {
1937
+ balance: formatUnits2(assets, vaultInfo.tokenDecimals),
1938
+ vaultInfo
1939
+ }
1940
+ ];
1989
1941
  }
1990
1942
  };
1991
1943
 
@@ -1997,59 +1949,233 @@ var availableProtocols = [
1997
1949
  name: "Spark",
1998
1950
  website: "https://spark.fi/",
1999
1951
  logo: "/logos/spark.png",
2000
- supportedChains: [1, 8453, 42161],
1952
+ supportedChains: [8453],
2001
1953
  riskLevel: "low",
2002
- isPremium: false
1954
+ isActive: true
2003
1955
  },
2004
1956
  instance: new SparkProtocol()
2005
1957
  }
2006
1958
  ];
2007
1959
 
2008
- // src/tools/ApiKeysValidator.ts
2009
- var ApiKeysValidator = class {
2010
- // TODO: Implement the validation logic
1960
+ // src/protocols/implementations/ProxyProtocol.ts
1961
+ import { encodeFunctionData as encodeFunctionData3, erc20Abi as erc20Abi5, parseUnits as parseUnits3 } from "viem";
1962
+ var ProxyProtocol = class extends BaseProtocol {
2011
1963
  /**
2012
- * Validates whether the provided API key is valid
2013
- *
2014
- * @internal
2015
- * @param apiKey API key from {@link ProtocolsRouterConfig}
2016
- * @returns True if the API key is considered valid
1964
+ * Initialize the Spark protocol with the provided chain manager
1965
+ * @param chainManager Chain manager instance used for network operations
2017
1966
  */
2018
- validate(apiKey) {
2019
- logger.info("Validating api key...", apiKey, "ApiKeysValidator");
2020
- return true;
2021
- }
2022
- };
2023
-
2024
- // src/router/base/ProtocolRouterBase.ts
2025
- var ProtocolRouterBase = class {
2026
- /**
2027
- * Initialize a base protocol router
2028
- * @param riskLevel Risk level required by the integrator
2029
- * @param chainManager Chain manager instance for network operations
2030
- * @param minApy Optional minimum APY filter
2031
- * @param apiKey Optional API key for premium protocol access
2032
- */
2033
- constructor(riskLevel, chainManager, minApy, apiKey) {
2034
- // TODO: Add an API key validation
2035
- /** API key validator instance */
2036
- this.apiKeyValidator = new ApiKeysValidator();
2037
- this.riskLevel = riskLevel;
2038
- this.minApy = minApy;
2039
- this.apiKey = apiKey;
1967
+ async init(chainManager, protocolsSecurityConfig, apiClient) {
2040
1968
  this.chainManager = chainManager;
1969
+ this.selectedChainId = chainManager.getSupportedChain();
1970
+ this.publicClient = chainManager.getPublicClient(this.selectedChainId);
1971
+ this.apiClient = apiClient;
1972
+ this.protocolsSecurityConfig = protocolsSecurityConfig;
1973
+ }
1974
+ /**
1975
+ * Log a vault-related operation after deposit or withdraw funds
1976
+ * @param userAddress Address of the user who performed the operation
1977
+ * @param hash Hash of the operation
1978
+ * @param vaultInfo Information about the vault where the operation was performed
1979
+ * @param chainId Chain ID where the operation was performed
1980
+ * @param amount Amount of the operation
1981
+ * @param operationType Type of the operation
1982
+ * @param operationStatus Status of the operation
1983
+ */
1984
+ async logOperation(userAddress, hash, vaultInfo, chainId, amount, operationType, operationStatus) {
1985
+ const apiResponse = await this.apiClient.sendRequest("log", void 0, void 0, {
1986
+ userAddress,
1987
+ protocolId: vaultInfo.protocolId,
1988
+ vaultAddress: vaultInfo.vaultAddress,
1989
+ transactionHash: hash,
1990
+ chainId: chainId.toString(),
1991
+ amount,
1992
+ status: operationStatus,
1993
+ operationType
1994
+ });
1995
+ if (!apiResponse.success) {
1996
+ throw new Error(
1997
+ apiResponse.error || `Failed to log operation: ${operationType} for vault: ${vaultInfo}`
1998
+ );
1999
+ }
2000
+ }
2001
+ /**
2002
+ * Get the best vaults to deposit funds
2003
+ * @param stableVaultsLimit Limit of stable vaults to get. Optional, default is 1
2004
+ * @param nonStableVaultsLimit Limit of non-stable vaults to get. Optional, default is 1
2005
+ * @returns Best vaults to deposit funds in 2 groups: stable and non-stable
2006
+ */
2007
+ async getBestVaults(stableVaultsLimit = 1, nonStableVaultsLimit = 1) {
2008
+ const pathParams = {
2009
+ risk_level: this.protocolsSecurityConfig.riskLevel,
2010
+ chain_id: this.selectedChainId.toString(),
2011
+ stable_vaults_limit: stableVaultsLimit.toString(),
2012
+ non_stable_vaults_limit: nonStableVaultsLimit.toString()
2013
+ };
2014
+ const apiResponse = await this.apiClient.sendRequest("vaults", pathParams);
2015
+ if (!apiResponse.success) {
2016
+ throw new Error(apiResponse.error || "Failed to get best vaults");
2017
+ }
2018
+ const vaults = apiResponse.data;
2019
+ return {
2020
+ stable: vaults.stableVaults.map((vault) => {
2021
+ return {
2022
+ ...vault,
2023
+ metadata: {
2024
+ apy: vault.metadata?.apy,
2025
+ poolTvlUsd: vault.metadata?.poolTvlUsd
2026
+ }
2027
+ };
2028
+ }),
2029
+ nonStable: vaults.nonStableVaults.map((vault) => {
2030
+ return {
2031
+ ...vault,
2032
+ metadata: {
2033
+ apy: vault.metadata?.apy,
2034
+ poolTvlUsd: vault.metadata?.poolTvlUsd
2035
+ }
2036
+ };
2037
+ })
2038
+ };
2039
+ }
2040
+ /**
2041
+ * Deposit funds to a provided vault
2042
+ * @param vaultInfo Information about the vault to deposit funds to
2043
+ * @param amount Amount of funds to deposit
2044
+ * @param smartWallet Smart wallet to use for the deposit
2045
+ * @returns Result of the deposit transaction
2046
+ */
2047
+ async deposit(vaultInfo, amount, smartWallet) {
2048
+ const currentAddress = await smartWallet.getAddress();
2049
+ const operationsCallData = [];
2050
+ const depositTokenDecimals = vaultInfo.tokenDecimals;
2051
+ const depositTokenAddress = vaultInfo.tokenAddress;
2052
+ const vaultAddress = vaultInfo.vaultAddress;
2053
+ const rawDepositAmount = parseUnits3(amount, depositTokenDecimals);
2054
+ const allowance = await this.checkAllowance(
2055
+ depositTokenAddress,
2056
+ vaultAddress,
2057
+ currentAddress,
2058
+ this.selectedChainId
2059
+ );
2060
+ if (allowance < rawDepositAmount) {
2061
+ const approveData = {
2062
+ to: depositTokenAddress,
2063
+ data: encodeFunctionData3({
2064
+ abi: erc20Abi5,
2065
+ functionName: "approve",
2066
+ args: [vaultAddress, rawDepositAmount]
2067
+ })
2068
+ };
2069
+ operationsCallData.push(approveData);
2070
+ }
2071
+ if (!vaultInfo.protocolId) {
2072
+ throw new Error("Vault protocol ID is required");
2073
+ }
2074
+ const apiResponse = await this.apiClient.sendRequest(
2075
+ "deposit",
2076
+ void 0,
2077
+ vaultInfo.protocolId,
2078
+ {
2079
+ vaultInfo,
2080
+ amount: amount.toString(),
2081
+ chainId: this.selectedChainId.toString()
2082
+ }
2083
+ );
2084
+ if (!apiResponse.success) {
2085
+ throw new Error(apiResponse.error || "Failed to receive deposit operations call data");
2086
+ }
2087
+ const receivedOperationsCallData = apiResponse.data;
2088
+ operationsCallData.push(receivedOperationsCallData);
2089
+ const hash = await smartWallet.sendBatch(operationsCallData, this.selectedChainId);
2090
+ const operationStatus = hash ? "completed" : "failed";
2091
+ this.logOperation(
2092
+ currentAddress,
2093
+ hash,
2094
+ vaultInfo,
2095
+ this.selectedChainId,
2096
+ amount,
2097
+ "deposit",
2098
+ operationStatus
2099
+ );
2100
+ return { hash, success: true };
2101
+ }
2102
+ /**
2103
+ * Withdraw funds from a provided vault
2104
+ * @param vaultInfo Information about the vault to withdraw funds from
2105
+ * @param amount Amount of funds to withdraw
2106
+ * @param smartWallet Smart wallet to use for the withdrawal
2107
+ * @returns Result of the withdrawal transaction
2108
+ */
2109
+ async withdraw(vaultInfo, amount, smartWallet) {
2110
+ const currentAddress = await smartWallet.getAddress();
2111
+ const earningBalances = await smartWallet.getEarnBalances();
2112
+ if (!earningBalances) {
2113
+ throw new Error("No earning balances found");
2114
+ }
2115
+ const earningBalance = earningBalances.find((balance) => balance.vaultInfo.id === vaultInfo.id);
2116
+ if (!earningBalance) {
2117
+ throw new Error("No earning balance found");
2118
+ }
2119
+ const balanceInfo = earningBalance.balance;
2120
+ const amountToWithdraw = amount ? amount : balanceInfo.currentBalance;
2121
+ const apiResponse = await this.apiClient.sendRequest(
2122
+ "withdraw",
2123
+ void 0,
2124
+ vaultInfo.protocolId,
2125
+ {
2126
+ vaultInfo,
2127
+ amount: amountToWithdraw,
2128
+ chainId: this.selectedChainId.toString()
2129
+ }
2130
+ );
2131
+ if (!apiResponse.success) {
2132
+ throw new Error(apiResponse.error || "Failed to receive withdraw operations call data");
2133
+ }
2134
+ const withdrawOperationCallData = apiResponse.data;
2135
+ const hash = await smartWallet.send(withdrawOperationCallData, this.selectedChainId);
2136
+ const operationStatus = hash ? "completed" : "failed";
2137
+ this.logOperation(
2138
+ currentAddress,
2139
+ hash,
2140
+ vaultInfo,
2141
+ this.selectedChainId,
2142
+ amountToWithdraw,
2143
+ "withdrawal",
2144
+ operationStatus
2145
+ );
2146
+ return { hash, success: true };
2147
+ }
2148
+ /**
2149
+ * Get the balances of a user by a provided address
2150
+ * @param walletAddress Address of the user to get the balances of
2151
+ * @param protocolId Protocol ID to get the balances for. Optional, default is undefined
2152
+ * @returns Balances of the user in the protocol vaults
2153
+ */
2154
+ async getBalances(walletAddress, protocolId) {
2155
+ const pathParams = {
2156
+ chain_id: this.selectedChainId.toString(),
2157
+ protocol_id: protocolId || "",
2158
+ userAddress: walletAddress
2159
+ };
2160
+ const apiResponse = await this.apiClient.sendRequest("balances", pathParams);
2161
+ if (!apiResponse.success) {
2162
+ throw new Error(apiResponse.error || "Failed to get balances");
2163
+ }
2164
+ const balances = apiResponse.data;
2165
+ return balances;
2041
2166
  }
2042
2167
  };
2043
2168
 
2044
2169
  // src/router/ProtocolRouter.ts
2045
- var ProtocolRouter = class extends ProtocolRouterBase {
2170
+ var ProtocolRouter = class {
2046
2171
  /**
2047
2172
  * Initialize the protocol router
2048
2173
  * @param config Router configuration including risk level, min APY, and optional API key
2049
2174
  * @param chainManager Chain manager instance for network validation
2050
2175
  */
2051
- constructor(config, chainManager) {
2052
- super(config.riskLevel, chainManager, config.minApy, config.apiKey);
2176
+ constructor(chainManager, isApiKeyValid) {
2177
+ this.chainManager = chainManager;
2178
+ this.isApiKeyValid = isApiKeyValid;
2053
2179
  }
2054
2180
  /**
2055
2181
  * Get all protocols available for the current configuration
@@ -2057,13 +2183,9 @@ var ProtocolRouter = class extends ProtocolRouterBase {
2057
2183
  * Includes all non-premium protocols and premium protocols if the API key is valid
2058
2184
  * @returns Array of available protocol definitions
2059
2185
  */
2060
- getProtocols() {
2061
- const isKeyValid = this.apiKeyValidator.validate(this.apiKey);
2186
+ getActivePublicProtocols() {
2062
2187
  const allAvailableProtocols = availableProtocols.filter((protocol) => {
2063
- if (!protocol.info.isPremium) {
2064
- return true;
2065
- }
2066
- return protocol.info.isPremium && isKeyValid;
2188
+ return protocol.info.isActive;
2067
2189
  });
2068
2190
  return allAvailableProtocols;
2069
2191
  }
@@ -2088,18 +2210,20 @@ var ProtocolRouter = class extends ProtocolRouterBase {
2088
2210
  * @throws Error if no protocols are available for the current risk level
2089
2211
  * @returns Protocol instance considered the best match
2090
2212
  */
2091
- recommend() {
2092
- const protocols = this.getProtocols();
2213
+ select() {
2214
+ if (this.isApiKeyValid) {
2215
+ return new ProxyProtocol();
2216
+ }
2217
+ const protocols = this.getActivePublicProtocols();
2093
2218
  const eligibleProtocols = protocols.filter((protocol) => {
2094
- const riskMatches = protocol.info.riskLevel === this.riskLevel;
2095
2219
  const isSupportedChain = this.isProtocolSupportedChain(protocol.info.supportedChains);
2096
- return riskMatches && isSupportedChain;
2220
+ return isSupportedChain;
2097
2221
  });
2098
2222
  if (eligibleProtocols.length === 0) {
2099
- throw new Error(`No protocols available for risk level: ${this.riskLevel}`);
2223
+ throw new Error(`No protocols available`);
2100
2224
  }
2101
2225
  const bestProtocol = eligibleProtocols[0];
2102
- return bestProtocol;
2226
+ return bestProtocol.instance;
2103
2227
  }
2104
2228
  };
2105
2229
 
@@ -2319,8 +2443,161 @@ var CoinbaseCDP = class {
2319
2443
  }
2320
2444
  };
2321
2445
 
2446
+ // src/protocols/ProtocolsNamespace.ts
2447
+ var ProtocolsNamespace = class {
2448
+ constructor(protocol) {
2449
+ this.protocol = protocol;
2450
+ }
2451
+ /**
2452
+ * Find the best vaults for protocols that were selected based on integrator's settings
2453
+ *
2454
+ * @returns Best vaults for protocols that were selected based on integrator's settings
2455
+ */
2456
+ async getBestVaults(stableVaultsLimit = 1, nonStableVaultsLimit = 1) {
2457
+ return await this.protocol.getBestVaults(stableVaultsLimit, nonStableVaultsLimit);
2458
+ }
2459
+ };
2460
+
2461
+ // src/constants/general.ts
2462
+ var BACKEND_HOSTNAME = process.env.NODE_ENV === "dev" ? "http://localhost:3000" : "https://mycelium-cloud-production.up.railway.app";
2463
+
2464
+ // src/tools/ApiClient.ts
2465
+ import axios2 from "axios";
2466
+ var ApiClient = class {
2467
+ constructor(apiKey) {
2468
+ this.client = axios2.create({
2469
+ baseURL: BACKEND_HOSTNAME
2470
+ });
2471
+ /** URL settings for the endpoint: get the best vaults to deposit funds */
2472
+ this.bestVaultUrlSettings = {
2473
+ method: "GET",
2474
+ path: "api/v1/public/protocols/best"
2475
+ };
2476
+ /** URL settings for the endpoint: deposit funds to a provided vault */
2477
+ this.depositUrlSettings = {
2478
+ method: "POST",
2479
+ path: "api/v1/public/protocols/details/:protocolId/deposit"
2480
+ };
2481
+ /** URL settings for the endpoint: log a vault-related operation after deposit or withdraw funds */
2482
+ this.logOperationSettings = {
2483
+ method: "POST",
2484
+ path: "api/v1/public/log/operation"
2485
+ };
2486
+ /** URL settings for the endpoint: withdraw funds from a provided vault */
2487
+ this.withdrawUrlSettings = {
2488
+ method: "POST",
2489
+ path: "api/v1/public/protocols/details/:protocolId/withdraw"
2490
+ };
2491
+ /** URL settings for the endpoint: get the balances of a user by a provided address */
2492
+ this.balancesUrlSettings = {
2493
+ method: "GET",
2494
+ path: "api/v1/public/user/:userAddress/balances"
2495
+ };
2496
+ /** URL settings for the endpoint: validate the API key */
2497
+ this.apiKeyValidUrlSettings = {
2498
+ method: "GET",
2499
+ path: "api/v1/public/valid"
2500
+ };
2501
+ /** URL settings for the endpoint: get the config for services */
2502
+ this.configUrlSettings = {
2503
+ method: "GET",
2504
+ path: "api/v1/public/config"
2505
+ };
2506
+ /** URL settings mapping with operation types */
2507
+ this.operationTypeToUrlSettings = {
2508
+ deposit: this.depositUrlSettings,
2509
+ withdraw: this.withdrawUrlSettings,
2510
+ log: this.logOperationSettings,
2511
+ vaults: this.bestVaultUrlSettings,
2512
+ balances: this.balancesUrlSettings,
2513
+ apiKeyValidation: this.apiKeyValidUrlSettings,
2514
+ config: this.configUrlSettings
2515
+ };
2516
+ this.apiKey = apiKey;
2517
+ if (!this.validateApiKeyFormat()) {
2518
+ throw new Error("Invalid API key format");
2519
+ }
2520
+ }
2521
+ /**
2522
+ * Send a request to the backend API
2523
+ * @param path Path of the endpoint to send the request to
2524
+ * @param method Method of the request
2525
+ * @param body Body of the request
2526
+ * @returns Response from the backend API
2527
+ */
2528
+ async sendRequest(operationType, params, protocolId, body) {
2529
+ const { path, method } = this.operationTypeToUrlSettings[operationType];
2530
+ let requestPath = path;
2531
+ if (protocolId) {
2532
+ requestPath = requestPath.replace(":protocolId", protocolId);
2533
+ }
2534
+ if (params?.userAddress) {
2535
+ requestPath = requestPath.replace(":userAddress", params.userAddress);
2536
+ delete params.userAddress;
2537
+ }
2538
+ const urlParams = new URLSearchParams(params).toString();
2539
+ if (urlParams) {
2540
+ requestPath += `?${urlParams}`;
2541
+ }
2542
+ const response = await this.client.request({
2543
+ method,
2544
+ url: requestPath,
2545
+ data: body,
2546
+ headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json" }
2547
+ });
2548
+ if (response.status !== 200) {
2549
+ throw new Error(`Failed to send request to ${path}`);
2550
+ }
2551
+ const apiResponse = response.data;
2552
+ return apiResponse;
2553
+ }
2554
+ /**
2555
+ * Validates whether the provided API key is valid
2556
+ *
2557
+ * @internal
2558
+ * @param apiKey API key from {@link ProtocolsRouterConfig}
2559
+ * @returns True if the API key is considered valid
2560
+ */
2561
+ async validate() {
2562
+ if (!this.validateApiKeyFormat()) {
2563
+ throw new Error("Invalid API key format");
2564
+ }
2565
+ const apiResponse = await this.sendRequest("apiKeyValidation");
2566
+ if (!apiResponse.success) {
2567
+ throw new Error(apiResponse.error || "Failed to validate API key");
2568
+ }
2569
+ return true;
2570
+ }
2571
+ /**
2572
+ *
2573
+ * Validates the format of the API key. Must start with 'sk_' and contain only hexadecimal characters
2574
+ *
2575
+ * @internal
2576
+ * @param apiKey API key from {@link ProtocolsRouterConfig}
2577
+ * @returns
2578
+ */
2579
+ validateApiKeyFormat() {
2580
+ if (!this.apiKey) {
2581
+ return false;
2582
+ }
2583
+ const prefix = "sk_";
2584
+ if (!this.apiKey.startsWith(prefix)) {
2585
+ return false;
2586
+ }
2587
+ const keyPart = this.apiKey.slice(prefix.length);
2588
+ if (keyPart.length < 32 || keyPart.length > 128) {
2589
+ return false;
2590
+ }
2591
+ const hexPattern = /^[0-9a-fA-F]+$/;
2592
+ if (!hexPattern.test(keyPart)) {
2593
+ return false;
2594
+ }
2595
+ return true;
2596
+ }
2597
+ };
2598
+
2322
2599
  // src/index.ts
2323
- var MyceliumSDK = class {
2600
+ var MyceliumSDK = class _MyceliumSDK {
2324
2601
  /**
2325
2602
  * Creates a new SDK instance
2326
2603
  *
@@ -2328,7 +2605,7 @@ var MyceliumSDK = class {
2328
2605
  * @throws Throws if an unsupported wallet provider is given
2329
2606
  * @see MyceliumSDKConfig
2330
2607
  */
2331
- constructor(config) {
2608
+ constructor(config, isPremiumAvailable, apiClient) {
2332
2609
  /**
2333
2610
  * Ramp namespace to manage ramp operations. Methods are available on {@link RampNamespace}
2334
2611
  * @internal
@@ -2353,11 +2630,14 @@ var MyceliumSDK = class {
2353
2630
  bundlerUrl: "https://public.pimlico.io/v2/8453/rpc"
2354
2631
  }
2355
2632
  );
2356
- if (!config.chain) {
2357
- logger.warn(
2358
- "No chain config provided, using default public RPC and Bundler URLs",
2359
- "MyceliumSDK"
2633
+ if (config.protocolsSecurityConfig) {
2634
+ this.protocol = this.selectProtocol(
2635
+ config.protocolsSecurityConfig,
2636
+ isPremiumAvailable,
2637
+ apiClient
2360
2638
  );
2639
+ } else {
2640
+ throw new Error("Protocols router config is required");
2361
2641
  }
2362
2642
  if (config.coinbaseCDPConfig) {
2363
2643
  this.coinbaseCDP = new CoinbaseCDP(
@@ -2368,11 +2648,63 @@ var MyceliumSDK = class {
2368
2648
  );
2369
2649
  this.fundingNamespace = new FundingNamespace(this.coinbaseCDP);
2370
2650
  }
2371
- const protocolsRouterConfig = config.protocolsRouterConfig || {
2372
- riskLevel: "low"
2373
- };
2374
- this.protocol = this.findProtocol(protocolsRouterConfig);
2375
2651
  this.wallet = this.createWalletNamespace(config.walletsConfig);
2652
+ this.protocols = new ProtocolsNamespace(this.protocol);
2653
+ }
2654
+ /**
2655
+ * Initializes the SDK
2656
+ * @param config SDK configuration (networks, wallets, protocol router settings)
2657
+ * @returns SDK instance
2658
+ */
2659
+ static async init(config) {
2660
+ let finalConfig;
2661
+ let isPremiumAvailable = false;
2662
+ if ("apiKey" in config && config.apiKey) {
2663
+ const apiClient = new ApiClient(config.apiKey);
2664
+ isPremiumAvailable = await apiClient.validate();
2665
+ if (isPremiumAvailable) {
2666
+ const apiResponse = await apiClient.sendRequest("config");
2667
+ if (!apiResponse.success) {
2668
+ throw new Error(apiResponse.error || "Failed to get onchain config");
2669
+ }
2670
+ const backendConfig = apiResponse.data;
2671
+ finalConfig = {
2672
+ integratorId: backendConfig.integratorId,
2673
+ walletsConfig: {
2674
+ embeddedWalletConfig: {
2675
+ provider: {
2676
+ type: "privy",
2677
+ providerConfig: {
2678
+ appId: backendConfig.privyAppId,
2679
+ appSecret: backendConfig.privyAppSecret
2680
+ }
2681
+ }
2682
+ },
2683
+ smartWalletConfig: {
2684
+ provider: {
2685
+ type: "default"
2686
+ }
2687
+ }
2688
+ },
2689
+ chain: {
2690
+ chainId: config.chainId || backendConfig.chainId,
2691
+ rpcUrl: backendConfig.rpcUrl,
2692
+ bundlerUrl: backendConfig.bundlerUrl
2693
+ },
2694
+ protocolsSecurityConfig: config.protocolsSecurityConfig,
2695
+ coinbaseCDPConfig: {
2696
+ apiKeyId: backendConfig.coinbaseCdpApiKey,
2697
+ apiKeySecret: backendConfig.coinbaseCdpApiKeySecret
2698
+ }
2699
+ };
2700
+ const sdk2 = new _MyceliumSDK(finalConfig, isPremiumAvailable, apiClient);
2701
+ sdk2.apiClient = apiClient;
2702
+ return sdk2;
2703
+ }
2704
+ }
2705
+ finalConfig = config;
2706
+ const sdk = new _MyceliumSDK(finalConfig, isPremiumAvailable);
2707
+ return sdk;
2376
2708
  }
2377
2709
  /**
2378
2710
  * Returns the chain manager instance for multi-chain operations
@@ -2410,10 +2742,13 @@ var MyceliumSDK = class {
2410
2742
  * @param config Protocol router configuration (e.g. risk level)
2411
2743
  * @returns Selected protocol object of the type {@link Protocol}
2412
2744
  */
2413
- findProtocol(config) {
2414
- const protocolRouter = new ProtocolRouter(config, this.chainManager);
2415
- const protocol = protocolRouter.recommend();
2416
- protocol.instance.init(this.chainManager);
2745
+ selectProtocol(config, isPremiumAvailable, apiClient) {
2746
+ const protocolRouter = new ProtocolRouter(this.chainManager, isPremiumAvailable);
2747
+ const protocol = protocolRouter.select();
2748
+ if (!config) {
2749
+ throw new Error("Protocols security config is required");
2750
+ }
2751
+ protocol.init(this.chainManager, config, apiClient);
2417
2752
  return protocol;
2418
2753
  }
2419
2754
  /**