@vue-solana/core 3.0.1 → 4.0.0-rc.1
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 +39 -2
- package/dist/action.d.ts +10 -3
- package/dist/action.mjs +4 -4
- package/dist/address.d.ts +7 -2
- package/dist/address.mjs +8 -2
- package/dist/clusters.d.ts +1 -1
- package/dist/clusters.mjs +10 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.mjs +4 -1
- package/dist/index.d.ts +4 -11
- package/dist/index.mjs +2 -8
- package/dist/ios-wallet.d.ts +1 -2
- package/dist/ios-wallet.mjs +675 -1
- package/dist/kit.d.ts +1 -1
- package/dist/kit.mjs +22 -9
- package/dist/mobile-wallet.d.ts +12 -2
- package/dist/mobile-wallet.mjs +4 -1
- package/dist/rpc.d.ts +1 -1
- package/dist/shared/{core.DaUlAmcN.mjs → core.A4I__4IR.mjs} +86 -6
- package/dist/shared/{core.C9vxHRXl.d.mts → core.BhF1J_tt.d.ts} +40 -2
- package/dist/timeout.d.ts +22 -1
- package/dist/timeout.mjs +53 -17
- package/dist/token-accounts.d.ts +1 -1
- package/dist/token-accounts.mjs +31 -2
- package/dist/transaction.d.ts +9 -1
- package/dist/transaction.mjs +52 -10
- package/dist/types.d.ts +1 -1
- package/dist/wallet-standard.d.ts +24 -4
- package/dist/wallet-standard.mjs +1 -1
- package/dist/wallet.d.ts +1 -1
- package/package.json +13 -5
- package/dist/action.d.mts +0 -28
- package/dist/address.d.mts +0 -16
- package/dist/buffer-polyfill.d.mts +0 -7
- package/dist/clusters.d.mts +0 -10
- package/dist/errors.d.mts +0 -17
- package/dist/index.d.mts +0 -21
- package/dist/ios-wallet.d.mts +0 -62
- package/dist/kit.d.mts +0 -3
- package/dist/mobile-wallet-support.d.mts +0 -3
- package/dist/mobile-wallet.d.mts +0 -20
- package/dist/rpc.d.mts +0 -7
- package/dist/shared/core.C9vxHRXl.d.ts +0 -193
- package/dist/shared/core.DJsPYgx_.mjs +0 -625
- package/dist/timeout.d.mts +0 -4
- package/dist/token-accounts.d.mts +0 -36
- package/dist/transaction.d.mts +0 -18
- package/dist/types.d.mts +0 -3
- package/dist/wallet-standard.d.mts +0 -22
- package/dist/wallet.d.mts +0 -25
package/dist/kit.mjs
CHANGED
|
@@ -1,25 +1,38 @@
|
|
|
1
|
-
import { getBase64Encoder, getBase58Decoder, signBytes, createClient, extendClient, createKeyPairFromBytes, isSolanaError, SOLANA_ERROR__KEYS__PUBLIC_KEY_MUST_MATCH_PRIVATE_KEY } from '@solana/kit';
|
|
1
|
+
import { getBase64Encoder, getBase58Decoder, signBytes, createClient, extendClient, createRpc, createDefaultRpcTransport, createSolanaRpcApi, DEFAULT_RPC_CONFIG, createSubscriptionRpc, createDefaultRpcSubscriptionsTransport, createDefaultSolanaRpcSubscriptionsChannelCreator, createSolanaRpcSubscriptionsApi, DEFAULT_RPC_SUBSCRIPTIONS_CONFIG, createKeyPairFromBytes, isSolanaError, SOLANA_ERROR__KEYS__PUBLIC_KEY_MUST_MATCH_PRIVATE_KEY } from '@solana/kit';
|
|
2
2
|
export * from '@solana/kit';
|
|
3
|
-
import { solanaRpc, rpcAirdrop } from '@solana/kit-plugin-rpc';
|
|
3
|
+
import { solanaRpc, rpcAirdrop, rpcGetMinimumBalance, rpcTransactionPlanner, rpcTransactionPlanSigningExecutor, rpcTransactionPlanSendingExecutor } from '@solana/kit-plugin-rpc';
|
|
4
4
|
import { DEFAULT_CLUSTER, getClusterEndpoint, getWebSocketEndpoint, getClusterWebSocketEndpoint } from './clusters.mjs';
|
|
5
5
|
|
|
6
|
-
function buildSolanaClient(endpoint, wsEndpoint, payer) {
|
|
6
|
+
function buildSolanaClient(endpoint, wsEndpoint, payer, commitment) {
|
|
7
7
|
const client = createClient().use(
|
|
8
8
|
(current) => extendClient(current, payer ? { payer } : {})
|
|
9
9
|
);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const rpc = commitment ? createRpc({
|
|
11
|
+
api: createSolanaRpcApi({ ...DEFAULT_RPC_CONFIG, defaultCommitment: commitment }),
|
|
12
|
+
transport: createDefaultRpcTransport({ url: endpoint })
|
|
13
|
+
}) : void 0;
|
|
14
|
+
const rpcSubscriptions = commitment ? createSubscriptionRpc({
|
|
15
|
+
api: createSolanaRpcSubscriptionsApi({
|
|
16
|
+
...DEFAULT_RPC_SUBSCRIPTIONS_CONFIG,
|
|
17
|
+
defaultCommitment: commitment
|
|
18
|
+
}),
|
|
19
|
+
transport: createDefaultRpcSubscriptionsTransport({
|
|
20
|
+
createChannel: createDefaultSolanaRpcSubscriptionsChannelCreator({
|
|
21
|
+
url: wsEndpoint
|
|
22
|
+
})
|
|
14
23
|
})
|
|
15
|
-
)
|
|
24
|
+
}) : void 0;
|
|
25
|
+
if (!rpc || !rpcSubscriptions) {
|
|
26
|
+
return client.use(solanaRpc({ rpcUrl: endpoint, rpcSubscriptionsUrl: wsEndpoint })).use(rpcAirdrop());
|
|
27
|
+
}
|
|
28
|
+
return client.use((current) => extendClient(current, { rpc, rpcSubscriptions })).use(rpcGetMinimumBalance()).use(rpcTransactionPlanner()).use(rpcTransactionPlanSigningExecutor()).use(rpcTransactionPlanSendingExecutor()).use(rpcAirdrop());
|
|
16
29
|
}
|
|
17
30
|
function createSolanaClient(config = {}) {
|
|
18
31
|
const cluster = config.cluster ?? DEFAULT_CLUSTER;
|
|
19
32
|
const endpoint = config.endpoint ?? getClusterEndpoint(cluster);
|
|
20
33
|
const wsEndpoint = config.wsEndpoint ?? (config.endpoint ? getWebSocketEndpoint(endpoint) : getClusterWebSocketEndpoint(cluster));
|
|
21
34
|
const payer = config.payer ?? resolvePayerFromSecretKey(config.payerSecretKey);
|
|
22
|
-
return buildSolanaClient(endpoint, wsEndpoint, payer);
|
|
35
|
+
return buildSolanaClient(endpoint, wsEndpoint, payer, config.commitment);
|
|
23
36
|
}
|
|
24
37
|
function resolvePayerFromSecretKey(payerSecretKey) {
|
|
25
38
|
if (!payerSecretKey) {
|
package/dist/mobile-wallet.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { isSolanaMobileWalletSupported } from './mobile-wallet-support.js';
|
|
2
|
-
import { a as SolanaChain } from './shared/core.
|
|
2
|
+
import { a as SolanaChain } from './shared/core.BhF1J_tt.js';
|
|
3
3
|
import '@solana/kit-plugin-rpc';
|
|
4
4
|
import '@solana/kit';
|
|
5
5
|
|
|
@@ -14,7 +14,17 @@ interface RegisterSolanaMobileWalletOptions {
|
|
|
14
14
|
remoteHostAuthority?: string;
|
|
15
15
|
}
|
|
16
16
|
declare function registerSolanaMobileWallet(options?: RegisterSolanaMobileWalletOptions): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Clears this package's local record of which Mobile Wallet Adapter
|
|
19
|
+
* registration keys have been applied. This only affects the deduplication guard
|
|
20
|
+
* inside `registerSolanaMobileWallet()`; it does not (and cannot) unregister an
|
|
21
|
+
* MWA wallet already installed into the host's Wallet Standard registry, because
|
|
22
|
+
* `@solana-mobile/wallet-standard-mobile` provides no unregister API. Calling
|
|
23
|
+
* `registerSolanaMobileWallet()` after this may therefore install a duplicate
|
|
24
|
+
* host-side registration. Intended for test/HMR reset only.
|
|
25
|
+
*/
|
|
26
|
+
declare function unregisterSolanaMobileWallet(): void;
|
|
17
27
|
declare function getDefaultMobileWalletAppIdentity(): SolanaMobileWalletAppIdentity;
|
|
18
28
|
|
|
19
|
-
export { getDefaultMobileWalletAppIdentity, registerSolanaMobileWallet };
|
|
29
|
+
export { getDefaultMobileWalletAppIdentity, registerSolanaMobileWallet, unregisterSolanaMobileWallet };
|
|
20
30
|
export type { RegisterSolanaMobileWalletOptions, SolanaMobileWalletAppIdentity };
|
package/dist/mobile-wallet.mjs
CHANGED
|
@@ -28,6 +28,9 @@ function registerSolanaMobileWallet(options = {}) {
|
|
|
28
28
|
registeredMobileWalletKeys.add(registrationKey);
|
|
29
29
|
return true;
|
|
30
30
|
}
|
|
31
|
+
function unregisterSolanaMobileWallet() {
|
|
32
|
+
registeredMobileWalletKeys.clear();
|
|
33
|
+
}
|
|
31
34
|
function getDefaultMobileWalletAppIdentity() {
|
|
32
35
|
if (typeof window === "undefined") {
|
|
33
36
|
return {
|
|
@@ -54,4 +57,4 @@ function getDocumentIconPath() {
|
|
|
54
57
|
return icon.href;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
export { getDefaultMobileWalletAppIdentity, isSolanaMobileWalletSupported, registerSolanaMobileWallet };
|
|
60
|
+
export { getDefaultMobileWalletAppIdentity, isSolanaMobileWalletSupported, registerSolanaMobileWallet, unregisterSolanaMobileWallet };
|
package/dist/rpc.d.ts
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
import { StandardEvents, StandardDisconnect, StandardConnect } from '@wallet-standard/features';
|
|
2
2
|
import { SolanaSignTransaction, SolanaSignIn, SolanaSignAndSendTransaction, SolanaSignMessage } from '@solana/wallet-standard-features';
|
|
3
|
-
import
|
|
3
|
+
import { isSignatureBytes, verifySignature, getBase58Decoder } from '@solana/kit';
|
|
4
|
+
import { createSolanaError } from '../errors.mjs';
|
|
4
5
|
import { getWallets } from '@wallet-standard/app';
|
|
5
6
|
|
|
7
|
+
async function assertWalletSignature(publicKey, signedMessage, signature, label) {
|
|
8
|
+
if (!isSignatureBytes(signature)) {
|
|
9
|
+
throw createSolanaError(
|
|
10
|
+
"INVALID_SIGNATURE",
|
|
11
|
+
`The wallet returned a malformed ${label} signature.`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
let key;
|
|
15
|
+
try {
|
|
16
|
+
key = await globalThis.crypto.subtle.importKey(
|
|
17
|
+
"raw",
|
|
18
|
+
publicKey,
|
|
19
|
+
"Ed25519",
|
|
20
|
+
true,
|
|
21
|
+
["verify"]
|
|
22
|
+
);
|
|
23
|
+
} catch {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let valid;
|
|
27
|
+
try {
|
|
28
|
+
valid = await verifySignature(key, signature, signedMessage);
|
|
29
|
+
} catch {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (!valid) {
|
|
33
|
+
throw createSolanaError(
|
|
34
|
+
"INVALID_SIGNATURE",
|
|
35
|
+
`The wallet returned an invalid ${label} signature.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
6
40
|
const SOLANA_CHAINS = [
|
|
7
41
|
"solana:mainnet",
|
|
8
42
|
"solana:testnet",
|
|
@@ -42,16 +76,20 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
42
76
|
let disconnecting = false;
|
|
43
77
|
let manuallyDisconnected = false;
|
|
44
78
|
const eventsFeature = wallet.features[StandardEvents];
|
|
45
|
-
eventsFeature?.on("change", (properties) => {
|
|
79
|
+
const unsubscribeChange = eventsFeature?.on("change", (properties) => {
|
|
46
80
|
if (properties.accounts) {
|
|
47
81
|
accounts = properties.accounts;
|
|
48
82
|
account = allowAccountUpdates && !manuallyDisconnected ? getSolanaAccount(accounts, options.chain) : void 0;
|
|
49
83
|
options.onChange?.();
|
|
50
84
|
}
|
|
51
85
|
});
|
|
86
|
+
function dispose() {
|
|
87
|
+
unsubscribeChange?.();
|
|
88
|
+
}
|
|
52
89
|
return {
|
|
53
90
|
platform: walletInfo.platform,
|
|
54
91
|
source: walletInfo.source,
|
|
92
|
+
dispose,
|
|
55
93
|
get publicKey() {
|
|
56
94
|
return account ? account.address : null;
|
|
57
95
|
},
|
|
@@ -110,7 +148,30 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
110
148
|
if (!result) {
|
|
111
149
|
throw new Error("Solana wallet did not return a sign-in result");
|
|
112
150
|
}
|
|
113
|
-
|
|
151
|
+
const signInResult = toSolanaSignInResult(result);
|
|
152
|
+
const requestedAddress = input?.address ?? account?.address;
|
|
153
|
+
const signInAccount = accounts.find(
|
|
154
|
+
(candidate) => candidate.address === signInResult.account.address
|
|
155
|
+
);
|
|
156
|
+
if (!signInAccount) {
|
|
157
|
+
throw createSolanaError(
|
|
158
|
+
"INVALID_SIGNATURE",
|
|
159
|
+
"The wallet returned a sign-in account it does not expose."
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (requestedAddress !== void 0 && requestedAddress !== signInAccount.address) {
|
|
163
|
+
throw createSolanaError(
|
|
164
|
+
"INVALID_SIGNATURE",
|
|
165
|
+
`The wallet signed in as ${signInResult.account.address} instead of the requested ${requestedAddress}.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
await assertWalletSignature(
|
|
169
|
+
signInAccount.publicKey,
|
|
170
|
+
signInResult.signedMessage,
|
|
171
|
+
signInResult.signature,
|
|
172
|
+
"sign-in"
|
|
173
|
+
);
|
|
174
|
+
return signInResult;
|
|
114
175
|
} : void 0,
|
|
115
176
|
signMessage: hasSignMessage(wallet) ? async (message) => {
|
|
116
177
|
const activeAccount = getActiveAccount(account);
|
|
@@ -121,6 +182,12 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
121
182
|
if (!result) {
|
|
122
183
|
throw new Error("Solana wallet did not return a message signature");
|
|
123
184
|
}
|
|
185
|
+
await assertWalletSignature(
|
|
186
|
+
activeAccount.publicKey,
|
|
187
|
+
result.signedMessage,
|
|
188
|
+
result.signature,
|
|
189
|
+
"message"
|
|
190
|
+
);
|
|
124
191
|
return result;
|
|
125
192
|
} : void 0,
|
|
126
193
|
signTransaction: hasSignTransaction(wallet) ? async (transaction) => {
|
|
@@ -158,7 +225,7 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
158
225
|
if (!result) {
|
|
159
226
|
throw new Error("Solana wallet did not return a transaction signature");
|
|
160
227
|
}
|
|
161
|
-
return { signature:
|
|
228
|
+
return { signature: getBase58Decoder().decode(result.signature) };
|
|
162
229
|
} : void 0,
|
|
163
230
|
signAndSendTransactions: hasSignAndSendTransaction(wallet) ? async (transactions, sendOptions) => {
|
|
164
231
|
const activeAccount = getActiveAccount(account);
|
|
@@ -179,11 +246,24 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
179
246
|
if (!result) {
|
|
180
247
|
throw new Error("Solana wallet did not return a transaction signature");
|
|
181
248
|
}
|
|
182
|
-
return
|
|
249
|
+
return getBase58Decoder().decode(result.signature);
|
|
183
250
|
});
|
|
184
251
|
} : void 0
|
|
185
252
|
};
|
|
186
253
|
}
|
|
254
|
+
async function disconnectSolanaStandardWallet(walletInfo) {
|
|
255
|
+
const wallet = walletInfo.wallet;
|
|
256
|
+
if (typeof wallet !== "object" && typeof wallet !== "function") {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const features = wallet?.features;
|
|
260
|
+
const feature = features?.[StandardDisconnect];
|
|
261
|
+
if (typeof feature?.disconnect !== "function") {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
await feature.disconnect();
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
187
267
|
async function signAllThroughFeature(wallet, getAccount, transactions, chain) {
|
|
188
268
|
const activeAccount = getAccount();
|
|
189
269
|
const results = await wallet.features[SolanaSignTransaction].signTransaction(
|
|
@@ -301,4 +381,4 @@ function getWalletUrl(wallet) {
|
|
|
301
381
|
return "url" in wallet && typeof wallet.url === "string" ? wallet.url : void 0;
|
|
302
382
|
}
|
|
303
383
|
|
|
304
|
-
export { SOLANA_CHAINS as S, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME as a, adaptSolanaStandardWallet as b, getSolanaChain as c, getRegisteredSolanaWallets as g, isSolanaStandardWallet as i, subscribeSolanaWallets as s };
|
|
384
|
+
export { SOLANA_CHAINS as S, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME as a, adaptSolanaStandardWallet as b, getSolanaChain as c, disconnectSolanaStandardWallet as d, getRegisteredSolanaWallets as g, isSolanaStandardWallet as i, subscribeSolanaWallets as s };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _solana_kit_plugin_rpc from '@solana/kit-plugin-rpc';
|
|
2
2
|
import * as _solana_kit from '@solana/kit';
|
|
3
|
-
import {
|
|
3
|
+
import { Address, ReadonlyUint8Array, Slot, Commitment, TransactionSigner, Signature } from '@solana/kit';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Solana cluster names. `mainnet` is Solana's official mainnet cluster name.
|
|
@@ -82,9 +82,21 @@ interface SolanaWallet {
|
|
|
82
82
|
source?: SolanaWalletInfo["source"];
|
|
83
83
|
connect: () => Promise<void>;
|
|
84
84
|
disconnect: () => Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Releases wallet-event subscriptions captured at adapt time (e.g. the
|
|
87
|
+
* Wallet Standard `change` listener). The wallet stays connected; only
|
|
88
|
+
* event delivery stops. Idempotent. Present on adapted wallets; plain
|
|
89
|
+
* caller-supplied wallets typically omit it.
|
|
90
|
+
*/
|
|
91
|
+
dispose?: () => void;
|
|
85
92
|
signMessage?: (message: Uint8Array) => Promise<SolanaSignMessageResult>;
|
|
86
93
|
signIn?: (input?: SolanaSignInInput) => Promise<SolanaSignInResult>;
|
|
87
94
|
signTransaction?: (transaction: SolanaTransaction) => Promise<SolanaTransaction>;
|
|
95
|
+
/**
|
|
96
|
+
* @deprecated Prefer `signTransactions` (identical signature). `signTransactions`
|
|
97
|
+
* is tried first in `useSignTransactions()`; `signAllTransactions` remains as
|
|
98
|
+
* the legacy Wallet Standard naming.
|
|
99
|
+
*/
|
|
88
100
|
signAllTransactions?: (transactions: SolanaTransaction[]) => Promise<SolanaTransaction[]>;
|
|
89
101
|
signTransactions?: (transactions: SolanaTransaction[]) => Promise<SolanaTransaction[]>;
|
|
90
102
|
signAndSendTransaction?: (transaction: SolanaTransaction, options?: SendTransactionOptions) => Promise<{
|
|
@@ -128,6 +140,26 @@ interface SendTransactionOptions {
|
|
|
128
140
|
interface ConfirmTransactionOptions {
|
|
129
141
|
commitment?: Commitment;
|
|
130
142
|
timeoutMs?: number;
|
|
143
|
+
/**
|
|
144
|
+
* Milliseconds between `getSignatureStatuses` polls. Defaults to 1500.
|
|
145
|
+
* Must be greater than 0: with no delay between polls an absent signature
|
|
146
|
+
* would hammer the RPC until the timeout expires.
|
|
147
|
+
*/
|
|
148
|
+
pollIntervalMs?: number;
|
|
149
|
+
/**
|
|
150
|
+
* Rejects without further polling when the caller's own `AbortSignal`
|
|
151
|
+
* fires. An aborted confirmation rejects with the signal's reason (an
|
|
152
|
+
* `AbortError` by default) rather than a timeout error.
|
|
153
|
+
*/
|
|
154
|
+
abortSignal?: AbortSignal;
|
|
155
|
+
/**
|
|
156
|
+
* Pass `true` to search transaction history when the signature may have
|
|
157
|
+
* left the recent status cache. Defaults to `false`: an older signature
|
|
158
|
+
* never appears in `getSignatureStatuses` results, so confirming one
|
|
159
|
+
* without this flag resolves to `TRANSACTION_NOT_FOUND` after the timeout
|
|
160
|
+
* rather than confirming.
|
|
161
|
+
*/
|
|
162
|
+
searchTransactionHistory?: boolean;
|
|
131
163
|
}
|
|
132
164
|
interface TransactionStatus {
|
|
133
165
|
slot: Slot;
|
|
@@ -141,9 +173,10 @@ interface TransactionConfirmation {
|
|
|
141
173
|
status: TransactionStatus;
|
|
142
174
|
}
|
|
143
175
|
|
|
144
|
-
declare function buildSolanaClient(endpoint: string, wsEndpoint: string, payer: TransactionSigner | undefined): _solana_kit.Client<{
|
|
176
|
+
declare function buildSolanaClient(endpoint: string, wsEndpoint: string, payer: TransactionSigner | undefined, commitment: Commitment | undefined): _solana_kit.Client<{
|
|
145
177
|
signTransactions: (input: _solana_kit.InstructionPlanInput | _solana_kit.TransactionPlanInput, config?: {
|
|
146
178
|
abortSignal?: AbortSignal;
|
|
179
|
+
maxInstructionsPerTransaction?: number;
|
|
147
180
|
}) => Promise<_solana_kit.TransactionPlanResult<_solana_kit_plugin_rpc.RpcSignContext>>;
|
|
148
181
|
payer: TransactionSigner;
|
|
149
182
|
rpc: _solana_kit.Rpc<_solana_kit.RequestAirdropApi & _solana_kit.GetAccountInfoApi & _solana_kit.GetAgGenesisCertApi & _solana_kit.GetBalanceApi & _solana_kit.GetBlockApi & _solana_kit.GetBlockCommitmentApi & _solana_kit.GetBlockHeightApi & _solana_kit.GetBlockProductionApi & _solana_kit.GetBlocksApi & _solana_kit.GetBlocksWithLimitApi & _solana_kit.GetBlockTimeApi & _solana_kit.GetClusterNodesApi & _solana_kit.GetEpochInfoApi & _solana_kit.GetEpochScheduleApi & _solana_kit.GetFeeForMessageApi & _solana_kit.GetFirstAvailableBlockApi & _solana_kit.GetGenesisHashApi & _solana_kit.GetHealthApi & _solana_kit.GetHighestSnapshotSlotApi & _solana_kit.GetIdentityApi & _solana_kit.GetInflationGovernorApi & _solana_kit.GetInflationRateApi & _solana_kit.GetInflationRewardApi & _solana_kit.GetLargestAccountsApi & _solana_kit.GetLatestBlockhashApi & _solana_kit.GetLeaderScheduleApi & _solana_kit.GetMaxRetransmitSlotApi & _solana_kit.GetMaxShredInsertSlotApi & _solana_kit.GetMinimumBalanceForRentExemptionApi & _solana_kit.GetMultipleAccountsApi & _solana_kit.GetProgramAccountsApi & _solana_kit.GetRecentPerformanceSamplesApi & _solana_kit.GetRecentPrioritizationFeesApi & _solana_kit.GetSignaturesForAddressApi & _solana_kit.GetSignatureStatusesApi & _solana_kit.GetSlotApi & _solana_kit.GetSlotLeaderApi & _solana_kit.GetSlotLeadersApi & _solana_kit.GetStakeMinimumDelegationApi & _solana_kit.GetSupplyApi & _solana_kit.GetTokenAccountBalanceApi & _solana_kit.GetTokenAccountsByDelegateApi & _solana_kit.GetTokenAccountsByOwnerApi & _solana_kit.GetTokenLargestAccountsApi & _solana_kit.GetTokenSupplyApi & _solana_kit.GetTransactionApi & _solana_kit.GetTransactionCountApi & _solana_kit.GetTransactionsForAddressApi & _solana_kit.GetVersionApi & _solana_kit.GetVoteAccountsApi & _solana_kit.IsBlockhashValidApi & _solana_kit.MinimumLedgerSlotApi & _solana_kit.SendTransactionApi & _solana_kit.SimulateTransactionApi>;
|
|
@@ -152,9 +185,11 @@ declare function buildSolanaClient(endpoint: string, wsEndpoint: string, payer:
|
|
|
152
185
|
transactionPlanner: _solana_kit.TransactionPlanner;
|
|
153
186
|
planTransaction: (input: _solana_kit.InstructionPlanInput, config?: {
|
|
154
187
|
abortSignal?: AbortSignal;
|
|
188
|
+
maxInstructionsPerTransaction?: number;
|
|
155
189
|
}) => Promise<_solana_kit.SingleTransactionPlan["message"]>;
|
|
156
190
|
planTransactions: (input: _solana_kit.InstructionPlanInput, config?: {
|
|
157
191
|
abortSignal?: AbortSignal;
|
|
192
|
+
maxInstructionsPerTransaction?: number;
|
|
158
193
|
}) => Promise<_solana_kit.TransactionPlan>;
|
|
159
194
|
signTransaction: (input: _solana_kit.InstructionPlanInput | (_solana_kit.TransactionMessage & _solana_kit.TransactionMessageWithFeePayer<string>) | Readonly<{
|
|
160
195
|
kind: "single";
|
|
@@ -162,6 +197,7 @@ declare function buildSolanaClient(endpoint: string, wsEndpoint: string, payer:
|
|
|
162
197
|
planType: "transactionPlan";
|
|
163
198
|
}>, config?: {
|
|
164
199
|
abortSignal?: AbortSignal;
|
|
200
|
+
maxInstructionsPerTransaction?: number;
|
|
165
201
|
}) => Promise<_solana_kit.SuccessfulSingleTransactionPlanResult<_solana_kit_plugin_rpc.RpcSignContext>>;
|
|
166
202
|
transactionPlanExecutor: _solana_kit.TransactionPlanExecutor<_solana_kit_plugin_rpc.RpcSendContext>;
|
|
167
203
|
sendTransaction: (input: _solana_kit.InstructionPlanInput | (_solana_kit.TransactionMessage & _solana_kit.TransactionMessageWithFeePayer<string>) | Readonly<{
|
|
@@ -170,9 +206,11 @@ declare function buildSolanaClient(endpoint: string, wsEndpoint: string, payer:
|
|
|
170
206
|
planType: "transactionPlan";
|
|
171
207
|
}>, config?: {
|
|
172
208
|
abortSignal?: AbortSignal;
|
|
209
|
+
maxInstructionsPerTransaction?: number;
|
|
173
210
|
}) => Promise<_solana_kit.SuccessfulSingleTransactionPlanResult<_solana_kit_plugin_rpc.RpcSendContext>>;
|
|
174
211
|
sendTransactions: (input: _solana_kit.InstructionPlanInput | _solana_kit.TransactionPlanInput, config?: {
|
|
175
212
|
abortSignal?: AbortSignal;
|
|
213
|
+
maxInstructionsPerTransaction?: number;
|
|
176
214
|
}) => Promise<_solana_kit.TransactionPlanResult<_solana_kit_plugin_rpc.RpcSendContext>>;
|
|
177
215
|
airdrop: (address: Address, amount: _solana_kit.Lamports, abortSignal?: AbortSignal) => Promise<_solana_kit.Signature | undefined>;
|
|
178
216
|
}>;
|
package/dist/timeout.d.ts
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
import { SolanaErrorCode } from './errors.js';
|
|
2
|
+
|
|
3
|
+
interface WithTimeoutOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Rejects without racing when the caller's own `AbortSignal` fires first.
|
|
6
|
+
* An aborted wait rejects with the signal's reason (an `AbortError` by
|
|
7
|
+
* default) rather than the timeout error.
|
|
8
|
+
*/
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
/**
|
|
11
|
+
* Error code for the timeout rejection when `createError` is not given.
|
|
12
|
+
* Defaults to `"TRANSACTION_TIMEOUT"`.
|
|
13
|
+
*/
|
|
14
|
+
code?: SolanaErrorCode;
|
|
15
|
+
/**
|
|
16
|
+
* Message for the timeout rejection when `createError` is not given.
|
|
17
|
+
*/
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number | undefined, createError?: () => unknown, options?: WithTimeoutOptions): Promise<T>;
|
|
21
|
+
declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number | undefined, options?: WithTimeoutOptions): Promise<T>;
|
|
2
22
|
declare function withSolanaTimeout<T>(promise: Promise<T>, timeoutMs: number | undefined, message: string): Promise<T>;
|
|
3
23
|
|
|
4
24
|
export { withSolanaTimeout, withTimeout };
|
|
25
|
+
export type { WithTimeoutOptions };
|
package/dist/timeout.mjs
CHANGED
|
@@ -1,28 +1,64 @@
|
|
|
1
1
|
import { createSolanaError } from './errors.mjs';
|
|
2
2
|
|
|
3
|
-
function withTimeout(promise, timeoutMs,
|
|
3
|
+
function withTimeout(promise, timeoutMs, createErrorOrOptions, maybeOptions) {
|
|
4
|
+
const createError = typeof createErrorOrOptions === "function" ? createErrorOrOptions : void 0;
|
|
5
|
+
const {
|
|
6
|
+
signal,
|
|
7
|
+
code = "TRANSACTION_TIMEOUT",
|
|
8
|
+
message
|
|
9
|
+
} = (typeof createErrorOrOptions === "function" ? maybeOptions : createErrorOrOptions) ?? {};
|
|
4
10
|
if (timeoutMs === void 0) {
|
|
5
|
-
return promise;
|
|
11
|
+
return signal ? raceWithSignal(promise, signal) : promise;
|
|
6
12
|
}
|
|
13
|
+
if (typeof timeoutMs !== "number" || Number.isNaN(timeoutMs) || timeoutMs < 0) {
|
|
14
|
+
throw createSolanaError(
|
|
15
|
+
"INVALID_INPUT",
|
|
16
|
+
`Invalid timeout: expected a non-negative number of milliseconds, received ${String(timeoutMs)}`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
signal?.throwIfAborted();
|
|
7
20
|
let timeoutId;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let onAbort;
|
|
22
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
23
|
+
timeoutId = setTimeout(() => {
|
|
24
|
+
try {
|
|
25
|
+
reject(createError?.() ?? createSolanaError(code, message ?? "Operation timed out"));
|
|
26
|
+
} catch (error) {
|
|
27
|
+
reject(error);
|
|
28
|
+
}
|
|
29
|
+
}, timeoutMs);
|
|
30
|
+
if (signal) {
|
|
31
|
+
onAbort = () => reject(signal.reason);
|
|
32
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
const raced = signal ? raceWithSignal(promise, signal) : promise;
|
|
36
|
+
return Promise.race([raced, timeoutPromise]).finally(() => {
|
|
23
37
|
if (timeoutId) {
|
|
24
38
|
clearTimeout(timeoutId);
|
|
25
39
|
}
|
|
40
|
+
if (signal && onAbort) {
|
|
41
|
+
signal.removeEventListener("abort", onAbort);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function raceWithSignal(promise, signal) {
|
|
46
|
+
if (signal.aborted) {
|
|
47
|
+
return Promise.reject(signal.reason);
|
|
48
|
+
}
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const onAbort = () => reject(signal.reason);
|
|
51
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
52
|
+
promise.then(
|
|
53
|
+
(value) => {
|
|
54
|
+
signal.removeEventListener("abort", onAbort);
|
|
55
|
+
resolve(value);
|
|
56
|
+
},
|
|
57
|
+
(cause) => {
|
|
58
|
+
signal.removeEventListener("abort", onAbort);
|
|
59
|
+
reject(cause);
|
|
60
|
+
}
|
|
61
|
+
);
|
|
26
62
|
});
|
|
27
63
|
}
|
|
28
64
|
function withSolanaTimeout(promise, timeoutMs, message) {
|
package/dist/token-accounts.d.ts
CHANGED
package/dist/token-accounts.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { address } from '@solana/kit';
|
|
2
|
-
import { normalizeSolanaError } from './errors.mjs';
|
|
1
|
+
import { address, isAddress } from '@solana/kit';
|
|
2
|
+
import { normalizeSolanaError, createSolanaError } from './errors.mjs';
|
|
3
3
|
|
|
4
4
|
const TOKEN_PROGRAM_ADDRESS = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
5
5
|
const TOKEN_2022_PROGRAM_ADDRESS = address("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
|
|
@@ -54,6 +54,13 @@ function tokenAccountInfoFromParsed(address2, data) {
|
|
|
54
54
|
if (!parsed) {
|
|
55
55
|
throw new Error(`Token account ${address2} has no parsed data`);
|
|
56
56
|
}
|
|
57
|
+
const mismatches = validateParsedTokenAccount(parsed);
|
|
58
|
+
if (mismatches.length > 0) {
|
|
59
|
+
throw createSolanaError(
|
|
60
|
+
"RPC_FAILURE",
|
|
61
|
+
`Token account ${address2} returned malformed data (${mismatches.join(", ")})`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
57
64
|
return {
|
|
58
65
|
address: address2,
|
|
59
66
|
mint: parsed.mint,
|
|
@@ -64,5 +71,27 @@ function tokenAccountInfoFromParsed(address2, data) {
|
|
|
64
71
|
isNative: parsed.isNative
|
|
65
72
|
};
|
|
66
73
|
}
|
|
74
|
+
function validateParsedTokenAccount(parsed) {
|
|
75
|
+
const mismatches = [];
|
|
76
|
+
if (typeof parsed.mint !== "string" || !isAddress(parsed.mint)) {
|
|
77
|
+
mismatches.push("mint");
|
|
78
|
+
}
|
|
79
|
+
if (typeof parsed.owner !== "string" || !isAddress(parsed.owner)) {
|
|
80
|
+
mismatches.push("owner");
|
|
81
|
+
}
|
|
82
|
+
if (typeof parsed.tokenAmount?.amount !== "string" || !/^\d+$/.test(parsed.tokenAmount.amount)) {
|
|
83
|
+
mismatches.push("tokenAmount.amount");
|
|
84
|
+
}
|
|
85
|
+
if (typeof parsed.tokenAmount?.decimals !== "number" || !Number.isInteger(parsed.tokenAmount.decimals) || parsed.tokenAmount.decimals < 0) {
|
|
86
|
+
mismatches.push("tokenAmount.decimals");
|
|
87
|
+
}
|
|
88
|
+
if (parsed.state !== "frozen" && parsed.state !== "initialized" && parsed.state !== "uninitialized") {
|
|
89
|
+
mismatches.push("state");
|
|
90
|
+
}
|
|
91
|
+
if (typeof parsed.isNative !== "boolean") {
|
|
92
|
+
mismatches.push("isNative");
|
|
93
|
+
}
|
|
94
|
+
return mismatches;
|
|
95
|
+
}
|
|
67
96
|
|
|
68
97
|
export { getTokenAccount, getTokenAccountsByOwner, getTokenBalance };
|
package/dist/transaction.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Signature } from '@solana/kit';
|
|
2
|
-
import { b as SolanaClient, C as ConfirmTransactionOptions, T as TransactionConfirmation, k as SolanaWallet, j as SolanaTransaction, S as SendTransactionOptions } from './shared/core.
|
|
2
|
+
import { b as SolanaClient, C as ConfirmTransactionOptions, T as TransactionConfirmation, k as SolanaWallet, j as SolanaTransaction, S as SendTransactionOptions } from './shared/core.BhF1J_tt.js';
|
|
3
3
|
import '@solana/kit-plugin-rpc';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -12,6 +12,14 @@ declare function signAndSendTransaction(client: SolanaClient, wallet: SolanaWall
|
|
|
12
12
|
/**
|
|
13
13
|
* Confirm a transaction signature against the kit RPC until it reaches the
|
|
14
14
|
* requested commitment.
|
|
15
|
+
*
|
|
16
|
+
* Kit's `sendAndConfirmTransaction` cannot back this: it needs the whole
|
|
17
|
+
* transaction plus a `rpcSubscriptions` websocket and sends the transaction
|
|
18
|
+
* itself, whereas this confirms a signature a wallet already submitted.
|
|
19
|
+
*
|
|
20
|
+
* Kit's `getSignatureStatuses` takes no commitment parameter — the commitment
|
|
21
|
+
* check below is client-side. A missing status means the signature is unknown
|
|
22
|
+
* (not found), distinct from a failed transaction or an expired wait.
|
|
15
23
|
*/
|
|
16
24
|
declare function confirmTransactionSignature(client: SolanaClient, signature: Signature, options?: ConfirmTransactionOptions): Promise<TransactionConfirmation>;
|
|
17
25
|
|
package/dist/transaction.mjs
CHANGED
|
@@ -31,17 +31,36 @@ async function signAndSendTransaction(client, wallet, transaction, options) {
|
|
|
31
31
|
async function confirmTransactionSignature(client, signature, options = {}) {
|
|
32
32
|
const commitment = options.commitment ?? DEFAULT_CONFIRMATION_COMMITMENT;
|
|
33
33
|
const timeoutMs = options.timeoutMs ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
|
|
34
|
-
|
|
34
|
+
const pollIntervalMs = options.pollIntervalMs ?? SIGNATURE_STATUS_POLL_INTERVAL_MS;
|
|
35
|
+
const { abortSignal, searchTransactionHistory = false } = options;
|
|
36
|
+
if (typeof timeoutMs !== "number" || Number.isNaN(timeoutMs) || timeoutMs < 0) {
|
|
37
|
+
throw createSolanaError(
|
|
38
|
+
"INVALID_INPUT",
|
|
39
|
+
`Invalid confirmation timeout: expected a non-negative number of milliseconds, received ${String(timeoutMs)}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
if (typeof pollIntervalMs !== "number" || Number.isNaN(pollIntervalMs) || pollIntervalMs <= 0) {
|
|
43
|
+
throw createSolanaError(
|
|
44
|
+
"INVALID_INPUT",
|
|
45
|
+
`Invalid confirmation poll interval: expected a positive number of milliseconds, received ${String(pollIntervalMs)}`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
abortSignal?.throwIfAborted();
|
|
49
|
+
const deadline = Date.now() + timeoutMs;
|
|
50
|
+
let sawStatus = false;
|
|
35
51
|
try {
|
|
36
|
-
while (
|
|
37
|
-
|
|
52
|
+
while (Date.now() < deadline) {
|
|
53
|
+
abortSignal?.throwIfAborted();
|
|
54
|
+
const response = await client.rpc.getSignatureStatuses([signature], { searchTransactionHistory }).send({ abortSignal });
|
|
38
55
|
const [status] = response.value;
|
|
39
56
|
if (!status) {
|
|
40
|
-
|
|
57
|
+
await wait(pollIntervalMs, abortSignal);
|
|
58
|
+
continue;
|
|
41
59
|
}
|
|
60
|
+
sawStatus = true;
|
|
42
61
|
if (status.err) {
|
|
43
62
|
throw createSolanaError(
|
|
44
|
-
"
|
|
63
|
+
"TRANSACTION_FAILED",
|
|
45
64
|
`Transaction ${signature} failed to reach ${commitment} commitment.`,
|
|
46
65
|
{ cause: status.err }
|
|
47
66
|
);
|
|
@@ -49,14 +68,22 @@ async function confirmTransactionSignature(client, signature, options = {}) {
|
|
|
49
68
|
if (hasReachedCommitment(status.confirmationStatus, commitment)) {
|
|
50
69
|
return { signature, commitment, status };
|
|
51
70
|
}
|
|
52
|
-
await wait(
|
|
53
|
-
|
|
71
|
+
await wait(pollIntervalMs, abortSignal);
|
|
72
|
+
}
|
|
73
|
+
if (!sawStatus) {
|
|
74
|
+
throw createSolanaError("TRANSACTION_NOT_FOUND", `Transaction ${signature} was not found.`);
|
|
54
75
|
}
|
|
55
76
|
throw createSolanaError(
|
|
56
77
|
"TRANSACTION_TIMEOUT",
|
|
57
78
|
`Timed out waiting for transaction ${signature} to reach ${commitment} commitment.`
|
|
58
79
|
);
|
|
59
80
|
} catch (cause) {
|
|
81
|
+
if (abortSignal?.aborted) {
|
|
82
|
+
throw abortSignal.reason ?? cause;
|
|
83
|
+
}
|
|
84
|
+
if (isAbortErrorLike(cause)) {
|
|
85
|
+
throw cause;
|
|
86
|
+
}
|
|
60
87
|
throw normalizeSolanaError(cause, "RPC_FAILURE");
|
|
61
88
|
}
|
|
62
89
|
}
|
|
@@ -69,10 +96,25 @@ function hasReachedCommitment(actualStatus, targetCommitment) {
|
|
|
69
96
|
}
|
|
70
97
|
return (COMMITMENT_RANK[actualStatus] ?? 0) >= (COMMITMENT_RANK[targetCommitment] ?? 0);
|
|
71
98
|
}
|
|
72
|
-
function wait(ms) {
|
|
73
|
-
|
|
74
|
-
|
|
99
|
+
function wait(ms, signal) {
|
|
100
|
+
if (ms <= 0) {
|
|
101
|
+
signal?.throwIfAborted();
|
|
102
|
+
return Promise.resolve();
|
|
103
|
+
}
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const timeoutId = setTimeout(() => {
|
|
106
|
+
signal?.removeEventListener("abort", onAbort);
|
|
107
|
+
resolve();
|
|
108
|
+
}, ms);
|
|
109
|
+
function onAbort() {
|
|
110
|
+
clearTimeout(timeoutId);
|
|
111
|
+
reject(signal.reason);
|
|
112
|
+
}
|
|
113
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
75
114
|
});
|
|
76
115
|
}
|
|
116
|
+
function isAbortErrorLike(cause) {
|
|
117
|
+
return typeof cause === "object" && cause !== null && cause.name === "AbortError";
|
|
118
|
+
}
|
|
77
119
|
|
|
78
120
|
export { confirmTransactionSignature, signAndSendTransaction };
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '@solana/kit';
|
|
2
|
-
export { C as ConfirmTransactionOptions, S as SendTransactionOptions, a as SolanaChain, c as SolanaCluster, d as SolanaConfig, e as SolanaContext, f as SolanaSignInAccount, g as SolanaSignInInput, h as SolanaSignInResult, i as SolanaSignMessageResult, j as SolanaTransaction, k as SolanaWallet, l as SolanaWalletInfo, T as TransactionConfirmation, m as TransactionStatus } from './shared/core.
|
|
2
|
+
export { C as ConfirmTransactionOptions, S as SendTransactionOptions, a as SolanaChain, c as SolanaCluster, d as SolanaConfig, e as SolanaContext, f as SolanaSignInAccount, g as SolanaSignInInput, h as SolanaSignInResult, i as SolanaSignMessageResult, j as SolanaTransaction, k as SolanaWallet, l as SolanaWalletInfo, T as TransactionConfirmation, m as TransactionStatus } from './shared/core.BhF1J_tt.js';
|
|
3
3
|
import '@solana/kit-plugin-rpc';
|