@vue-solana/core 0.1.2 → 0.2.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.
- package/README.md +26 -30
- package/dist/index.cjs +209 -0
- package/dist/index.d.cts +33 -6
- package/dist/index.d.mts +33 -6
- package/dist/index.d.ts +33 -6
- package/dist/index.mjs +202 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -14,9 +14,9 @@ Official Solana docs:
|
|
|
14
14
|
|
|
15
15
|
Full Vue Solana docs:
|
|
16
16
|
|
|
17
|
-
- [`@vue-solana/core`](https://
|
|
18
|
-
- [Getting Started](https://
|
|
19
|
-
- [Troubleshooting](https://
|
|
17
|
+
- [`@vue-solana/core`](https://vue-solana-docs.vercel.app/packages/core)
|
|
18
|
+
- [Getting Started](https://vue-solana-docs.vercel.app/getting-started)
|
|
19
|
+
- [Troubleshooting](https://vue-solana-docs.vercel.app/troubleshooting)
|
|
20
20
|
|
|
21
21
|
## Install
|
|
22
22
|
|
|
@@ -31,29 +31,29 @@ npm install @vue-solana/core @solana/web3-compat
|
|
|
31
31
|
## Quick Start
|
|
32
32
|
|
|
33
33
|
```ts
|
|
34
|
-
import { createSolanaContext } from
|
|
34
|
+
import { createSolanaContext } from "@vue-solana/core";
|
|
35
35
|
|
|
36
36
|
const solana = createSolanaContext({
|
|
37
|
-
cluster:
|
|
38
|
-
})
|
|
37
|
+
cluster: "devnet",
|
|
38
|
+
});
|
|
39
39
|
|
|
40
|
-
const { blockhash } = await solana.connection.getLatestBlockhash()
|
|
40
|
+
const { blockhash } = await solana.connection.getLatestBlockhash();
|
|
41
41
|
|
|
42
|
-
console.log(solana.endpoint, blockhash)
|
|
42
|
+
console.log(solana.endpoint, blockhash);
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
## Configuration
|
|
46
46
|
|
|
47
47
|
```ts
|
|
48
|
-
import type { SolanaConfig } from
|
|
48
|
+
import type { SolanaConfig } from "@vue-solana/core";
|
|
49
49
|
|
|
50
50
|
const config: SolanaConfig = {
|
|
51
|
-
cluster:
|
|
52
|
-
endpoint:
|
|
53
|
-
wsEndpoint:
|
|
54
|
-
commitment:
|
|
55
|
-
autoConnect: false
|
|
56
|
-
}
|
|
51
|
+
cluster: "devnet",
|
|
52
|
+
endpoint: "https://api.devnet.solana.com",
|
|
53
|
+
wsEndpoint: "wss://api.devnet.solana.com",
|
|
54
|
+
commitment: "confirmed",
|
|
55
|
+
autoConnect: false,
|
|
56
|
+
};
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
Supported clusters are `mainnet-beta`, `testnet`, `devnet`, and `localnet`. If `endpoint` is omitted, the package uses the public Solana RPC endpoint for the selected cluster. If `wsEndpoint` is omitted, it is derived from the RPC endpoint.
|
|
@@ -82,25 +82,25 @@ https://faucet.solana.com
|
|
|
82
82
|
## Wallet Interface
|
|
83
83
|
|
|
84
84
|
```ts
|
|
85
|
-
import type { SolanaWallet } from
|
|
85
|
+
import type { SolanaWallet } from "@vue-solana/core";
|
|
86
86
|
|
|
87
87
|
const wallet: SolanaWallet = {
|
|
88
88
|
publicKey: null,
|
|
89
89
|
connected: false,
|
|
90
90
|
connect: async () => {},
|
|
91
91
|
disconnect: async () => {},
|
|
92
|
-
signTransaction: async transaction => transaction
|
|
93
|
-
}
|
|
92
|
+
signTransaction: async (transaction) => transaction,
|
|
93
|
+
};
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
Browser
|
|
96
|
+
Browser wallets discovered through the Solana Wallet Standard are adapted into `SolanaWallet`. You can also provide a custom object that implements `SolanaWallet` for tests or custom adapters.
|
|
97
97
|
|
|
98
98
|
## Examples
|
|
99
99
|
|
|
100
100
|
For complete runnable Vue and Nuxt examples that use this package through the framework integrations, see:
|
|
101
101
|
|
|
102
|
-
- [`examples/vue-vite`](https://
|
|
103
|
-
- [`examples/nuxt`](https://
|
|
102
|
+
- [`examples/vue-vite`](https://vue-solana-docs.vercel.app/examples/vue-vite)
|
|
103
|
+
- [`examples/nuxt`](https://vue-solana-docs.vercel.app/examples/nuxt)
|
|
104
104
|
|
|
105
105
|
## Known TypeScript Issue
|
|
106
106
|
|
|
@@ -109,12 +109,8 @@ For complete runnable Vue and Nuxt examples that use this package through the fr
|
|
|
109
109
|
If TypeScript cannot resolve `@solana/web3-compat`, add `types/web3-compat.d.ts` to your app:
|
|
110
110
|
|
|
111
111
|
```ts
|
|
112
|
-
declare module
|
|
113
|
-
export type {
|
|
114
|
-
Commitment,
|
|
115
|
-
SendOptions,
|
|
116
|
-
TransactionSignature
|
|
117
|
-
} from '@solana/web3.js'
|
|
112
|
+
declare module "@solana/web3-compat" {
|
|
113
|
+
export type { Commitment, SendOptions, TransactionSignature } from "@solana/web3.js";
|
|
118
114
|
export {
|
|
119
115
|
Connection,
|
|
120
116
|
Keypair,
|
|
@@ -122,8 +118,8 @@ declare module '@solana/web3-compat' {
|
|
|
122
118
|
SystemProgram,
|
|
123
119
|
Transaction,
|
|
124
120
|
TransactionInstruction,
|
|
125
|
-
VersionedTransaction
|
|
126
|
-
} from
|
|
121
|
+
VersionedTransaction,
|
|
122
|
+
} from "@solana/web3.js";
|
|
127
123
|
}
|
|
128
124
|
```
|
|
129
125
|
|
|
@@ -131,4 +127,4 @@ Make sure your `tsconfig.json` includes `types/**/*.d.ts` or another pattern tha
|
|
|
131
127
|
|
|
132
128
|
## Status
|
|
133
129
|
|
|
134
|
-
This package is early-stage. RPC helpers and transaction
|
|
130
|
+
This package is early-stage. RPC helpers, wallet primitives, and transaction helpers are usable.
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const web3Compat = require('@solana/web3-compat');
|
|
4
|
+
const app = require('@wallet-standard/app');
|
|
5
|
+
const features = require('@wallet-standard/features');
|
|
6
|
+
const walletStandardFeatures = require('@solana/wallet-standard-features');
|
|
7
|
+
const bs58 = require('bs58');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
10
|
+
|
|
11
|
+
const bs58__default = /*#__PURE__*/_interopDefaultCompat(bs58);
|
|
4
12
|
|
|
5
13
|
const DEFAULT_CLUSTER = "devnet";
|
|
6
14
|
const CLUSTER_ENDPOINTS = {
|
|
@@ -82,13 +90,214 @@ async function signAndSendTransaction(connection, wallet, transaction, options)
|
|
|
82
90
|
return connection.sendRawTransaction(rawTransaction, options);
|
|
83
91
|
}
|
|
84
92
|
|
|
93
|
+
const SOLANA_CHAINS = [
|
|
94
|
+
"solana:mainnet",
|
|
95
|
+
"solana:testnet",
|
|
96
|
+
"solana:devnet",
|
|
97
|
+
"solana:localnet"
|
|
98
|
+
];
|
|
99
|
+
function getSolanaChain(cluster) {
|
|
100
|
+
if (cluster === "mainnet-beta") {
|
|
101
|
+
return "solana:mainnet";
|
|
102
|
+
}
|
|
103
|
+
return `solana:${cluster}`;
|
|
104
|
+
}
|
|
105
|
+
function isSolanaStandardWallet(wallet) {
|
|
106
|
+
return features.StandardConnect in wallet.features && features.StandardDisconnect in wallet.features && wallet.chains.some((chain) => SOLANA_CHAINS.includes(chain));
|
|
107
|
+
}
|
|
108
|
+
function getRegisteredSolanaWallets() {
|
|
109
|
+
if (typeof window === "undefined") {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
return app.getWallets().get().filter(isSolanaStandardWallet).map(createSolanaWalletInfo);
|
|
113
|
+
}
|
|
114
|
+
function subscribeSolanaWallets(listener) {
|
|
115
|
+
if (typeof window === "undefined") {
|
|
116
|
+
return () => {
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const wallets = app.getWallets();
|
|
120
|
+
const offRegister = wallets.on("register", listener);
|
|
121
|
+
const offUnregister = wallets.on("unregister", listener);
|
|
122
|
+
return () => {
|
|
123
|
+
offRegister();
|
|
124
|
+
offUnregister();
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
128
|
+
const wallet = walletInfo.wallet;
|
|
129
|
+
let accounts = wallet.accounts;
|
|
130
|
+
let account = options.account;
|
|
131
|
+
let allowAccountUpdates = Boolean(options.account);
|
|
132
|
+
let connecting = false;
|
|
133
|
+
let disconnecting = false;
|
|
134
|
+
let manuallyDisconnected = false;
|
|
135
|
+
const eventsFeature = wallet.features[features.StandardEvents];
|
|
136
|
+
eventsFeature?.on("change", (properties) => {
|
|
137
|
+
if (properties.accounts) {
|
|
138
|
+
accounts = properties.accounts;
|
|
139
|
+
account = allowAccountUpdates && !manuallyDisconnected ? getSolanaAccount(accounts, options.chain) : void 0;
|
|
140
|
+
options.onChange?.();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return {
|
|
144
|
+
get publicKey() {
|
|
145
|
+
return account ? new web3Compat.PublicKey(account.publicKey) : null;
|
|
146
|
+
},
|
|
147
|
+
get connected() {
|
|
148
|
+
return Boolean(account);
|
|
149
|
+
},
|
|
150
|
+
get connecting() {
|
|
151
|
+
return connecting;
|
|
152
|
+
},
|
|
153
|
+
get disconnecting() {
|
|
154
|
+
return disconnecting;
|
|
155
|
+
},
|
|
156
|
+
async connect() {
|
|
157
|
+
connecting = true;
|
|
158
|
+
manuallyDisconnected = false;
|
|
159
|
+
options.onChange?.();
|
|
160
|
+
try {
|
|
161
|
+
const feature = wallet.features[features.StandardConnect];
|
|
162
|
+
const result = await feature.connect();
|
|
163
|
+
accounts = result.accounts;
|
|
164
|
+
allowAccountUpdates = true;
|
|
165
|
+
account = getSolanaAccount(accounts, options.chain);
|
|
166
|
+
if (!account) {
|
|
167
|
+
throw new Error("Solana wallet did not authorize a Solana account");
|
|
168
|
+
}
|
|
169
|
+
} finally {
|
|
170
|
+
connecting = false;
|
|
171
|
+
options.onChange?.();
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
async disconnect() {
|
|
175
|
+
const feature = wallet.features[features.StandardDisconnect];
|
|
176
|
+
disconnecting = true;
|
|
177
|
+
manuallyDisconnected = true;
|
|
178
|
+
allowAccountUpdates = false;
|
|
179
|
+
account = void 0;
|
|
180
|
+
options.onChange?.();
|
|
181
|
+
try {
|
|
182
|
+
await feature.disconnect();
|
|
183
|
+
accounts = [];
|
|
184
|
+
account = void 0;
|
|
185
|
+
} catch (error) {
|
|
186
|
+
manuallyDisconnected = false;
|
|
187
|
+
allowAccountUpdates = true;
|
|
188
|
+
account = getSolanaAccount(accounts, options.chain);
|
|
189
|
+
throw error;
|
|
190
|
+
} finally {
|
|
191
|
+
disconnecting = false;
|
|
192
|
+
options.onChange?.();
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
signTransaction: hasSignTransaction(wallet) ? async (transaction) => {
|
|
196
|
+
const activeAccount = getActiveAccount(account);
|
|
197
|
+
const [result] = await wallet.features[walletStandardFeatures.SolanaSignTransaction].signTransaction({
|
|
198
|
+
account: activeAccount,
|
|
199
|
+
transaction: serializeTransaction(transaction),
|
|
200
|
+
chain: options.chain
|
|
201
|
+
});
|
|
202
|
+
if (!result) {
|
|
203
|
+
throw new Error("Solana wallet did not return a signed transaction");
|
|
204
|
+
}
|
|
205
|
+
return deserializeTransaction(transaction, result.signedTransaction);
|
|
206
|
+
} : void 0,
|
|
207
|
+
signAllTransactions: hasSignTransaction(wallet) ? async (transactions) => {
|
|
208
|
+
const activeAccount = getActiveAccount(account);
|
|
209
|
+
const results = await wallet.features[walletStandardFeatures.SolanaSignTransaction].signTransaction(
|
|
210
|
+
...transactions.map((transaction) => ({
|
|
211
|
+
account: activeAccount,
|
|
212
|
+
transaction: serializeTransaction(transaction),
|
|
213
|
+
chain: options.chain
|
|
214
|
+
}))
|
|
215
|
+
);
|
|
216
|
+
return results.map(
|
|
217
|
+
(result, index) => deserializeTransaction(transactions[index], result.signedTransaction)
|
|
218
|
+
);
|
|
219
|
+
} : void 0,
|
|
220
|
+
signAndSendTransaction: hasSignAndSendTransaction(wallet) ? async (transaction, sendOptions) => {
|
|
221
|
+
const activeAccount = getActiveAccount(account);
|
|
222
|
+
const [result] = await wallet.features[walletStandardFeatures.SolanaSignAndSendTransaction].signAndSendTransaction({
|
|
223
|
+
account: activeAccount,
|
|
224
|
+
transaction: serializeTransaction(transaction),
|
|
225
|
+
chain: options.chain ?? getSolanaAccountChain(activeAccount),
|
|
226
|
+
options: sendOptions
|
|
227
|
+
});
|
|
228
|
+
if (!result) {
|
|
229
|
+
throw new Error("Solana wallet did not return a transaction signature");
|
|
230
|
+
}
|
|
231
|
+
return { signature: bs58__default.encode(result.signature) };
|
|
232
|
+
} : void 0
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function createSolanaWalletInfo(wallet) {
|
|
236
|
+
return {
|
|
237
|
+
name: wallet.name,
|
|
238
|
+
icon: wallet.icon,
|
|
239
|
+
chains: wallet.chains,
|
|
240
|
+
accounts: wallet.accounts.map((account) => ({
|
|
241
|
+
address: account.address,
|
|
242
|
+
publicKey: Uint8Array.from(account.publicKey),
|
|
243
|
+
chains: account.chains,
|
|
244
|
+
label: account.label,
|
|
245
|
+
icon: account.icon
|
|
246
|
+
})),
|
|
247
|
+
wallet
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function getSolanaAccount(accounts, chain) {
|
|
251
|
+
return accounts.find((account) => account.chains.some((accountChain) => accountChain === chain)) ?? accounts.find(
|
|
252
|
+
(account) => account.chains.some((accountChain) => SOLANA_CHAINS.includes(accountChain))
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
function getActiveAccount(account) {
|
|
256
|
+
if (!account) {
|
|
257
|
+
throw new Error("Solana wallet is not connected");
|
|
258
|
+
}
|
|
259
|
+
return account;
|
|
260
|
+
}
|
|
261
|
+
function getSolanaAccountChain(account) {
|
|
262
|
+
const chain = account.chains.find(
|
|
263
|
+
(accountChain) => SOLANA_CHAINS.includes(accountChain)
|
|
264
|
+
);
|
|
265
|
+
if (!chain) {
|
|
266
|
+
throw new Error("Solana wallet account does not support a Solana chain");
|
|
267
|
+
}
|
|
268
|
+
return chain;
|
|
269
|
+
}
|
|
270
|
+
function hasSignTransaction(wallet) {
|
|
271
|
+
return walletStandardFeatures.SolanaSignTransaction in wallet.features;
|
|
272
|
+
}
|
|
273
|
+
function hasSignAndSendTransaction(wallet) {
|
|
274
|
+
return walletStandardFeatures.SolanaSignAndSendTransaction in wallet.features;
|
|
275
|
+
}
|
|
276
|
+
function serializeTransaction(transaction) {
|
|
277
|
+
if (transaction instanceof web3Compat.Transaction) {
|
|
278
|
+
return transaction.serialize({ requireAllSignatures: false, verifySignatures: false });
|
|
279
|
+
}
|
|
280
|
+
return transaction.serialize();
|
|
281
|
+
}
|
|
282
|
+
function deserializeTransaction(source, bytes) {
|
|
283
|
+
if (source instanceof web3Compat.Transaction) {
|
|
284
|
+
return web3Compat.Transaction.from(bytes);
|
|
285
|
+
}
|
|
286
|
+
return web3Compat.VersionedTransaction.deserialize(bytes);
|
|
287
|
+
}
|
|
288
|
+
|
|
85
289
|
exports.DEFAULT_CLUSTER = DEFAULT_CLUSTER;
|
|
290
|
+
exports.adaptSolanaStandardWallet = adaptSolanaStandardWallet;
|
|
86
291
|
exports.assertWalletCanSign = assertWalletCanSign;
|
|
87
292
|
exports.assertWalletConnected = assertWalletConnected;
|
|
88
293
|
exports.createSolanaConnection = createSolanaConnection;
|
|
89
294
|
exports.createSolanaContext = createSolanaContext;
|
|
90
295
|
exports.getClusterEndpoint = getClusterEndpoint;
|
|
91
296
|
exports.getClusterWebSocketEndpoint = getClusterWebSocketEndpoint;
|
|
297
|
+
exports.getRegisteredSolanaWallets = getRegisteredSolanaWallets;
|
|
298
|
+
exports.getSolanaChain = getSolanaChain;
|
|
92
299
|
exports.getWebSocketEndpoint = getWebSocketEndpoint;
|
|
300
|
+
exports.isSolanaStandardWallet = isSolanaStandardWallet;
|
|
93
301
|
exports.isWalletConnected = isWalletConnected;
|
|
94
302
|
exports.signAndSendTransaction = signAndSendTransaction;
|
|
303
|
+
exports.subscribeSolanaWallets = subscribeSolanaWallets;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SendOptions, Commitment, Connection, Transaction, VersionedTransaction, PublicKey, TransactionSignature } from '@solana/web3-compat';
|
|
2
|
+
import { WalletAccount, Wallet } from '@wallet-standard/base';
|
|
2
3
|
|
|
3
|
-
type SolanaCluster =
|
|
4
|
+
type SolanaCluster = "mainnet-beta" | "testnet" | "devnet" | "localnet";
|
|
5
|
+
type SolanaChain = "solana:mainnet" | "solana:testnet" | "solana:devnet" | "solana:localnet";
|
|
4
6
|
interface SolanaConfig {
|
|
5
7
|
cluster?: SolanaCluster;
|
|
6
8
|
endpoint?: string;
|
|
@@ -19,6 +21,7 @@ interface SolanaWallet {
|
|
|
19
21
|
publicKey: PublicKey | null;
|
|
20
22
|
connected: boolean;
|
|
21
23
|
connecting?: boolean;
|
|
24
|
+
disconnecting?: boolean;
|
|
22
25
|
connect: () => Promise<void>;
|
|
23
26
|
disconnect: () => Promise<void>;
|
|
24
27
|
signTransaction?: <T extends SolanaTransaction>(transaction: T) => Promise<T>;
|
|
@@ -27,6 +30,19 @@ interface SolanaWallet {
|
|
|
27
30
|
signature: TransactionSignature;
|
|
28
31
|
}>;
|
|
29
32
|
}
|
|
33
|
+
interface SolanaWalletInfo {
|
|
34
|
+
name: string;
|
|
35
|
+
icon: string;
|
|
36
|
+
chains: readonly string[];
|
|
37
|
+
accounts: readonly {
|
|
38
|
+
address: string;
|
|
39
|
+
publicKey: Uint8Array;
|
|
40
|
+
chains: readonly string[];
|
|
41
|
+
label?: string;
|
|
42
|
+
icon?: string;
|
|
43
|
+
}[];
|
|
44
|
+
wallet: unknown;
|
|
45
|
+
}
|
|
30
46
|
interface SendTransactionOptions extends SendOptions {
|
|
31
47
|
skipPreflight?: boolean;
|
|
32
48
|
}
|
|
@@ -41,11 +57,22 @@ declare function createSolanaContext(config?: SolanaConfig): SolanaContext;
|
|
|
41
57
|
|
|
42
58
|
declare function signAndSendTransaction(connection: Connection, wallet: SolanaWallet, transaction: SolanaTransaction, options?: SendTransactionOptions): Promise<TransactionSignature>;
|
|
43
59
|
|
|
44
|
-
declare function isWalletConnected(wallet: Pick<SolanaWallet,
|
|
60
|
+
declare function isWalletConnected(wallet: Pick<SolanaWallet, "connected" | "publicKey"> | null | undefined): boolean;
|
|
45
61
|
declare function assertWalletConnected(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & {
|
|
46
|
-
publicKey: NonNullable<SolanaWallet[
|
|
62
|
+
publicKey: NonNullable<SolanaWallet["publicKey"]>;
|
|
47
63
|
};
|
|
48
|
-
declare function assertWalletCanSign(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & Required<Pick<SolanaWallet,
|
|
64
|
+
declare function assertWalletCanSign(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & Required<Pick<SolanaWallet, "signTransaction">>;
|
|
65
|
+
|
|
66
|
+
interface AdaptSolanaWalletOptions {
|
|
67
|
+
chain?: SolanaChain;
|
|
68
|
+
account?: WalletAccount;
|
|
69
|
+
onChange?: () => void;
|
|
70
|
+
}
|
|
71
|
+
declare function getSolanaChain(cluster: SolanaCluster): SolanaChain;
|
|
72
|
+
declare function isSolanaStandardWallet(wallet: Wallet): boolean;
|
|
73
|
+
declare function getRegisteredSolanaWallets(): SolanaWalletInfo[];
|
|
74
|
+
declare function subscribeSolanaWallets(listener: () => void): () => void;
|
|
75
|
+
declare function adaptSolanaStandardWallet(walletInfo: SolanaWalletInfo, options?: AdaptSolanaWalletOptions): SolanaWallet;
|
|
49
76
|
|
|
50
|
-
export { DEFAULT_CLUSTER, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getWebSocketEndpoint, isWalletConnected, signAndSendTransaction };
|
|
51
|
-
export type { SendTransactionOptions, SolanaCluster, SolanaConfig, SolanaContext, SolanaTransaction, SolanaWallet };
|
|
77
|
+
export { DEFAULT_CLUSTER, adaptSolanaStandardWallet, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getRegisteredSolanaWallets, getSolanaChain, getWebSocketEndpoint, isSolanaStandardWallet, isWalletConnected, signAndSendTransaction, subscribeSolanaWallets };
|
|
78
|
+
export type { AdaptSolanaWalletOptions, SendTransactionOptions, SolanaChain, SolanaCluster, SolanaConfig, SolanaContext, SolanaTransaction, SolanaWallet, SolanaWalletInfo };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SendOptions, Commitment, Connection, Transaction, VersionedTransaction, PublicKey, TransactionSignature } from '@solana/web3-compat';
|
|
2
|
+
import { WalletAccount, Wallet } from '@wallet-standard/base';
|
|
2
3
|
|
|
3
|
-
type SolanaCluster =
|
|
4
|
+
type SolanaCluster = "mainnet-beta" | "testnet" | "devnet" | "localnet";
|
|
5
|
+
type SolanaChain = "solana:mainnet" | "solana:testnet" | "solana:devnet" | "solana:localnet";
|
|
4
6
|
interface SolanaConfig {
|
|
5
7
|
cluster?: SolanaCluster;
|
|
6
8
|
endpoint?: string;
|
|
@@ -19,6 +21,7 @@ interface SolanaWallet {
|
|
|
19
21
|
publicKey: PublicKey | null;
|
|
20
22
|
connected: boolean;
|
|
21
23
|
connecting?: boolean;
|
|
24
|
+
disconnecting?: boolean;
|
|
22
25
|
connect: () => Promise<void>;
|
|
23
26
|
disconnect: () => Promise<void>;
|
|
24
27
|
signTransaction?: <T extends SolanaTransaction>(transaction: T) => Promise<T>;
|
|
@@ -27,6 +30,19 @@ interface SolanaWallet {
|
|
|
27
30
|
signature: TransactionSignature;
|
|
28
31
|
}>;
|
|
29
32
|
}
|
|
33
|
+
interface SolanaWalletInfo {
|
|
34
|
+
name: string;
|
|
35
|
+
icon: string;
|
|
36
|
+
chains: readonly string[];
|
|
37
|
+
accounts: readonly {
|
|
38
|
+
address: string;
|
|
39
|
+
publicKey: Uint8Array;
|
|
40
|
+
chains: readonly string[];
|
|
41
|
+
label?: string;
|
|
42
|
+
icon?: string;
|
|
43
|
+
}[];
|
|
44
|
+
wallet: unknown;
|
|
45
|
+
}
|
|
30
46
|
interface SendTransactionOptions extends SendOptions {
|
|
31
47
|
skipPreflight?: boolean;
|
|
32
48
|
}
|
|
@@ -41,11 +57,22 @@ declare function createSolanaContext(config?: SolanaConfig): SolanaContext;
|
|
|
41
57
|
|
|
42
58
|
declare function signAndSendTransaction(connection: Connection, wallet: SolanaWallet, transaction: SolanaTransaction, options?: SendTransactionOptions): Promise<TransactionSignature>;
|
|
43
59
|
|
|
44
|
-
declare function isWalletConnected(wallet: Pick<SolanaWallet,
|
|
60
|
+
declare function isWalletConnected(wallet: Pick<SolanaWallet, "connected" | "publicKey"> | null | undefined): boolean;
|
|
45
61
|
declare function assertWalletConnected(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & {
|
|
46
|
-
publicKey: NonNullable<SolanaWallet[
|
|
62
|
+
publicKey: NonNullable<SolanaWallet["publicKey"]>;
|
|
47
63
|
};
|
|
48
|
-
declare function assertWalletCanSign(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & Required<Pick<SolanaWallet,
|
|
64
|
+
declare function assertWalletCanSign(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & Required<Pick<SolanaWallet, "signTransaction">>;
|
|
65
|
+
|
|
66
|
+
interface AdaptSolanaWalletOptions {
|
|
67
|
+
chain?: SolanaChain;
|
|
68
|
+
account?: WalletAccount;
|
|
69
|
+
onChange?: () => void;
|
|
70
|
+
}
|
|
71
|
+
declare function getSolanaChain(cluster: SolanaCluster): SolanaChain;
|
|
72
|
+
declare function isSolanaStandardWallet(wallet: Wallet): boolean;
|
|
73
|
+
declare function getRegisteredSolanaWallets(): SolanaWalletInfo[];
|
|
74
|
+
declare function subscribeSolanaWallets(listener: () => void): () => void;
|
|
75
|
+
declare function adaptSolanaStandardWallet(walletInfo: SolanaWalletInfo, options?: AdaptSolanaWalletOptions): SolanaWallet;
|
|
49
76
|
|
|
50
|
-
export { DEFAULT_CLUSTER, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getWebSocketEndpoint, isWalletConnected, signAndSendTransaction };
|
|
51
|
-
export type { SendTransactionOptions, SolanaCluster, SolanaConfig, SolanaContext, SolanaTransaction, SolanaWallet };
|
|
77
|
+
export { DEFAULT_CLUSTER, adaptSolanaStandardWallet, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getRegisteredSolanaWallets, getSolanaChain, getWebSocketEndpoint, isSolanaStandardWallet, isWalletConnected, signAndSendTransaction, subscribeSolanaWallets };
|
|
78
|
+
export type { AdaptSolanaWalletOptions, SendTransactionOptions, SolanaChain, SolanaCluster, SolanaConfig, SolanaContext, SolanaTransaction, SolanaWallet, SolanaWalletInfo };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SendOptions, Commitment, Connection, Transaction, VersionedTransaction, PublicKey, TransactionSignature } from '@solana/web3-compat';
|
|
2
|
+
import { WalletAccount, Wallet } from '@wallet-standard/base';
|
|
2
3
|
|
|
3
|
-
type SolanaCluster =
|
|
4
|
+
type SolanaCluster = "mainnet-beta" | "testnet" | "devnet" | "localnet";
|
|
5
|
+
type SolanaChain = "solana:mainnet" | "solana:testnet" | "solana:devnet" | "solana:localnet";
|
|
4
6
|
interface SolanaConfig {
|
|
5
7
|
cluster?: SolanaCluster;
|
|
6
8
|
endpoint?: string;
|
|
@@ -19,6 +21,7 @@ interface SolanaWallet {
|
|
|
19
21
|
publicKey: PublicKey | null;
|
|
20
22
|
connected: boolean;
|
|
21
23
|
connecting?: boolean;
|
|
24
|
+
disconnecting?: boolean;
|
|
22
25
|
connect: () => Promise<void>;
|
|
23
26
|
disconnect: () => Promise<void>;
|
|
24
27
|
signTransaction?: <T extends SolanaTransaction>(transaction: T) => Promise<T>;
|
|
@@ -27,6 +30,19 @@ interface SolanaWallet {
|
|
|
27
30
|
signature: TransactionSignature;
|
|
28
31
|
}>;
|
|
29
32
|
}
|
|
33
|
+
interface SolanaWalletInfo {
|
|
34
|
+
name: string;
|
|
35
|
+
icon: string;
|
|
36
|
+
chains: readonly string[];
|
|
37
|
+
accounts: readonly {
|
|
38
|
+
address: string;
|
|
39
|
+
publicKey: Uint8Array;
|
|
40
|
+
chains: readonly string[];
|
|
41
|
+
label?: string;
|
|
42
|
+
icon?: string;
|
|
43
|
+
}[];
|
|
44
|
+
wallet: unknown;
|
|
45
|
+
}
|
|
30
46
|
interface SendTransactionOptions extends SendOptions {
|
|
31
47
|
skipPreflight?: boolean;
|
|
32
48
|
}
|
|
@@ -41,11 +57,22 @@ declare function createSolanaContext(config?: SolanaConfig): SolanaContext;
|
|
|
41
57
|
|
|
42
58
|
declare function signAndSendTransaction(connection: Connection, wallet: SolanaWallet, transaction: SolanaTransaction, options?: SendTransactionOptions): Promise<TransactionSignature>;
|
|
43
59
|
|
|
44
|
-
declare function isWalletConnected(wallet: Pick<SolanaWallet,
|
|
60
|
+
declare function isWalletConnected(wallet: Pick<SolanaWallet, "connected" | "publicKey"> | null | undefined): boolean;
|
|
45
61
|
declare function assertWalletConnected(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & {
|
|
46
|
-
publicKey: NonNullable<SolanaWallet[
|
|
62
|
+
publicKey: NonNullable<SolanaWallet["publicKey"]>;
|
|
47
63
|
};
|
|
48
|
-
declare function assertWalletCanSign(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & Required<Pick<SolanaWallet,
|
|
64
|
+
declare function assertWalletCanSign(wallet: SolanaWallet | null | undefined): asserts wallet is SolanaWallet & Required<Pick<SolanaWallet, "signTransaction">>;
|
|
65
|
+
|
|
66
|
+
interface AdaptSolanaWalletOptions {
|
|
67
|
+
chain?: SolanaChain;
|
|
68
|
+
account?: WalletAccount;
|
|
69
|
+
onChange?: () => void;
|
|
70
|
+
}
|
|
71
|
+
declare function getSolanaChain(cluster: SolanaCluster): SolanaChain;
|
|
72
|
+
declare function isSolanaStandardWallet(wallet: Wallet): boolean;
|
|
73
|
+
declare function getRegisteredSolanaWallets(): SolanaWalletInfo[];
|
|
74
|
+
declare function subscribeSolanaWallets(listener: () => void): () => void;
|
|
75
|
+
declare function adaptSolanaStandardWallet(walletInfo: SolanaWalletInfo, options?: AdaptSolanaWalletOptions): SolanaWallet;
|
|
49
76
|
|
|
50
|
-
export { DEFAULT_CLUSTER, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getWebSocketEndpoint, isWalletConnected, signAndSendTransaction };
|
|
51
|
-
export type { SendTransactionOptions, SolanaCluster, SolanaConfig, SolanaContext, SolanaTransaction, SolanaWallet };
|
|
77
|
+
export { DEFAULT_CLUSTER, adaptSolanaStandardWallet, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getRegisteredSolanaWallets, getSolanaChain, getWebSocketEndpoint, isSolanaStandardWallet, isWalletConnected, signAndSendTransaction, subscribeSolanaWallets };
|
|
78
|
+
export type { AdaptSolanaWalletOptions, SendTransactionOptions, SolanaChain, SolanaCluster, SolanaConfig, SolanaContext, SolanaTransaction, SolanaWallet, SolanaWalletInfo };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { Connection } from '@solana/web3-compat';
|
|
1
|
+
import { Connection, PublicKey, Transaction, VersionedTransaction } from '@solana/web3-compat';
|
|
2
|
+
import { getWallets } from '@wallet-standard/app';
|
|
3
|
+
import { StandardEvents, StandardDisconnect, StandardConnect } from '@wallet-standard/features';
|
|
4
|
+
import { SolanaSignAndSendTransaction, SolanaSignTransaction } from '@solana/wallet-standard-features';
|
|
5
|
+
import bs58 from 'bs58';
|
|
2
6
|
|
|
3
7
|
const DEFAULT_CLUSTER = "devnet";
|
|
4
8
|
const CLUSTER_ENDPOINTS = {
|
|
@@ -80,4 +84,200 @@ async function signAndSendTransaction(connection, wallet, transaction, options)
|
|
|
80
84
|
return connection.sendRawTransaction(rawTransaction, options);
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
const SOLANA_CHAINS = [
|
|
88
|
+
"solana:mainnet",
|
|
89
|
+
"solana:testnet",
|
|
90
|
+
"solana:devnet",
|
|
91
|
+
"solana:localnet"
|
|
92
|
+
];
|
|
93
|
+
function getSolanaChain(cluster) {
|
|
94
|
+
if (cluster === "mainnet-beta") {
|
|
95
|
+
return "solana:mainnet";
|
|
96
|
+
}
|
|
97
|
+
return `solana:${cluster}`;
|
|
98
|
+
}
|
|
99
|
+
function isSolanaStandardWallet(wallet) {
|
|
100
|
+
return StandardConnect in wallet.features && StandardDisconnect in wallet.features && wallet.chains.some((chain) => SOLANA_CHAINS.includes(chain));
|
|
101
|
+
}
|
|
102
|
+
function getRegisteredSolanaWallets() {
|
|
103
|
+
if (typeof window === "undefined") {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
return getWallets().get().filter(isSolanaStandardWallet).map(createSolanaWalletInfo);
|
|
107
|
+
}
|
|
108
|
+
function subscribeSolanaWallets(listener) {
|
|
109
|
+
if (typeof window === "undefined") {
|
|
110
|
+
return () => {
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const wallets = getWallets();
|
|
114
|
+
const offRegister = wallets.on("register", listener);
|
|
115
|
+
const offUnregister = wallets.on("unregister", listener);
|
|
116
|
+
return () => {
|
|
117
|
+
offRegister();
|
|
118
|
+
offUnregister();
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
122
|
+
const wallet = walletInfo.wallet;
|
|
123
|
+
let accounts = wallet.accounts;
|
|
124
|
+
let account = options.account;
|
|
125
|
+
let allowAccountUpdates = Boolean(options.account);
|
|
126
|
+
let connecting = false;
|
|
127
|
+
let disconnecting = false;
|
|
128
|
+
let manuallyDisconnected = false;
|
|
129
|
+
const eventsFeature = wallet.features[StandardEvents];
|
|
130
|
+
eventsFeature?.on("change", (properties) => {
|
|
131
|
+
if (properties.accounts) {
|
|
132
|
+
accounts = properties.accounts;
|
|
133
|
+
account = allowAccountUpdates && !manuallyDisconnected ? getSolanaAccount(accounts, options.chain) : void 0;
|
|
134
|
+
options.onChange?.();
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
get publicKey() {
|
|
139
|
+
return account ? new PublicKey(account.publicKey) : null;
|
|
140
|
+
},
|
|
141
|
+
get connected() {
|
|
142
|
+
return Boolean(account);
|
|
143
|
+
},
|
|
144
|
+
get connecting() {
|
|
145
|
+
return connecting;
|
|
146
|
+
},
|
|
147
|
+
get disconnecting() {
|
|
148
|
+
return disconnecting;
|
|
149
|
+
},
|
|
150
|
+
async connect() {
|
|
151
|
+
connecting = true;
|
|
152
|
+
manuallyDisconnected = false;
|
|
153
|
+
options.onChange?.();
|
|
154
|
+
try {
|
|
155
|
+
const feature = wallet.features[StandardConnect];
|
|
156
|
+
const result = await feature.connect();
|
|
157
|
+
accounts = result.accounts;
|
|
158
|
+
allowAccountUpdates = true;
|
|
159
|
+
account = getSolanaAccount(accounts, options.chain);
|
|
160
|
+
if (!account) {
|
|
161
|
+
throw new Error("Solana wallet did not authorize a Solana account");
|
|
162
|
+
}
|
|
163
|
+
} finally {
|
|
164
|
+
connecting = false;
|
|
165
|
+
options.onChange?.();
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
async disconnect() {
|
|
169
|
+
const feature = wallet.features[StandardDisconnect];
|
|
170
|
+
disconnecting = true;
|
|
171
|
+
manuallyDisconnected = true;
|
|
172
|
+
allowAccountUpdates = false;
|
|
173
|
+
account = void 0;
|
|
174
|
+
options.onChange?.();
|
|
175
|
+
try {
|
|
176
|
+
await feature.disconnect();
|
|
177
|
+
accounts = [];
|
|
178
|
+
account = void 0;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
manuallyDisconnected = false;
|
|
181
|
+
allowAccountUpdates = true;
|
|
182
|
+
account = getSolanaAccount(accounts, options.chain);
|
|
183
|
+
throw error;
|
|
184
|
+
} finally {
|
|
185
|
+
disconnecting = false;
|
|
186
|
+
options.onChange?.();
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
signTransaction: hasSignTransaction(wallet) ? async (transaction) => {
|
|
190
|
+
const activeAccount = getActiveAccount(account);
|
|
191
|
+
const [result] = await wallet.features[SolanaSignTransaction].signTransaction({
|
|
192
|
+
account: activeAccount,
|
|
193
|
+
transaction: serializeTransaction(transaction),
|
|
194
|
+
chain: options.chain
|
|
195
|
+
});
|
|
196
|
+
if (!result) {
|
|
197
|
+
throw new Error("Solana wallet did not return a signed transaction");
|
|
198
|
+
}
|
|
199
|
+
return deserializeTransaction(transaction, result.signedTransaction);
|
|
200
|
+
} : void 0,
|
|
201
|
+
signAllTransactions: hasSignTransaction(wallet) ? async (transactions) => {
|
|
202
|
+
const activeAccount = getActiveAccount(account);
|
|
203
|
+
const results = await wallet.features[SolanaSignTransaction].signTransaction(
|
|
204
|
+
...transactions.map((transaction) => ({
|
|
205
|
+
account: activeAccount,
|
|
206
|
+
transaction: serializeTransaction(transaction),
|
|
207
|
+
chain: options.chain
|
|
208
|
+
}))
|
|
209
|
+
);
|
|
210
|
+
return results.map(
|
|
211
|
+
(result, index) => deserializeTransaction(transactions[index], result.signedTransaction)
|
|
212
|
+
);
|
|
213
|
+
} : void 0,
|
|
214
|
+
signAndSendTransaction: hasSignAndSendTransaction(wallet) ? async (transaction, sendOptions) => {
|
|
215
|
+
const activeAccount = getActiveAccount(account);
|
|
216
|
+
const [result] = await wallet.features[SolanaSignAndSendTransaction].signAndSendTransaction({
|
|
217
|
+
account: activeAccount,
|
|
218
|
+
transaction: serializeTransaction(transaction),
|
|
219
|
+
chain: options.chain ?? getSolanaAccountChain(activeAccount),
|
|
220
|
+
options: sendOptions
|
|
221
|
+
});
|
|
222
|
+
if (!result) {
|
|
223
|
+
throw new Error("Solana wallet did not return a transaction signature");
|
|
224
|
+
}
|
|
225
|
+
return { signature: bs58.encode(result.signature) };
|
|
226
|
+
} : void 0
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function createSolanaWalletInfo(wallet) {
|
|
230
|
+
return {
|
|
231
|
+
name: wallet.name,
|
|
232
|
+
icon: wallet.icon,
|
|
233
|
+
chains: wallet.chains,
|
|
234
|
+
accounts: wallet.accounts.map((account) => ({
|
|
235
|
+
address: account.address,
|
|
236
|
+
publicKey: Uint8Array.from(account.publicKey),
|
|
237
|
+
chains: account.chains,
|
|
238
|
+
label: account.label,
|
|
239
|
+
icon: account.icon
|
|
240
|
+
})),
|
|
241
|
+
wallet
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function getSolanaAccount(accounts, chain) {
|
|
245
|
+
return accounts.find((account) => account.chains.some((accountChain) => accountChain === chain)) ?? accounts.find(
|
|
246
|
+
(account) => account.chains.some((accountChain) => SOLANA_CHAINS.includes(accountChain))
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
function getActiveAccount(account) {
|
|
250
|
+
if (!account) {
|
|
251
|
+
throw new Error("Solana wallet is not connected");
|
|
252
|
+
}
|
|
253
|
+
return account;
|
|
254
|
+
}
|
|
255
|
+
function getSolanaAccountChain(account) {
|
|
256
|
+
const chain = account.chains.find(
|
|
257
|
+
(accountChain) => SOLANA_CHAINS.includes(accountChain)
|
|
258
|
+
);
|
|
259
|
+
if (!chain) {
|
|
260
|
+
throw new Error("Solana wallet account does not support a Solana chain");
|
|
261
|
+
}
|
|
262
|
+
return chain;
|
|
263
|
+
}
|
|
264
|
+
function hasSignTransaction(wallet) {
|
|
265
|
+
return SolanaSignTransaction in wallet.features;
|
|
266
|
+
}
|
|
267
|
+
function hasSignAndSendTransaction(wallet) {
|
|
268
|
+
return SolanaSignAndSendTransaction in wallet.features;
|
|
269
|
+
}
|
|
270
|
+
function serializeTransaction(transaction) {
|
|
271
|
+
if (transaction instanceof Transaction) {
|
|
272
|
+
return transaction.serialize({ requireAllSignatures: false, verifySignatures: false });
|
|
273
|
+
}
|
|
274
|
+
return transaction.serialize();
|
|
275
|
+
}
|
|
276
|
+
function deserializeTransaction(source, bytes) {
|
|
277
|
+
if (source instanceof Transaction) {
|
|
278
|
+
return Transaction.from(bytes);
|
|
279
|
+
}
|
|
280
|
+
return VersionedTransaction.deserialize(bytes);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export { DEFAULT_CLUSTER, adaptSolanaStandardWallet, assertWalletCanSign, assertWalletConnected, createSolanaConnection, createSolanaContext, getClusterEndpoint, getClusterWebSocketEndpoint, getRegisteredSolanaWallets, getSolanaChain, getWebSocketEndpoint, isSolanaStandardWallet, isWalletConnected, signAndSendTransaction, subscribeSolanaWallets };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue-solana/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Framework-agnostic primitives for Vue Solana libraries.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,12 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@solana/
|
|
41
|
+
"@solana/wallet-standard-features": "^1.3.0",
|
|
42
|
+
"@solana/web3-compat": "^0.0.21",
|
|
43
|
+
"@wallet-standard/app": "^1.1.1",
|
|
44
|
+
"@wallet-standard/base": "^1.1.1",
|
|
45
|
+
"@wallet-standard/features": "^1.1.1",
|
|
46
|
+
"bs58": "^6.0.0"
|
|
42
47
|
},
|
|
43
48
|
"devDependencies": {
|
|
44
49
|
"typescript": "^5.8.3",
|