@txnlab/use-wallet 1.3.1 → 2.0.0-alpha.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 (108) hide show
  1. package/README.md +490 -188
  2. package/dist/cjs/index.js +231 -129
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/jest.config.d.ts +7 -0
  5. package/dist/cjs/src/clients/algosigner/client.d.ts +3 -3
  6. package/dist/cjs/src/clients/algosigner/types.d.ts +2 -8
  7. package/dist/cjs/src/clients/base/base.d.ts +3 -2
  8. package/dist/cjs/src/clients/base/index.d.ts +2 -2
  9. package/dist/cjs/src/clients/daffi/client.d.ts +5 -4
  10. package/dist/cjs/src/clients/daffi/types.d.ts +5 -7
  11. package/dist/cjs/src/clients/defly/client.d.ts +6 -5
  12. package/dist/cjs/src/clients/defly/types.d.ts +5 -7
  13. package/dist/cjs/src/clients/exodus/client.d.ts +6 -5
  14. package/dist/cjs/src/clients/exodus/types.d.ts +5 -10
  15. package/dist/cjs/src/clients/index.d.ts +1 -1
  16. package/dist/cjs/src/clients/kmd/client.d.ts +4 -5
  17. package/dist/cjs/src/clients/kmd/types.d.ts +4 -9
  18. package/dist/cjs/src/clients/mnemonic/client.d.ts +4 -5
  19. package/dist/cjs/src/clients/mnemonic/types.d.ts +2 -9
  20. package/dist/cjs/src/clients/myalgo/client.d.ts +6 -5
  21. package/dist/cjs/src/clients/myalgo/types.d.ts +10 -12
  22. package/dist/cjs/src/clients/pera/client.d.ts +6 -5
  23. package/dist/cjs/src/clients/pera/types.d.ts +5 -7
  24. package/dist/cjs/src/clients/{walletconnect → walletconnect2}/client.d.ts +8 -7
  25. package/dist/cjs/src/clients/walletconnect2/constants.d.ts +6 -0
  26. package/dist/cjs/src/clients/walletconnect2/index.d.ts +2 -0
  27. package/dist/cjs/src/clients/walletconnect2/types.d.ts +38 -0
  28. package/dist/cjs/src/clients/walletconnect2/utils.d.ts +2 -0
  29. package/dist/cjs/src/hooks/index.d.ts +1 -0
  30. package/dist/cjs/src/hooks/useInitializeProviders.d.ts +9 -0
  31. package/dist/cjs/src/hooks/useInitializeProviders.test.d.ts +4 -0
  32. package/dist/cjs/src/hooks/useWallet.d.ts +4 -13
  33. package/dist/cjs/src/hooks/useWallet.test.d.ts +4 -0
  34. package/dist/cjs/src/index.d.ts +1 -1
  35. package/dist/cjs/src/store/state/clientStore.d.ts +2 -23
  36. package/dist/cjs/src/testUtils/createWrapper.d.ts +6 -0
  37. package/dist/cjs/src/testUtils/mockAccounts.d.ts +3 -0
  38. package/dist/cjs/src/testUtils/mockClients.d.ts +33 -0
  39. package/dist/cjs/src/types/index.d.ts +1 -0
  40. package/dist/cjs/src/types/node.d.ts +2 -1
  41. package/dist/cjs/src/types/providers.d.ts +71 -0
  42. package/dist/cjs/src/types/wallet.d.ts +5 -3
  43. package/dist/cjs/src/utils/clearAccounts.d.ts +1 -1
  44. package/dist/cjs/src/utils/encodeNFDTransactionArray.spec.d.ts +1 -0
  45. package/dist/cjs/src/utils/initializeProviders.d.ts +2 -12
  46. package/dist/cjs/src/utils/initializeProviders.test.d.ts +4 -0
  47. package/dist/cjs/src/utils/providers.d.ts +1 -1
  48. package/dist/cjs/src/utils/providers.spec.d.ts +1 -0
  49. package/dist/cjs/src/utils/reconnectProviders.d.ts +1 -5
  50. package/dist/cjs/src/utils/reconnectProviders.test.d.ts +1 -0
  51. package/dist/cjs/src/utils/types.d.ts +2 -0
  52. package/dist/esm/index.js +231 -130
  53. package/dist/esm/jest.config.d.ts +7 -0
  54. package/dist/esm/src/clients/algosigner/client.d.ts +3 -3
  55. package/dist/esm/src/clients/algosigner/types.d.ts +2 -8
  56. package/dist/esm/src/clients/base/base.d.ts +3 -2
  57. package/dist/esm/src/clients/base/index.d.ts +2 -2
  58. package/dist/esm/src/clients/daffi/client.d.ts +5 -4
  59. package/dist/esm/src/clients/daffi/types.d.ts +5 -7
  60. package/dist/esm/src/clients/defly/client.d.ts +6 -5
  61. package/dist/esm/src/clients/defly/types.d.ts +5 -7
  62. package/dist/esm/src/clients/exodus/client.d.ts +6 -5
  63. package/dist/esm/src/clients/exodus/types.d.ts +5 -10
  64. package/dist/esm/src/clients/index.d.ts +1 -1
  65. package/dist/esm/src/clients/kmd/client.d.ts +4 -5
  66. package/dist/esm/src/clients/kmd/types.d.ts +4 -9
  67. package/dist/esm/src/clients/mnemonic/client.d.ts +4 -5
  68. package/dist/esm/src/clients/mnemonic/types.d.ts +2 -9
  69. package/dist/esm/src/clients/myalgo/client.d.ts +6 -5
  70. package/dist/esm/src/clients/myalgo/types.d.ts +10 -12
  71. package/dist/esm/src/clients/pera/client.d.ts +6 -5
  72. package/dist/esm/src/clients/pera/types.d.ts +5 -7
  73. package/dist/esm/src/clients/{walletconnect → walletconnect2}/client.d.ts +8 -7
  74. package/dist/esm/src/clients/walletconnect2/constants.d.ts +6 -0
  75. package/dist/esm/src/clients/walletconnect2/index.d.ts +2 -0
  76. package/dist/esm/src/clients/walletconnect2/types.d.ts +38 -0
  77. package/dist/esm/src/clients/walletconnect2/utils.d.ts +2 -0
  78. package/dist/esm/src/hooks/index.d.ts +1 -0
  79. package/dist/esm/src/hooks/useInitializeProviders.d.ts +9 -0
  80. package/dist/esm/src/hooks/useInitializeProviders.test.d.ts +4 -0
  81. package/dist/esm/src/hooks/useWallet.d.ts +4 -13
  82. package/dist/esm/src/hooks/useWallet.test.d.ts +4 -0
  83. package/dist/esm/src/index.d.ts +1 -1
  84. package/dist/esm/src/store/state/clientStore.d.ts +2 -23
  85. package/dist/esm/src/testUtils/createWrapper.d.ts +6 -0
  86. package/dist/esm/src/testUtils/mockAccounts.d.ts +3 -0
  87. package/dist/esm/src/testUtils/mockClients.d.ts +33 -0
  88. package/dist/esm/src/types/index.d.ts +1 -0
  89. package/dist/esm/src/types/node.d.ts +2 -1
  90. package/dist/esm/src/types/providers.d.ts +71 -0
  91. package/dist/esm/src/types/wallet.d.ts +5 -3
  92. package/dist/esm/src/utils/clearAccounts.d.ts +1 -1
  93. package/dist/esm/src/utils/encodeNFDTransactionArray.spec.d.ts +1 -0
  94. package/dist/esm/src/utils/initializeProviders.d.ts +2 -12
  95. package/dist/esm/src/utils/initializeProviders.test.d.ts +4 -0
  96. package/dist/esm/src/utils/providers.d.ts +1 -1
  97. package/dist/esm/src/utils/providers.spec.d.ts +1 -0
  98. package/dist/esm/src/utils/reconnectProviders.d.ts +1 -5
  99. package/dist/esm/src/utils/reconnectProviders.test.d.ts +1 -0
  100. package/dist/esm/src/utils/types.d.ts +2 -0
  101. package/dist/index.d.ts +240 -254
  102. package/package.json +17 -18
  103. package/dist/cjs/src/clients/walletconnect/constants.d.ts +0 -2
  104. package/dist/cjs/src/clients/walletconnect/index.d.ts +0 -2
  105. package/dist/cjs/src/clients/walletconnect/types.d.ts +0 -55
  106. package/dist/esm/src/clients/walletconnect/constants.d.ts +0 -2
  107. package/dist/esm/src/clients/walletconnect/index.d.ts +0 -2
  108. package/dist/esm/src/clients/walletconnect/types.d.ts +0 -55
