@layerswap/wallet-starknet 1.0.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 (36) hide show
  1. package/dist/esm/StarknetProvider.js +116 -0
  2. package/dist/esm/index.js +15 -0
  3. package/dist/esm/jsons/ERC20.json +258 -0
  4. package/dist/esm/starknetAddressUtilsProvider.js +26 -0
  5. package/dist/esm/starknetBalanceProvider.js +42 -0
  6. package/dist/esm/starknetGasProvider.js +43 -0
  7. package/dist/esm/starknetNftProvider.js +48 -0
  8. package/dist/esm/useStarknetConnection.js +159 -0
  9. package/dist/esm/utils/KnownStarknetConnectors.js +24 -0
  10. package/dist/esm/utils/index.js +3 -0
  11. package/dist/esm/utils/resolveIcon.js +9 -0
  12. package/dist/esm/utils/starkNetAddressValidator.js +46 -0
  13. package/dist/tsconfig.tsbuildinfo +1 -0
  14. package/dist/types/StarknetProvider.d.ts +6 -0
  15. package/dist/types/StarknetProvider.d.ts.map +1 -0
  16. package/dist/types/index.d.ts +3 -0
  17. package/dist/types/index.d.ts.map +1 -0
  18. package/dist/types/starknetAddressUtilsProvider.d.ts +7 -0
  19. package/dist/types/starknetAddressUtilsProvider.d.ts.map +1 -0
  20. package/dist/types/starknetBalanceProvider.d.ts +6 -0
  21. package/dist/types/starknetBalanceProvider.d.ts.map +1 -0
  22. package/dist/types/starknetGasProvider.d.ts +9 -0
  23. package/dist/types/starknetGasProvider.d.ts.map +1 -0
  24. package/dist/types/starknetNftProvider.d.ts +6 -0
  25. package/dist/types/starknetNftProvider.d.ts.map +1 -0
  26. package/dist/types/useStarknetConnection.d.ts +3 -0
  27. package/dist/types/useStarknetConnection.d.ts.map +1 -0
  28. package/dist/types/utils/KnownStarknetConnectors.d.ts +6 -0
  29. package/dist/types/utils/KnownStarknetConnectors.d.ts.map +1 -0
  30. package/dist/types/utils/index.d.ts +4 -0
  31. package/dist/types/utils/index.d.ts.map +1 -0
  32. package/dist/types/utils/resolveIcon.d.ts +6 -0
  33. package/dist/types/utils/resolveIcon.d.ts.map +1 -0
  34. package/dist/types/utils/starkNetAddressValidator.d.ts +2 -0
  35. package/dist/types/utils/starkNetAddressValidator.d.ts.map +1 -0
  36. package/package.json +66 -0
