@meshconnect/web-link-sdk 2.1.0-rc.0 → 2.1.0-rc.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.
Files changed (51) hide show
  1. package/jest.setup.ts +4 -0
  2. package/package.json +20 -9
  3. package/src/Link.test.ts +395 -0
  4. package/src/Link.ts +350 -0
  5. package/src/index.ts +3 -0
  6. package/src/utils/__snapshots__/popup.test.ts.snap +90 -0
  7. package/src/utils/event-types.test.ts +24 -0
  8. package/src/utils/event-types.ts +226 -0
  9. package/src/utils/popup.test.ts +50 -0
  10. package/src/utils/popup.ts +132 -0
  11. package/src/utils/sdk-specs.test.ts +17 -0
  12. package/src/utils/sdk-specs.ts +6 -0
  13. package/src/utils/style.test.ts +33 -0
  14. package/src/utils/style.ts +15 -0
  15. package/src/utils/types.ts +156 -0
  16. package/src/utils/version.ts +1 -0
  17. package/src/utils/wagmiCoreConnectorsUtils.ts +332 -0
  18. package/src/utils/wallet-browser-event-types.ts +102 -0
  19. package/tools/copy.js +25 -0
  20. package/tools/update-version.js +10 -0
  21. package/tsconfig.json +14 -0
  22. package/Link.d.ts +0 -2
  23. package/Link.js +0 -420
  24. package/cjs/Link.js +0 -424
  25. package/cjs/index.js +0 -21
  26. package/cjs/utils/event-types.js +0 -31
  27. package/cjs/utils/popup.js +0 -39
  28. package/cjs/utils/sdk-specs.js +0 -8
  29. package/cjs/utils/style.js +0 -18
  30. package/cjs/utils/types.js +0 -2
  31. package/cjs/utils/version.js +0 -4
  32. package/cjs/utils/wagmiCoreConnectorsUtils.js +0 -425
  33. package/cjs/utils/wallet-browser-event-types.js +0 -17
  34. package/index.d.ts +0 -3
  35. package/index.js +0 -3
  36. package/utils/event-types.d.ts +0 -152
  37. package/utils/event-types.js +0 -27
  38. package/utils/popup.d.ts +0 -3
  39. package/utils/popup.js +0 -34
  40. package/utils/sdk-specs.d.ts +0 -4
  41. package/utils/sdk-specs.js +0 -5
  42. package/utils/style.d.ts +0 -3
  43. package/utils/style.js +0 -13
  44. package/utils/types.d.ts +0 -134
  45. package/utils/types.js +0 -1
  46. package/utils/version.d.ts +0 -1
  47. package/utils/version.js +0 -1
  48. package/utils/wagmiCoreConnectorsUtils.d.ts +0 -11
  49. package/utils/wagmiCoreConnectorsUtils.js +0 -414
  50. package/utils/wallet-browser-event-types.d.ts +0 -59
  51. package/utils/wallet-browser-event-types.js +0 -13
