@solana/react 2.0.0-20241006045741
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/LICENSE +20 -0
- package/README.md +311 -0
- package/dist/index.browser.cjs +294 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.mjs +286 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.native.mjs +286 -0
- package/dist/index.native.mjs.map +1 -0
- package/dist/index.node.cjs +294 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.mjs +286 -0
- package/dist/index.node.mjs.map +1 -0
- package/dist/types/chain.d.ts +5 -0
- package/dist/types/chain.d.ts.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/useSignAndSendTransaction.d.ts +16 -0
- package/dist/types/useSignAndSendTransaction.d.ts.map +1 -0
- package/dist/types/useSignIn.d.ts +13 -0
- package/dist/types/useSignIn.d.ts.map +1 -0
- package/dist/types/useSignMessage.d.ts +11 -0
- package/dist/types/useSignMessage.d.ts.map +1 -0
- package/dist/types/useSignTransaction.d.ts +16 -0
- package/dist/types/useSignTransaction.d.ts.map +1 -0
- package/dist/types/useWalletAccountMessageSigner.d.ts +7 -0
- package/dist/types/useWalletAccountMessageSigner.d.ts.map +1 -0
- package/dist/types/useWalletAccountTransactionSendingSigner.d.ts +9 -0
- package/dist/types/useWalletAccountTransactionSendingSigner.d.ts.map +1 -0
- package/dist/types/useWalletAccountTransactionSigner.d.ts +10 -0
- package/dist/types/useWalletAccountTransactionSigner.d.ts.map +1 -0
- package/package.json +99 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2023 Solana Labs, Inc
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
[![npm][npm-image]][npm-url]
|
|
2
|
+
[![npm-downloads][npm-downloads-image]][npm-url]
|
|
3
|
+
[![semantic-release][semantic-release-image]][semantic-release-url]
|
|
4
|
+
<br />
|
|
5
|
+
[![code-style-prettier][code-style-prettier-image]][code-style-prettier-url]
|
|
6
|
+
|
|
7
|
+
[code-style-prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square
|
|
8
|
+
[code-style-prettier-url]: https://github.com/prettier/prettier
|
|
9
|
+
[npm-downloads-image]: https://img.shields.io/npm/dm/@solana/react/rc.svg?style=flat
|
|
10
|
+
[npm-image]: https://img.shields.io/npm/v/@solana/react/rc.svg?style=flat
|
|
11
|
+
[npm-url]: https://www.npmjs.com/package/@solana/react/v/rc
|
|
12
|
+
[semantic-release-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
|
|
13
|
+
[semantic-release-url]: https://github.com/semantic-release/semantic-release
|
|
14
|
+
|
|
15
|
+
# @solana/react
|
|
16
|
+
|
|
17
|
+
This package contains React hooks for building Solana apps.
|
|
18
|
+
|
|
19
|
+
## Hooks
|
|
20
|
+
|
|
21
|
+
### `useSignIn(uiWalletAccount, chain)`
|
|
22
|
+
|
|
23
|
+
Given a `UiWallet` or `UiWalletAccount` this hook returns a function that you can call to trigger a wallet's [‘Sign In With Solana’](https://phantom.app/learn/developers/sign-in-with-solana) feature.
|
|
24
|
+
|
|
25
|
+
#### Example
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { useSignIn } from '@solana/react';
|
|
29
|
+
|
|
30
|
+
function SignInButton({ wallet }) {
|
|
31
|
+
const csrfToken = useCsrfToken();
|
|
32
|
+
const signIn = useSignIn(wallet);
|
|
33
|
+
return (
|
|
34
|
+
<button
|
|
35
|
+
onClick={async () => {
|
|
36
|
+
try {
|
|
37
|
+
const { account, signedMessage, signature } = await signIn({
|
|
38
|
+
requestId: csrfToken,
|
|
39
|
+
});
|
|
40
|
+
// Authenticate the user, typically on the server, by verifying that
|
|
41
|
+
// `signedMessage` was signed by the person who holds the private key for
|
|
42
|
+
// `account.publicKey`.
|
|
43
|
+
//
|
|
44
|
+
// Authorize the user, also on the server, by decoding `signedMessage` as the
|
|
45
|
+
// text of a Sign In With Solana message, verifying that it was not modified
|
|
46
|
+
// from the values your application expects, and that its content is sufficient
|
|
47
|
+
// to grant them access.
|
|
48
|
+
window.alert(`You are now signed in with the address ${account.address}`);
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.error('Failed to sign in', e);
|
|
51
|
+
}
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
Sign In
|
|
55
|
+
</button>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### `useWalletAccountMessageSigner(uiWalletAccount)`
|
|
61
|
+
|
|
62
|
+
Given a `UiWalletAccount`, this hook returns an object that conforms to the `MessageModifyingSigner` interface of `@solana/signers`.
|
|
63
|
+
|
|
64
|
+
#### Example
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { useWalletAccountMessageSigner } from '@solana/react';
|
|
68
|
+
import { createSignableMessage } from '@solana/signers';
|
|
69
|
+
|
|
70
|
+
function SignMessageButton({ account, text }) {
|
|
71
|
+
const messageSigner = useWalletAccountMessageSigner(account);
|
|
72
|
+
return (
|
|
73
|
+
<button
|
|
74
|
+
onClick={async () => {
|
|
75
|
+
try {
|
|
76
|
+
const signableMessage = createSignableMessage(text);
|
|
77
|
+
const [signedMessage] = await messageSigner.modifyAndSignMessages([signableMessage]);
|
|
78
|
+
const messageWasModified = signableMessage.content !== signedMessage.content;
|
|
79
|
+
const signatureBytes = signedMessage.signatures[messageSigner.address];
|
|
80
|
+
window.alert(
|
|
81
|
+
`Signature bytes: ${signatureBytes.toString()}${
|
|
82
|
+
messageWasModified ? ' (message was modified)' : ''
|
|
83
|
+
}`,
|
|
84
|
+
);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.error('Failed to sign message', e);
|
|
87
|
+
}
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
Sign Message: {text}
|
|
91
|
+
</button>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> [!NOTE]
|
|
97
|
+
> The type `MessageModifyingSigner` is returned from this hook instead of `MessageSigner` or `MessagePartialSigner`. This is a conservative assumption based on the fact that your application can not control whether or not the wallet will modify the message before signing it.
|
|
98
|
+
|
|
99
|
+
### `useWalletAccountTransactionSigner(uiWalletAccount, chain)`
|
|
100
|
+
|
|
101
|
+
Given a `UiWalletAccount` and a chain that begins with `solana:`, this hook returns an object that conforms to the `TransactionModifyingSigner` interface of `@solana/signers`.
|
|
102
|
+
|
|
103
|
+
#### Example
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { useWalletAccountTransactionSigner } from '@solana/react';
|
|
107
|
+
|
|
108
|
+
function SignTransactionButton({ account, transaction }) {
|
|
109
|
+
const transactionSigner = useWalletAccountTransactionSigner(account, 'solana:devnet');
|
|
110
|
+
return (
|
|
111
|
+
<button
|
|
112
|
+
onClick={async () => {
|
|
113
|
+
try {
|
|
114
|
+
const [{ signatures }] = await transactionSigner.modifyAndSignTransactions([transaction]);
|
|
115
|
+
const signatureBytes = signatures[transactionSigner.address];
|
|
116
|
+
window.alert(`Signature bytes: ${signatureBytes.toString()}`);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
console.error('Failed to sign transaction', e);
|
|
119
|
+
}
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
Sign Transaction
|
|
123
|
+
</button>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
> [!NOTE]
|
|
129
|
+
> The type `TransactionModifyingSigner` is returned from this hook instead of `TransactionSigner` or `TransactionPartialSigner`. This is a conservative assumption based on the fact that your application can not control whether or not the wallet will modify the transaction before signing it (eg. to add guard instructions, or a priority fee budget).
|
|
130
|
+
|
|
131
|
+
### `useWalletAccountTransactionSendingSigner(uiWalletAccount, chain)`
|
|
132
|
+
|
|
133
|
+
Given a `UiWalletAccount` and a chain that begins with `solana:`, this hook returns an object that conforms to the `TransactionSendingSigner` interface of `@solana/signers`.
|
|
134
|
+
|
|
135
|
+
#### Example
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import { useWalletAccountTransactionSendingSigner } from '@solana/react';
|
|
139
|
+
import {
|
|
140
|
+
appendTransactionMessageInstruction,
|
|
141
|
+
createSolanaRpc,
|
|
142
|
+
getBase58Decoder,
|
|
143
|
+
pipe,
|
|
144
|
+
setTransactionMessageFeePayerSigner,
|
|
145
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
146
|
+
signAndSendTransactionMessageWithSigners,
|
|
147
|
+
} from '@solana/web3.js';
|
|
148
|
+
|
|
149
|
+
function RecordMemoButton({ account, rpc, text }) {
|
|
150
|
+
const signer = useWalletAccountTransactionSendingSigner(account, 'solana:devnet');
|
|
151
|
+
return (
|
|
152
|
+
<button
|
|
153
|
+
onClick={async () => {
|
|
154
|
+
try {
|
|
155
|
+
const { value: latestBlockhash } = await createSolanaRpc('https://api.devnet.solana.com')
|
|
156
|
+
.getLatestBlockhash()
|
|
157
|
+
.send();
|
|
158
|
+
const message = pipe(
|
|
159
|
+
createTransactionMessage({ version: 'legacy' }),
|
|
160
|
+
m => setTransactionMessageFeePayerSigner(signer, m),
|
|
161
|
+
m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
|
|
162
|
+
m => appendTransactionMessageInstruction(getAddMemoInstruction({ memo: text }), m),
|
|
163
|
+
);
|
|
164
|
+
const signatureBytes = await signAndSendTransactionMessageWithSigners(message);
|
|
165
|
+
const base58Signature = getBase58Decoder().decode(signature);
|
|
166
|
+
window.alert(`View transaction: https://explorer.solana.com/tx/${base58Signature}?cluster=devnet`);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
console.error('Failed to record memo', e);
|
|
169
|
+
}
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
Record Memo
|
|
173
|
+
</button>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### `useSignMessage(uiWalletAccount)`
|
|
179
|
+
|
|
180
|
+
Given a `UiWalletAccount`, this hook returns a function you can call to sign a byte array.
|
|
181
|
+
|
|
182
|
+
#### Arguments
|
|
183
|
+
|
|
184
|
+
A config object with the following properties:
|
|
185
|
+
|
|
186
|
+
- `message`: A `Uint8Array` of bytes to sign
|
|
187
|
+
|
|
188
|
+
#### Returns
|
|
189
|
+
|
|
190
|
+
An object with the following properties:
|
|
191
|
+
|
|
192
|
+
- `signature`: The 64-byte Ed25519 signature as a `Uint8Array`
|
|
193
|
+
- `signedMessage`: The `Uint8Array` of bytes signed by the wallet. These bytes might differ from the input bytes if the wallet modified the message
|
|
194
|
+
|
|
195
|
+
#### Example
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import { useSignMessage } from '@solana/react';
|
|
199
|
+
|
|
200
|
+
function SignMessageButton({ account, messageBytes }) {
|
|
201
|
+
const signMessage = useSignMessage(account);
|
|
202
|
+
return (
|
|
203
|
+
<button
|
|
204
|
+
onClick={async () => {
|
|
205
|
+
try {
|
|
206
|
+
const { signature } = await signMessage({
|
|
207
|
+
message: messageBytes,
|
|
208
|
+
});
|
|
209
|
+
window.alert(`Signature bytes: ${signature.toString()}`);
|
|
210
|
+
} catch (e) {
|
|
211
|
+
console.error('Failed to sign message', e);
|
|
212
|
+
}
|
|
213
|
+
}}
|
|
214
|
+
>
|
|
215
|
+
Sign Message
|
|
216
|
+
</button>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### `useSignTransaction(uiWalletAccount, chain)`
|
|
222
|
+
|
|
223
|
+
Given a `UiWalletAccount` and a chain that begins with `solana:`, this hook returns a function you can call to sign a serialized transaction.
|
|
224
|
+
|
|
225
|
+
#### Arguments
|
|
226
|
+
|
|
227
|
+
A config object with the following properties:
|
|
228
|
+
|
|
229
|
+
- `options`: An object with the following properties:
|
|
230
|
+
- `minContextSlot`: A slot at which any blockhash/nonce in the transaction is known to exist. This may be used by the signer and/or RPC to determine the validity of the blockhashes/nonces it has observed.
|
|
231
|
+
- `transaction`: A `Uint8Array` of bytes that conforms to the [Solana transaction schema](https://solana.com/docs/core/transactions#transaction)
|
|
232
|
+
|
|
233
|
+
#### Returns
|
|
234
|
+
|
|
235
|
+
An object with the following properties:
|
|
236
|
+
|
|
237
|
+
- `signedTransaction`: A `Uint8Array` of bytes that conforms to the [Solana transaction schema](https://solana.com/docs/core/transactions#transaction)
|
|
238
|
+
|
|
239
|
+
#### Example
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import { useSignTransaction } from '@solana/react';
|
|
243
|
+
|
|
244
|
+
function SignTransactionButton({ account, transactionBytes }) {
|
|
245
|
+
const signTransaction = useSignTransaction(account, 'solana:devnet');
|
|
246
|
+
return (
|
|
247
|
+
<button
|
|
248
|
+
onClick={async () => {
|
|
249
|
+
try {
|
|
250
|
+
const { signedTransaction } = await signTransaction({
|
|
251
|
+
transaction: transactionBytes,
|
|
252
|
+
});
|
|
253
|
+
window.alert(`Signed transaction bytes: ${signedTransaction.toString()}`);
|
|
254
|
+
} catch (e) {
|
|
255
|
+
console.error('Failed to sign transaction', e);
|
|
256
|
+
}
|
|
257
|
+
}}
|
|
258
|
+
>
|
|
259
|
+
Sign Transaction
|
|
260
|
+
</button>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### `useSignAndSendTransaction(uiWalletAccount, chain)`
|
|
266
|
+
|
|
267
|
+
Given a `UiWalletAccount` and a chain that begins with `solana:`, this hook returns a function you can call to sign and send a serialized transaction.
|
|
268
|
+
|
|
269
|
+
#### Arguments
|
|
270
|
+
|
|
271
|
+
A config object with the following properties:
|
|
272
|
+
|
|
273
|
+
- `options`: An object with the following properties:
|
|
274
|
+
- `minContextSlot`: A slot at which any blockhash/nonce in the transaction is known to exist. This may be used by the signer and/or RPC to determine the validity of the blockhashes/nonces it has observed.
|
|
275
|
+
- `transaction`: A `Uint8Array` of bytes that conforms to the [Solana transaction schema](https://solana.com/docs/core/transactions#transaction)
|
|
276
|
+
|
|
277
|
+
#### Returns
|
|
278
|
+
|
|
279
|
+
That function returns an object with the following properties:
|
|
280
|
+
|
|
281
|
+
- `signature`: A `Uint8Array` of bytes representing the signature of the sent transaction.
|
|
282
|
+
|
|
283
|
+
#### Example
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
import { getBase58Decoder } from '@solana/codecs-strings';
|
|
287
|
+
import { useSignAndSendTransaction } from '@solana/react';
|
|
288
|
+
|
|
289
|
+
function SignAndSendTransactionButton({ account, transactionBytes }) {
|
|
290
|
+
const signAndSendTransaction = useSignAndSendTransaction(account, 'solana:devnet');
|
|
291
|
+
return (
|
|
292
|
+
<button
|
|
293
|
+
onClick={async () => {
|
|
294
|
+
try {
|
|
295
|
+
const { signature } = await signAndSendTransaction({
|
|
296
|
+
transaction: transactionBytes,
|
|
297
|
+
});
|
|
298
|
+
const base58TransactionSignature = getBase58Decoder().decode(signature);
|
|
299
|
+
window.alert(
|
|
300
|
+
`View transaction: https://explorer.solana.com/tx/${base58TransactionSignature}?cluster=devnet`,
|
|
301
|
+
);
|
|
302
|
+
} catch (e) {
|
|
303
|
+
console.error('Failed to send transaction', e);
|
|
304
|
+
}
|
|
305
|
+
}}
|
|
306
|
+
>
|
|
307
|
+
Sign and Send Transaction
|
|
308
|
+
</button>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
```
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var walletStandardFeatures = require('@solana/wallet-standard-features');
|
|
4
|
+
var errors = require('@wallet-standard/errors');
|
|
5
|
+
var ui = require('@wallet-standard/ui');
|
|
6
|
+
var uiRegistry = require('@wallet-standard/ui-registry');
|
|
7
|
+
var react = require('react');
|
|
8
|
+
var addresses = require('@solana/addresses');
|
|
9
|
+
var errors$1 = require('@solana/errors');
|
|
10
|
+
var promises = require('@solana/promises');
|
|
11
|
+
var transactions = require('@solana/transactions');
|
|
12
|
+
|
|
13
|
+
// src/useSignAndSendTransaction.ts
|
|
14
|
+
function useSignAndSendTransaction(uiWalletAccount, chain) {
|
|
15
|
+
const signAndSendTransactions = useSignAndSendTransactions(uiWalletAccount, chain);
|
|
16
|
+
return react.useCallback(
|
|
17
|
+
async (input) => {
|
|
18
|
+
const [result] = await signAndSendTransactions(input);
|
|
19
|
+
return result;
|
|
20
|
+
},
|
|
21
|
+
[signAndSendTransactions]
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function useSignAndSendTransactions(uiWalletAccount, chain) {
|
|
25
|
+
if (!uiWalletAccount.chains.includes(chain)) {
|
|
26
|
+
throw new errors.WalletStandardError(errors.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED, {
|
|
27
|
+
address: uiWalletAccount.address,
|
|
28
|
+
chain,
|
|
29
|
+
featureName: walletStandardFeatures.SolanaSignAndSendTransaction,
|
|
30
|
+
supportedChains: [...uiWalletAccount.chains],
|
|
31
|
+
supportedFeatures: [...uiWalletAccount.features]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const signAndSendTransactionFeature = ui.getWalletAccountFeature(
|
|
35
|
+
uiWalletAccount,
|
|
36
|
+
walletStandardFeatures.SolanaSignAndSendTransaction
|
|
37
|
+
);
|
|
38
|
+
const account = uiRegistry.getWalletAccountForUiWalletAccount_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(uiWalletAccount);
|
|
39
|
+
return react.useCallback(
|
|
40
|
+
async (...inputs) => {
|
|
41
|
+
const inputsWithChainAndAccount = inputs.map(({ options, ...rest }) => {
|
|
42
|
+
const minContextSlot = options?.minContextSlot;
|
|
43
|
+
return {
|
|
44
|
+
...rest,
|
|
45
|
+
account,
|
|
46
|
+
chain,
|
|
47
|
+
...minContextSlot != null ? {
|
|
48
|
+
options: {
|
|
49
|
+
minContextSlot: Number(minContextSlot)
|
|
50
|
+
}
|
|
51
|
+
} : null
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
const results = await signAndSendTransactionFeature.signAndSendTransaction(...inputsWithChainAndAccount);
|
|
55
|
+
return results;
|
|
56
|
+
},
|
|
57
|
+
[account, chain, signAndSendTransactionFeature]
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
function useSignIn(uiWalletHandle) {
|
|
61
|
+
const signIns = useSignIns(uiWalletHandle);
|
|
62
|
+
return react.useCallback(
|
|
63
|
+
async (input) => {
|
|
64
|
+
const [result] = await signIns(input);
|
|
65
|
+
return result;
|
|
66
|
+
},
|
|
67
|
+
[signIns]
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
function useSignIns(uiWalletHandle) {
|
|
71
|
+
let signMessageFeature;
|
|
72
|
+
if ("address" in uiWalletHandle && typeof uiWalletHandle.address === "string") {
|
|
73
|
+
uiRegistry.getWalletAccountForUiWalletAccount_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(uiWalletHandle);
|
|
74
|
+
signMessageFeature = ui.getWalletAccountFeature(
|
|
75
|
+
uiWalletHandle,
|
|
76
|
+
walletStandardFeatures.SolanaSignIn
|
|
77
|
+
);
|
|
78
|
+
} else {
|
|
79
|
+
signMessageFeature = ui.getWalletFeature(uiWalletHandle, walletStandardFeatures.SolanaSignIn);
|
|
80
|
+
}
|
|
81
|
+
const wallet = uiRegistry.getWalletForHandle_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(uiWalletHandle);
|
|
82
|
+
return react.useCallback(
|
|
83
|
+
async (...inputs) => {
|
|
84
|
+
const inputsWithAddressAndChainId = inputs.map((input) => ({
|
|
85
|
+
...input,
|
|
86
|
+
// Prioritize the `UiWalletAccount` address if it exists.
|
|
87
|
+
..."address" in uiWalletHandle ? { address: uiWalletHandle.address } : null
|
|
88
|
+
}));
|
|
89
|
+
const results = await signMessageFeature.signIn(...inputsWithAddressAndChainId);
|
|
90
|
+
const resultsWithoutSignatureType = results.map(
|
|
91
|
+
({
|
|
92
|
+
account,
|
|
93
|
+
signatureType: _,
|
|
94
|
+
// Solana signatures are always of type `ed25519` so drop this property.
|
|
95
|
+
...rest
|
|
96
|
+
}) => ({
|
|
97
|
+
...rest,
|
|
98
|
+
account: uiRegistry.getOrCreateUiWalletAccountForStandardWalletAccount_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(
|
|
99
|
+
wallet,
|
|
100
|
+
account
|
|
101
|
+
)
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
return resultsWithoutSignatureType;
|
|
105
|
+
},
|
|
106
|
+
[signMessageFeature, uiWalletHandle, wallet]
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
function useSignMessage(...config) {
|
|
110
|
+
const signMessages = useSignMessages(...config);
|
|
111
|
+
return react.useCallback(
|
|
112
|
+
async (input) => {
|
|
113
|
+
const [result] = await signMessages(input);
|
|
114
|
+
return result;
|
|
115
|
+
},
|
|
116
|
+
[signMessages]
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
function useSignMessages(uiWalletAccount) {
|
|
120
|
+
const signMessageFeature = ui.getWalletAccountFeature(
|
|
121
|
+
uiWalletAccount,
|
|
122
|
+
walletStandardFeatures.SolanaSignMessage
|
|
123
|
+
);
|
|
124
|
+
const account = uiRegistry.getWalletAccountForUiWalletAccount_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(uiWalletAccount);
|
|
125
|
+
return react.useCallback(
|
|
126
|
+
async (...inputs) => {
|
|
127
|
+
const inputsWithAccount = inputs.map((input) => ({ ...input, account }));
|
|
128
|
+
const results = await signMessageFeature.signMessage(...inputsWithAccount);
|
|
129
|
+
const resultsWithoutSignatureType = results.map(
|
|
130
|
+
({
|
|
131
|
+
signatureType: _,
|
|
132
|
+
// Solana signatures are always of type `ed25519` so drop this property.
|
|
133
|
+
...rest
|
|
134
|
+
}) => rest
|
|
135
|
+
);
|
|
136
|
+
return resultsWithoutSignatureType;
|
|
137
|
+
},
|
|
138
|
+
[signMessageFeature, account]
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
function useSignTransaction(uiWalletAccount, chain) {
|
|
142
|
+
const signTransactions = useSignTransactions(uiWalletAccount, chain);
|
|
143
|
+
return react.useCallback(
|
|
144
|
+
async (input) => {
|
|
145
|
+
const [result] = await signTransactions(input);
|
|
146
|
+
return result;
|
|
147
|
+
},
|
|
148
|
+
[signTransactions]
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
function useSignTransactions(uiWalletAccount, chain) {
|
|
152
|
+
if (!uiWalletAccount.chains.includes(chain)) {
|
|
153
|
+
throw new errors.WalletStandardError(errors.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED, {
|
|
154
|
+
address: uiWalletAccount.address,
|
|
155
|
+
chain,
|
|
156
|
+
featureName: walletStandardFeatures.SolanaSignAndSendTransaction,
|
|
157
|
+
supportedChains: [...uiWalletAccount.chains],
|
|
158
|
+
supportedFeatures: [...uiWalletAccount.features]
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
const signTransactionFeature = ui.getWalletAccountFeature(
|
|
162
|
+
uiWalletAccount,
|
|
163
|
+
walletStandardFeatures.SolanaSignTransaction
|
|
164
|
+
);
|
|
165
|
+
const account = uiRegistry.getWalletAccountForUiWalletAccount_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(uiWalletAccount);
|
|
166
|
+
return react.useCallback(
|
|
167
|
+
async (...inputs) => {
|
|
168
|
+
const inputsWithAccountAndChain = inputs.map(({ options, ...rest }) => {
|
|
169
|
+
const minContextSlot = options?.minContextSlot;
|
|
170
|
+
return {
|
|
171
|
+
...rest,
|
|
172
|
+
account,
|
|
173
|
+
chain,
|
|
174
|
+
...minContextSlot != null ? {
|
|
175
|
+
options: {
|
|
176
|
+
minContextSlot: Number(minContextSlot)
|
|
177
|
+
}
|
|
178
|
+
} : null
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
const results = await signTransactionFeature.signTransaction(...inputsWithAccountAndChain);
|
|
182
|
+
return results;
|
|
183
|
+
},
|
|
184
|
+
[signTransactionFeature, account, chain]
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
function useWalletAccountMessageSigner(uiWalletAccount) {
|
|
188
|
+
const signMessage = useSignMessage(uiWalletAccount);
|
|
189
|
+
return react.useMemo(
|
|
190
|
+
() => ({
|
|
191
|
+
address: addresses.address(uiWalletAccount.address),
|
|
192
|
+
async modifyAndSignMessages(messages, config) {
|
|
193
|
+
config?.abortSignal?.throwIfAborted();
|
|
194
|
+
if (messages.length > 1) {
|
|
195
|
+
throw new errors$1.SolanaError(errors$1.SOLANA_ERROR__SIGNER__WALLET_MULTISIGN_UNIMPLEMENTED);
|
|
196
|
+
}
|
|
197
|
+
if (messages.length === 0) {
|
|
198
|
+
return messages;
|
|
199
|
+
}
|
|
200
|
+
const { content: originalMessage, signatures: originalSignatureMap } = messages[0];
|
|
201
|
+
const input = {
|
|
202
|
+
message: originalMessage
|
|
203
|
+
};
|
|
204
|
+
const { signedMessage, signature } = await promises.getAbortablePromise(signMessage(input), config?.abortSignal);
|
|
205
|
+
const messageWasModified = originalMessage.length !== signedMessage.length || originalMessage.some((originalByte, ii) => originalByte !== signedMessage[ii]);
|
|
206
|
+
const originalSignature = originalSignatureMap[uiWalletAccount.address];
|
|
207
|
+
const signatureIsNew = !originalSignature?.every((originalByte, ii) => originalByte === signature[ii]);
|
|
208
|
+
if (!signatureIsNew && !messageWasModified) {
|
|
209
|
+
return messages;
|
|
210
|
+
}
|
|
211
|
+
const nextSignatureMap = messageWasModified ? { [uiWalletAccount.address]: signature } : { ...originalSignatureMap, [uiWalletAccount.address]: signature };
|
|
212
|
+
const outputMessages = Object.freeze([
|
|
213
|
+
Object.freeze({
|
|
214
|
+
content: signedMessage,
|
|
215
|
+
signatures: Object.freeze(nextSignatureMap)
|
|
216
|
+
})
|
|
217
|
+
]);
|
|
218
|
+
return outputMessages;
|
|
219
|
+
}
|
|
220
|
+
}),
|
|
221
|
+
[uiWalletAccount, signMessage]
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
function useWalletAccountTransactionSigner(uiWalletAccount, chain) {
|
|
225
|
+
const encoderRef = react.useRef();
|
|
226
|
+
const signTransaction = useSignTransaction(uiWalletAccount, chain);
|
|
227
|
+
return react.useMemo(
|
|
228
|
+
() => ({
|
|
229
|
+
address: addresses.address(uiWalletAccount.address),
|
|
230
|
+
async modifyAndSignTransactions(transactions$1, config = {}) {
|
|
231
|
+
const { abortSignal, ...options } = config;
|
|
232
|
+
abortSignal?.throwIfAborted();
|
|
233
|
+
const transactionCodec = encoderRef.current ||= transactions.getTransactionCodec();
|
|
234
|
+
if (transactions$1.length > 1) {
|
|
235
|
+
throw new errors$1.SolanaError(errors$1.SOLANA_ERROR__SIGNER__WALLET_MULTISIGN_UNIMPLEMENTED);
|
|
236
|
+
}
|
|
237
|
+
if (transactions$1.length === 0) {
|
|
238
|
+
return transactions$1;
|
|
239
|
+
}
|
|
240
|
+
const [transaction] = transactions$1;
|
|
241
|
+
const wireTransactionBytes = transactionCodec.encode(transaction);
|
|
242
|
+
const inputWithOptions = {
|
|
243
|
+
...options,
|
|
244
|
+
transaction: wireTransactionBytes
|
|
245
|
+
};
|
|
246
|
+
const { signedTransaction } = await promises.getAbortablePromise(signTransaction(inputWithOptions), abortSignal);
|
|
247
|
+
const decodedSignedTransaction = transactionCodec.decode(
|
|
248
|
+
signedTransaction
|
|
249
|
+
);
|
|
250
|
+
return Object.freeze([decodedSignedTransaction]);
|
|
251
|
+
}
|
|
252
|
+
}),
|
|
253
|
+
[uiWalletAccount.address, signTransaction]
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
function useWalletAccountTransactionSendingSigner(uiWalletAccount, chain) {
|
|
257
|
+
const encoderRef = react.useRef();
|
|
258
|
+
const signAndSendTransaction = useSignAndSendTransaction(uiWalletAccount, chain);
|
|
259
|
+
return react.useMemo(
|
|
260
|
+
() => ({
|
|
261
|
+
address: addresses.address(uiWalletAccount.address),
|
|
262
|
+
async signAndSendTransactions(transactions$1, config = {}) {
|
|
263
|
+
const { abortSignal, ...options } = config;
|
|
264
|
+
abortSignal?.throwIfAborted();
|
|
265
|
+
const transactionEncoder = encoderRef.current ||= transactions.getTransactionEncoder();
|
|
266
|
+
if (transactions$1.length > 1) {
|
|
267
|
+
throw new errors$1.SolanaError(errors$1.SOLANA_ERROR__SIGNER__WALLET_MULTISIGN_UNIMPLEMENTED);
|
|
268
|
+
}
|
|
269
|
+
if (transactions$1.length === 0) {
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
const [transaction] = transactions$1;
|
|
273
|
+
const wireTransactionBytes = transactionEncoder.encode(transaction);
|
|
274
|
+
const inputWithOptions = {
|
|
275
|
+
...options,
|
|
276
|
+
transaction: wireTransactionBytes
|
|
277
|
+
};
|
|
278
|
+
const { signature } = await promises.getAbortablePromise(signAndSendTransaction(inputWithOptions), abortSignal);
|
|
279
|
+
return Object.freeze([signature]);
|
|
280
|
+
}
|
|
281
|
+
}),
|
|
282
|
+
[signAndSendTransaction, uiWalletAccount.address]
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
exports.useSignAndSendTransaction = useSignAndSendTransaction;
|
|
287
|
+
exports.useSignIn = useSignIn;
|
|
288
|
+
exports.useSignMessage = useSignMessage;
|
|
289
|
+
exports.useSignTransaction = useSignTransaction;
|
|
290
|
+
exports.useWalletAccountMessageSigner = useWalletAccountMessageSigner;
|
|
291
|
+
exports.useWalletAccountTransactionSendingSigner = useWalletAccountTransactionSendingSigner;
|
|
292
|
+
exports.useWalletAccountTransactionSigner = useWalletAccountTransactionSigner;
|
|
293
|
+
//# sourceMappingURL=index.browser.cjs.map
|
|
294
|
+
//# sourceMappingURL=index.browser.cjs.map
|