@shapeshiftoss/swap-widget 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +77 -34
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { useAppKitAccount as useAppKitAccount3 } from "@reown/appkit/react";
3
3
  import { useCallback as useCallback11, useEffect as useEffect10, useMemo as useMemo12, useRef as useRef7, useState as useState8 } from "react";
4
4
 
5
5
  // src/api/client.ts
6
- var DEFAULT_API_BASE_URL = import.meta.env.VITE_SWAP_WIDGET_API_URL ?? "https://api.shapeshift.com";
6
+ var DEFAULT_API_BASE_URL = "https://api.shapeshift.com";
7
7
  var createApiClient = (config = {}) => {
8
8
  const baseUrl = config.baseUrl ?? DEFAULT_API_BASE_URL;
9
9
  const fetchWithConfig = async (endpoint, params, method = "GET", timeoutMs = 3e4) => {
@@ -1330,7 +1330,7 @@ var useStatusPolling = ({
1330
1330
 
1331
1331
  // src/hooks/useSwapApproval.ts
1332
1332
  import { useEffect as useEffect3, useRef as useRef2 } from "react";
1333
- import { createPublicClient as createPublicClient2, encodeFunctionData, erc20Abi as erc20Abi2, http as http2 } from "viem";
1333
+ import { createPublicClient as createPublicClient2, http as http2 } from "viem";
1334
1334
 
1335
1335
  // src/constants/chains.ts
1336
1336
  import {
@@ -1443,6 +1443,15 @@ var useSwapApproval = () => {
1443
1443
  });
1444
1444
  return;
1445
1445
  }
1446
+ if (!sellAmountBaseUnit || sellAmountBaseUnit === "0") {
1447
+ actorRef.send({ type: "APPROVAL_ERROR", error: "No sell amount specified" });
1448
+ return;
1449
+ }
1450
+ const approvalTxs = quote.approval.approvalTxs;
1451
+ if (!approvalTxs?.length) {
1452
+ actorRef.send({ type: "APPROVAL_ERROR", error: "No approval transactions in quote" });
1453
+ return;
1454
+ }
1446
1455
  const requiredChainId = getEvmNetworkId(sellAsset.chainId);
1447
1456
  const client = walletClient;
1448
1457
  const currentChainId = await client.getChainId();
@@ -1458,28 +1467,24 @@ var useSwapApproval = () => {
1458
1467
  nativeCurrency,
1459
1468
  rpcUrls: { default: { http: [] } }
1460
1469
  };
1461
- if (!sellAmountBaseUnit || sellAmountBaseUnit === "0") {
1462
- actorRef.send({ type: "APPROVAL_ERROR", error: "No sell amount specified" });
1463
- return;
1464
- }
1465
- const approvalData = encodeFunctionData({
1466
- abi: erc20Abi2,
1467
- functionName: "approve",
1468
- args: [quote.approval.spender, BigInt(sellAmountBaseUnit)]
1469
- });
1470
- const approvalHash = await client.sendTransaction({
1471
- to: sellAssetAddress,
1472
- data: approvalData,
1473
- value: BigInt(0),
1474
- chain,
1475
- account: walletAddress
1476
- });
1477
1470
  const rpcUrl = chain.rpcUrls?.default?.http?.[0];
1478
1471
  const publicClient = createPublicClient2({
1479
1472
  chain,
1480
1473
  transport: rpcUrl ? http2(rpcUrl) : http2()
1481
1474
  });
1482
- await publicClient.waitForTransactionReceipt({ hash: approvalHash });
1475
+ let approvalHash;
1476
+ for (const approvalTx of approvalTxs) {
1477
+ approvalHash = await client.sendTransaction({
1478
+ to: approvalTx.to,
1479
+ data: approvalTx.data,
1480
+ value: BigInt(approvalTx.value),
1481
+ chain,
1482
+ account: walletAddress
1483
+ });
1484
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: approvalHash });
1485
+ if (receipt.status !== "success") throw new Error("Approval transaction reverted");
1486
+ }
1487
+ if (!approvalHash) throw new Error("Expected at least one approval transaction");
1483
1488
  actorRef.send({ type: "APPROVAL_SUCCESS", txHash: approvalHash });
1484
1489
  } catch (error) {
1485
1490
  actorRef.send({
@@ -1623,7 +1628,7 @@ import { useQueries, useQueryClient } from "@tanstack/react-query";
1623
1628
  import { getBalance, readContract } from "@wagmi/core";
1624
1629
  import PQueue from "p-queue";
1625
1630
  import { useCallback as useCallback3, useMemo as useMemo4 } from "react";
1626
- import { erc20Abi as erc20Abi3 } from "viem";
1631
+ import { erc20Abi as erc20Abi2 } from "viem";
1627
1632
  import { useConfig } from "wagmi";
1628
1633
  var CONCURRENCY_LIMIT = 5;
1629
1634
  var DELAY_BETWEEN_BATCHES_MS = 50;
@@ -1823,7 +1828,7 @@ var useMultiChainBalance = (evmAddress, utxoAddress, solanaAddress, assetId, pre
1823
1828
  if (isErc20 && evmParsed.tokenAddress) {
1824
1829
  const result2 = await readContract(config, {
1825
1830
  address: evmParsed.tokenAddress,
1826
- abi: erc20Abi3,
1831
+ abi: erc20Abi2,
1827
1832
  functionName: "balanceOf",
1828
1833
  args: [evmAddress],
1829
1834
  chainId: evmParsed.evmChainId
@@ -1936,7 +1941,7 @@ var useMultiChainBalances = (evmAddress, utxoAddress, solanaAddress, assetIds, a
1936
1941
  if (asset.tokenAddress) {
1937
1942
  const result2 = await readContract(config, {
1938
1943
  address: asset.tokenAddress,
1939
- abi: erc20Abi3,
1944
+ abi: erc20Abi2,
1940
1945
  functionName: "balanceOf",
1941
1946
  args: [evmAddress],
1942
1947
  // @ts-ignore - swap-widget supports more chains than main app's wagmi type registration
@@ -2459,13 +2464,13 @@ var executeEvm = async (txData, walletClient, walletAddress) => {
2459
2464
  account: getAddress2(walletAddress)
2460
2465
  });
2461
2466
  };
2462
- var executeUtxoDeposit = (txData, bitcoin3) => {
2467
+ var executeUtxo = (txData, bitcoin3) => {
2463
2468
  if (!bitcoin3.isConnected || !bitcoin3.address) throw new Error("Bitcoin wallet not connected");
2464
2469
  bitcoin3.reset();
2465
2470
  return bitcoin3.sendTransfer({
2466
- recipientAddress: txData.depositAddress,
2471
+ recipientAddress: txData.to,
2467
2472
  amount: txData.value,
2468
- memo: txData.memo
2473
+ memo: txData.opReturnData
2469
2474
  });
2470
2475
  };
2471
2476
  var executeSolana = async (txData, solana3) => {
@@ -2473,7 +2478,13 @@ var executeSolana = async (txData, solana3) => {
2473
2478
  throw new Error("Solana wallet not connected");
2474
2479
  }
2475
2480
  solana3.reset();
2476
- const { Transaction, PublicKey: PublicKey3, TransactionInstruction } = await import("@solana/web3.js");
2481
+ const {
2482
+ ComputeBudgetProgram,
2483
+ PublicKey: PublicKey3,
2484
+ TransactionInstruction,
2485
+ TransactionMessage,
2486
+ VersionedTransaction
2487
+ } = await import("@solana/web3.js");
2477
2488
  const instructions = txData.instructions.map((ix) => {
2478
2489
  return new TransactionInstruction({
2479
2490
  keys: ix.keys.map((key) => ({
@@ -2485,11 +2496,41 @@ var executeSolana = async (txData, solana3) => {
2485
2496
  data: Buffer.from(ix.data, "base64")
2486
2497
  });
2487
2498
  });
2488
- const transaction = new Transaction().add(...instructions);
2489
2499
  const conn = solana3.connection;
2500
+ const includeComputeBudget = instructions.some(
2501
+ (ix) => ix.programId.equals(ComputeBudgetProgram.programId)
2502
+ );
2503
+ if (includeComputeBudget) {
2504
+ const recentFees = await conn.getRecentPrioritizationFees();
2505
+ const fees = recentFees.map((fee) => fee.prioritizationFee).filter((fee) => fee > 0).sort((a, b) => a - b);
2506
+ const priorityFee = fees[Math.floor(fees.length * 0.75)] ?? 0;
2507
+ if (priorityFee > 0) {
2508
+ instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }));
2509
+ }
2510
+ }
2511
+ const lookupTableAccounts = (await Promise.all(
2512
+ txData.addressLookupTableAddresses.map(async (address) => {
2513
+ const { value } = await conn.getAddressLookupTable(new PublicKey3(address));
2514
+ return value;
2515
+ })
2516
+ )).filter((account) => account !== null);
2490
2517
  const { blockhash } = await conn.getLatestBlockhash("confirmed");
2491
- transaction.recentBlockhash = blockhash;
2492
- transaction.feePayer = new PublicKey3(solana3.address);
2518
+ const message = new TransactionMessage({
2519
+ payerKey: new PublicKey3(solana3.address),
2520
+ recentBlockhash: blockhash,
2521
+ instructions
2522
+ }).compileToV0Message(lookupTableAccounts);
2523
+ return solana3.sendTransaction({ transaction: new VersionedTransaction(message) });
2524
+ };
2525
+ var executeSolanaSerializedTx = async (txData, solana3) => {
2526
+ if (!solana3.isConnected || !solana3.address || !solana3.connection) {
2527
+ throw new Error("Solana wallet not connected");
2528
+ }
2529
+ solana3.reset();
2530
+ const { VersionedTransaction } = await import("@solana/web3.js");
2531
+ const transaction = VersionedTransaction.deserialize(
2532
+ new Uint8Array(Buffer.from(txData.serializedTx, "base64"))
2533
+ );
2493
2534
  return solana3.sendTransaction({ transaction });
2494
2535
  };
2495
2536
  var useSwapExecution = () => {
@@ -2525,12 +2566,14 @@ var useSwapExecution = () => {
2525
2566
  switch (txData.type) {
2526
2567
  case "evm":
2527
2568
  return executeEvm(txData, walletClient, walletAddress);
2528
- case "utxo_deposit":
2529
- return executeUtxoDeposit(txData, bitcoin3);
2530
- case "solana":
2569
+ case "utxo":
2570
+ return executeUtxo(txData, bitcoin3);
2571
+ case "solana_instructions":
2531
2572
  return executeSolana(txData, solana3);
2532
- case "utxo_psbt":
2533
- case "cosmos":
2573
+ case "solana_serialized_tx":
2574
+ return executeSolanaSerializedTx(txData, solana3);
2575
+ case "cosmossdk_msg_send":
2576
+ case "cosmossdk_msg_deposit":
2534
2577
  throw new Error("This swap is not yet supported \u2014 please try a different route");
2535
2578
  default: {
2536
2579
  const _exhaustive = txData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshiftoss/swap-widget",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "description": "Embeddable swap widget using ShapeShift API",
5
5
  "repository": "https://github.com/shapeshift/web",
6
6
  "license": "MIT",
@@ -30,9 +30,9 @@
30
30
  "p-queue": "^8.0.1",
31
31
  "react-virtuoso": "^4.7.11",
32
32
  "xstate": "5.28.0",
33
+ "@shapeshiftoss/utils": "^1.1.0",
33
34
  "@shapeshiftoss/caip": "^8.16.10",
34
- "@shapeshiftoss/types": "^8.6.8",
35
- "@shapeshiftoss/utils": "^1.1.0"
35
+ "@shapeshiftoss/types": "^9.0.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@wagmi/core": "^2.0.0",