@funkit/fun-relay 2.2.0-next.4 → 2.2.0-next.6

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.mjs CHANGED
@@ -578,9 +578,9 @@ function getReferrer(clientId) {
578
578
  return clientId ? `${FUN_RELAY_REFERRER}|${clientId}` : FUN_RELAY_REFERRER;
579
579
  }
580
580
  var RelayQuoteClientError = class extends Error {
581
- constructor(statusCode, relayErrorCode, message) {
581
+ constructor(statusCode, relayErrorCode, message, requestId = "") {
582
582
  super(
583
- `An error occurred trying to generate a relay quote: ${relayErrorCode} - ${message}`
583
+ `An error occurred trying to generate a relay quote: ${relayErrorCode} - ReqId ${requestId || "NO_REQ_ID"} - ${message}`
584
584
  );
585
585
  this.statusCode = statusCode;
586
586
  this.relayErrorCode = relayErrorCode;
@@ -772,7 +772,8 @@ async function getRelayQuote({
772
772
  throw new RelayQuoteClientError(
773
773
  apiError.statusCode,
774
774
  rawError.errorCode,
775
- rawError.message ?? apiError.message
775
+ rawError.message ?? apiError.message,
776
+ rawError.requestId
776
777
  );
777
778
  }
778
779
  }
@@ -832,7 +833,7 @@ import {
832
833
  encodeFunctionData as encodeFunctionData2,
833
834
  toFunctionSelector
834
835
  } from "viem";
835
- import { mainnet as mainnet2 } from "viem/chains";
836
+ import { mainnet as mainnet3 } from "viem/chains";
836
837
 
837
838
  // src/dynamicRoutes/abi.ts
838
839
  var UNWRAP_AND_CALL_ABI = [
@@ -1275,7 +1276,7 @@ var ASSET_LOGO_SRCS = {
1275
1276
  IMX: "https://sdk-cdn.fun.xyz/images/imx.svg",
1276
1277
  INJ: "https://sdk-cdn.fun.xyz/images/inj.svg",
1277
1278
  LDO: "https://sdk-cdn.fun.xyz/images/ldo.svg",
1278
- LINK: "https://sdk-cdn.fun.xyz/images/link.svg",
1279
+ LINK: "https://sdk-cdn.fun.xyz/images/link.png",
1279
1280
  LUCK: "https://sdk-cdn.fun.xyz/images/luck.png",
1280
1281
  MATIC: "https://sdk-cdn.fun.xyz/images/matic.svg",
1281
1282
  MFER: "https://sdk-cdn.fun.xyz/images/mfer.png",
@@ -1293,7 +1294,7 @@ var ASSET_LOGO_SRCS = {
1293
1294
  SOL: "https://sdk-cdn.fun.xyz/images/sol.svg",
1294
1295
  SUSDS: "https://sdk-cdn.fun.xyz/images/susds.svg",
1295
1296
  TYBG: "https://sdk-cdn.fun.xyz/images/tybg.png",
1296
- UNI: "https://sdk-cdn.fun.xyz/images/uni.svg",
1297
+ UNI: "https://sdk-cdn.fun.xyz/images/uni.png",
1297
1298
  USDC: "https://sdk-cdn.fun.xyz/images/usdc.svg",
1298
1299
  "USDC.E": "https://sdk-cdn.fun.xyz/images/usdc.svg",
1299
1300
  USDE: "https://sdk-cdn.fun.xyz/images/usde.svg",
@@ -1334,7 +1335,8 @@ var ASSET_LOGO_SRCS = {
1334
1335
  MON: "https://sdk-cdn.fun.xyz/images/monad.svg",
1335
1336
  WMON: "https://sdk-cdn.fun.xyz/images/wmon.svg",
1336
1337
  AUSD: "https://sdk-cdn.fun.xyz/images/ausd.svg",
1337
- SUSHI: "https://sdk-cdn.fun.xyz/images/sushi.svg"
1338
+ SUSHI: "https://sdk-cdn.fun.xyz/images/sushi.svg",
1339
+ SKY: "https://sdk-cdn.fun.xyz/images/sky.svg"
1338
1340
  };
1339
1341
 
1340
1342
  // src/dynamicRoutes/consts.ts
@@ -1348,6 +1350,25 @@ var tokenAddresses = {
1348
1350
  },
1349
1351
  USDC: {
1350
1352
  [mainnet.id]: getAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
1353
+ },
1354
+ // LIT is currently unused
1355
+ LIT: {
1356
+ [mainnet.id]: getAddress("0x232CE3bd40fCd6f80f3d55A522d03f25Df784Ee2")
1357
+ },
1358
+ LINK: {
1359
+ [mainnet.id]: getAddress("0x514910771AF9Ca656af840dff83E8264EcF986CA")
1360
+ },
1361
+ UNI: {
1362
+ [mainnet.id]: getAddress("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984")
1363
+ },
1364
+ AAVE: {
1365
+ [mainnet.id]: getAddress("0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9")
1366
+ },
1367
+ SKY: {
1368
+ [mainnet.id]: getAddress("0x56072C95FAA701256059aa122697B133aDEd9279")
1369
+ },
1370
+ LDO: {
1371
+ [mainnet.id]: getAddress("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32")
1351
1372
  }
1352
1373
  };
1353
1374
  var UNWRAP_AND_CALL_ADDRESS = {
@@ -1362,6 +1383,8 @@ var LIGHTER_DEPOSIT_ADDRESS = getAddress(
1362
1383
  var MATCH_ALL_CONDITION = "*";
1363
1384
 
1364
1385
  // src/dynamicRoutes/utils.ts
1386
+ import { erc20Abi as ERC20_ABI } from "viem";
1387
+ import { mainnet as mainnet2 } from "viem/chains";
1365
1388
  var createPath = (config) => {
1366
1389
  return config;
1367
1390
  };
@@ -1444,6 +1467,35 @@ var initDynamicRouting = (dynamicRoutes, dynamicRoutingConfig) => {
1444
1467
  );
1445
1468
  return indexedDynamicRoutingConfig;
1446
1469
  };
1470
+ var MAX_APPROVAL = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
1471
+ var getApprovalCalldata = ({
1472
+ tokenAddress,
1473
+ spenderAddress,
1474
+ amount
1475
+ }) => {
1476
+ return {
1477
+ contractAbi: ERC20_ABI,
1478
+ contractAddress: tokenAddress,
1479
+ functionName: "approve",
1480
+ functionArgs: [spenderAddress, amount]
1481
+ };
1482
+ };
1483
+ var getResetApprovalCalldata = ({
1484
+ tokenAddress,
1485
+ spenderAddress
1486
+ }) => {
1487
+ return getApprovalCalldata({
1488
+ tokenAddress,
1489
+ spenderAddress,
1490
+ amount: "0"
1491
+ });
1492
+ };
1493
+ var RESET_APPROVAL_TOKENS = [tokenAddresses.LDO[mainnet2.id]].map(
1494
+ (address) => address.toLowerCase()
1495
+ );
1496
+ var shouldResetApproval = (tokenAddress) => {
1497
+ return RESET_APPROVAL_TOKENS.includes(tokenAddress.toLowerCase());
1498
+ };
1447
1499
 
1448
1500
  // src/dynamicRoutes/lighter.ts
1449
1501
  var NATIVE_TOKEN = FUNKIT_NATIVE_TOKEN;
@@ -1452,14 +1504,31 @@ var RELAY_LIGHTER_ETH_SPOT_ADDRESS = "0x0000000000000000000000000000000000000001
1452
1504
  var RELAY_LIGHTER_USDC_PERPS_ADDRESS = "0x0000000000000000000000000000000000000000";
1453
1505
  var TICK_SIZE_FOR_ASSET_INDEX = {
1454
1506
  [3 /* USDC */]: BigInt(1),
1455
- [1 /* ETH */]: BigInt(10 ** 10)
1507
+ [1 /* ETH */]: BigInt(10 ** 10),
1508
+ [2 /* LIT */]: BigInt(10 ** 10),
1509
+ [5 /* LINK */]: BigInt(10 ** 10),
1510
+ [6 /* UNI */]: BigInt(10 ** 10),
1511
+ [7 /* AAVE */]: BigInt(10 ** 10),
1512
+ [8 /* SKY */]: BigInt(10 ** 10),
1513
+ [9 /* LDO */]: BigInt(10 ** 10)
1456
1514
  };
1457
1515
  var DEPOSIT_TOKEN_FOR_ASSET_INDEX = {
1458
- [3 /* USDC */]: tokenAddresses.USDC[mainnet2.id],
1459
- [1 /* ETH */]: NATIVE_TOKEN
1516
+ [3 /* USDC */]: tokenAddresses.USDC[mainnet3.id],
1517
+ [1 /* ETH */]: NATIVE_TOKEN,
1518
+ [2 /* LIT */]: tokenAddresses.LIT[mainnet3.id],
1519
+ [5 /* LINK */]: tokenAddresses.LINK[mainnet3.id],
1520
+ [6 /* UNI */]: tokenAddresses.UNI[mainnet3.id],
1521
+ [7 /* AAVE */]: tokenAddresses.AAVE[mainnet3.id],
1522
+ [8 /* SKY */]: tokenAddresses.SKY[mainnet3.id],
1523
+ [9 /* LDO */]: tokenAddresses.LDO[mainnet3.id]
1460
1524
  };
1461
1525
  var USDC_PERPS_SYMBOL = "USDC (Perps)";
1462
1526
  var ETH_SPOT_SYMBOL = "ETH (Spot)";
1527
+ var LINK_SPOT_SYMBOL = "LINK (Spot)";
1528
+ var UNI_SPOT_SYMBOL = "UNI (Spot)";
1529
+ var AAVE_SPOT_SYMBOL = "AAVE (Spot)";
1530
+ var SKY_SPOT_SYMBOL = "SKY (Spot)";
1531
+ var LDO_SPOT_SYMBOL = "LDO (Spot)";
1463
1532
  var generateLighterMainnetDepositActions = ({
1464
1533
  address,
1465
1534
  assetIndex,
@@ -1502,22 +1571,18 @@ var generateLighterMainnetDepositActions = ({
1502
1571
  });
1503
1572
  return [
1504
1573
  // Step 1: Approve WETH to UnwrapWETHAndCall
1505
- {
1506
- contractAbi: erc20Abi,
1507
- contractAddress: tokenAddresses.WETH[mainnet2.id],
1508
- functionName: "approve",
1509
- functionArgs: [
1510
- UNWRAP_AND_CALL_ADDRESS[mainnet2.id],
1511
- "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1512
- ]
1513
- },
1574
+ getApprovalCalldata({
1575
+ tokenAddress: tokenAddresses.WETH[mainnet3.id],
1576
+ spenderAddress: UNWRAP_AND_CALL_ADDRESS[mainnet3.id],
1577
+ amount: MAX_APPROVAL
1578
+ }),
1514
1579
  // Step 2: UnwrapWETHAndCall pulls WETH, unwraps to ETH, sends to VaultWrapper, calls deposit
1515
1580
  {
1516
1581
  contractAbi: UNWRAP_AND_CALL_ABI,
1517
- contractAddress: UNWRAP_AND_CALL_ADDRESS[mainnet2.id],
1582
+ contractAddress: UNWRAP_AND_CALL_ADDRESS[mainnet3.id],
1518
1583
  functionName: "unwrapAndCall",
1519
1584
  functionArgs: [
1520
- VAULT_DEPOSITOR_ADDRESS[mainnet2.id],
1585
+ VAULT_DEPOSITOR_ADDRESS[mainnet3.id],
1521
1586
  // target (VaultWrapper)
1522
1587
  vaultWrapperCalldata
1523
1588
  // VaultWrapper.deposit() calldata
@@ -1525,52 +1590,53 @@ var generateLighterMainnetDepositActions = ({
1525
1590
  }
1526
1591
  ];
1527
1592
  }
1528
- if (depositToken === tokenAddresses.USDC[mainnet2.id]) {
1529
- return [
1530
- // Step 1: Approve USDC to VaultDepositor
1531
- {
1532
- contractAbi: erc20Abi,
1533
- contractAddress: tokenAddresses.USDC[mainnet2.id],
1534
- functionName: "approve",
1535
- functionArgs: [
1536
- VAULT_DEPOSITOR_ADDRESS[mainnet2.id],
1537
- "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1538
- // Max approval
1539
- ]
1540
- },
1541
- // Step 2: VaultDepositor pulls USDC and calls Lighter deposit
1542
- {
1543
- contractAbi: VAULT_DEPOSITOR_ABI,
1544
- contractAddress: VAULT_DEPOSITOR_ADDRESS[mainnet2.id],
1545
- functionName: "depositWithTick",
1546
- functionArgs: [
1547
- tokenAddresses.USDC[mainnet2.id],
1548
- // token (USDC)
1549
- LIGHTER_DEPOSIT_ADDRESS,
1550
- // vault (Lighter deposit contract)
1551
- lighterDepositCalldata,
1552
- // callData
1553
- 0n,
1554
- // minAmountOut
1555
- tickSize,
1556
- // tickSize
1557
- dustRecipient
1558
- // dustRecipient
1559
- ]
1560
- }
1561
- ];
1562
- }
1593
+ const resetApprovalNeeded = shouldResetApproval(depositToken);
1594
+ return [
1595
+ // Special handling of LDO token as it requires approval reset before approval can be set to a new value due to non-standard implementation of the approve function.
1596
+ ...resetApprovalNeeded ? [
1597
+ getResetApprovalCalldata({
1598
+ tokenAddress: depositToken,
1599
+ spenderAddress: VAULT_DEPOSITOR_ADDRESS[mainnet3.id]
1600
+ })
1601
+ ] : [],
1602
+ // Step 1: Approve deposit token to VaultDepositor
1603
+ getApprovalCalldata({
1604
+ tokenAddress: depositToken,
1605
+ spenderAddress: VAULT_DEPOSITOR_ADDRESS[mainnet3.id],
1606
+ amount: MAX_APPROVAL
1607
+ }),
1608
+ // Step 2: VaultDepositor pulls deposit token and calls Lighter deposit
1609
+ {
1610
+ contractAbi: VAULT_DEPOSITOR_ABI,
1611
+ contractAddress: VAULT_DEPOSITOR_ADDRESS[mainnet3.id],
1612
+ functionName: "depositWithTick",
1613
+ functionArgs: [
1614
+ depositToken,
1615
+ // token (deposit token)
1616
+ LIGHTER_DEPOSIT_ADDRESS,
1617
+ // vault (Lighter deposit contract)
1618
+ lighterDepositCalldata,
1619
+ // callData
1620
+ 0n,
1621
+ // minAmountOut
1622
+ tickSize,
1623
+ // tickSize
1624
+ dustRecipient
1625
+ // dustRecipient
1626
+ ]
1627
+ }
1628
+ ];
1563
1629
  };
1564
1630
  var LIGHTER_USDC_PERPS_FUN_MAINNET_DEPOSIT = createPath({
1565
- targetChain: mainnet2.id.toString(),
1566
- targetAsset: tokenAddresses.USDC[mainnet2.id],
1631
+ targetChain: mainnet3.id.toString(),
1632
+ targetAsset: tokenAddresses.USDC[mainnet3.id],
1567
1633
  targetAssetTicker: USDC_PERPS_SYMBOL,
1568
1634
  iconSrc: ASSET_LOGO_SRCS.USDC,
1569
1635
  generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1570
1636
  if (!outputConfig) {
1571
1637
  return [];
1572
1638
  }
1573
- if (outputConfig.targetChain !== mainnet2.id.toString()) {
1639
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1574
1640
  return [];
1575
1641
  }
1576
1642
  return generateLighterMainnetDepositActions({
@@ -1581,15 +1647,15 @@ var LIGHTER_USDC_PERPS_FUN_MAINNET_DEPOSIT = createPath({
1581
1647
  }
1582
1648
  });
1583
1649
  var LIGHTER_ETH_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1584
- targetChain: mainnet2.id.toString(),
1585
- targetAsset: tokenAddresses.WETH[mainnet2.id],
1650
+ targetChain: mainnet3.id.toString(),
1651
+ targetAsset: tokenAddresses.WETH[mainnet3.id],
1586
1652
  targetAssetTicker: ETH_SPOT_SYMBOL,
1587
1653
  iconSrc: ASSET_LOGO_SRCS.ETH,
1588
1654
  generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1589
1655
  if (!outputConfig) {
1590
1656
  return [];
1591
1657
  }
1592
- if (outputConfig.targetChain !== mainnet2.id.toString()) {
1658
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1593
1659
  return [];
1594
1660
  }
1595
1661
  return generateLighterMainnetDepositActions({
@@ -1599,6 +1665,101 @@ var LIGHTER_ETH_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1599
1665
  });
1600
1666
  }
1601
1667
  });
1668
+ var LIGHTER_LINK_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1669
+ targetChain: mainnet3.id.toString(),
1670
+ targetAsset: tokenAddresses.LINK[mainnet3.id],
1671
+ targetAssetTicker: LINK_SPOT_SYMBOL,
1672
+ iconSrc: ASSET_LOGO_SRCS.LINK,
1673
+ generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1674
+ if (!outputConfig) {
1675
+ return [];
1676
+ }
1677
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1678
+ return [];
1679
+ }
1680
+ return generateLighterMainnetDepositActions({
1681
+ address,
1682
+ assetIndex: 5 /* LINK */,
1683
+ routeType: 1 /* Spot */
1684
+ });
1685
+ }
1686
+ });
1687
+ var LIGHTER_SKY_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1688
+ targetChain: mainnet3.id.toString(),
1689
+ targetAsset: tokenAddresses.SKY[mainnet3.id],
1690
+ targetAssetTicker: SKY_SPOT_SYMBOL,
1691
+ iconSrc: ASSET_LOGO_SRCS.SKY,
1692
+ generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1693
+ if (!outputConfig) {
1694
+ return [];
1695
+ }
1696
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1697
+ return [];
1698
+ }
1699
+ return generateLighterMainnetDepositActions({
1700
+ address,
1701
+ assetIndex: 8 /* SKY */,
1702
+ routeType: 1 /* Spot */
1703
+ });
1704
+ }
1705
+ });
1706
+ var LIGHTER_UNI_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1707
+ targetChain: mainnet3.id.toString(),
1708
+ targetAsset: tokenAddresses.UNI[mainnet3.id],
1709
+ targetAssetTicker: UNI_SPOT_SYMBOL,
1710
+ iconSrc: ASSET_LOGO_SRCS.UNI,
1711
+ generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1712
+ if (!outputConfig) {
1713
+ return [];
1714
+ }
1715
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1716
+ return [];
1717
+ }
1718
+ return generateLighterMainnetDepositActions({
1719
+ address,
1720
+ assetIndex: 6 /* UNI */,
1721
+ routeType: 1 /* Spot */
1722
+ });
1723
+ }
1724
+ });
1725
+ var LIGHTER_AAVE_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1726
+ targetChain: mainnet3.id.toString(),
1727
+ targetAsset: tokenAddresses.AAVE[mainnet3.id],
1728
+ targetAssetTicker: AAVE_SPOT_SYMBOL,
1729
+ iconSrc: ASSET_LOGO_SRCS.AAVE,
1730
+ generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1731
+ if (!outputConfig) {
1732
+ return [];
1733
+ }
1734
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1735
+ return [];
1736
+ }
1737
+ return generateLighterMainnetDepositActions({
1738
+ address,
1739
+ assetIndex: 7 /* AAVE */,
1740
+ routeType: 1 /* Spot */
1741
+ });
1742
+ }
1743
+ });
1744
+ var LIGHTER_LDO_SPOT_FUN_MAINNET_DEPOSIT = createPath({
1745
+ targetChain: mainnet3.id.toString(),
1746
+ targetAsset: tokenAddresses.LDO[mainnet3.id],
1747
+ targetAssetTicker: LDO_SPOT_SYMBOL,
1748
+ iconSrc: ASSET_LOGO_SRCS.LDO,
1749
+ generateActionsParams: (address) => async (_finalTargetAssetAmount, outputConfig) => {
1750
+ if (!outputConfig) {
1751
+ return [];
1752
+ }
1753
+ if (outputConfig.targetChain !== mainnet3.id.toString()) {
1754
+ return [];
1755
+ }
1756
+ return generateLighterMainnetDepositActions({
1757
+ address,
1758
+ assetIndex: 9 /* LDO */,
1759
+ routeType: 1 /* Spot */
1760
+ });
1761
+ }
1762
+ });
1602
1763
  var LIGHTER_DYNAMIC_ROUTES = [
1603
1764
  createRoute({
1604
1765
  id: "LIGHTER_ETH_SPOT",
@@ -1641,6 +1802,37 @@ var LIGHTER_DYNAMIC_ROUTES = [
1641
1802
  paths: {
1642
1803
  FUN_MAINNET_DEPOSIT: LIGHTER_ETH_SPOT_FUN_MAINNET_DEPOSIT
1643
1804
  }
1805
+ }),
1806
+ // LINK, UNI, AAVE, SKY, LDO tokens
1807
+ createRoute({
1808
+ id: "LIGHTER_LINK_SPOT_NEW_USER",
1809
+ paths: {
1810
+ FUN_MAINNET_DEPOSIT: LIGHTER_LINK_SPOT_FUN_MAINNET_DEPOSIT
1811
+ }
1812
+ }),
1813
+ createRoute({
1814
+ id: "LIGHTER_SKY_SPOT_NEW_USER",
1815
+ paths: {
1816
+ FUN_MAINNET_DEPOSIT: LIGHTER_SKY_SPOT_FUN_MAINNET_DEPOSIT
1817
+ }
1818
+ }),
1819
+ createRoute({
1820
+ id: "LIGHTER_UNI_SPOT_NEW_USER",
1821
+ paths: {
1822
+ FUN_MAINNET_DEPOSIT: LIGHTER_UNI_SPOT_FUN_MAINNET_DEPOSIT
1823
+ }
1824
+ }),
1825
+ createRoute({
1826
+ id: "LIGHTER_AAVE_SPOT_NEW_USER",
1827
+ paths: {
1828
+ FUN_MAINNET_DEPOSIT: LIGHTER_AAVE_SPOT_FUN_MAINNET_DEPOSIT
1829
+ }
1830
+ }),
1831
+ createRoute({
1832
+ id: "LIGHTER_LDO_SPOT_NEW_USER",
1833
+ paths: {
1834
+ FUN_MAINNET_DEPOSIT: LIGHTER_LDO_SPOT_FUN_MAINNET_DEPOSIT
1835
+ }
1644
1836
  })
1645
1837
  ];
1646
1838
 
@@ -1678,6 +1870,7 @@ export {
1678
1870
  initDynamicRouting,
1679
1871
  initializeRelayClient,
1680
1872
  isRelayExecutionTerminalStatus,
1681
- parseRelayFees
1873
+ parseRelayFees,
1874
+ shouldResetApproval
1682
1875
  };
1683
1876
  //# sourceMappingURL=index.mjs.map