@layerswap/wallet-fuel 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @layerswap/wallet-fuel
2
+
3
+ Fuel wallet provider for the Layerswap Widget. Enables Fuel blockchain wallet connections and transactions.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @layerswap/wallet-fuel wagmi viem @wagmi/core @tanstack/react-query
9
+ # or
10
+ yarn add @layerswap/wallet-fuel wagmi viem @wagmi/core @tanstack/react-query
11
+ # or
12
+ pnpm add @layerswap/wallet-fuel wagmi viem @wagmi/core @tanstack/react-query
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```tsx
18
+ import { LayerswapProvider, Swap } from "@layerswap/widget";
19
+ import { createFuelProvider } from "@layerswap/wallet-fuel";
20
+
21
+ export default function Page() {
22
+ const fuelProvider = createFuelProvider();
23
+
24
+ return (
25
+ <LayerswapProvider walletProviders={[fuelProvider]}>
26
+ <Swap />
27
+ </LayerswapProvider>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ Use `createFuelProvider()` to create a Fuel wallet provider:
35
+
36
+ ```tsx
37
+ import { createFuelProvider } from "@layerswap/wallet-fuel";
38
+
39
+ const fuelProvider = createFuelProvider({
40
+ // Custom configuration options
41
+ });
42
+ ```
43
+
44
+ ## Documentation
45
+
46
+ For detailed setup instructions, configuration options, and usage examples, see the [Fuel Wallet Provider documentation](https://docs.layerswap.io/integration/UI/Widget/WalletManagement/FuelProvider).
47
+
48
+ ## Features
49
+
50
+ - Fuel wallet connection via Fuel SDK
51
+ - Balance checking
52
+ - Gas estimation
53
+ - Address validation and utilities
54
+ - Fuel transaction support
55
+ - Integration with `@fuels/react` for React hooks
56
+
57
+ ## TypeScript
58
+
59
+ This package includes TypeScript definitions. All types are exported from the main entry point.
60
+
61
+ ## License
62
+
63
+ MIT
64
+
65
+ ## Repository
66
+
67
+ [GitHub](https://github.com/layerswap/layerswapapp/tree/main/packages/wallets/fuel)
68
+
@@ -6,9 +6,10 @@ import { FueletWalletConnector } from './connectors/fuelet-wallet';
6
6
  import { FuelWalletConnector } from './connectors/fuel-wallet';
7
7
  import { useSettingsState } from '@layerswap/widget/internal';
8
8
  import { NetworkType } from '@layerswap/widget/types';
9
- import { useMemo } from 'react';
9
+ import { useMemo, useContext } from 'react';
10
+ import { QueryClient, QueryClientContext, QueryClientProvider } from '@tanstack/react-query';
10
11
  const HOST_URL = 'https://api.bako.global';
11
- const FuelProviderWrapper = ({ children }) => {
12
+ const Comp = ({ children }) => {
12
13
  const { networks } = useSettingsState();
13
14
  const fuelConfig = {
14
15
  connectors: [
@@ -24,4 +25,12 @@ const FuelProviderWrapper = ({ children }) => {
24
25
  })), [networks]);
25
26
  return (_jsx(FuelProvider, { uiConfig: { suggestBridge: false }, theme: 'dark', fuelConfig: fuelConfig, networks: fuelNetworks, children: children }));
26
27
  };
28
+ const queryClient = new QueryClient();
29
+ const FuelProviderWrapper = ({ children }) => {
30
+ const context = useContext(QueryClientContext);
31
+ if (context) {
32
+ return _jsx(Comp, { children: children });
33
+ }
34
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(Comp, { children: children }) }));
35
+ };
27
36
  export default FuelProviderWrapper;
@@ -46,14 +46,13 @@ export class FuelBalanceProvider extends BalanceProvider {
46
46
  decimals: token.decimals,
47
47
  isNativeCurrency: network.token?.symbol === token.symbol,
48
48
  token: token.symbol,
49
- request_time: new Date().toJSON(),
50
- error: balance?.amount === undefined ? `Could not fetch balance for ${token.symbol}` : undefined
49
+ request_time: new Date().toJSON()
51
50
  };
52
51
  balances.push(balanceObj);
53
52
  }
54
53
  }
55
54
  catch (e) {
56
- return network.tokens.map((currency) => (this.resolveTokenBalanceFetchError(e, currency, network)));
55
+ throw e;
57
56
  }
58
57
  return balances;
59
58
  };
@@ -1,5 +1,5 @@
1
1
  import WatchdogAbi from './jsons/FUELWATCHDOG.json';
2
- import { KnownInternalNames, formatUnits } from "@layerswap/widget/internal";
2
+ import { ErrorHandler, KnownInternalNames, formatUnits } from "@layerswap/widget/internal";
3
3
  export class FuelGasProvider {
4
4
  supportsNetwork(network) {
5
5
  return (KnownInternalNames.Networks.FuelMainnet.includes(network.name) || KnownInternalNames.Networks.FuelTestnet.includes(network.name));
@@ -32,7 +32,14 @@ export class FuelGasProvider {
32
32
  return { gas: formatedGas, token: network.token };
33
33
  }
34
34
  catch (e) {
35
- console.log(e);
35
+ const error = e;
36
+ ErrorHandler({
37
+ type: "GasProviderError",
38
+ message: error.message,
39
+ name: error.name,
40
+ stack: error.stack,
41
+ cause: error.cause
42
+ });
36
43
  }
37
44
  }
38
45
  }
package/dist/esm/index.js CHANGED
@@ -1,13 +1,52 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { FuelAddressUtilsProvider } from "./fuelAddressUtilsProvider";
2
3
  import { FuelBalanceProvider } from "./fuelBalanceProvider";
3
4
  import { FuelGasProvider } from "./fuelGasProvider";
4
5
  import FuelProviderWrapper from "./FuelProvider";
5
6
  import useFuelConnection from "./useFuelConnection";
7
+ import React from "react";
8
+ import { useFuelTransfer } from "./transferProvider/useFuelTransfer";
9
+ export function createFuelProvider(config = {}) {
10
+ const { customHook, balanceProviders, gasProviders, addressUtilsProviders, transferProviders } = config;
11
+ const WrapperComponent = ({ children }) => {
12
+ return (_jsx(FuelProviderWrapper, { children: children }));
13
+ };
14
+ const walletConnectionProvider = customHook || useFuelConnection;
15
+ const defaultBalanceProviders = [new FuelBalanceProvider()];
16
+ const finalBalanceProviders = balanceProviders !== undefined
17
+ ? (Array.isArray(balanceProviders) ? balanceProviders : [balanceProviders])
18
+ : defaultBalanceProviders;
19
+ const defaultGasProviders = [new FuelGasProvider()];
20
+ const finalGasProviders = gasProviders !== undefined
21
+ ? (Array.isArray(gasProviders) ? gasProviders : [gasProviders])
22
+ : defaultGasProviders;
23
+ const defaultAddressUtilsProviders = [new FuelAddressUtilsProvider()];
24
+ const finalAddressUtilsProviders = addressUtilsProviders !== undefined
25
+ ? (Array.isArray(addressUtilsProviders) ? addressUtilsProviders : [addressUtilsProviders])
26
+ : defaultAddressUtilsProviders;
27
+ const defaultTransferProviders = [useFuelTransfer];
28
+ const finalTransferProviders = transferProviders !== undefined
29
+ ? (Array.isArray(transferProviders) ? transferProviders : [transferProviders])
30
+ : defaultTransferProviders;
31
+ return {
32
+ id: "fuel",
33
+ wrapper: WrapperComponent,
34
+ walletConnectionProvider,
35
+ addressUtilsProvider: finalAddressUtilsProviders,
36
+ gasProvider: finalGasProviders,
37
+ balanceProvider: finalBalanceProviders,
38
+ transferProvider: finalTransferProviders,
39
+ };
40
+ }
41
+ /**
42
+ * @deprecated Use createFuelProvider() instead. This export will be removed in a future version.
43
+ */
6
44
  export const FuelProvider = {
7
45
  id: "fuel",
8
46
  wrapper: FuelProviderWrapper,
9
47
  walletConnectionProvider: useFuelConnection,
10
- addressUtilsProvider: new FuelAddressUtilsProvider(),
11
- balanceProvider: new FuelBalanceProvider(),
12
- gasProvider: new FuelGasProvider(),
48
+ addressUtilsProvider: [new FuelAddressUtilsProvider()],
49
+ gasProvider: [new FuelGasProvider()],
50
+ balanceProvider: [new FuelBalanceProvider()],
51
+ transferProvider: [useFuelTransfer],
13
52
  };
@@ -0,0 +1,57 @@
1
+ import { ActionMessageType } from "@layerswap/widget/types";
2
+ import { useFuel } from '@fuels/react';
3
+ import { Provider } from '@fuel-ts/account';
4
+ import { transactionBuilder } from "./transactionBuilder";
5
+ import { KnownInternalNames } from "@layerswap/widget/internal";
6
+ const supportedNetworks = [
7
+ KnownInternalNames.Networks.FuelTestnet,
8
+ KnownInternalNames.Networks.FuelDevnet,
9
+ KnownInternalNames.Networks.FuelMainnet
10
+ ];
11
+ export function useFuelTransfer() {
12
+ const { fuel } = useFuel();
13
+ return {
14
+ supportsNetwork(network) {
15
+ return supportedNetworks.includes(network.name);
16
+ },
17
+ async executeTransfer(params) {
18
+ if (!fuel) {
19
+ throw new Error("Fuel not initialized");
20
+ }
21
+ const { callData, network, selectedWallet, swapId } = params;
22
+ const fuelProvider = new Provider(network.node_url);
23
+ const fuelWallet = await fuel.getWallet(selectedWallet.address, fuelProvider);
24
+ if (!fuelWallet) {
25
+ throw new Error("Fuel wallet not found");
26
+ }
27
+ try {
28
+ const scriptTransaction = await transactionBuilder({ fuelWallet, callData });
29
+ await fuelProvider.simulate(scriptTransaction);
30
+ const transactionResponse = await fuelWallet.sendTransaction(scriptTransaction);
31
+ if (swapId && transactionResponse) {
32
+ return transactionResponse.id;
33
+ }
34
+ throw new Error("No transaction ID returned");
35
+ }
36
+ catch (error) {
37
+ const e = new Error();
38
+ e.message = error.message;
39
+ if (error.message === "The account(s) sending the transaction don't have enough funds to cover the transaction."
40
+ || error.message === "the target cannot be met due to no coins available or exceeding the 255 coin limit.") {
41
+ e.name = ActionMessageType.InsufficientFunds;
42
+ throw e;
43
+ }
44
+ else if (error.message === "Request cancelled without user response!"
45
+ || error.message === "User rejected the transaction!"
46
+ || error.message === "User canceled sending transaction") {
47
+ e.name = ActionMessageType.TransactionRejected;
48
+ throw e;
49
+ }
50
+ else {
51
+ e.name = ActionMessageType.UnexpectedErrorMessage;
52
+ throw e;
53
+ }
54
+ }
55
+ }
56
+ };
57
+ }
@@ -1,12 +1,11 @@
1
- import { useConnectors, useFuel as useGlobalFuel, } from '@fuels/react';
2
- import { FuelConnectorEventTypes, Provider, } from '@fuel-ts/account';
1
+ import { useConnectors, useFuel as useGlobalFuel } from '@fuels/react';
2
+ import { FuelConnectorEventTypes } from '@fuel-ts/account';
3
3
  import { Address } from '@fuel-ts/address';
4
4
  import { useWalletStore, sleep, KnownInternalNames } from "@layerswap/widget/internal";
5
5
  import { useEffect, useMemo } from "react";
6
- import { transactionBuilder } from "./services/transferService/transactionBuilder";
7
6
  import { BAKO_STATE } from "./connectors/bako-safe/Bako";
8
- import { TransactionMessageType } from "@layerswap/widget/types";
9
7
  import { resolveFuelWalletConnectorIcon } from './utils';
8
+ import { useFuelTransfer } from './transferProvider/useFuelTransfer';
10
9
  export default function useFuelConnection({ networks }) {
11
10
  const commonSupportedNetworks = [
12
11
  KnownInternalNames.Networks.FuelTestnet,
@@ -51,7 +50,6 @@ export default function useFuelConnection({ networks }) {
51
50
  await sleep(1000);
52
51
  return await attemptConnection(true);
53
52
  }
54
- console.log(e);
55
53
  throw new Error(e);
56
54
  }
57
55
  };
@@ -65,6 +63,7 @@ export default function useFuelConnection({ networks }) {
65
63
  await fuelConnector.disconnect();
66
64
  }
67
65
  catch (e) {
66
+ //TODO: handle error
68
67
  console.log(e);
69
68
  }
70
69
  finally {
@@ -81,6 +80,7 @@ export default function useFuelConnection({ networks }) {
81
80
  }
82
81
  }
83
82
  catch (e) {
83
+ //TODO: handle error
84
84
  console.log(e);
85
85
  }
86
86
  };
@@ -91,6 +91,7 @@ export default function useFuelConnection({ networks }) {
91
91
  throw new Error('Could not switch account');
92
92
  }
93
93
  catch (e) {
94
+ //TODO: handle error
94
95
  console.log(e);
95
96
  }
96
97
  };
@@ -104,41 +105,11 @@ export default function useFuelConnection({ networks }) {
104
105
  throw new Error('Could not switch chain');
105
106
  }
106
107
  catch (e) {
108
+ //TODO: handle error
107
109
  console.log(e);
108
110
  }
109
111
  };
110
- const transfer = async (params) => {
111
- const { callData, network, selectedWallet, swapId } = params;
112
- const fuelProvider = new Provider(network.node_url);
113
- const fuelWallet = await fuel.getWallet(selectedWallet.address, fuelProvider);
114
- if (!fuelWallet)
115
- throw Error("Fuel wallet not found");
116
- try {
117
- const scriptTransaction = await transactionBuilder({ fuelWallet, callData });
118
- await fuelProvider.simulate(scriptTransaction);
119
- const transactionResponse = await fuelWallet.sendTransaction(scriptTransaction);
120
- if (swapId && transactionResponse) {
121
- return transactionResponse.id;
122
- }
123
- }
124
- catch (error) {
125
- const e = new Error();
126
- e.message = error.message;
127
- if (error === "The account(s) sending the transaction don't have enough funds to cover the transaction."
128
- || error === "the target cannot be met due to no coins available or exceeding the 255 coin limit.") {
129
- error.name = TransactionMessageType.InsufficientFunds;
130
- throw e;
131
- }
132
- else if (error === "Request cancelled without user response!" || error === "User rejected the transaction!" || error === "User canceled sending transaction") {
133
- e.name = TransactionMessageType.TransactionRejected;
134
- throw e;
135
- }
136
- else {
137
- e.name = TransactionMessageType.UexpectedErrorMessage;
138
- throw e;
139
- }
140
- }
141
- };
112
+ const { executeTransfer: transfer } = useFuelTransfer();
142
113
  const connectedConnectors = useMemo(() => connectors.filter(w => w.connected), [connectors]);
143
114
  useEffect(() => {
144
115
  (async () => {
@@ -163,6 +134,7 @@ export default function useFuelConnection({ networks }) {
163
134
  }
164
135
  }
165
136
  catch (e) {
137
+ //TODO: handle error
166
138
  console.log(e);
167
139
  }
168
140
  }
@@ -205,6 +177,7 @@ export default function useFuelConnection({ networks }) {
205
177
  connectedWallets,
206
178
  name,
207
179
  id,
180
+ ready: connectors.length > 0
208
181
  };
209
182
  return provider;
210
183
  }