@@ -0,0 +1,159 @@
1
+ import { useConnect, useDisconnect } from "@starknet-react/core";
2
+ import { TransactionMessageType } from "@layerswap/widget/types";
3
+ import { KnownInternalNames, useWalletStore } from "@layerswap/widget/internal";
4
+ import { resolveStarknetWalletConnectorIcon } from "./utils";
5
+ const starknetNames = [KnownInternalNames.Networks.StarkNetGoerli, KnownInternalNames.Networks.StarkNetMainnet, KnownInternalNames.Networks.StarkNetSepolia];
6
+ export default function useStarknetConnection({ networks }) {
7
+ const commonSupportedNetworks = [
8
+ KnownInternalNames.Networks.StarkNetMainnet,
9
+ KnownInternalNames.Networks.StarkNetGoerli,
10
+ KnownInternalNames.Networks.StarkNetSepolia
11
+ ];
12
+ const withdrawalSupportedNetworks = [
13
+ ...commonSupportedNetworks
14
+ ];
15
+ const name = 'Starknet';
16
+ const id = 'starknet';
17
+ const { connectors } = useConnect();
18
+ const { disconnectAsync } = useDisconnect();
19
+ const wallets = useWalletStore((state) => state.connectedWallets);
20
+ const addWallet = useWalletStore((state) => state.connectWallet);
21
+ const removeWallet = useWalletStore((state) => state.disconnectWallet);
22
+ const isMainnet = networks?.some(network => network.name === KnownInternalNames.Networks.StarkNetMainnet);
23
+ const getWallet = () => {
24
+ const wallet = wallets.find(wallet => wallet.providerName === name);
25
+ if (!wallet)
26
+ return;
27
+ return [wallet];
28
+ };
29
+ const connectWallet = async ({ connector }) => {
30
+ try {
31
+ const wallet = getWallet();
32
+ if (wallet) {
33
+ await disconnectWallets();
34
+ }
35
+ const starknetConnector = connectors.find(c => c.id === connector.id);
36
+ const result = await starknetConnector?.connect({});
37
+ const walletChain = `0x${result?.chainId?.toString(16)}`;
38
+ const wrongChanin = walletChain == '0x534e5f4d41494e' ? !isMainnet : isMainnet;
39
+ if (result?.account && wrongChanin) {
40
+ disconnectWallets();
41
+ const errorMessage = `Please switch the network in your wallet to ${isMainnet ? 'Mainnet' : 'Sepolia'} and click connect again`;
42
+ throw new Error(errorMessage);
43
+ }
44
+ if (result?.account && starknetConnector) {
45
+ const starkent = networks.find(n => n.name === KnownInternalNames.Networks.StarkNetMainnet || n.name === KnownInternalNames.Networks.StarkNetSepolia);
46
+ const { RpcProvider, WalletAccount } = await import('starknet');
47
+ const rpcProvider = new RpcProvider({
48
+ nodeUrl: starkent?.node_url,
49
+ });
50
+ const starknetWalletAccount = await WalletAccount.connectSilent(rpcProvider, starknetConnector.wallet);
51
+ const wallet = {
52
+ id: connector.name,
53
+ displayName: `${connector.name} - Starknet`,
54
+ address: result?.account,
55
+ addresses: [result?.account],
56
+ chainId: walletChain,
57
+ icon: resolveStarknetWalletConnectorIcon({ connector: connector.name, address: result?.account }),
58
+ providerName: name,
59
+ metadata: {
60
+ starknetAccount: starknetWalletAccount,
61
+ // wallet: account
62
+ },
63
+ isActive: true,
64
+ disconnect: () => disconnectWallets(),
65
+ withdrawalSupportedNetworks,
66
+ autofillSupportedNetworks: commonSupportedNetworks,
67
+ asSourceSupportedNetworks: commonSupportedNetworks,
68
+ networkIcon: networks.find(n => starknetNames.some(name => name === n.name))?.logo
69
+ };
70
+ addWallet(wallet);
71
+ return wallet;
72
+ }
73
+ }
74
+ catch (e) {
75
+ console.log(e);
76
+ throw new Error(e);
77
+ }
78
+ };
79
+ const disconnectWallets = async () => {
80
+ try {
81
+ await disconnectAsync();
82
+ removeWallet(name);
83
+ }
84
+ catch (e) {
85
+ console.log(e);
86
+ }
87
+ };
88
+ const availableWalletsForConnect = connectors.map(connector => {
89
+ const name = (!connectorsConfigs.some(c => c.id === connector.id) || connector?.["_wallet"]) ? connector.name : `${connectorsConfigs.find(c => c.id === connector.id)?.name}`;
90
+ return {
91
+ name: name,
92
+ id: connector.id,
93
+ icon: typeof connector.icon === 'string' ? connector.icon : (connector.icon.light.startsWith('data:') ? connector.icon.light : `data:image/svg+xml;base64,${btoa(connector.icon.light.replaceAll('currentColor', '#FFFFFF'))}`),
94
+ type: connector?.["_wallet"] ? 'injected' : 'other',
95
+ installUrl: connector?.["_wallet"] ? undefined : connectorsConfigs.find(c => c.id === connector.id)?.installLink,
96
+ };
97
+ });
98
+ const switchAccount = async (wallet, address) => {
99
+ // as we do not have multiple accounts management we will leave the method empty
100
+ };
101
+ const transfer = async (params, wallet) => {
102
+ const { callData } = params;
103
+ try {
104
+ const { transaction_hash: transferTxHash } = (await wallet?.metadata?.starknetAccount?.execute(JSON.parse(callData || "")) || {});
105
+ if (transferTxHash) {
106
+ return transferTxHash;
107
+ }
108
+ }
109
+ catch (error) {
110
+ const e = new Error();
111
+ e.message = error;
112
+ if (error === "An error occurred (USER_REFUSED_OP)" || error === "Execute failed") {
113
+ e.name = TransactionMessageType.TransactionRejected;
114
+ throw e;
115
+ }
116
+ else if (error === "failedTransfer") {
117
+ e.name = TransactionMessageType.TransactionFailed;
118
+ throw e;
119
+ }
120
+ else {
121
+ e.name = TransactionMessageType.UexpectedErrorMessage;
122
+ throw e;
123
+ }
124
+ }
125
+ };
126
+ const provider = {
127
+ connectWallet,
128
+ disconnectWallets,
129
+ switchAccount,
130
+ transfer,
131
+ connectedWallets: getWallet(),
132
+ activeWallet: getWallet()?.[0],
133
+ withdrawalSupportedNetworks,
134
+ autofillSupportedNetworks: commonSupportedNetworks,
135
+ asSourceSupportedNetworks: commonSupportedNetworks,
136
+ availableWalletsForConnect,
137
+ name,
138
+ id,
139
+ providerIcon: networks.find(n => starknetNames.some(name => name === n.name))?.logo,
140
+ };
141
+ return provider;
142
+ }
143
+ const connectorsConfigs = [
144
+ {
145
+ id: "braavos",
146
+ name: "Braavos",
147
+ installLink: "https://chromewebstore.google.com/detail/braavos-starknet-wallet/jnlgamecbpmbajjfhmmmlhejkemejdma"
148
+ },
149
+ {
150
+ id: "argentX",
151
+ name: 'Argent X',
152
+ installLink: "https://chromewebstore.google.com/detail/argent-x-starknet-wallet/dlcobpjiigpikoobohmabehhmhfoodbb"
153
+ },
154
+ {
155
+ id: "keplr",
156
+ name: 'Keplr',
157
+ installLink: "https://chromewebstore.google.com/detail/keplr/dmkamcknogkgcdfhhbddcghachkejeap"
158
+ }
159
+ ];
@@ -0,0 +1,24 @@
1
+ import { ArgentXIcon, ArgentIcon, BraavosIcon, KeplrIcon } from "@layerswap/widget/internal";
2
+ const KnownStarknetConnectors = [
3
+ {
4
+ id: 'ready wallet (formerly argent)',
5
+ icon: ArgentXIcon
6
+ },
7
+ {
8
+ id: 'ready (formerly argent)',
9
+ icon: ArgentIcon
10
+ },
11
+ {
12
+ id: 'Ready (formerly Argent)',
13
+ icon: ArgentIcon
14
+ },
15
+ {
16
+ id: 'braavos',
17
+ icon: BraavosIcon
18
+ },
19
+ {
20
+ id: 'keplr',
21
+ icon: KeplrIcon
22
+ }
23
+ ];
24
+ export default KnownStarknetConnectors;
@@ -0,0 +1,3 @@
1
+ export * from "./starkNetAddressValidator";
2
+ export * from "./KnownStarknetConnectors";
3
+ export * from "./resolveIcon";
@@ -0,0 +1,9 @@
1
+ import { walletIconResolver } from "@layerswap/widget/internal";
2
+ import KnownStarknetConnectors from "./KnownStarknetConnectors";
3
+ export const resolveStarknetWalletConnectorIcon = ({ connector, address, iconUrl }) => {
4
+ const knownConnector = KnownStarknetConnectors.find(c => c.id.toLowerCase() === connector?.toLowerCase());
5
+ if (knownConnector && knownConnector.icon)
6
+ return knownConnector.icon;
7
+ else
8
+ return walletIconResolver(address, iconUrl);
9
+ };
@@ -0,0 +1,46 @@
1
+ import BN from 'bn.js';
2
+ const TWO = toBN(2);
3
+ const MASK_251 = TWO.pow(toBN(251));
4
+ const MASK_221 = TWO.pow(toBN(221));
5
+ export function validateAndParseAddress(address) {
6
+ if (typeof address !== 'string') {
7
+ return false;
8
+ }
9
+ if (!assertInRange(address, MASK_221, MASK_251)) {
10
+ return false;
11
+ }
12
+ const result = addAddressPadding(address);
13
+ if (!result.match(/^(0x)?[0-9a-fA-F]{64}$/)) {
14
+ return false;
15
+ }
16
+ return true;
17
+ }
18
+ function addAddressPadding(address) {
19
+ return addHexPrefix(removeHexPrefix(address).padStart(64, '0'));
20
+ }
21
+ function addHexPrefix(hex) {
22
+ return `0x${removeHexPrefix(hex)}`;
23
+ }
24
+ function removeHexPrefix(hex) {
25
+ return hex.replace(/^0x/, '');
26
+ }
27
+ function assertInRange(input, lowerBound, upperBound) {
28
+ try {
29
+ const inputBn = toBN(input);
30
+ if (!inputBn.gte(toBN(lowerBound)) || !inputBn.lt(toBN(upperBound))) {
31
+ return false;
32
+ }
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ return true;
38
+ }
39
+ function toBN(number, base) {
40
+ if (typeof number === 'string' && isHex(number) && !base)
41
+ return new BN(removeHexPrefix(number), 'hex');
42
+ return new BN(number, base);
43
+ }
44
+ function isHex(hex) {
45
+ return hex.startsWith('0x');
46
+ }