package/README.md CHANGED
@@ -1,115 +1,208 @@
1
- # @TxnLab/use-wallet
1
+ # @txnlab/use-wallet
2
2
 
3
- React hooks for using Algorand compatible wallets with web applications. Flexible and extensible, `use-wallet` supports a variety of wallets and connection protocols. It also provides a simple interface for connecting, disconnecting, switching between accounts and signing transactions.
3
+ `@txnlab/use-wallet` is a React library that provides a simplified, consistent interface for integrating multiple Algorand wallets into your decentralized applications (dApps).
4
4
 
5
- ## Supported Providers
5
+ ## Overview
6
6
 
7
- - [Pera](https://perawallet.app/)
8
- - [MyAlgo](https://wallet.myalgo.com/home)
9
- - [Defly](https://defly.app)
10
- - [AlgoSigner](https://www.purestake.com/technology/algosigner)
11
- - [Exodus](https://www.exodus.com)
12
- - [WalletConnect](https://walletconnect.com)
13
- - [Daffi](https://www.daffi.me/)
14
- - [KMD](https://developer.algorand.org/docs/rest-apis/kmd)
7
+ With the `useWallet` hook and utility functions, you can:
15
8
 
16
- ## Demo
9
+ - Easily add or remove wallet support with a few lines of code
10
+ - Configure each wallet provider as needed for your application
11
+ - Allow users to easily switch between active accounts and wallet providers
12
+ - Sign and send transactions
13
+ - Restore sessions for returning users
17
14
 
18
- Preview a basic implementation in [Storybook](https://txnlab.github.io/use-wallet) or check out [this example](https://github.com/gabrielkuettel/use-wallet-example).
15
+ This library supports most Algorand wallet providers, including Defly, Pera, Daffi, and Exodus (see [Supported Wallet Providers](#supported-wallet-providers) for the full list).
19
16
 
20
- ## Quick Start
17
+ <!-- It provides an abstraction layer that handles the initialization, connection, and transaction signing logic, eliminating the need to interact with each wallet's individual API. -->
21
18
 
22
- ### Yarn
19
+ As of version 2.x it includes [WalletConnect 2.0 support](#walletconnect-20-support).
23
20
 
24
- ```bash
25
- yarn add @txnlab/use-wallet
26
- ```
21
+ ## Table of Contents
22
+
23
+ - [Live Examples](#live-examples)
24
+ - [Installation](#installation)
25
+ - [Initializing Providers](#initializing-providers)
26
+ - [The `useWallet` Hook](#the-usewallet-hook)
27
+ - [Type Definitions](#type-definitions)
28
+ - [Connect Menu](#connect-menu)
29
+ - [Displaying Account Details](#displaying-account-details)
30
+ - [Signing and Sending Transactions](#signing-and-sending-transactions)
31
+ - [Checking Connection Status](#checking-connection-status)
32
+ - [Supported Wallet Providers](#supported-wallet-providers)
33
+ - [Legacy Wallet Support](#legacy-wallet-support)
34
+ - [Provider Configuration](#provider-configuration)
35
+ - [Default configuration](#default-configuration)
36
+ - [Node configuration](#node-configuration)
37
+ - [Customize provider support](#customize-provider-support)
38
+ - [Provider objects](#provider-objects)
39
+ - [Static imports](#static-imports)
40
+ - [WalletConnect 2.0 Support](#walletconnect-20-support)
41
+ - [Migration Guide](#migration-guide)
42
+ - [Local Development](#local-development)
43
+ - [Used By](#used-by)
44
+ - [License](#license)
45
+
46
+ ## Live Examples
47
+
48
+ **Storybook demo** - https://txnlab.github.io/use-wallet
49
+
50
+ **Next.js example**
27
51
 
28
- Install peer dependencies (if needed)
52
+ - Demo - https://next-use-wallet.vercel.app/
53
+ - Code - https://github.com/TxnLab/next-use-wallet
54
+
55
+ **NFDomains** - https://app.nf.domains/
56
+
57
+ ## Installation
58
+
59
+ Since this library uses React Hooks, your app will need to be using React 16.8 or higher.
60
+
61
+ First, install the library
29
62
 
30
63
  ```bash
31
- yarn add algosdk @blockshake/defly-connect @perawallet/connect @randlabs/myalgo-connect @walletconnect/client algorand-walletconnect-qrcode-modal @json-rpc-tools/utils @daffiwallet/connect
64
+ npm install @txnlab/use-wallet
32
65
  ```
33
66
 
34
- ### NPM
67
+ If you haven't already, install the Algorand JS SDK
35
68
 
36
69
  ```bash
37
- npm install @txnlab/use-wallet
70
+ npm install algosdk
38
71
  ```
39
72
 
40
- Install peer dependencies (if needed)
73
+ Finally, install the peer dependencies for the wallets you wish to support. To use the default configuration:
41
74
 
42
75
  ```bash
43
- npm install algosdk @blockshake/defly-connect @perawallet/connect @randlabs/myalgo-connect @walletconnect/client algorand-walletconnect-qrcode-modal @json-rpc-tools/utils @daffiwallet/connect
76
+ npm install @perawallet/connect @blockshake/defly-connect @daffiwallet/connect
44
77
  ```
45
78
 
46
- ### Set up the Wallet Provider
79
+ Replace `npm install` with `yarn add` or `pnpm add` in the commands above, depending on your preferred package manager.
47
80
 
48
- In `app.js`, initialize the Wallet Provider so that the `useWallet` hook can be used in the child components, and use the `reconnectProviders` function to restore sessions for users returning to the app.
81
+ ## Initializing Providers
82
+
83
+ In the root of your app, initialize the `WalletProvider` with the `useInitializeProviders` hook.
84
+
85
+ This example initializes `useWallet` with the default configuration options. See [Provider Configuration](#provider-configuration) for more options.
49
86
 
50
87
  ```jsx
51
88
  import React from 'react'
52
- import { reconnectProviders, initializeProviders, WalletProvider } from '@txnlab/use-wallet'
53
-
54
- const walletProviders = initializeProviders()
89
+ import { WalletProvider, useInitializeProviders } from '@txnlab/use-wallet'
55
90
 
56
91
  export default function App() {
57
- // Reconnect the session when the user returns to the dApp
58
- React.useEffect(() => {
59
- reconnectProviders(walletProviders)
60
- }, [])
92
+ // default configuration
93
+ const providers = useInitializeProviders()
94
+
95
+ return (
96
+ <WalletProvider value={providers}>
97
+ <div className="App">{/* ... */}</div>
98
+ </WalletProvider>
99
+ )
100
+ }
101
+ ```
61
102
 
62
- return <WalletProvider value={walletProviders}>...</WalletProvider>
103
+ ## The `useWallet` Hook
104
+
105
+ The `useWallet` hook is used to access wallet provider and account state, send unsigned transactions to be signed, and send signed transactions to the node from anywhere in your app. It returns an object with the following properties:
106
+
107
+ - `providers` - Array of wallet providers that have been initialized (see `Provider` in [Type Definitions](#type-definitions))
108
+ - `activeAccount` - The currently active account in the active provider (see `Account` in [Type Definitions](#type-definitions))
109
+ - `connectedAccounts` - Array of accounts from all connected wallet providers
110
+ - `connectedActiveAccounts` - Array of accounts from the active wallet provider
111
+ - `activeAddress` - The address of `activeAccount`
112
+ - `status`, `isReady`, `isActive` - The current connection status, see [Check connection status](#check-connection-status)
113
+ - `signTransactions` - Function that sends unsigned transactions to active wallet provider for signature
114
+ - `sendTransactions` - Function that sends signed transactions to the node
115
+ - `groupTransactionsBySender` - Utility function that groups transactions by sender address
116
+ - `getAddress` - Utility function that returns the address of the `activeAccount`
117
+ - `getAccountInfo` - Utility function that fetches `activeAccount` account information from the node
118
+ - `getAssets` - Utility function that fetches `activeAccount` asset info/balances from the node
119
+ - `signer` - Function used by the [KMD](#kmd-algorand-key-management-daemon) provider to sign transactions
120
+
121
+ ## Type Definitions
122
+
123
+ ### `Provider`
124
+
125
+ ```ts
126
+ type Provider = {
127
+ accounts: Account[]
128
+ isActive: boolean
129
+ isConnected: boolean
130
+ connect: () => Promise<void>
131
+ disconnect: () => Promise<void>
132
+ reconnect: () => Promise<void>
133
+ setActiveProvider: () => void
134
+ setActiveAccount: (account: string) => void
135
+ metadata: Metadata
63
136
  }
64
137
  ```
65
138
 
66
- The `reconnectProviders` function is used to restore session states of wallets that rely on the `WalletConnect` protocol.
139
+ Each provider has two connection states: `isConnected` and `isActive`.
67
140
 
68
- By default, all of the supported providers except for `KMD` are returned by `useConnectWallet`. An array can be passed to `initializeProviders` to determine which providers your dApp supports, as shown below.
141
+ `isConnected` means that the user has authorized the provider in the app. Multiple providers can be connected at the same time.
69
142
 
70
- ```jsx
71
- import { initializeProviders, PROVIDER_ID } from '@txnlab/use-wallet'
143
+ `isActive` means that the provider is currently active and will be used to sign and send transactions.
144
+
145
+ ### `Account`
72
146
 
73
- const walletProviders = initializeProviders([PROVIDER_ID.KMD_WALLET, PROVIDER_ID.WALLET_CONNECT])
147
+ ```ts
148
+ interface Account {
149
+ providerId: PROVIDER_ID
150
+ name: string
151
+ address: string
152
+ authAddr?: string
153
+ }
74
154
  ```
75
155
 
76
- For more configuration options, see [Provider Configuration](#provider-configuration).
156
+ The `activeAccount` is the account that will be used to sign and send transactions.
157
+
158
+ To get the currently active wallet provider, read the `providerId` property of `activeAccount`.
159
+
160
+ ## Connect Menu
77
161
 
78
- ### Connect
162
+ In your app's UI you will need a menu for the user to `connect` or `disconnect` wallet providers, `setActiveProvider`, and `setActiveAccount`.
79
163
 
80
- Map through the `providers` object to list the providers and enable users to connect.
164
+ This is a bare-bones example for demonstration purposes. For a styled example, see https://app.nf.domains/
81
165
 
82
166
  ```jsx
83
167
  import React from 'react'
84
168
  import { useWallet } from '@txnlab/use-wallet'
85
169
 
86
- export default function Connect() {
170
+ export default function ConnectMenu() {
87
171
  const { providers, activeAccount } = useWallet()
88
172
 
89
- // Map through the providers.
90
- // Render account information and "connect", "set active", and "disconnect" buttons.
91
- // Finally, map through the `accounts` property to render a dropdown for each connected account.
173
+ // 1. Map over `providers` array
174
+ // 2. Show the provider name/icon and "Connect", "Set Active", and "Disconnect" buttons
175
+ // 3. If active, map `provider.accounts` to render a select menu of connected accounts
176
+
92
177
  return (
93
178
  <div>
94
179
  {providers?.map((provider) => (
95
- <div key={'provider-' + provider.metadata.id}>
180
+ <div key={provider.metadata.id}>
96
181
  <h4>
97
- <img width={30} height={30} alt="" src={provider.metadata.icon} />
182
+ <img
183
+ width={30}
184
+ height={30}
185
+ alt={`${provider.metadata.name} icon`}
186
+ src={provider.metadata.icon}
187
+ />
98
188
  {provider.metadata.name} {provider.isActive && '[active]'}
99
189
  </h4>
190
+
100
191
  <div>
101
- <button onClick={provider.connect} disabled={provider.isConnected}>
192
+ <button type="button" onClick={provider.connect} disabled={provider.isConnected}>
102
193
  Connect
103
194
  </button>
104
- <button onClick={provider.disconnect} disabled={!provider.isConnected}>
195
+ <button type="button" onClick={provider.disconnect} disabled={!provider.isConnected}>
105
196
  Disconnect
106
197
  </button>
107
198
  <button
199
+ type="button"
108
200
  onClick={provider.setActiveProvider}
109
201
  disabled={!provider.isConnected || provider.isActive}
110
202
  >
111
203
  Set Active
112
204
  </button>
205
+
113
206
  <div>
114
207
  {provider.isActive && provider.accounts.length && (
115
208
  <select
@@ -132,27 +225,51 @@ export default function Connect() {
132
225
  }
133
226
  ```
134
227
 
135
- Each provider has two connection states: `isConnected` and `isActive`.
228
+ ## Displaying Account Details
136
229
 
137
- `isConnected` means that the user has authorized the provider to talk to the dApp. The connection flow does not need to be restarted when switching to this wallet from a different one.
230
+ The `activeAccount` object can be used to display details for the currently active account.
138
231
 
139
- `isActive` indicates that the provider is currently active and will be used to sign and send transactions when using the `useWallet` hook.
232
+ ```jsx
233
+ import React from 'react'
234
+ import { useWallet } from '@txnlab/use-wallet'
140
235
 
141
- The `activeAccount` is the primary account that is currently active and will be used to sign and send transactions.
236
+ export default function Account() {
237
+ const { activeAccount } = useWallet()
142
238
 
143
- ### Sign and send transactions
239
+ if (!activeAccount) {
240
+ return <p>No account active.</p>
241
+ }
144
242
 
145
- Construct a transaction using `algosdk`, and sign and send the transaction using the `signTransactions` and `sendTransactions` functions provided by the `useWallet` hook.
243
+ return (
244
+ <div>
245
+ <h4>Active Account</h4>
246
+ <p>
247
+ Name: <span>{activeAccount.name}</span>
248
+ </p>
249
+ <p>
250
+ Address: <span>{activeAccount.address}</span>
251
+ </p>
252
+ <p>
253
+ Provider: <span>{activeAccount.providerId}</span>
254
+ </p>
255
+ </div>
256
+ )
257
+ }
258
+ ```
259
+
260
+ ## Signing and Sending Transactions
261
+
262
+ Here is an example of a signing and sending simple pay transaction using `signTransactions` and `sendTransactions`.
146
263
 
147
264
  ```jsx
148
265
  import React from 'react'
266
+ import algosdk from 'algosdk'
149
267
  import {
150
268
  useWallet,
151
269
  DEFAULT_NODE_BASEURL,
152
270
  DEFAULT_NODE_TOKEN,
153
271
  DEFAULT_NODE_PORT
154
272
  } from '@txnlab/use-wallet'
155
- import algosdk from 'algosdk'
156
273
 
157
274
  const algodClient = new algosdk.Algodv2(DEFAULT_NODE_TOKEN, DEFAULT_NODE_BASEURL, DEFAULT_NODE_PORT)
158
275
 
@@ -160,28 +277,29 @@ export default function Transact() {
160
277
  const { activeAddress, signTransactions, sendTransactions } = useWallet()
161
278
 
162
279
  const sendTransaction = async (from?: string, to?: string, amount?: number) => {
163
- if (!from || !to || !amount) {
164
- throw new Error('Missing transaction params.')
280
+ try {
281
+ if (!from || !to || !amount) {
282
+ throw new Error('Missing transaction params.')
283
+ }
284
+
285
+ const suggestedParams = await algodClient.getTransactionParams().do()
286
+
287
+ const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
288
+ from,
289
+ to,
290
+ amount,
291
+ suggestedParams
292
+ })
293
+
294
+ const encodedTransaction = algosdk.encodeUnsignedTransaction(transaction)
295
+ const signedTransactions = await signTransactions([encodedTransaction])
296
+ const waitRoundsToConfirm = 4
297
+ const { id } = await sendTransactions(signedTransactions, waitRoundsToConfirm)
298
+
299
+ console.log('Successfully sent transaction. Transaction ID: ', id)
300
+ } catch (error) {
301
+ console.error(error)
165
302
  }
166
-
167
- const suggestedParams = await algodClient.getTransactionParams().do()
168
-
169
- const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
170
- from,
171
- to,
172
- amount,
173
- suggestedParams
174
- })
175
-
176
- const encodedTransaction = algosdk.encodeUnsignedTransaction(transaction)
177
-
178
- const signedTransactions = await signTransactions([encodedTransaction])
179
-
180
- const waitRoundsToConfirm = 4
181
-
182
- const { id } = await sendTransactions(signedTransactions, waitRoundsToConfirm)
183
-
184
- console.log('Successfully sent transaction. Transaction ID: ', id)
185
303
  }
186
304
 
187
305
  if (!activeAddress) {
@@ -190,10 +308,7 @@ export default function Transact() {
190
308
 
191
309
  return (
192
310
  <div>
193
- <button
194
- onClick={() => sendTransaction(activeAddress, activeAddress, 1000)}
195
- className="button"
196
- >
311
+ <button type="button" onClick={() => sendTransaction(activeAddress, activeAddress, 1000)}>
197
312
  Sign and send transactions
198
313
  </button>
199
314
  </div>
@@ -201,41 +316,42 @@ export default function Transact() {
201
316
  }
202
317
  ```
203
318
 
204
- ### Display account details
205
-
206
- The `activeAccount` object can be used to display details for the currently active account. For convenience, the `activeAddress` property shows the currently active address.
319
+ ### signTransactions
207
320
 
208
321
  ```jsx
209
- import React from 'react'
210
- import { useWallet } from '@txnlab/use-wallet'
322
+ const signTransactions: (
323
+ transactions: Uint8Array[] | Uint8Array[][],
324
+ indexesToSign?: number[],
325
+ returnGroup?: boolean // defaults to true
326
+ ) => Promise<Uint8Array[]>
327
+ ```
211
328
 
212
- export default function Account() {
213
- const { activeAccount } = useWallet()
329
+ The `signTransactions` function will accept an array of transactions or an array of transaction groups.
214
330
 
215
- if (!activeAccount) {
216
- return <p>No account active.</p>
217
- }
331
+ You can optionally specify which transactions should be signed by providing an array of indexes as the second argument, `indexesToSign`.
218
332
 
219
- return (
220
- <div>
221
- <h4>Active Account</h4>
222
- <p>
223
- Name: <span>{activeAccount.name}</span>
224
- </p>
225
- <p>
226
- Address: <span>{activeAccount.address}</span>
227
- </p>
228
- <p>
229
- Provider: <span>{activeAccount.providerId}</span>
230
- </p>
231
- </div>
232
- )
233
- }
333
+ By setting `returnGroup` to `false`, the returned promise will resolve to an array of signed transactions only. Otherwise it will return flat array of all transactions by default.
334
+
335
+ ### sendTransactions
336
+
337
+ ```jsx
338
+ const sendTransactions: (
339
+ signedTransactions: Uint8Array[],
340
+ waitRoundsToConfirm?: number
341
+ ) => Promise<PendingTransactionResponse & { id: string }>
234
342
  ```
235
343
 
236
- ### Check connection status
344
+ If `signTransactions` is successful, the returned array of transactions can be passed to `sendTransactions` to be sent to the network.
345
+
346
+ It will wait for confirmation before resolving the promise. Use the optional argument `waitRoundsToConfirm` to indicate how many rounds to wait for confirmation.
347
+
348
+ The promise will resolve to an object containing the transaction `id` and the [`PendingTransactionResponse`](https://developer.algorand.org/docs/rest-apis/algod/#pendingtransactionresponse) from the Algorand REST API.
237
349
 
238
- The `isActive` and `isReady` properties can be used to check the status of the wallets. The `isActive` property determines whether or not an account is currently active. The `isReady` property shows if `use-wallet` has mounted and successfully read the connection status from the providers. These properties are useful when setting up client side access restrictions, for example, by redirecting a user if no wallet is active, as shown below.
350
+ ## Checking Connection Status
351
+
352
+ The `isActive` and `isReady` properties can be used to check the status of the wallet providers. The `isActive` property determines whether or not an account is currently active. The `isReady` property indicates whether `use-wallet` has mounted and successfully read the connection status from the providers.
353
+
354
+ These properties are useful when setting up client side access restrictions, for example, by redirecting a user if no wallet provider `isActive`, as shown below.
239
355
 
240
356
  ```jsx
241
357
  const { isActive, isReady } = useWallet()
@@ -251,107 +367,292 @@ useEffect(() => {
251
367
  })
252
368
  ```
253
369
 
370
+ ## Supported Wallet Providers
371
+
372
+ ### Pera Wallet
373
+
374
+ - Website - https://perawallet.app/
375
+ - Download Pera Mobile - [iOS](https://apps.apple.com/us/app/algorand-wallet/id1459898525) / [Android](https://play.google.com/store/apps/details?id=com.algorand.android)
376
+ - Pera Web Wallet - https://web.perawallet.app/
377
+ - Pera Connect - https://github.com/perawallet/connect
378
+
379
+ ### Defly Wallet
380
+
381
+ - Website - https://defly.app/
382
+ - Download Defly Wallet - [iOS](https://apps.apple.com/us/app/defly/id1602672723) / [Android](https://play.google.com/store/apps/details?id=io.blockshake.defly.app)
383
+ - Defly Connect - https://github.com/blockshake-io/defly-connect
384
+
385
+ ### Daffi Wallet
386
+
387
+ - Website - https://www.daffi.me/
388
+ - Download Daffi Wallet - [iOS](https://apps.apple.com/kn/app/daffiwallet/id1659597876) / [Android](https://play.google.com/store/apps/details?id=me.daffi.daffi_wallet)
389
+ - Daffi Connect - https://github.com/RDinitiativ/daffiwallet_connect
390
+
391
+ ### WalletConnect
392
+
393
+ - Website - https://walletconnect.com/
394
+ - Documentation - https://docs.walletconnect.com/
395
+ - WalletConnect Cloud - https://cloud.walletconnect.com/
396
+ - Web3Modal - https://web3modal.com/
397
+
398
+ ### Exodus Wallet
399
+
400
+ - Website - https://www.exodus.com/
401
+ - Download - https://www.exodus.com/download/
402
+
403
+ ### KMD (Algorand Key Management Daemon)
404
+
405
+ - Documentation - https://developer.algorand.org/docs/rest-apis/kmd
406
+
407
+ ## Legacy Wallet Support
408
+
409
+ Support for these wallets will be removed in a future release.
410
+
411
+ ### AlgoSigner
412
+
413
+ - GitHub - https://github.com/PureStake/algosigner
414
+ - EOL Press Release - https://www.algorand.foundation/news/algosigner-support-ending
415
+
416
+ ### MyAlgo
417
+
418
+ - Website - https://wallet.myalgo.com/home
419
+ - FAQ - https://wallet.myalgo.com/home#faq
420
+
254
421
  ## Provider Configuration
255
422
 
256
- The `initializeProviders` functon accepts a configuration object that can be used to configure the nodes that the providers use to send transactions, as shown below.
423
+ ### Default Configuration
424
+
425
+ Calling `useInitializeProviders` with no arguments initializes the default supported wallet providers with the default node configuration:
426
+
427
+ | Key | Default Value |
428
+ | --------------------- | ------------------------------------------------------------------------------ |
429
+ | providers | `[PROVIDER_ID.PERA, PROVIDER_ID.DEFLY, PROVIDER_ID.DAFFI, PROVIDER_ID.EXODUS]` |
430
+ | nodeConfig.network | `'mainnet'` |
431
+ | nodeConfig.nodeServer | `'https://mainnet-api.algonode.cloud'` |
432
+ | nodeConfig.nodeToken | `''` |
433
+ | nodeConfig.nodePort | `443` |
434
+ | algosdkStatic | `undefined` |
257
435
 
258
436
  ```jsx
259
- const walletProviders = initializeProviders([], {
260
- network: 'devmodenet',
261
- nodeServer: 'http://algod',
262
- nodeToken: 'xxxxxxxxx',
263
- nodePort: '8080'
437
+ import React from 'react'
438
+ import { WalletProvider, useInitializeProviders } from '@txnlab/use-wallet'
439
+
440
+ export default function App() {
441
+ const providers = useInitializeProviders()
442
+
443
+ return (
444
+ <WalletProvider value={providers}>
445
+ <div className="App">{/* ... */}</div>
446
+ </WalletProvider>
447
+ )
448
+ }
449
+ ```
450
+
451
+ ### Node configuration
452
+
453
+ To configure the Algorand node that providers will use to send transactions, you can set the `nodeConfig` property. The `network` property should be specified as `mainnet`, `testnet`, `betanet` or the name of your local development network.
454
+
455
+ Refer to your wallet providers' documentation to see which networks they support.
456
+
457
+ ```jsx
458
+ const providers = await initializeProviders({
459
+ nodeConfig: {
460
+ network: 'testnet',
461
+ nodeServer: 'https://testnet-api.algonode.cloud',
462
+ nodeToken: '',
463
+ nodePort: '443'
464
+ }
264
465
  })
265
466
  ```
266
467
 
267
- Passing an empty array as the first argument enables all of the default providers. The `network` property should be specified as `betanet`, `testnet`, `mainnet` or the name of your local development network.
468
+ ### Customize provider support
268
469
 
269
- For more custom configuration options, the providers can be configured individually by creating an object and passing it to the `WalletProvider` where the key contains the provider ID, and the value calls the `init` function of the provider client. See below for an example:
470
+ You can choose which wallet providers to support by setting the `providers` property to an array of provider IDs or [provider objects](#provider-objects). The example below shows provider IDs being used.
270
471
 
271
472
  ```jsx
272
- ...
473
+ // Only initialize Pera and Defly providers
474
+ const providers = useInitializeProviders({
475
+ providers: [PROVIDER_ID.PERA, PROVIDER_ID.DEFLY]
476
+ })
477
+ ```
273
478
 
274
- import {
275
- PROVIDER_ID,
276
- pera,
277
- myalgo,
278
- } from "@txnlab/use-wallet";
279
-
280
- const walletProviders = {
281
- [PROVIDER_ID.PERA]: pera.init({
282
- clientOptions: {
283
- shouldShowSignTxnToast: true,
284
- },
285
- }),
286
- [PROVIDER_ID.MYALGO]: myalgo.init({
287
- network: "devmodenet",
288
- algodOptions: ["xxxxxxxxx", "http://algod", "8080"],
289
- clientOptions: { disableLedgerNano: true },
290
- }),
291
- };
292
-
293
- ...
294
-
295
- <WalletProvider value={walletProviders}>
296
- ...
297
- </WalletProvider>
479
+ ### Provider objects
480
+
481
+ Some wallet providers have accompanying client libraries that can be configured. You can pass an object to the providers array to set `clientOptions`, as shown below.
482
+
483
+ ```jsx
484
+ const providers = useInitializeProviders({
485
+ providers: [
486
+ PROVIDER_ID.DEFLY, // use default options for Defly Connect
487
+ { id: PROVIDER_ID.PERA, clientOptions: { shouldShowSignTxnToast: false } },
488
+ { id: PROVIDER_ID.MYALGO, clientOptions: { disableLedgerNano: false } },
489
+ PROVIDER_ID.EXODUS // Exodus has no client library
490
+ ]
491
+ })
298
492
  ```
299
493
 
300
- ## Static Imports
494
+ See each provider's documentation for the available client options.
495
+
496
+ You will need to use provider objects for [static imports](#static-imports), and for [WalletConnect 2.0](#walletconnect-20) support.
497
+
498
+ **TypeScript:** The provider objects are type-safe, so your IDE should be able to provide autocomplete suggestions for the client's available options based on the `id` that is set.
301
499
 
302
- By default, `use-wallet` dynamically imports all of the dependencies for the providiers, as well as `algosdk`, to reduce bundle size.
500
+ ### Static Imports
303
501
 
304
- Some React frameworks, like [Remix](https://remix.run/), do not support dynamic imports. To get around this, those dependencies can be imported in your application and passed to the `useWallet` provider. See below for an example.
502
+ By default, `use-wallet` dynamically imports all of the dependencies for the providers, as well as `algosdk`, to reduce bundle size.
503
+
504
+ Some React frameworks, like [Remix](https://remix.run/), do not support dynamic imports. To get around this, provider clients can be imported in your application and passed to the provider objects `clientStatic` property.
505
+
506
+ Set the imported `algosdk` to the `algosdkStatic` root property.
305
507
 
306
508
  ```jsx
307
- ...
308
-
309
- import algosdk from "algosdk";
310
- import MyAlgoConnect from "@randlabs/myalgo-connect";
311
- import { PeraWalletConnect } from "@perawallet/connect";
312
- import { DeflyWalletConnect } from "@blockshake/defly-connect";
313
- import WalletConnect from "@walletconnect/client";
314
- import QRCodeModal from "algorand-walletconnect-qrcode-modal";
315
-
316
- const walletProviders = {
317
- [PROVIDER_ID.PERA]: pera.init({
318
- algosdkStatic: algosdk,
319
- clientStatic: PeraWalletConnect,
320
- }),
321
- [PROVIDER_ID.MYALGO]: myalgo.init({
322
- algosdkStatic: algosdk,
323
- clientStatic: MyAlgoConnect,
324
- }),
325
- [PROVIDER_ID.DEFLY]: defly.init({
326
- algosdkStatic: algosdk,
327
- clientStatic: DeflyWalletConnect,
328
- }),
329
- [PROVIDER_ID.EXODUS]: exodus.init({
330
- algosdkStatic: algosdk,
331
- }),
332
- [PROVIDER_ID.ALGOSIGNER]: algosigner.init({
333
- algosdkStatic: algosdk,
334
- }),
335
- [PROVIDER_ID.WALLETCONNECT]: walletconnect.init({
336
- algosdkStatic: algosdk,
337
- clientStatic: WalletConnect,
338
- modalStatic: QRCodeModal,
339
- }),
340
- };
509
+ import React from 'react'
510
+ import algosdk from 'algosdk'
511
+ import { PROVIDER_ID, WalletProvider, useInitializeProviders } from '@txnlab/use-wallet'
512
+ import { DeflyWalletConnect } from '@blockshake/defly-connect'
513
+ import { PeraWalletConnect } from '@perawallet/connect'
514
+ import SignClient from '@walletconnect/sign-client'
515
+ import { WalletConnectModal } from '@walletconnect/modal'
341
516
 
342
517
  export default function App() {
343
- ...
518
+ const providers = useInitializeProviders({
519
+ providers: [
520
+ { id: PROVIDER_ID.PERA, clientStatic: PeraWalletConnect },
521
+ { id: PROVIDER_ID.DEFLY, clientStatic: DeflyWalletConnect },
522
+ {
523
+ id: PROVIDER_ID.WALLETCONNECT,
524
+ clientStatic: SignClient,
525
+ modalStatic: WalletConnectModal,
526
+ clientOptions: {
527
+ projectId: '<YOUR_PROJECT_ID>',
528
+ metadata: {
529
+ name: 'Example Dapp',
530
+ description: 'Example Dapp',
531
+ url: '#',
532
+ icons: ['https://walletconnect.com/walletconnect-logo.png']
533
+ }
534
+ }
535
+ },
536
+ PROVIDER_ID.EXODUS
537
+ ],
538
+ algosdkStatic: algosdk
539
+ })
344
540
 
345
541
  return (
346
- <WalletProvider value={walletProviders}>
347
- ...
542
+ <WalletProvider value={providers}>
543
+ <div className="App">{/* ... */}</div>
348
544
  </WalletProvider>
349
- );
545
+ )
350
546
  }
547
+ ```
548
+
549
+ ## WalletConnect 2.0 Support
550
+
551
+ `use-wallet` v2 introduces support for WalletConnect 2.0. This is a major upgrade to the WalletConnect protocol, and introduces a number of breaking changes for app developers to contend with.
552
+
553
+ However, Algorand apps with `use-wallet` will be able to support the new protocol with minimal effort:
554
+
555
+ 1. **Obtain a project ID** - You will need to obtain a project ID from [WalletConnect Cloud](https://cloud.walletconnect.com/). This is a simple process, and there is no waiting period. Every app will need its own unique project ID.
556
+
557
+ 2. **Install peer dependencies** - Install `@walletconnect/sign-client` and `@walletconnect/modal`.
558
+
559
+ 3. **Update provider configuration** - You will need to use a provider object to initialize WalletConnect, and pass your `clientOptions` as shown below
351
560
 
561
+ ```jsx
562
+ const providers = useInitializeProviders({
563
+ providers: [
564
+ {
565
+ id: PROVIDER_ID.WALLETCONNECT,
566
+ clientOptions: {
567
+ projectId: '<YOUR_PROJECT_ID>',
568
+ metadata: {
569
+ name: 'Example Dapp',
570
+ description: 'Example Dapp',
571
+ url: '#',
572
+ icons: ['https://walletconnect.com/walletconnect-logo.png']
573
+ }
574
+ }
575
+ }
576
+ // other providers...
577
+ ]
578
+ })
352
579
  ```
353
580
 
354
- Note that some of the providers do not require static imports to be provided. This is usually the case of providers that are browser extensions.
581
+ Since it requires the unique `projectId`, the WalletConnect provider is not initialized by default. This is a change from v1. If you want to support WalletConnect, it must be added to the `providers` array.
582
+
583
+ See [Migrating to WalletConnect 2.0](#migrating-to-walletconnect-20) below for more information.
584
+
585
+ ## Migration Guide
586
+
587
+ Version 2.x is a major version bump, and includes some breaking changes from 1.x.
588
+
589
+ ### initializeProviders
590
+
591
+ `initializeProviders` is now asynchronous, and must be called from inside a `useEffect` hook.
592
+
593
+ To simplify this, the `useInitializeProviders` hook is now provided, which calls `initializeProviders` internally. It accepts a single object as an argument.
594
+
595
+ The providers array should be set as the `providers` property.
596
+
597
+ ```diff
598
+ - const providers = initializeProviders([PROVIDER_ID.PERA, PROVIDER_ID.DEFLY])
599
+ + const providers = useInitializeProviders({
600
+ + providers: [PROVIDER_ID.PERA, PROVIDER_ID.DEFLY]
601
+ + })
602
+ ```
603
+
604
+ Node configuration should be set as the `nodeConfig` property.
605
+
606
+ ```diff
607
+ - const providers = initializeProviders([], {
608
+ - network: 'testnet',
609
+ - nodeServer: 'https://testnet-api.algonode.cloud',
610
+ - nodeToken: '',
611
+ - nodePort: '443'
612
+ - })
613
+ + const providers = useInitializeProviders({
614
+ + nodeConfig: {
615
+ + network: 'testnet',
616
+ + nodeServer: 'https://testnet-api.algonode.cloud',
617
+ + nodeToken: '',
618
+ + nodePort: '443'
619
+ + }
620
+ + })
621
+ ```
622
+
623
+ See [Provider Configuration](#provider-configuration) for more details.
624
+
625
+ ### shouldShowSignTxnToast
626
+
627
+ Pera Connect and Defly Connect both have a `shouldShowSignTxnToast` option that is set to `true` by default. `use-wallet` v1 set this to `false` by default, and required setting the option back to `true` to achieve the libraries' default behavior.
628
+
629
+ In v2 this option is set to `true` by default. If your app has this option explicitly set you can remove it from your configuration. If you wish to disable the toast(s), you must now explicitly set the option to `false`.
630
+
631
+ ```jsx
632
+ const providers = useInitializeProviders({
633
+ providers: [
634
+ { id: PROVIDER_ID.DEFLY, clientOptions: { shouldShowSignTxnToast: false } },
635
+ { id: PROVIDER_ID.PERA, clientOptions: { shouldShowSignTxnToast: false } }
636
+ // other providers...
637
+ ]
638
+ })
639
+ ```
640
+
641
+ ### WalletConnect provider
642
+
643
+ The WalletConnect provider now supports WalletConnect 2.0. To continue supporting this provider, or to add support to your application, you must install the `@walletconnect/sign-client` and `@walletconnect/modal` packages.
644
+
645
+ ```bash
646
+ npm install @walletconnect/sign-client @walletconnect/modal
647
+ ```
648
+
649
+ The peer dependencies for WalletConnect 1.x should be uninstalled.
650
+
651
+ ```bash
652
+ npm uninstall @walletconnect/client @json-rpc-tools/utils algorand-walletconnect-qrcode-modal
653
+ ```
654
+
655
+ WalletConnect is no longer initialized by default. To add support for WalletConnect, you must add it to the `providers` array, and pass your `clientOptions` as described in [WalletConnect 2.0 Support](#walletconnect-20-support) above.
355
656
 
356
657
  ## Local Development
357
658
 
@@ -365,7 +666,6 @@ yarn install
365
666
 
366
667
  ```bash
367
668
  yarn dev
368
-
369
669
  ```
370
670
 
371
671
  To develop against a local version of `use-wallet` in your application, do the following:
@@ -397,17 +697,19 @@ In the root of your application, run:
397
697
  ```bash
398
698
  cd node_modules/react
399
699
  yarn link
700
+ cd ../react-dom
701
+ yarn link
400
702
  ```
401
703
 
402
- In the root of `use-wallet` directory, run:
704
+ In the root of the `use-wallet` directory, run:
403
705
 
404
706
  ```bash
405
- yarn link react
707
+ yarn link react react-dom
406
708
  ```
407
709
 
408
710
  ## Used By
409
711
 
410
- Are you using `@txnlab/use-wallet`? We'd love to include you here. Let us know! [Twitter](https://twitter.com/NFDomains) | [Discord](https://discord.gg/7XcuMTfeZP) | [Email](mailto:admin@txnlab.dev)
712
+ Are you using `@txnlab/use-wallet`? We'd love to include your project here. Let us know! [Twitter](https://twitter.com/NFDomains) | [Discord](https://discord.gg/7XcuMTfeZP) | [Email](mailto:admin@txnlab.dev)
411
713
 
412
714
  - [@algoscan/use-wallet-ui](https://github.com/algoscan/use-wallet-ui)
413
715
  - [@algoworldnft/algoworld-swapper](https://github.com/algoworldnft/algoworld-swapper)