@@ -0,0 +1,332 @@
1
+ import {
2
+ getConnectors,
3
+ connect,
4
+ disconnect,
5
+ getAccount,
6
+ signMessage,
7
+ getBalance,
8
+ sendTransaction,
9
+ switchChain,
10
+ simulateContract,
11
+ writeContract,
12
+ createConfig,
13
+ http,
14
+ fallback,
15
+ type Connector,
16
+ type GetAccountReturnType,
17
+ type Config,
18
+ type GetBalanceReturnType,
19
+ type Transport,
20
+ BaseError,
21
+ ChainNotConfiguredError,
22
+ ConnectorAccountNotFoundError,
23
+ ConnectorAlreadyConnectedError,
24
+ ConnectorNotConnectedError,
25
+ ConnectorNotFoundError,
26
+ ProviderNotFoundError,
27
+ SwitchChainNotSupportedError
28
+ } from '@wagmi/core'
29
+
30
+ import { injected } from '@wagmi/connectors'
31
+ import {
32
+ WagmiInjectedConnectorData,
33
+ ConnectReturnTypeAndTxHash,
34
+ IncomingConfig,
35
+ Abi
36
+ } from './types'
37
+ import { parseUnits, Hash, Chain } from 'viem'
38
+
39
+ let resolveConfigReady: (value: Config | PromiseLike<Config>) => void
40
+
41
+ const configReady = new Promise<Config>(resolve => {
42
+ resolveConfigReady = resolve
43
+ })
44
+
45
+ const setConfig = (config: IncomingConfig) => {
46
+ try {
47
+ const transports: Record<number, Transport> = {}
48
+
49
+ for (const chainId in config.transports) {
50
+ const urls = config.transports[chainId]
51
+ if (Array.isArray(urls)) {
52
+ // If the URL is an array, create a fallback transport with multiple transports
53
+ transports[chainId] = fallback(urls.map(url => http(url)))
54
+ } else {
55
+ // If the URL is a string, create a single HTTP transport
56
+ transports[chainId] = http(urls)
57
+ }
58
+ }
59
+ const chainsTuple = [...config.chains] as [Chain, ...Chain[]]
60
+
61
+ const dynamicConfig = createConfig({
62
+ chains: chainsTuple,
63
+ multiInjectedProviderDiscovery: true,
64
+ transports: transports,
65
+ connectors: [injected()]
66
+ })
67
+
68
+ resolveConfigReady(dynamicConfig)
69
+ } catch (error) {
70
+ console.error('Error setting configuration:', error)
71
+ }
72
+ }
73
+
74
+ window.addEventListener('message', event => {
75
+ if (event.data.type === 'walletBrowserConfigInitialize') {
76
+ try {
77
+ const parsedConfig = JSON.parse(event.data.payload) as IncomingConfig
78
+ setConfig(parsedConfig)
79
+ } catch (error) {
80
+ console.error('Error parsing configuration:', error)
81
+ }
82
+ }
83
+ })
84
+
85
+ const configPromise = configReady
86
+
87
+ export const getWagmiCoreInjectedData = async (): Promise<
88
+ WagmiInjectedConnectorData[] | Error
89
+ > => {
90
+ return withWagmiErrorHandling(async () => {
91
+ const config = await configPromise
92
+ const connectors = await getConnectors(config)
93
+
94
+ const mappedConnectors: WagmiInjectedConnectorData[] = connectors.map(
95
+ ({ id, name, type, uid, icon }) => ({
96
+ id,
97
+ name,
98
+ type,
99
+ uid,
100
+ icon: icon || undefined
101
+ })
102
+ )
103
+ return mappedConnectors
104
+ })
105
+ }
106
+
107
+ export const connectToSpecificWallet = async (
108
+ walletName: string
109
+ ): Promise<ConnectReturnTypeAndTxHash | Error> => {
110
+ return withWagmiErrorHandling(async () => {
111
+ const config = await configPromise
112
+ const connectors = getConnectors(config)
113
+
114
+ const selectedConnector = connectors.find(
115
+ (connector: Connector) =>
116
+ connector.name.toLowerCase() === walletName.toLowerCase()
117
+ )
118
+
119
+ if (!selectedConnector) {
120
+ throw new Error(`No connector found for wallet: ${walletName}`)
121
+ }
122
+
123
+ await disconnectCurrentAccount(config, selectedConnector)
124
+
125
+ const result = await connect(config, { connector: selectedConnector })
126
+
127
+ const accountInfo = await getAccount(config)
128
+ const txSigned = await signedMessage(config, accountInfo)
129
+
130
+ return {
131
+ accounts: [...result.accounts],
132
+ chainId: result.chainId,
133
+ txSigned: txSigned as `0x${string}`
134
+ }
135
+ })
136
+ }
137
+
138
+ export const signedMessage = async (
139
+ config: Config,
140
+ accountInfo: GetAccountReturnType
141
+ ): Promise<Hash | Error> => {
142
+ if (!accountInfo.address) {
143
+ return new Error('Address not found')
144
+ }
145
+
146
+ return withWagmiErrorHandling(async () => {
147
+ const signedMessage = await signMessage(config, {
148
+ account: accountInfo.address,
149
+ message: 'Sign to verify ownership of wallet'
150
+ })
151
+
152
+ return signedMessage
153
+ })
154
+ }
155
+
156
+ export const walletBalance = async (
157
+ account: string,
158
+ chainId: number
159
+ ): Promise<GetBalanceReturnType | Error> => {
160
+ return withWagmiErrorHandling(async () => {
161
+ const config = await configPromise
162
+ const balance = await getBalance(config, {
163
+ address: account as `0x${string}`,
164
+ chainId: chainId
165
+ })
166
+ return balance
167
+ })
168
+ }
169
+
170
+ export const switchChainFromSDK = async (
171
+ chainId: number
172
+ ): Promise<Chain | Error> => {
173
+ return await withWagmiErrorHandling(async () => {
174
+ const config = await configPromise
175
+ const result = await switchChain(config, { chainId })
176
+ return result
177
+ })
178
+ }
179
+
180
+ export const sendTransactionFromSDK = async (
181
+ toAddress: string,
182
+ amount: number,
183
+ decimalPlaces: number,
184
+ chainId: number,
185
+ account: string
186
+ ): Promise<Hash | Error> => {
187
+ return await withWagmiErrorHandling(async () => {
188
+ const config = await configPromise
189
+ const result = await sendTransaction(config, {
190
+ to: formatAddress(toAddress) as `0x${string}`,
191
+ value: parseUnits(amount.toFixed(decimalPlaces) || '0', decimalPlaces),
192
+ chainId: chainId,
193
+ account: formatAddress(account) as `0x${string}`
194
+ })
195
+ return result
196
+ })
197
+ }
198
+
199
+ const formatAddress = (address: string) =>
200
+ address.startsWith('0x') ? address : `0x${address}`
201
+
202
+ export const sendNonNativeTransactionFromSDK = async (
203
+ address: string,
204
+ abi: Abi,
205
+ functionName: string,
206
+ args: any[], // eslint-disable-line @typescript-eslint/no-explicit-any
207
+ value?: bigint
208
+ ): Promise<Hash | Error> => {
209
+ return await withWagmiErrorHandling(async () => {
210
+ const config = await configPromise
211
+ const { connector } = await getAccount(config)
212
+ const { request } = await simulateContract(config, {
213
+ address: formatAddress(address) as `0x${string}`,
214
+ abi: abi,
215
+ functionName: functionName,
216
+ args: args,
217
+ value: value,
218
+ connector
219
+ })
220
+ const result = await writeContract(config, request)
221
+ return result
222
+ })
223
+ }
224
+
225
+ const disconnectCurrentAccount = async (
226
+ config: Config,
227
+ currentConnector: Connector
228
+ ): Promise<void | Error> => {
229
+ return await withWagmiErrorHandling(async () => {
230
+ await disconnect(config, { connector: currentConnector })
231
+ })
232
+ }
233
+
234
+ export const disconnectAllAccounts = async (): Promise<void | Error> => {
235
+ const config = await configPromise
236
+ return withWagmiErrorHandling(async () => {
237
+ await disconnect(config)
238
+ })
239
+ }
240
+
241
+ /**
242
+ * Wrapper function for Wagmi Core functions that handles errors
243
+ * @param fn - The function to wrap
244
+ * @returns - The result of the function or an error
245
+ */
246
+ async function withWagmiErrorHandling<T>(
247
+ fn: () => Promise<T>
248
+ ): Promise<T | Error> {
249
+ try {
250
+ return await fn()
251
+ } catch (error) {
252
+ if (error instanceof BaseError) {
253
+ return handleWagmiError(error)
254
+ } else {
255
+ if (error instanceof Error) {
256
+ throw new Error(error.message)
257
+ } else {
258
+ throw new Error('An unexpected error has occurred')
259
+ }
260
+ }
261
+ }
262
+ }
263
+
264
+ const handleWagmiError = (error: unknown): Error => {
265
+ if (error instanceof ChainNotConfiguredError) {
266
+ return handleChainNotConfiguredError(error)
267
+ } else if (error instanceof ConnectorAccountNotFoundError) {
268
+ return handleConnectorAccountNotFoundError(error)
269
+ } else if (error instanceof ConnectorAlreadyConnectedError) {
270
+ return handleConnectorAlreadyConnectedError(error)
271
+ } else if (error instanceof ConnectorNotConnectedError) {
272
+ return handleConnectorNotConnectedError(error)
273
+ } else if (error instanceof ConnectorNotFoundError) {
274
+ return handleConnectorNotFoundError(error)
275
+ } else if (error instanceof ProviderNotFoundError) {
276
+ return handleProviderNotFoundError(error)
277
+ } else if (error instanceof SwitchChainNotSupportedError) {
278
+ return handleSwitchChainNotSupportedError(error)
279
+ } else if (error instanceof BaseError) {
280
+ return handleBaseError(error)
281
+ } else {
282
+ // Handle unknown error types
283
+ if (error instanceof Error) {
284
+ throw new Error(error.message)
285
+ } else {
286
+ throw new Error('An unexpected error has occurred')
287
+ }
288
+ }
289
+ }
290
+
291
+ // All errors extend base error
292
+ const handleBaseError = (error: BaseError): Error => {
293
+ throw new Error(error.message)
294
+ }
295
+
296
+ const handleChainNotConfiguredError = (
297
+ error: ChainNotConfiguredError
298
+ ): Error => {
299
+ throw new Error(`Chain not configured: ${error.message}`)
300
+ }
301
+
302
+ const handleConnectorAccountNotFoundError = (
303
+ error: ConnectorAccountNotFoundError
304
+ ): Error => {
305
+ throw new Error(`Connector account not found: ${error.message}`)
306
+ }
307
+
308
+ const handleConnectorAlreadyConnectedError = (
309
+ error: ConnectorAlreadyConnectedError
310
+ ): Error => {
311
+ throw new Error(`Connector already connected: ${error.message}`)
312
+ }
313
+
314
+ const handleConnectorNotConnectedError = (
315
+ error: ConnectorNotConnectedError
316
+ ): Error => {
317
+ throw new Error(`Connector not connected: ${error.message}`)
318
+ }
319
+
320
+ const handleConnectorNotFoundError = (error: ConnectorNotFoundError): Error => {
321
+ throw new Error(`Connector not found: ${error.message}`)
322
+ }
323
+
324
+ const handleProviderNotFoundError = (error: ProviderNotFoundError): Error => {
325
+ throw new Error(`Provider not found: ${error.message}`)
326
+ }
327
+
328
+ const handleSwitchChainNotSupportedError = (
329
+ error: SwitchChainNotSupportedError
330
+ ): Error => {
331
+ throw new Error(`Switch chain not supported: ${error.message}`)
332
+ }
@@ -0,0 +1,102 @@
1
+ export type WalletBrowserEventType =
2
+ | WalletBrowserInjectedWalletSelected
3
+ | WalletBrowserChainSwitchRequest
4
+ | WalletBrowserTransferBalanceRequest
5
+ | WalletBrowserNativeTransferRequest
6
+ | WalletBrowserNonNativeTransferRequest
7
+ | WalletBrowserNativeSmartDeposit
8
+ | WalletBrowserNonNativeSmartDeposit
9
+ | WalletBrowserDisconnect
10
+
11
+ const WALLET_BROWSER_EVENT_TYPE_KEYS = [
12
+ 'walletBrowserInjectedWalletSelected',
13
+ 'walletBrowserChainSwitchRequest',
14
+ 'walletBrowserTransferBalanceRequest',
15
+ 'walletBrowserNativeTransferRequest',
16
+ 'walletBrowserNonNativeTransferRequest',
17
+ 'walletBrowserNativeSmartDeposit',
18
+ 'walletBrowserNonNativeSmartDeposit',
19
+ 'walletBrowserDisconnect'
20
+ ] as const
21
+
22
+ export type WalletBrowserEventTypeKeys =
23
+ (typeof WALLET_BROWSER_EVENT_TYPE_KEYS)[number]
24
+
25
+ export function isWalletBrowserEventTypeKey(
26
+ key: string
27
+ ): key is WalletBrowserEventTypeKeys {
28
+ return WALLET_BROWSER_EVENT_TYPE_KEYS.includes(
29
+ key as WalletBrowserEventTypeKeys
30
+ )
31
+ }
32
+
33
+ interface WalletBrowserEventBase {
34
+ type: WalletBrowserEventTypeKeys
35
+ }
36
+
37
+ export interface WalletBrowserInjectedWalletSelected
38
+ extends WalletBrowserEventBase {
39
+ type: 'walletBrowserInjectedWalletSelected'
40
+ payload: {
41
+ integrationName: string
42
+ }
43
+ }
44
+
45
+ export interface WalletBrowserChainSwitchRequest
46
+ extends WalletBrowserEventBase {
47
+ type: 'walletBrowserChainSwitchRequest'
48
+ payload: {
49
+ chainId: number
50
+ }
51
+ }
52
+
53
+ export interface WalletBrowserTransferBalanceRequest
54
+ extends WalletBrowserEventBase {
55
+ type: 'walletBrowserTransferBalanceRequest'
56
+ payload: {
57
+ account: string
58
+ chainId: number
59
+ }
60
+ }
61
+
62
+ export interface WalletBrowserNativeTransferRequest
63
+ extends WalletBrowserEventBase {
64
+ type: 'walletBrowserNativeTransferRequest'
65
+ payload: {
66
+ toAddress: string
67
+ amount: number
68
+ decimalPlaces: number
69
+ chainId: number
70
+ account: string
71
+ }
72
+ }
73
+
74
+ interface SmartContractPayload {
75
+ address: string
76
+ abi: string
77
+ functionName: string
78
+ args: any[] // eslint-disable-line @typescript-eslint/no-explicit-any
79
+ value?: bigint
80
+ }
81
+
82
+ export interface WalletBrowserNonNativeTransferRequest
83
+ extends WalletBrowserEventBase {
84
+ type: 'walletBrowserNonNativeTransferRequest'
85
+ payload: SmartContractPayload
86
+ }
87
+
88
+ export interface WalletBrowserNativeSmartDeposit
89
+ extends WalletBrowserEventBase {
90
+ type: 'walletBrowserNativeSmartDeposit'
91
+ payload: SmartContractPayload
92
+ }
93
+
94
+ export interface WalletBrowserNonNativeSmartDeposit
95
+ extends WalletBrowserEventBase {
96
+ type: 'walletBrowserNonNativeSmartDeposit'
97
+ payload: SmartContractPayload
98
+ }
99
+
100
+ export interface WalletBrowserDisconnect extends WalletBrowserEventBase {
101
+ type: 'walletBrowserDisconnect'
102
+ }
package/tools/copy.js ADDED
@@ -0,0 +1,25 @@
1
+ import fs from 'fs'
2
+
3
+ const rawData = fs.readFileSync('package.json')
4
+ const packageModel = JSON.parse(rawData)
5
+ delete packageModel.main
6
+ delete packageModel.module
7
+ delete packageModel.types
8
+ delete packageModel.scripts
9
+ delete packageModel.type
10
+
11
+ packageModel.main = './cjs/index.js'
12
+ packageModel.module = './index.js'
13
+ packageModel.types = './index.d.ts'
14
+
15
+ const versionFromNodeApi = fs.readFileSync('../node-api/package.json')
16
+ const version = JSON.parse(versionFromNodeApi).version
17
+
18
+ packageModel.dependencies['@meshconnect/node-api'] = `^${version}`
19
+
20
+ const data = JSON.stringify(packageModel, null, 2)
21
+ fs.writeFileSync('dist/package.json', data)
22
+ console.log('package.json.dist was copied to ./dist folder')
23
+
24
+ fs.copyFileSync('README.md', 'dist/README.md')
25
+ console.log('README.md was copied to ./dist folder')
@@ -0,0 +1,10 @@
1
+ import fs from 'fs'
2
+
3
+ const rawData = fs.readFileSync('package.json')
4
+ const packageModel = JSON.parse(rawData)
5
+ const version = packageModel?.version || '2.0.0'
6
+
7
+ fs.writeFileSync(
8
+ 'src/utils/version.ts',
9
+ `export const sdkVersion = '${version}'\n`
10
+ )
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist/",
5
+ "declaration": true,
6
+ "declarationDir": "./dist/",
7
+ "rootDir": "./src/",
8
+ "baseUrl": "./",
9
+ "paths": {
10
+ "@/*": ["src/*"]
11
+ }
12
+ },
13
+ "include": ["src/"]
14
+ }
package/Link.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { LinkOptions, Link } from './utils/types';
2
- export declare const createLink: (options: LinkOptions) => Link;