@solana/client 0.0.0 → 0.1.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 +3 -3
- package/dist/index.browser.cjs +2796 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.mjs +2745 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.native.mjs +2745 -0
- package/dist/index.native.mjs.map +1 -0
- package/dist/index.node.cjs +2796 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.mjs +2745 -0
- package/dist/index.node.mjs.map +1 -0
- package/dist/types/client/actions.d.ts +18 -0
- package/dist/types/client/actions.d.ts.map +1 -0
- package/dist/types/client/createClient.d.ts +9 -0
- package/dist/types/client/createClient.d.ts.map +1 -0
- package/dist/types/client/createClientHelpers.d.ts +3 -0
- package/dist/types/client/createClientHelpers.d.ts.map +1 -0
- package/dist/types/client/createClientStore.d.ts +29 -0
- package/dist/types/client/createClientStore.d.ts.map +1 -0
- package/dist/types/client/watchers.d.ts +16 -0
- package/dist/types/client/watchers.d.ts.map +1 -0
- package/dist/types/controllers/solTransferController.d.ts +21 -0
- package/dist/types/controllers/solTransferController.d.ts.map +1 -0
- package/dist/types/controllers/splTransferController.d.ts +24 -0
- package/dist/types/controllers/splTransferController.d.ts.map +1 -0
- package/dist/types/features/sol.d.ts +41 -0
- package/dist/types/features/sol.d.ts.map +1 -0
- package/dist/types/features/spl.d.ts +59 -0
- package/dist/types/features/spl.d.ts.map +1 -0
- package/dist/types/features/transactions.d.ts +79 -0
- package/dist/types/features/transactions.d.ts.map +1 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logging/logger.d.ts +24 -0
- package/dist/types/logging/logger.d.ts.map +1 -0
- package/dist/types/numeric/amounts.d.ts +30 -0
- package/dist/types/numeric/amounts.d.ts.map +1 -0
- package/dist/types/numeric/lamports.d.ts +46 -0
- package/dist/types/numeric/lamports.d.ts.map +1 -0
- package/dist/types/numeric/math.d.ts +74 -0
- package/dist/types/numeric/math.d.ts.map +1 -0
- package/dist/types/numeric/rational.d.ts +27 -0
- package/dist/types/numeric/rational.d.ts.map +1 -0
- package/dist/types/rpc/createSolanaRpcClient.d.ts +42 -0
- package/dist/types/rpc/createSolanaRpcClient.d.ts.map +1 -0
- package/dist/types/serialization/json.d.ts +31 -0
- package/dist/types/serialization/json.d.ts.map +1 -0
- package/dist/types/signatures/status.d.ts +12 -0
- package/dist/types/signatures/status.d.ts.map +1 -0
- package/dist/types/signers/walletTransactionSigner.d.ts +33 -0
- package/dist/types/signers/walletTransactionSigner.d.ts.map +1 -0
- package/dist/types/state/asyncState.d.ts +12 -0
- package/dist/types/state/asyncState.d.ts.map +1 -0
- package/dist/types/transactions/base64.d.ts +12 -0
- package/dist/types/transactions/base64.d.ts.map +1 -0
- package/dist/types/transactions/prepareTransaction.d.ts +16 -0
- package/dist/types/transactions/prepareTransaction.d.ts.map +1 -0
- package/dist/types/transactions/referenceKeys.d.ts +10 -0
- package/dist/types/transactions/referenceKeys.d.ts.map +1 -0
- package/dist/types/transactions/transactionPoolController.d.ts +53 -0
- package/dist/types/transactions/transactionPoolController.d.ts.map +1 -0
- package/dist/types/types.d.ts +205 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils/addressLike.d.ts +5 -0
- package/dist/types/utils/addressLike.d.ts.map +1 -0
- package/dist/types/utils/stableStringify.d.ts +2 -0
- package/dist/types/utils/stableStringify.d.ts.map +1 -0
- package/dist/types/utils.d.ts +21 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/wallet/registry.d.ts +9 -0
- package/dist/types/wallet/registry.d.ts.map +1 -0
- package/dist/types/wallet/standard.d.ts +36 -0
- package/dist/types/wallet/standard.d.ts.map +1 -0
- package/package.json +83 -79
|
@@ -0,0 +1,2745 @@
|
|
|
1
|
+
import { createSolanaRpc, createSolanaRpcSubscriptions, address, getBase64EncodedWireTransaction, compileTransaction, partiallySignTransactionMessageWithSigners, appendTransactionMessageInstruction, setTransactionMessageLifetimeUsingBlockhash, isTransactionSendingSigner, getMessagePackerInstructionPlanFromInstructions, signature, AccountRole, pipe, createTransactionMessage, setTransactionMessageFeePayer, singleTransactionPlan, signAndSendTransactionMessageWithSigners, createTransactionPlanExecutor, signTransactionMessageWithSigners, isSolanaError, SOLANA_ERROR__TRANSACTION_ERROR__ALREADY_PROCESSED, createTransactionPlanner, setTransactionMessageFeePayerSigner, isTransactionPartialSigner, SOLANA_ERROR__INSTRUCTION_ERROR__COMPUTATIONAL_BUDGET_EXCEEDED, isInstructionForProgram, isInstructionWithData, SolanaError, SOLANA_ERROR__INSTRUCTION_ERROR__GENERIC_ERROR, airdropFactory, signatureBytes } from '@solana/kit';
|
|
2
|
+
import { createBlockHeightExceedencePromiseFactory, createRecentSignatureConfirmationPromiseFactory, waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';
|
|
3
|
+
import { getBase58Decoder, getBase58Encoder } from '@solana/codecs-strings';
|
|
4
|
+
import { getTransferSolInstruction } from '@solana-program/system';
|
|
5
|
+
import { TOKEN_PROGRAM_ADDRESS, fetchMint, findAssociatedTokenPda, getCreateAssociatedTokenInstruction, getTransferCheckedInstruction } from '@solana-program/token';
|
|
6
|
+
import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction, COMPUTE_BUDGET_PROGRAM_ADDRESS, ComputeBudgetInstruction } from '@solana-program/compute-budget';
|
|
7
|
+
import { createStore } from 'zustand/vanilla';
|
|
8
|
+
import { getTransactionDecoder, getTransactionEncoder } from '@solana/transactions';
|
|
9
|
+
import { SolanaSignMessage, SolanaSignTransaction, SolanaSignAndSendTransaction } from '@solana/wallet-standard-features';
|
|
10
|
+
import { getWallets } from '@wallet-standard/app';
|
|
11
|
+
import { StandardConnect, StandardDisconnect } from '@wallet-standard/features';
|
|
12
|
+
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
15
|
+
|
|
16
|
+
// src/utils.ts
|
|
17
|
+
function deepFreeze(value) {
|
|
18
|
+
if (typeof value !== "object" || value === null) {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
const objectValue = value;
|
|
22
|
+
for (const key of Reflect.ownKeys(objectValue)) {
|
|
23
|
+
const property = objectValue[key];
|
|
24
|
+
deepFreeze(property);
|
|
25
|
+
}
|
|
26
|
+
return Object.freeze(value);
|
|
27
|
+
}
|
|
28
|
+
__name(deepFreeze, "deepFreeze");
|
|
29
|
+
function now() {
|
|
30
|
+
return Date.now();
|
|
31
|
+
}
|
|
32
|
+
__name(now, "now");
|
|
33
|
+
function toErrorMessage(error) {
|
|
34
|
+
if (error instanceof Error) {
|
|
35
|
+
return error.message;
|
|
36
|
+
}
|
|
37
|
+
if (typeof error === "string") {
|
|
38
|
+
return error;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
return JSON.stringify(error);
|
|
42
|
+
} catch {
|
|
43
|
+
return String(error);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
__name(toErrorMessage, "toErrorMessage");
|
|
47
|
+
|
|
48
|
+
// src/logging/logger.ts
|
|
49
|
+
function createLogger(logger) {
|
|
50
|
+
if (logger) {
|
|
51
|
+
return logger;
|
|
52
|
+
}
|
|
53
|
+
return ({ data, level, message }) => {
|
|
54
|
+
const payload = data ? { ...data } : {};
|
|
55
|
+
switch (level) {
|
|
56
|
+
case "error":
|
|
57
|
+
console.error(`[react-core] ${message}`, payload);
|
|
58
|
+
break;
|
|
59
|
+
case "warn":
|
|
60
|
+
console.warn(`[react-core] ${message}`, payload);
|
|
61
|
+
break;
|
|
62
|
+
case "info":
|
|
63
|
+
console.info(`[react-core] ${message}`, payload);
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
console.debug(`[react-core] ${message}`, payload);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
__name(createLogger, "createLogger");
|
|
71
|
+
function formatError(error) {
|
|
72
|
+
return {
|
|
73
|
+
error,
|
|
74
|
+
message: toErrorMessage(error)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
__name(formatError, "formatError");
|
|
78
|
+
function createChainedAbortController(parent) {
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
if (!parent) {
|
|
81
|
+
return controller;
|
|
82
|
+
}
|
|
83
|
+
if (parent.aborted) {
|
|
84
|
+
controller.abort(parent.reason);
|
|
85
|
+
return controller;
|
|
86
|
+
}
|
|
87
|
+
const onAbort = /* @__PURE__ */ __name(() => {
|
|
88
|
+
controller.abort(parent.reason);
|
|
89
|
+
parent.removeEventListener("abort", onAbort);
|
|
90
|
+
}, "onAbort");
|
|
91
|
+
parent.addEventListener("abort", onAbort, { once: true });
|
|
92
|
+
return controller;
|
|
93
|
+
}
|
|
94
|
+
__name(createChainedAbortController, "createChainedAbortController");
|
|
95
|
+
function toBigint(value) {
|
|
96
|
+
if (value === void 0) {
|
|
97
|
+
return void 0;
|
|
98
|
+
}
|
|
99
|
+
return typeof value === "bigint" ? value : BigInt(Math.floor(value));
|
|
100
|
+
}
|
|
101
|
+
__name(toBigint, "toBigint");
|
|
102
|
+
var DEFAULT_SIMULATION_CONFIG = Object.freeze({
|
|
103
|
+
encoding: "base64",
|
|
104
|
+
replaceRecentBlockhash: true,
|
|
105
|
+
sigVerify: false
|
|
106
|
+
});
|
|
107
|
+
function createSolanaRpcClient(config) {
|
|
108
|
+
const endpoint = config.endpoint;
|
|
109
|
+
const websocketEndpoint = config.websocketEndpoint ?? endpoint;
|
|
110
|
+
const commitment = config.commitment ?? "confirmed";
|
|
111
|
+
const rpc = createSolanaRpc(endpoint, config.rpcConfig);
|
|
112
|
+
const rpcSubscriptions = createSolanaRpcSubscriptions(websocketEndpoint, config.rpcSubscriptionsConfig);
|
|
113
|
+
async function sendAndConfirmTransaction(transaction, options = {}) {
|
|
114
|
+
const abortController = createChainedAbortController(options.abortSignal);
|
|
115
|
+
const targetCommitment = options.commitment ?? commitment;
|
|
116
|
+
const wireTransaction = getBase64EncodedWireTransaction(transaction);
|
|
117
|
+
const response = await rpc.sendTransaction(wireTransaction, {
|
|
118
|
+
encoding: "base64",
|
|
119
|
+
maxRetries: toBigint(options.maxRetries),
|
|
120
|
+
minContextSlot: toBigint(options.minContextSlot),
|
|
121
|
+
preflightCommitment: targetCommitment,
|
|
122
|
+
skipPreflight: options.skipPreflight
|
|
123
|
+
}).send({ abortSignal: abortController.signal });
|
|
124
|
+
const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({
|
|
125
|
+
rpc,
|
|
126
|
+
rpcSubscriptions
|
|
127
|
+
});
|
|
128
|
+
const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({
|
|
129
|
+
rpc,
|
|
130
|
+
rpcSubscriptions
|
|
131
|
+
});
|
|
132
|
+
await waitForRecentTransactionConfirmation({
|
|
133
|
+
abortSignal: abortController.signal,
|
|
134
|
+
commitment: targetCommitment,
|
|
135
|
+
getBlockHeightExceedencePromise,
|
|
136
|
+
getRecentSignatureConfirmationPromise,
|
|
137
|
+
transaction
|
|
138
|
+
});
|
|
139
|
+
return response;
|
|
140
|
+
}
|
|
141
|
+
__name(sendAndConfirmTransaction, "sendAndConfirmTransaction");
|
|
142
|
+
async function simulateTransaction(transaction, options = {}) {
|
|
143
|
+
const wireTransaction = getBase64EncodedWireTransaction(transaction);
|
|
144
|
+
const baseConfig = options.config ?? {};
|
|
145
|
+
const mergedConfig = {
|
|
146
|
+
...DEFAULT_SIMULATION_CONFIG,
|
|
147
|
+
...baseConfig,
|
|
148
|
+
commitment: baseConfig.commitment ?? options.commitment ?? commitment
|
|
149
|
+
};
|
|
150
|
+
const normalizedConfig = mergedConfig.sigVerify === true && mergedConfig.replaceRecentBlockhash !== false ? { ...mergedConfig, replaceRecentBlockhash: false } : mergedConfig;
|
|
151
|
+
return rpc.simulateTransaction(wireTransaction, normalizedConfig).send({ abortSignal: options.abortSignal });
|
|
152
|
+
}
|
|
153
|
+
__name(simulateTransaction, "simulateTransaction");
|
|
154
|
+
return {
|
|
155
|
+
commitment,
|
|
156
|
+
endpoint,
|
|
157
|
+
rpc,
|
|
158
|
+
rpcSubscriptions,
|
|
159
|
+
sendAndConfirmTransaction,
|
|
160
|
+
simulateTransaction,
|
|
161
|
+
websocketEndpoint
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
__name(createSolanaRpcClient, "createSolanaRpcClient");
|
|
165
|
+
|
|
166
|
+
// src/wallet/registry.ts
|
|
167
|
+
function createWalletRegistry(connectors) {
|
|
168
|
+
const byId = /* @__PURE__ */ new Map();
|
|
169
|
+
for (const connector of connectors) {
|
|
170
|
+
if (!byId.has(connector.id)) {
|
|
171
|
+
byId.set(connector.id, connector);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
all: [...byId.values()],
|
|
176
|
+
/**
|
|
177
|
+
* Looks up a connector by identifier.
|
|
178
|
+
*
|
|
179
|
+
* @param id - Unique connector identifier.
|
|
180
|
+
* @returns The registered connector, if present.
|
|
181
|
+
*/
|
|
182
|
+
get(id) {
|
|
183
|
+
return byId.get(id);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
__name(createWalletRegistry, "createWalletRegistry");
|
|
188
|
+
function updateState(store, update) {
|
|
189
|
+
store.setState((state) => ({
|
|
190
|
+
...state,
|
|
191
|
+
...update,
|
|
192
|
+
lastUpdatedAt: now()
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
__name(updateState, "updateState");
|
|
196
|
+
function createActions({ connectors, logger: inputLogger, runtime, store }) {
|
|
197
|
+
const logger = inputLogger ?? createLogger();
|
|
198
|
+
function getCommitment(commitment) {
|
|
199
|
+
return commitment ?? store.getState().cluster.commitment;
|
|
200
|
+
}
|
|
201
|
+
__name(getCommitment, "getCommitment");
|
|
202
|
+
async function warmupCluster(endpoint, commitment) {
|
|
203
|
+
try {
|
|
204
|
+
const start = now();
|
|
205
|
+
await runtime.rpc.getLatestBlockhash({ commitment }).send({ abortSignal: AbortSignal.timeout(1e4) });
|
|
206
|
+
return now() - start;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
logger({
|
|
209
|
+
data: { endpoint, ...formatError(error) },
|
|
210
|
+
level: "warn",
|
|
211
|
+
message: "cluster warmup failed"
|
|
212
|
+
});
|
|
213
|
+
return void 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
__name(warmupCluster, "warmupCluster");
|
|
217
|
+
async function setCluster(endpoint, config) {
|
|
218
|
+
const nextCommitment = config?.commitment ?? store.getState().cluster.commitment;
|
|
219
|
+
const websocketEndpoint = config?.websocketEndpoint ?? endpoint;
|
|
220
|
+
store.setState((state) => ({
|
|
221
|
+
...state,
|
|
222
|
+
cluster: {
|
|
223
|
+
commitment: nextCommitment,
|
|
224
|
+
endpoint,
|
|
225
|
+
status: { status: "connecting" },
|
|
226
|
+
websocketEndpoint
|
|
227
|
+
},
|
|
228
|
+
lastUpdatedAt: now()
|
|
229
|
+
}));
|
|
230
|
+
try {
|
|
231
|
+
const newRpcClient = createSolanaRpcClient({
|
|
232
|
+
commitment: nextCommitment,
|
|
233
|
+
endpoint,
|
|
234
|
+
websocketEndpoint
|
|
235
|
+
});
|
|
236
|
+
runtime.rpc = newRpcClient.rpc;
|
|
237
|
+
runtime.rpcSubscriptions = newRpcClient.rpcSubscriptions;
|
|
238
|
+
const latencyMs = await warmupCluster(endpoint, nextCommitment);
|
|
239
|
+
store.setState((state) => ({
|
|
240
|
+
...state,
|
|
241
|
+
cluster: {
|
|
242
|
+
commitment: nextCommitment,
|
|
243
|
+
endpoint,
|
|
244
|
+
status: { latencyMs, status: "ready" },
|
|
245
|
+
websocketEndpoint
|
|
246
|
+
},
|
|
247
|
+
lastUpdatedAt: now()
|
|
248
|
+
}));
|
|
249
|
+
logger({
|
|
250
|
+
data: { endpoint, latencyMs, websocketEndpoint },
|
|
251
|
+
level: "info",
|
|
252
|
+
message: "cluster ready"
|
|
253
|
+
});
|
|
254
|
+
} catch (error) {
|
|
255
|
+
store.setState((state) => ({
|
|
256
|
+
...state,
|
|
257
|
+
cluster: {
|
|
258
|
+
commitment: nextCommitment,
|
|
259
|
+
endpoint,
|
|
260
|
+
status: { error, status: "error" },
|
|
261
|
+
websocketEndpoint
|
|
262
|
+
},
|
|
263
|
+
lastUpdatedAt: now()
|
|
264
|
+
}));
|
|
265
|
+
logger({
|
|
266
|
+
data: { endpoint, ...formatError(error) },
|
|
267
|
+
level: "error",
|
|
268
|
+
message: "cluster setup failed"
|
|
269
|
+
});
|
|
270
|
+
throw error;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
__name(setCluster, "setCluster");
|
|
274
|
+
async function connectWallet(connectorId, options = {}) {
|
|
275
|
+
const connector = connectors.get(connectorId);
|
|
276
|
+
if (!connector) {
|
|
277
|
+
throw new Error(`No wallet connector registered for id "${connectorId}".`);
|
|
278
|
+
}
|
|
279
|
+
if (!connector.isSupported()) {
|
|
280
|
+
throw new Error(`Wallet connector "${connectorId}" is not supported in this environment.`);
|
|
281
|
+
}
|
|
282
|
+
store.setState((state) => ({
|
|
283
|
+
...state,
|
|
284
|
+
lastUpdatedAt: now(),
|
|
285
|
+
wallet: { connectorId, status: "connecting" }
|
|
286
|
+
}));
|
|
287
|
+
try {
|
|
288
|
+
const session = await connector.connect(options);
|
|
289
|
+
store.setState((state) => ({
|
|
290
|
+
...state,
|
|
291
|
+
lastUpdatedAt: now(),
|
|
292
|
+
wallet: { connectorId, session, status: "connected" }
|
|
293
|
+
}));
|
|
294
|
+
logger({
|
|
295
|
+
data: { address: session.account.address.toString(), connectorId },
|
|
296
|
+
level: "info",
|
|
297
|
+
message: "wallet connected"
|
|
298
|
+
});
|
|
299
|
+
} catch (error) {
|
|
300
|
+
store.setState((state) => ({
|
|
301
|
+
...state,
|
|
302
|
+
lastUpdatedAt: now(),
|
|
303
|
+
wallet: { connectorId, error, status: "error" }
|
|
304
|
+
}));
|
|
305
|
+
logger({
|
|
306
|
+
data: { connectorId, ...formatError(error) },
|
|
307
|
+
level: "error",
|
|
308
|
+
message: "wallet connection failed"
|
|
309
|
+
});
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
__name(connectWallet, "connectWallet");
|
|
314
|
+
async function disconnectWallet2() {
|
|
315
|
+
const wallet = store.getState().wallet;
|
|
316
|
+
if (wallet.status === "disconnected") {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
if (wallet.status === "connected") {
|
|
321
|
+
await wallet.session.disconnect();
|
|
322
|
+
const connector = connectors.get(wallet.connectorId);
|
|
323
|
+
if (connector) {
|
|
324
|
+
await connector.disconnect();
|
|
325
|
+
}
|
|
326
|
+
} else if (wallet.status === "connecting") {
|
|
327
|
+
const connector = connectors.get(wallet.connectorId);
|
|
328
|
+
if (connector) {
|
|
329
|
+
await connector.disconnect();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} finally {
|
|
333
|
+
updateState(store, { wallet: { status: "disconnected" } });
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
__name(disconnectWallet2, "disconnectWallet");
|
|
337
|
+
async function fetchBalance(address4, commitment) {
|
|
338
|
+
const key = address4.toString();
|
|
339
|
+
store.setState((state) => ({
|
|
340
|
+
...state,
|
|
341
|
+
accounts: {
|
|
342
|
+
...state.accounts,
|
|
343
|
+
[key]: {
|
|
344
|
+
address: address4,
|
|
345
|
+
data: state.accounts[key]?.data,
|
|
346
|
+
error: void 0,
|
|
347
|
+
fetching: true,
|
|
348
|
+
lamports: state.accounts[key]?.lamports ?? null,
|
|
349
|
+
lastFetchedAt: now(),
|
|
350
|
+
slot: state.accounts[key]?.slot ?? null
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
lastUpdatedAt: now()
|
|
354
|
+
}));
|
|
355
|
+
try {
|
|
356
|
+
const response = await runtime.rpc.getBalance(address4, { commitment: getCommitment(commitment) }).send({ abortSignal: AbortSignal.timeout(1e4) });
|
|
357
|
+
const lamports2 = response.value;
|
|
358
|
+
store.setState((state) => ({
|
|
359
|
+
...state,
|
|
360
|
+
accounts: {
|
|
361
|
+
...state.accounts,
|
|
362
|
+
[key]: {
|
|
363
|
+
address: address4,
|
|
364
|
+
data: state.accounts[key]?.data,
|
|
365
|
+
error: void 0,
|
|
366
|
+
fetching: false,
|
|
367
|
+
lamports: lamports2,
|
|
368
|
+
lastFetchedAt: now(),
|
|
369
|
+
slot: response.context.slot
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
lastUpdatedAt: now()
|
|
373
|
+
}));
|
|
374
|
+
return lamports2;
|
|
375
|
+
} catch (error) {
|
|
376
|
+
store.setState((state) => ({
|
|
377
|
+
...state,
|
|
378
|
+
accounts: {
|
|
379
|
+
...state.accounts,
|
|
380
|
+
[key]: {
|
|
381
|
+
address: address4,
|
|
382
|
+
data: state.accounts[key]?.data,
|
|
383
|
+
error,
|
|
384
|
+
fetching: false,
|
|
385
|
+
lamports: state.accounts[key]?.lamports ?? null,
|
|
386
|
+
lastFetchedAt: now(),
|
|
387
|
+
slot: state.accounts[key]?.slot ?? null
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
lastUpdatedAt: now()
|
|
391
|
+
}));
|
|
392
|
+
logger({
|
|
393
|
+
data: { address: key, ...formatError(error) },
|
|
394
|
+
level: "error",
|
|
395
|
+
message: "balance fetch failed"
|
|
396
|
+
});
|
|
397
|
+
throw error;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
__name(fetchBalance, "fetchBalance");
|
|
401
|
+
async function fetchAccount(address4, commitment) {
|
|
402
|
+
const key = address4.toString();
|
|
403
|
+
store.setState((state) => ({
|
|
404
|
+
...state,
|
|
405
|
+
accounts: {
|
|
406
|
+
...state.accounts,
|
|
407
|
+
[key]: {
|
|
408
|
+
address: address4,
|
|
409
|
+
data: state.accounts[key]?.data,
|
|
410
|
+
error: void 0,
|
|
411
|
+
fetching: true,
|
|
412
|
+
lamports: state.accounts[key]?.lamports ?? null,
|
|
413
|
+
lastFetchedAt: now(),
|
|
414
|
+
slot: state.accounts[key]?.slot ?? null
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
lastUpdatedAt: now()
|
|
418
|
+
}));
|
|
419
|
+
try {
|
|
420
|
+
const response = await runtime.rpc.getAccountInfo(address4, { commitment: getCommitment(commitment), encoding: "base64" }).send({ abortSignal: AbortSignal.timeout(1e4) });
|
|
421
|
+
const value = response.value;
|
|
422
|
+
const lamports2 = value?.lamports ?? null;
|
|
423
|
+
store.setState((state) => ({
|
|
424
|
+
...state,
|
|
425
|
+
accounts: {
|
|
426
|
+
...state.accounts,
|
|
427
|
+
[key]: {
|
|
428
|
+
address: address4,
|
|
429
|
+
data: value,
|
|
430
|
+
error: void 0,
|
|
431
|
+
fetching: false,
|
|
432
|
+
lamports: lamports2,
|
|
433
|
+
lastFetchedAt: now(),
|
|
434
|
+
slot: response.context.slot
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
lastUpdatedAt: now()
|
|
438
|
+
}));
|
|
439
|
+
return store.getState().accounts[key];
|
|
440
|
+
} catch (error) {
|
|
441
|
+
store.setState((state) => ({
|
|
442
|
+
...state,
|
|
443
|
+
accounts: {
|
|
444
|
+
...state.accounts,
|
|
445
|
+
[key]: {
|
|
446
|
+
address: address4,
|
|
447
|
+
data: state.accounts[key]?.data,
|
|
448
|
+
error,
|
|
449
|
+
fetching: false,
|
|
450
|
+
lamports: state.accounts[key]?.lamports ?? null,
|
|
451
|
+
lastFetchedAt: now(),
|
|
452
|
+
slot: state.accounts[key]?.slot ?? null
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
lastUpdatedAt: now()
|
|
456
|
+
}));
|
|
457
|
+
logger({
|
|
458
|
+
data: { address: key, ...formatError(error) },
|
|
459
|
+
level: "error",
|
|
460
|
+
message: "account fetch failed"
|
|
461
|
+
});
|
|
462
|
+
throw error;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
__name(fetchAccount, "fetchAccount");
|
|
466
|
+
async function sendTransaction(transaction, commitment) {
|
|
467
|
+
const targetCommitment = getCommitment(commitment);
|
|
468
|
+
const abortController = new AbortController();
|
|
469
|
+
const signature4 = await runtime.rpc.sendTransaction(getBase64EncodedWireTransaction(transaction), {
|
|
470
|
+
encoding: "base64",
|
|
471
|
+
preflightCommitment: targetCommitment
|
|
472
|
+
}).send({ abortSignal: abortController.signal });
|
|
473
|
+
const key = signature4.toString();
|
|
474
|
+
store.setState((state) => ({
|
|
475
|
+
...state,
|
|
476
|
+
lastUpdatedAt: now(),
|
|
477
|
+
transactions: {
|
|
478
|
+
...state.transactions,
|
|
479
|
+
[key]: {
|
|
480
|
+
lastUpdatedAt: now(),
|
|
481
|
+
signature: signature4,
|
|
482
|
+
status: "sending"
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}));
|
|
486
|
+
const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({
|
|
487
|
+
rpc: runtime.rpc,
|
|
488
|
+
rpcSubscriptions: runtime.rpcSubscriptions
|
|
489
|
+
});
|
|
490
|
+
const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({
|
|
491
|
+
rpc: runtime.rpc,
|
|
492
|
+
rpcSubscriptions: runtime.rpcSubscriptions
|
|
493
|
+
});
|
|
494
|
+
try {
|
|
495
|
+
await waitForRecentTransactionConfirmation({
|
|
496
|
+
abortSignal: abortController.signal,
|
|
497
|
+
commitment: targetCommitment,
|
|
498
|
+
getBlockHeightExceedencePromise,
|
|
499
|
+
getRecentSignatureConfirmationPromise,
|
|
500
|
+
transaction
|
|
501
|
+
});
|
|
502
|
+
store.setState((state) => ({
|
|
503
|
+
...state,
|
|
504
|
+
lastUpdatedAt: now(),
|
|
505
|
+
transactions: {
|
|
506
|
+
...state.transactions,
|
|
507
|
+
[key]: {
|
|
508
|
+
lastUpdatedAt: now(),
|
|
509
|
+
signature: signature4,
|
|
510
|
+
status: "confirmed"
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}));
|
|
514
|
+
return signature4;
|
|
515
|
+
} catch (error) {
|
|
516
|
+
store.setState((state) => ({
|
|
517
|
+
...state,
|
|
518
|
+
lastUpdatedAt: now(),
|
|
519
|
+
transactions: {
|
|
520
|
+
...state.transactions,
|
|
521
|
+
[key]: {
|
|
522
|
+
error,
|
|
523
|
+
lastUpdatedAt: now(),
|
|
524
|
+
signature: signature4,
|
|
525
|
+
status: "failed"
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}));
|
|
529
|
+
logger({
|
|
530
|
+
data: { signature: key, ...formatError(error) },
|
|
531
|
+
level: "error",
|
|
532
|
+
message: "transaction failed to confirm"
|
|
533
|
+
});
|
|
534
|
+
throw error;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
__name(sendTransaction, "sendTransaction");
|
|
538
|
+
async function requestAirdrop(address4, lamports2) {
|
|
539
|
+
if (!("requestAirdrop" in runtime.rpc)) {
|
|
540
|
+
throw new Error("The current RPC endpoint does not support airdrops.");
|
|
541
|
+
}
|
|
542
|
+
const factory = airdropFactory({
|
|
543
|
+
rpc: runtime.rpc,
|
|
544
|
+
rpcSubscriptions: runtime.rpcSubscriptions
|
|
545
|
+
});
|
|
546
|
+
const signature4 = await factory({
|
|
547
|
+
commitment: getCommitment("confirmed"),
|
|
548
|
+
lamports: lamports2,
|
|
549
|
+
recipientAddress: address4
|
|
550
|
+
});
|
|
551
|
+
logger({
|
|
552
|
+
data: { address: address4.toString(), lamports: lamports2.toString(), signature: signature4 },
|
|
553
|
+
level: "info",
|
|
554
|
+
message: "airdrop requested"
|
|
555
|
+
});
|
|
556
|
+
return signature4;
|
|
557
|
+
}
|
|
558
|
+
__name(requestAirdrop, "requestAirdrop");
|
|
559
|
+
return {
|
|
560
|
+
connectWallet,
|
|
561
|
+
disconnectWallet: disconnectWallet2,
|
|
562
|
+
fetchAccount,
|
|
563
|
+
fetchBalance,
|
|
564
|
+
requestAirdrop,
|
|
565
|
+
sendTransaction,
|
|
566
|
+
setCluster
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
__name(createActions, "createActions");
|
|
570
|
+
|
|
571
|
+
// src/numeric/math.ts
|
|
572
|
+
var TEN = 10n;
|
|
573
|
+
function pow10(exponent) {
|
|
574
|
+
assertDecimals(exponent, "exponent");
|
|
575
|
+
return TEN ** BigInt(exponent);
|
|
576
|
+
}
|
|
577
|
+
__name(pow10, "pow10");
|
|
578
|
+
function assertNonNegative(value, label = "value") {
|
|
579
|
+
if (value < 0n) {
|
|
580
|
+
throw new RangeError(`${label} must be non-negative`);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
__name(assertNonNegative, "assertNonNegative");
|
|
584
|
+
function assertDecimals(decimals, label = "decimals") {
|
|
585
|
+
if (!Number.isInteger(decimals) || decimals < 0 || decimals > 38) {
|
|
586
|
+
throw new RangeError(`${label} must be an integer between 0 and 38`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
__name(assertDecimals, "assertDecimals");
|
|
590
|
+
function toBigint2(value, label = "value") {
|
|
591
|
+
if (typeof value === "bigint") {
|
|
592
|
+
return value;
|
|
593
|
+
}
|
|
594
|
+
if (typeof value === "number") {
|
|
595
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) {
|
|
596
|
+
throw new RangeError(`${label} must be a finite integer when provided as a number`);
|
|
597
|
+
}
|
|
598
|
+
if (!Number.isSafeInteger(value)) {
|
|
599
|
+
throw new RangeError(`${label} must be within the safe integer range when provided as a number`);
|
|
600
|
+
}
|
|
601
|
+
return BigInt(value);
|
|
602
|
+
}
|
|
603
|
+
const trimmed = value.trim();
|
|
604
|
+
const match = /^[-+]?\d+$/.exec(trimmed);
|
|
605
|
+
if (!match) {
|
|
606
|
+
throw new SyntaxError(`${label} must be an integer string`);
|
|
607
|
+
}
|
|
608
|
+
return BigInt(match[0]);
|
|
609
|
+
}
|
|
610
|
+
__name(toBigint2, "toBigint");
|
|
611
|
+
function checkedAdd(lhs, rhs, label = "result") {
|
|
612
|
+
const result = lhs + rhs;
|
|
613
|
+
assertNonNegative(result, label);
|
|
614
|
+
return result;
|
|
615
|
+
}
|
|
616
|
+
__name(checkedAdd, "checkedAdd");
|
|
617
|
+
function checkedSubtract(lhs, rhs, label = "result") {
|
|
618
|
+
const result = lhs - rhs;
|
|
619
|
+
assertNonNegative(result, label);
|
|
620
|
+
return result;
|
|
621
|
+
}
|
|
622
|
+
__name(checkedSubtract, "checkedSubtract");
|
|
623
|
+
function checkedMultiply(lhs, rhs, label = "result") {
|
|
624
|
+
const result = lhs * rhs;
|
|
625
|
+
assertNonNegative(result, label);
|
|
626
|
+
return result;
|
|
627
|
+
}
|
|
628
|
+
__name(checkedMultiply, "checkedMultiply");
|
|
629
|
+
function checkedDivide(dividend, divisor, label = "result") {
|
|
630
|
+
if (divisor === 0n) {
|
|
631
|
+
throw new RangeError("divisor must be non-zero");
|
|
632
|
+
}
|
|
633
|
+
const result = dividend / divisor;
|
|
634
|
+
assertNonNegative(result, label);
|
|
635
|
+
return result;
|
|
636
|
+
}
|
|
637
|
+
__name(checkedDivide, "checkedDivide");
|
|
638
|
+
|
|
639
|
+
// src/numeric/rational.ts
|
|
640
|
+
function divideWithRounding(dividend, divisor, rounding) {
|
|
641
|
+
if (divisor <= 0n) {
|
|
642
|
+
throw new RangeError("divisor must be positive");
|
|
643
|
+
}
|
|
644
|
+
const base = dividend / divisor;
|
|
645
|
+
const remainder = dividend % divisor;
|
|
646
|
+
if (remainder === 0n) {
|
|
647
|
+
return base;
|
|
648
|
+
}
|
|
649
|
+
switch (rounding) {
|
|
650
|
+
case "ceil":
|
|
651
|
+
return base + 1n;
|
|
652
|
+
case "round": {
|
|
653
|
+
const twice = remainder * 2n;
|
|
654
|
+
return twice >= divisor ? base + 1n : base;
|
|
655
|
+
}
|
|
656
|
+
default:
|
|
657
|
+
return base;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
__name(divideWithRounding, "divideWithRounding");
|
|
661
|
+
function createRatio(numeratorInput, denominatorInput) {
|
|
662
|
+
const numerator = toBigint2(numeratorInput, "numerator");
|
|
663
|
+
const denominator = toBigint2(denominatorInput, "denominator");
|
|
664
|
+
if (denominator <= 0n) {
|
|
665
|
+
throw new RangeError("denominator must be positive");
|
|
666
|
+
}
|
|
667
|
+
assertNonNegative(numerator, "numerator");
|
|
668
|
+
return Object.freeze({ denominator, numerator });
|
|
669
|
+
}
|
|
670
|
+
__name(createRatio, "createRatio");
|
|
671
|
+
function applyRatio(amount, ratio, options = {}) {
|
|
672
|
+
assertNonNegative(amount, "amount");
|
|
673
|
+
const dividend = amount * ratio.numerator;
|
|
674
|
+
const rounding = options.rounding ?? "floor";
|
|
675
|
+
return divideWithRounding(dividend, ratio.denominator, rounding);
|
|
676
|
+
}
|
|
677
|
+
__name(applyRatio, "applyRatio");
|
|
678
|
+
|
|
679
|
+
// src/numeric/amounts.ts
|
|
680
|
+
var DECIMAL_PATTERN = /^\d+(?:\.\d+)?$/;
|
|
681
|
+
function normalizeNumberInput(value, decimals, label) {
|
|
682
|
+
if (!Number.isFinite(value)) {
|
|
683
|
+
throw new RangeError(`${label} must be a finite number`);
|
|
684
|
+
}
|
|
685
|
+
if (Number.isInteger(value)) {
|
|
686
|
+
return value.toString(10);
|
|
687
|
+
}
|
|
688
|
+
const stringValue = value.toString(10);
|
|
689
|
+
if (stringValue.includes("e") || stringValue.includes("E")) {
|
|
690
|
+
throw new RangeError(`${label} cannot use exponential notation; provide a string instead`);
|
|
691
|
+
}
|
|
692
|
+
const parts = stringValue.split(".");
|
|
693
|
+
if (parts[1] && parts[1].length > decimals + 6) {
|
|
694
|
+
throw new RangeError(`${label} exceeds safe precision; provide a string instead`);
|
|
695
|
+
}
|
|
696
|
+
return stringValue;
|
|
697
|
+
}
|
|
698
|
+
__name(normalizeNumberInput, "normalizeNumberInput");
|
|
699
|
+
function decimalToBaseUnits(value, decimals, scale, options) {
|
|
700
|
+
const label = options.label ?? "value";
|
|
701
|
+
const rounding = options.rounding ?? "floor";
|
|
702
|
+
const sanitized = value.replace(/_/g, "").trim();
|
|
703
|
+
if (sanitized === "") {
|
|
704
|
+
throw new SyntaxError(`${label} must not be empty`);
|
|
705
|
+
}
|
|
706
|
+
if (!DECIMAL_PATTERN.test(sanitized)) {
|
|
707
|
+
throw new SyntaxError(`${label} must be a non-negative decimal string`);
|
|
708
|
+
}
|
|
709
|
+
const [integerPartRaw, fractionalRaw] = sanitized.split(".");
|
|
710
|
+
const integerPart = integerPartRaw || "0";
|
|
711
|
+
assertNonNegative(BigInt(integerPart), label);
|
|
712
|
+
let result = BigInt(integerPart) * scale;
|
|
713
|
+
const fractionalDigits = fractionalRaw ?? "";
|
|
714
|
+
if (decimals === 0) {
|
|
715
|
+
if (fractionalDigits.length === 0) {
|
|
716
|
+
return result;
|
|
717
|
+
}
|
|
718
|
+
const hasFractional = /[1-9]/.test(fractionalDigits);
|
|
719
|
+
if (rounding === "ceil" && hasFractional) {
|
|
720
|
+
return result + 1n;
|
|
721
|
+
}
|
|
722
|
+
if (rounding === "round" && fractionalDigits[0] !== void 0 && fractionalDigits[0] >= "5") {
|
|
723
|
+
return result + 1n;
|
|
724
|
+
}
|
|
725
|
+
return result;
|
|
726
|
+
}
|
|
727
|
+
const truncatedFractional = fractionalDigits.slice(0, decimals).padEnd(decimals, "0");
|
|
728
|
+
const fractionalComponent = truncatedFractional === "" ? 0n : BigInt(truncatedFractional);
|
|
729
|
+
result += fractionalComponent;
|
|
730
|
+
if (fractionalDigits.length > decimals) {
|
|
731
|
+
const remainderDigits = fractionalDigits.slice(decimals);
|
|
732
|
+
const hasRemainder = /[1-9]/.test(remainderDigits);
|
|
733
|
+
if (rounding === "ceil" && hasRemainder) {
|
|
734
|
+
result += 1n;
|
|
735
|
+
} else if (rounding === "round") {
|
|
736
|
+
const firstRemainderDigit = remainderDigits[0];
|
|
737
|
+
if (firstRemainderDigit !== void 0 && firstRemainderDigit >= "5") {
|
|
738
|
+
result += 1n;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
__name(decimalToBaseUnits, "decimalToBaseUnits");
|
|
745
|
+
function formatBaseUnits(amount, decimals, scale, options) {
|
|
746
|
+
assertNonNegative(amount, "amount");
|
|
747
|
+
const minimumFractionDigits = options.minimumFractionDigits ?? 0;
|
|
748
|
+
if (minimumFractionDigits < 0 || minimumFractionDigits > decimals) {
|
|
749
|
+
throw new RangeError("minimumFractionDigits must be between 0 and the token decimals");
|
|
750
|
+
}
|
|
751
|
+
const trimTrailingZeros = options.trimTrailingZeros ?? true;
|
|
752
|
+
if (decimals === 0) {
|
|
753
|
+
return amount.toString();
|
|
754
|
+
}
|
|
755
|
+
const whole = amount / scale;
|
|
756
|
+
let fraction = (amount % scale).toString().padStart(decimals, "0");
|
|
757
|
+
if (trimTrailingZeros) {
|
|
758
|
+
fraction = fraction.replace(/0+$/, "");
|
|
759
|
+
}
|
|
760
|
+
if (fraction.length < minimumFractionDigits) {
|
|
761
|
+
fraction = fraction.padEnd(minimumFractionDigits, "0");
|
|
762
|
+
}
|
|
763
|
+
if (fraction.length === 0) {
|
|
764
|
+
return whole.toString();
|
|
765
|
+
}
|
|
766
|
+
return `${whole.toString()}.${fraction}`;
|
|
767
|
+
}
|
|
768
|
+
__name(formatBaseUnits, "formatBaseUnits");
|
|
769
|
+
function createTokenAmount(decimals) {
|
|
770
|
+
assertDecimals(decimals, "decimals");
|
|
771
|
+
const scale = pow10(decimals);
|
|
772
|
+
function fromBaseUnits(value, label) {
|
|
773
|
+
const amount = toBigint2(value, label ?? "amount");
|
|
774
|
+
assertNonNegative(amount, label ?? "amount");
|
|
775
|
+
return amount;
|
|
776
|
+
}
|
|
777
|
+
__name(fromBaseUnits, "fromBaseUnits");
|
|
778
|
+
function fromDecimal(value, options = {}) {
|
|
779
|
+
const label = options.label ?? "value";
|
|
780
|
+
if (typeof value === "number") {
|
|
781
|
+
if (Number.isInteger(value)) {
|
|
782
|
+
if (!Number.isSafeInteger(value)) {
|
|
783
|
+
throw new RangeError(`${label} must be within the safe integer range when provided as a number`);
|
|
784
|
+
}
|
|
785
|
+
return fromBaseUnits(BigInt(value) * scale, label);
|
|
786
|
+
}
|
|
787
|
+
if (decimals === 0) {
|
|
788
|
+
throw new RangeError(`${label} cannot include fractional digits for a token with 0 decimals`);
|
|
789
|
+
}
|
|
790
|
+
const normalized = normalizeNumberInput(value, decimals, label);
|
|
791
|
+
return decimalToBaseUnits(normalized, decimals, scale, options);
|
|
792
|
+
}
|
|
793
|
+
return decimalToBaseUnits(value, decimals, scale, options);
|
|
794
|
+
}
|
|
795
|
+
__name(fromDecimal, "fromDecimal");
|
|
796
|
+
function toDecimalString(amount, options = {}) {
|
|
797
|
+
return formatBaseUnits(fromBaseUnits(amount), decimals, scale, options);
|
|
798
|
+
}
|
|
799
|
+
__name(toDecimalString, "toDecimalString");
|
|
800
|
+
function add(lhs, rhs) {
|
|
801
|
+
return checkedAdd(fromBaseUnits(lhs), fromBaseUnits(rhs));
|
|
802
|
+
}
|
|
803
|
+
__name(add, "add");
|
|
804
|
+
function subtract(lhs, rhs) {
|
|
805
|
+
return checkedSubtract(fromBaseUnits(lhs), fromBaseUnits(rhs));
|
|
806
|
+
}
|
|
807
|
+
__name(subtract, "subtract");
|
|
808
|
+
function multiplyByRatio(amount, ratio, options) {
|
|
809
|
+
return applyRatio(fromBaseUnits(amount), ratio, options);
|
|
810
|
+
}
|
|
811
|
+
__name(multiplyByRatio, "multiplyByRatio");
|
|
812
|
+
function isZero(amount) {
|
|
813
|
+
return fromBaseUnits(amount) === 0n;
|
|
814
|
+
}
|
|
815
|
+
__name(isZero, "isZero");
|
|
816
|
+
function compare(lhs, rhs) {
|
|
817
|
+
const left = fromBaseUnits(lhs);
|
|
818
|
+
const right = fromBaseUnits(rhs);
|
|
819
|
+
if (left > right) {
|
|
820
|
+
return 1;
|
|
821
|
+
}
|
|
822
|
+
if (left < right) {
|
|
823
|
+
return -1;
|
|
824
|
+
}
|
|
825
|
+
return 0;
|
|
826
|
+
}
|
|
827
|
+
__name(compare, "compare");
|
|
828
|
+
return Object.freeze({
|
|
829
|
+
add,
|
|
830
|
+
compare,
|
|
831
|
+
decimals,
|
|
832
|
+
fromBaseUnits,
|
|
833
|
+
fromDecimal,
|
|
834
|
+
isZero,
|
|
835
|
+
multiplyByRatio,
|
|
836
|
+
scale,
|
|
837
|
+
subtract,
|
|
838
|
+
toDecimalString
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
__name(createTokenAmount, "createTokenAmount");
|
|
842
|
+
|
|
843
|
+
// src/numeric/lamports.ts
|
|
844
|
+
var BASE_LAMPORTS = createTokenAmount(9);
|
|
845
|
+
var LAMPORTS_PER_SOL = BASE_LAMPORTS.scale;
|
|
846
|
+
var lamportsMath = Object.freeze({
|
|
847
|
+
/**
|
|
848
|
+
* Adds two lamport amounts.
|
|
849
|
+
*
|
|
850
|
+
* @param lhs - First lamport operand.
|
|
851
|
+
* @param rhs - Second lamport operand.
|
|
852
|
+
* @returns Sum as lamports.
|
|
853
|
+
*/
|
|
854
|
+
add(lhs, rhs) {
|
|
855
|
+
return BASE_LAMPORTS.add(lhs, rhs);
|
|
856
|
+
},
|
|
857
|
+
/**
|
|
858
|
+
* Compares two lamport amounts.
|
|
859
|
+
*
|
|
860
|
+
* @param lhs - First lamport operand.
|
|
861
|
+
* @param rhs - Second lamport operand.
|
|
862
|
+
* @returns `1`, `0`, or `-1` corresponding to the comparison result.
|
|
863
|
+
*/
|
|
864
|
+
compare(lhs, rhs) {
|
|
865
|
+
return BASE_LAMPORTS.compare(lhs, rhs);
|
|
866
|
+
},
|
|
867
|
+
decimals: BASE_LAMPORTS.decimals,
|
|
868
|
+
/**
|
|
869
|
+
* Validates and converts raw lamport inputs.
|
|
870
|
+
*
|
|
871
|
+
* @param value - Integer-like lamport amount.
|
|
872
|
+
* @param label - Optional label used for error reporting.
|
|
873
|
+
* @returns Normalized lamport bigint.
|
|
874
|
+
*/
|
|
875
|
+
fromLamports(value, label) {
|
|
876
|
+
return BASE_LAMPORTS.fromBaseUnits(value, label);
|
|
877
|
+
},
|
|
878
|
+
/**
|
|
879
|
+
* Converts SOL denominated values into lamports.
|
|
880
|
+
*
|
|
881
|
+
* @param value - Decimal representation of SOL.
|
|
882
|
+
* @param options - Optional rounding and labelling configuration.
|
|
883
|
+
* @returns Lamport amount.
|
|
884
|
+
*/
|
|
885
|
+
fromSol(value, options) {
|
|
886
|
+
return BASE_LAMPORTS.fromDecimal(value, options);
|
|
887
|
+
},
|
|
888
|
+
/**
|
|
889
|
+
* Determines whether a lamport amount equals zero.
|
|
890
|
+
*
|
|
891
|
+
* @param amount - Lamports to inspect.
|
|
892
|
+
* @returns `true` when the amount is zero.
|
|
893
|
+
*/
|
|
894
|
+
isZero(amount) {
|
|
895
|
+
return BASE_LAMPORTS.isZero(amount);
|
|
896
|
+
},
|
|
897
|
+
/**
|
|
898
|
+
* Applies a ratio to lamports.
|
|
899
|
+
*
|
|
900
|
+
* @param amount - Lamport amount to scale.
|
|
901
|
+
* @param ratio - Ratio produced by {@link createRatio}.
|
|
902
|
+
* @param options - Optional rounding configuration.
|
|
903
|
+
* @returns Scaled lamport amount.
|
|
904
|
+
*/
|
|
905
|
+
multiplyByRatio(amount, ratio, options) {
|
|
906
|
+
return BASE_LAMPORTS.multiplyByRatio(amount, ratio, options);
|
|
907
|
+
},
|
|
908
|
+
raw: BASE_LAMPORTS,
|
|
909
|
+
scale: BASE_LAMPORTS.scale,
|
|
910
|
+
/**
|
|
911
|
+
* Subtracts two lamport amounts.
|
|
912
|
+
*
|
|
913
|
+
* @param lhs - First lamport operand.
|
|
914
|
+
* @param rhs - Second lamport operand.
|
|
915
|
+
* @returns Difference as lamports.
|
|
916
|
+
*/
|
|
917
|
+
subtract(lhs, rhs) {
|
|
918
|
+
return BASE_LAMPORTS.subtract(lhs, rhs);
|
|
919
|
+
},
|
|
920
|
+
/**
|
|
921
|
+
* Formats lamports into a human-readable SOL string.
|
|
922
|
+
*
|
|
923
|
+
* @param amount - Lamport amount to format.
|
|
924
|
+
* @param options - Formatting preferences.
|
|
925
|
+
* @returns SOL string representation.
|
|
926
|
+
*/
|
|
927
|
+
toSolString(amount, options) {
|
|
928
|
+
return BASE_LAMPORTS.toDecimalString(amount, options);
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
function lamports(value, label) {
|
|
932
|
+
return lamportsMath.fromLamports(value, label);
|
|
933
|
+
}
|
|
934
|
+
__name(lamports, "lamports");
|
|
935
|
+
function lamportsFromSol(value, options) {
|
|
936
|
+
return lamportsMath.fromSol(value, options);
|
|
937
|
+
}
|
|
938
|
+
__name(lamportsFromSol, "lamportsFromSol");
|
|
939
|
+
function lamportsToSolString(amount, options) {
|
|
940
|
+
return lamportsMath.toSolString(amount, options);
|
|
941
|
+
}
|
|
942
|
+
__name(lamportsToSolString, "lamportsToSolString");
|
|
943
|
+
function isWalletSession(value) {
|
|
944
|
+
if (typeof value !== "object" || value === null) {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
return "account" in value && "connector" in value && "disconnect" in value;
|
|
948
|
+
}
|
|
949
|
+
__name(isWalletSession, "isWalletSession");
|
|
950
|
+
function createWalletTransactionSigner(session, config = {}) {
|
|
951
|
+
const { commitment } = config;
|
|
952
|
+
const address4 = session.account.address;
|
|
953
|
+
if (session.signTransaction) {
|
|
954
|
+
const signTransaction = session.signTransaction.bind(session);
|
|
955
|
+
const modifyingSigner = Object.freeze({
|
|
956
|
+
address: address4,
|
|
957
|
+
async modifyAndSignTransactions(transactions) {
|
|
958
|
+
const signedTransactions = [];
|
|
959
|
+
for (const transaction of transactions) {
|
|
960
|
+
const castTransaction = transaction;
|
|
961
|
+
const signed = await signTransaction(
|
|
962
|
+
castTransaction
|
|
963
|
+
);
|
|
964
|
+
const signature4 = signed.signatures[address4];
|
|
965
|
+
if (!signature4) {
|
|
966
|
+
throw new Error("Wallet did not populate the expected fee payer signature.");
|
|
967
|
+
}
|
|
968
|
+
const mergedTransaction = Object.freeze({
|
|
969
|
+
...castTransaction,
|
|
970
|
+
messageBytes: signed.messageBytes,
|
|
971
|
+
signatures: Object.freeze({
|
|
972
|
+
...castTransaction.signatures,
|
|
973
|
+
...signed.signatures
|
|
974
|
+
})
|
|
975
|
+
});
|
|
976
|
+
signedTransactions.push(mergedTransaction);
|
|
977
|
+
}
|
|
978
|
+
return Object.freeze(signedTransactions);
|
|
979
|
+
},
|
|
980
|
+
async signTransactions(transactions) {
|
|
981
|
+
const signedTransactions = await this.modifyAndSignTransactions(transactions);
|
|
982
|
+
return Object.freeze(
|
|
983
|
+
signedTransactions.map((signedTransaction) => {
|
|
984
|
+
const signature4 = signedTransaction.signatures[address4];
|
|
985
|
+
if (!signature4) {
|
|
986
|
+
throw new Error("Expected signer to produce a signature for the provided address.");
|
|
987
|
+
}
|
|
988
|
+
return Object.freeze({ [address4]: signature4 });
|
|
989
|
+
})
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
return {
|
|
994
|
+
mode: "partial",
|
|
995
|
+
signer: modifyingSigner
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
if (session.sendTransaction) {
|
|
999
|
+
const base58Encoder = getBase58Encoder();
|
|
1000
|
+
const sendTransaction = session.sendTransaction.bind(session);
|
|
1001
|
+
const sendingSigner = Object.freeze({
|
|
1002
|
+
address: address4,
|
|
1003
|
+
async signAndSendTransactions(transactions) {
|
|
1004
|
+
const signatures = [];
|
|
1005
|
+
for (const transaction of transactions) {
|
|
1006
|
+
const signatureString = await sendTransaction(
|
|
1007
|
+
transaction,
|
|
1008
|
+
commitment ? { commitment } : void 0
|
|
1009
|
+
);
|
|
1010
|
+
const bytes = base58Encoder.encode(signatureString);
|
|
1011
|
+
signatures.push(signatureBytes(bytes));
|
|
1012
|
+
}
|
|
1013
|
+
return signatures;
|
|
1014
|
+
}
|
|
1015
|
+
});
|
|
1016
|
+
return {
|
|
1017
|
+
mode: "send",
|
|
1018
|
+
signer: sendingSigner
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
throw new Error("Wallet session does not support signing or sending transactions.");
|
|
1022
|
+
}
|
|
1023
|
+
__name(createWalletTransactionSigner, "createWalletTransactionSigner");
|
|
1024
|
+
function resolveSignerMode(signer) {
|
|
1025
|
+
if (isTransactionPartialSigner(signer)) {
|
|
1026
|
+
return "partial";
|
|
1027
|
+
}
|
|
1028
|
+
if (isTransactionSendingSigner(signer)) {
|
|
1029
|
+
return "send";
|
|
1030
|
+
}
|
|
1031
|
+
return "partial";
|
|
1032
|
+
}
|
|
1033
|
+
__name(resolveSignerMode, "resolveSignerMode");
|
|
1034
|
+
|
|
1035
|
+
// src/features/sol.ts
|
|
1036
|
+
function ensureAddress(value) {
|
|
1037
|
+
return typeof value === "string" ? address(value) : value;
|
|
1038
|
+
}
|
|
1039
|
+
__name(ensureAddress, "ensureAddress");
|
|
1040
|
+
async function resolveLifetime(runtime, commitment, fallback) {
|
|
1041
|
+
if (fallback) {
|
|
1042
|
+
return fallback;
|
|
1043
|
+
}
|
|
1044
|
+
const { value } = await runtime.rpc.getLatestBlockhash({ commitment }).send();
|
|
1045
|
+
return value;
|
|
1046
|
+
}
|
|
1047
|
+
__name(resolveLifetime, "resolveLifetime");
|
|
1048
|
+
function resolveSigner(authority, commitment) {
|
|
1049
|
+
if (isWalletSession(authority)) {
|
|
1050
|
+
const { signer, mode } = createWalletTransactionSigner(authority, { commitment });
|
|
1051
|
+
return { mode, signer };
|
|
1052
|
+
}
|
|
1053
|
+
return { mode: resolveSignerMode(authority), signer: authority };
|
|
1054
|
+
}
|
|
1055
|
+
__name(resolveSigner, "resolveSigner");
|
|
1056
|
+
function toLamportAmount(input) {
|
|
1057
|
+
return lamportsMath.fromLamports(input);
|
|
1058
|
+
}
|
|
1059
|
+
__name(toLamportAmount, "toLamportAmount");
|
|
1060
|
+
function createSolTransferHelper(runtime) {
|
|
1061
|
+
async function prepareTransfer(config) {
|
|
1062
|
+
const commitment = config.commitment;
|
|
1063
|
+
const lifetime = await resolveLifetime(runtime, commitment, config.lifetime);
|
|
1064
|
+
const { signer, mode } = resolveSigner(config.authority, commitment);
|
|
1065
|
+
const destination = ensureAddress(config.destination);
|
|
1066
|
+
const amount = toLamportAmount(config.amount);
|
|
1067
|
+
const message = pipe(
|
|
1068
|
+
createTransactionMessage({ version: config.transactionVersion ?? 0 }),
|
|
1069
|
+
(m) => setTransactionMessageFeePayer(signer.address, m),
|
|
1070
|
+
(m) => setTransactionMessageLifetimeUsingBlockhash(lifetime, m),
|
|
1071
|
+
(m) => appendTransactionMessageInstruction(
|
|
1072
|
+
getTransferSolInstruction({ amount, destination, source: signer }),
|
|
1073
|
+
m
|
|
1074
|
+
)
|
|
1075
|
+
);
|
|
1076
|
+
return {
|
|
1077
|
+
commitment,
|
|
1078
|
+
lifetime,
|
|
1079
|
+
message,
|
|
1080
|
+
mode,
|
|
1081
|
+
signer,
|
|
1082
|
+
plan: singleTransactionPlan(message)
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
__name(prepareTransfer, "prepareTransfer");
|
|
1086
|
+
async function sendPreparedTransfer(prepared, options = {}) {
|
|
1087
|
+
if (prepared.mode === "send" && isTransactionSendingSigner(prepared.signer)) {
|
|
1088
|
+
const signatureBytes2 = await signAndSendTransactionMessageWithSigners(prepared.message, {
|
|
1089
|
+
abortSignal: options.abortSignal,
|
|
1090
|
+
minContextSlot: options.minContextSlot
|
|
1091
|
+
});
|
|
1092
|
+
const base58Decoder2 = getBase58Decoder();
|
|
1093
|
+
return signature(base58Decoder2.decode(signatureBytes2));
|
|
1094
|
+
}
|
|
1095
|
+
const commitment = options.commitment ?? prepared.commitment;
|
|
1096
|
+
const maxRetries = options.maxRetries === void 0 ? void 0 : typeof options.maxRetries === "bigint" ? options.maxRetries : BigInt(options.maxRetries);
|
|
1097
|
+
let latestSignature = null;
|
|
1098
|
+
const executor = createTransactionPlanExecutor({
|
|
1099
|
+
async executeTransactionMessage(message, config = {}) {
|
|
1100
|
+
const signed = await signTransactionMessageWithSigners(message, {
|
|
1101
|
+
abortSignal: config.abortSignal ?? options.abortSignal,
|
|
1102
|
+
minContextSlot: options.minContextSlot
|
|
1103
|
+
});
|
|
1104
|
+
const wire = getBase64EncodedWireTransaction(signed);
|
|
1105
|
+
const response = await runtime.rpc.sendTransaction(wire, {
|
|
1106
|
+
encoding: "base64",
|
|
1107
|
+
maxRetries,
|
|
1108
|
+
preflightCommitment: commitment,
|
|
1109
|
+
skipPreflight: options.skipPreflight
|
|
1110
|
+
}).send({ abortSignal: config.abortSignal ?? options.abortSignal });
|
|
1111
|
+
latestSignature = signature(response);
|
|
1112
|
+
return { transaction: signed };
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
await executor(prepared.plan ?? singleTransactionPlan(prepared.message), { abortSignal: options.abortSignal });
|
|
1116
|
+
if (!latestSignature) {
|
|
1117
|
+
throw new Error("Failed to resolve transaction signature.");
|
|
1118
|
+
}
|
|
1119
|
+
return latestSignature;
|
|
1120
|
+
}
|
|
1121
|
+
__name(sendPreparedTransfer, "sendPreparedTransfer");
|
|
1122
|
+
async function sendTransfer(config, options) {
|
|
1123
|
+
const prepared = await prepareTransfer(config);
|
|
1124
|
+
return await sendPreparedTransfer(prepared, options);
|
|
1125
|
+
}
|
|
1126
|
+
__name(sendTransfer, "sendTransfer");
|
|
1127
|
+
return {
|
|
1128
|
+
prepareTransfer,
|
|
1129
|
+
sendPreparedTransfer,
|
|
1130
|
+
sendTransfer
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
__name(createSolTransferHelper, "createSolTransferHelper");
|
|
1134
|
+
function ensureAddress2(value, fallback) {
|
|
1135
|
+
if (value) {
|
|
1136
|
+
return typeof value === "string" ? address(value) : value;
|
|
1137
|
+
}
|
|
1138
|
+
if (!fallback) {
|
|
1139
|
+
throw new Error("An address value was expected but not provided.");
|
|
1140
|
+
}
|
|
1141
|
+
return fallback;
|
|
1142
|
+
}
|
|
1143
|
+
__name(ensureAddress2, "ensureAddress");
|
|
1144
|
+
async function resolveLifetime2(runtime, commitment, fallback) {
|
|
1145
|
+
if (fallback) {
|
|
1146
|
+
return fallback;
|
|
1147
|
+
}
|
|
1148
|
+
const { value } = await runtime.rpc.getLatestBlockhash({ commitment }).send();
|
|
1149
|
+
return value;
|
|
1150
|
+
}
|
|
1151
|
+
__name(resolveLifetime2, "resolveLifetime");
|
|
1152
|
+
function resolveSigner2(authority, commitment) {
|
|
1153
|
+
if (isWalletSession(authority)) {
|
|
1154
|
+
const { signer, mode } = createWalletTransactionSigner(authority, { commitment });
|
|
1155
|
+
return { mode, signer };
|
|
1156
|
+
}
|
|
1157
|
+
return { mode: resolveSignerMode(authority), signer: authority };
|
|
1158
|
+
}
|
|
1159
|
+
__name(resolveSigner2, "resolveSigner");
|
|
1160
|
+
function createSplTokenHelper(runtime, config) {
|
|
1161
|
+
const mintAddress = ensureAddress2(config.mint);
|
|
1162
|
+
const tokenProgram = ensureAddress2(config.tokenProgram, address(TOKEN_PROGRAM_ADDRESS));
|
|
1163
|
+
let cachedDecimals = config.decimals;
|
|
1164
|
+
let cachedMath;
|
|
1165
|
+
async function resolveDecimals(commitment) {
|
|
1166
|
+
if (cachedDecimals !== void 0) {
|
|
1167
|
+
return cachedDecimals;
|
|
1168
|
+
}
|
|
1169
|
+
const account = await fetchMint(runtime.rpc, mintAddress, { commitment });
|
|
1170
|
+
cachedDecimals = account.data.decimals;
|
|
1171
|
+
return cachedDecimals;
|
|
1172
|
+
}
|
|
1173
|
+
__name(resolveDecimals, "resolveDecimals");
|
|
1174
|
+
async function getTokenMath(commitment) {
|
|
1175
|
+
if (cachedMath) {
|
|
1176
|
+
return cachedMath;
|
|
1177
|
+
}
|
|
1178
|
+
const decimals = await resolveDecimals(commitment);
|
|
1179
|
+
cachedMath = createTokenAmount(decimals);
|
|
1180
|
+
return cachedMath;
|
|
1181
|
+
}
|
|
1182
|
+
__name(getTokenMath, "getTokenMath");
|
|
1183
|
+
async function deriveAssociatedTokenAddress(owner) {
|
|
1184
|
+
const [ata] = await findAssociatedTokenPda({
|
|
1185
|
+
mint: mintAddress,
|
|
1186
|
+
owner: ensureAddress2(owner),
|
|
1187
|
+
tokenProgram
|
|
1188
|
+
});
|
|
1189
|
+
return ata;
|
|
1190
|
+
}
|
|
1191
|
+
__name(deriveAssociatedTokenAddress, "deriveAssociatedTokenAddress");
|
|
1192
|
+
async function fetchBalance(owner, commitment) {
|
|
1193
|
+
const ataAddress = await deriveAssociatedTokenAddress(owner);
|
|
1194
|
+
const decimals = await resolveDecimals(commitment);
|
|
1195
|
+
try {
|
|
1196
|
+
const { value } = await runtime.rpc.getTokenAccountBalance(ataAddress, { commitment }).send();
|
|
1197
|
+
const math = await getTokenMath(commitment);
|
|
1198
|
+
const amount = math.fromBaseUnits(value.amount, "balance");
|
|
1199
|
+
const uiAmount = value.uiAmountString ?? value.amount;
|
|
1200
|
+
return {
|
|
1201
|
+
amount,
|
|
1202
|
+
ataAddress,
|
|
1203
|
+
decimals,
|
|
1204
|
+
exists: true,
|
|
1205
|
+
uiAmount
|
|
1206
|
+
};
|
|
1207
|
+
} catch {
|
|
1208
|
+
return {
|
|
1209
|
+
amount: 0n,
|
|
1210
|
+
ataAddress,
|
|
1211
|
+
decimals,
|
|
1212
|
+
exists: false,
|
|
1213
|
+
uiAmount: "0"
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
__name(fetchBalance, "fetchBalance");
|
|
1218
|
+
async function prepareTransfer(config2) {
|
|
1219
|
+
const commitment = config2.commitment;
|
|
1220
|
+
const lifetime = await resolveLifetime2(runtime, commitment, config2.lifetime);
|
|
1221
|
+
const { signer, mode } = resolveSigner2(config2.authority, commitment);
|
|
1222
|
+
const sourceOwner = ensureAddress2(config2.sourceOwner, signer.address);
|
|
1223
|
+
const destinationOwner = ensureAddress2(config2.destinationOwner);
|
|
1224
|
+
const sourceAta = ensureAddress2(config2.sourceToken, await deriveAssociatedTokenAddress(sourceOwner));
|
|
1225
|
+
const destinationAta = ensureAddress2(
|
|
1226
|
+
config2.destinationToken,
|
|
1227
|
+
await deriveAssociatedTokenAddress(destinationOwner)
|
|
1228
|
+
);
|
|
1229
|
+
const math = await getTokenMath(commitment);
|
|
1230
|
+
const decimals = await resolveDecimals(commitment);
|
|
1231
|
+
const amount = config2.amountInBaseUnits ? math.fromBaseUnits(config2.amount, "amount") : math.fromDecimal(config2.amount, { label: "amount" });
|
|
1232
|
+
const instructionList = [];
|
|
1233
|
+
if (config2.ensureDestinationAta ?? true) {
|
|
1234
|
+
const { value } = await runtime.rpc.getAccountInfo(destinationAta, {
|
|
1235
|
+
commitment,
|
|
1236
|
+
dataSlice: { length: 0, offset: 0 },
|
|
1237
|
+
encoding: "base64"
|
|
1238
|
+
}).send();
|
|
1239
|
+
if (!value) {
|
|
1240
|
+
instructionList.push(
|
|
1241
|
+
getCreateAssociatedTokenInstruction({
|
|
1242
|
+
ata: destinationAta,
|
|
1243
|
+
mint: mintAddress,
|
|
1244
|
+
owner: destinationOwner,
|
|
1245
|
+
payer: signer,
|
|
1246
|
+
tokenProgram
|
|
1247
|
+
})
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
instructionList.push(
|
|
1252
|
+
getTransferCheckedInstruction({
|
|
1253
|
+
amount,
|
|
1254
|
+
authority: signer,
|
|
1255
|
+
decimals,
|
|
1256
|
+
destination: destinationAta,
|
|
1257
|
+
mint: mintAddress,
|
|
1258
|
+
source: sourceAta
|
|
1259
|
+
})
|
|
1260
|
+
);
|
|
1261
|
+
let message = pipe(
|
|
1262
|
+
createTransactionMessage({ version: config2.transactionVersion ?? 0 }),
|
|
1263
|
+
(m) => setTransactionMessageFeePayer(signer.address, m),
|
|
1264
|
+
(m) => setTransactionMessageLifetimeUsingBlockhash(lifetime, m)
|
|
1265
|
+
);
|
|
1266
|
+
for (const instruction of instructionList) {
|
|
1267
|
+
message = appendTransactionMessageInstruction(instruction, message);
|
|
1268
|
+
}
|
|
1269
|
+
return {
|
|
1270
|
+
amount,
|
|
1271
|
+
commitment,
|
|
1272
|
+
decimals,
|
|
1273
|
+
destinationAta,
|
|
1274
|
+
lifetime,
|
|
1275
|
+
message,
|
|
1276
|
+
mode,
|
|
1277
|
+
signer,
|
|
1278
|
+
sourceAta,
|
|
1279
|
+
plan: singleTransactionPlan(message)
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
__name(prepareTransfer, "prepareTransfer");
|
|
1283
|
+
async function sendPreparedTransfer(prepared, options = {}) {
|
|
1284
|
+
if (prepared.mode === "send" && isTransactionSendingSigner(prepared.signer)) {
|
|
1285
|
+
const signatureBytes2 = await signAndSendTransactionMessageWithSigners(prepared.message, {
|
|
1286
|
+
abortSignal: options.abortSignal,
|
|
1287
|
+
minContextSlot: options.minContextSlot
|
|
1288
|
+
});
|
|
1289
|
+
const base58Decoder2 = getBase58Decoder();
|
|
1290
|
+
return signature(base58Decoder2.decode(signatureBytes2));
|
|
1291
|
+
}
|
|
1292
|
+
const commitment = options.commitment ?? prepared.commitment;
|
|
1293
|
+
const maxRetries = options.maxRetries === void 0 ? void 0 : typeof options.maxRetries === "bigint" ? options.maxRetries : BigInt(options.maxRetries);
|
|
1294
|
+
let latestSignature = null;
|
|
1295
|
+
const executor = createTransactionPlanExecutor({
|
|
1296
|
+
async executeTransactionMessage(message, config2 = {}) {
|
|
1297
|
+
const signed = await signTransactionMessageWithSigners(message, {
|
|
1298
|
+
abortSignal: config2.abortSignal ?? options.abortSignal,
|
|
1299
|
+
minContextSlot: options.minContextSlot
|
|
1300
|
+
});
|
|
1301
|
+
const wire = getBase64EncodedWireTransaction(signed);
|
|
1302
|
+
const response = await runtime.rpc.sendTransaction(wire, {
|
|
1303
|
+
encoding: "base64",
|
|
1304
|
+
maxRetries,
|
|
1305
|
+
preflightCommitment: commitment,
|
|
1306
|
+
skipPreflight: options.skipPreflight
|
|
1307
|
+
}).send({ abortSignal: config2.abortSignal ?? options.abortSignal });
|
|
1308
|
+
latestSignature = signature(response);
|
|
1309
|
+
return { transaction: signed };
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
await executor(prepared.plan ?? singleTransactionPlan(prepared.message), { abortSignal: options.abortSignal });
|
|
1313
|
+
if (!latestSignature) {
|
|
1314
|
+
throw new Error("Failed to resolve transaction signature.");
|
|
1315
|
+
}
|
|
1316
|
+
return latestSignature;
|
|
1317
|
+
}
|
|
1318
|
+
__name(sendPreparedTransfer, "sendPreparedTransfer");
|
|
1319
|
+
async function sendTransfer(config2, options) {
|
|
1320
|
+
const prepared = await prepareTransfer(config2);
|
|
1321
|
+
try {
|
|
1322
|
+
return await sendPreparedTransfer(prepared, options);
|
|
1323
|
+
} catch (error) {
|
|
1324
|
+
if (isSolanaError(error, SOLANA_ERROR__TRANSACTION_ERROR__ALREADY_PROCESSED)) {
|
|
1325
|
+
const retriedPrepared = await prepareTransfer({ ...config2, lifetime: void 0 });
|
|
1326
|
+
return await sendPreparedTransfer(retriedPrepared, options);
|
|
1327
|
+
}
|
|
1328
|
+
throw error;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
__name(sendTransfer, "sendTransfer");
|
|
1332
|
+
return {
|
|
1333
|
+
deriveAssociatedTokenAddress,
|
|
1334
|
+
fetchBalance,
|
|
1335
|
+
prepareTransfer,
|
|
1336
|
+
sendPreparedTransfer,
|
|
1337
|
+
sendTransfer
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
__name(createSplTokenHelper, "createSplTokenHelper");
|
|
1341
|
+
function transactionToBase64(tx) {
|
|
1342
|
+
if ("messageBytes" in tx) {
|
|
1343
|
+
return getBase64EncodedWireTransaction(tx);
|
|
1344
|
+
}
|
|
1345
|
+
return getBase64EncodedWireTransaction(compileTransaction(tx));
|
|
1346
|
+
}
|
|
1347
|
+
__name(transactionToBase64, "transactionToBase64");
|
|
1348
|
+
async function transactionToBase64WithSigners(tx) {
|
|
1349
|
+
if ("messageBytes" in tx) {
|
|
1350
|
+
return transactionToBase64(tx);
|
|
1351
|
+
}
|
|
1352
|
+
const signed = await partiallySignTransactionMessageWithSigners(tx);
|
|
1353
|
+
return transactionToBase64(signed);
|
|
1354
|
+
}
|
|
1355
|
+
__name(transactionToBase64WithSigners, "transactionToBase64WithSigners");
|
|
1356
|
+
|
|
1357
|
+
// src/transactions/prepareTransaction.ts
|
|
1358
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT_MULTIPLIER = 1.1;
|
|
1359
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT = 2e5;
|
|
1360
|
+
var MAX_COMPUTE_UNIT_LIMIT = 14e5;
|
|
1361
|
+
function isComputeUnitLimitInstruction(instruction) {
|
|
1362
|
+
return instruction.programAddress === COMPUTE_BUDGET_PROGRAM_ADDRESS && instruction.data?.[0] === 2;
|
|
1363
|
+
}
|
|
1364
|
+
__name(isComputeUnitLimitInstruction, "isComputeUnitLimitInstruction");
|
|
1365
|
+
function didExceedComputeBudget(error) {
|
|
1366
|
+
let current = error;
|
|
1367
|
+
while (isSolanaError(current)) {
|
|
1368
|
+
if (isSolanaError(current, SOLANA_ERROR__INSTRUCTION_ERROR__COMPUTATIONAL_BUDGET_EXCEEDED)) {
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
current = current.cause;
|
|
1372
|
+
}
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
__name(didExceedComputeBudget, "didExceedComputeBudget");
|
|
1376
|
+
async function estimateComputeUnits(rpc, transaction) {
|
|
1377
|
+
let target = transaction;
|
|
1378
|
+
const hasLifetime = transaction.lifetimeConstraint !== void 0;
|
|
1379
|
+
if (!hasLifetime) {
|
|
1380
|
+
const latest = await rpc.getLatestBlockhash().send();
|
|
1381
|
+
target = setTransactionMessageLifetimeUsingBlockhash(
|
|
1382
|
+
latest.value,
|
|
1383
|
+
transaction
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
const base64Transaction = transactionToBase64(target);
|
|
1387
|
+
try {
|
|
1388
|
+
const { value } = await rpc.simulateTransaction(base64Transaction, {
|
|
1389
|
+
encoding: "base64",
|
|
1390
|
+
replaceRecentBlockhash: false,
|
|
1391
|
+
sigVerify: false
|
|
1392
|
+
}).send();
|
|
1393
|
+
return Number(value.unitsConsumed ?? 0) || 0;
|
|
1394
|
+
} catch (error) {
|
|
1395
|
+
if (didExceedComputeBudget(error)) {
|
|
1396
|
+
return MAX_COMPUTE_UNIT_LIMIT;
|
|
1397
|
+
}
|
|
1398
|
+
throw error;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
__name(estimateComputeUnits, "estimateComputeUnits");
|
|
1402
|
+
async function prepareTransaction(config) {
|
|
1403
|
+
const multiplier = config.computeUnitLimitMultiplier ?? DEFAULT_COMPUTE_UNIT_LIMIT_MULTIPLIER;
|
|
1404
|
+
const shouldResetBlockhash = config.blockhashReset !== false;
|
|
1405
|
+
const shouldResetComputeUnits = config.computeUnitLimitReset ?? false;
|
|
1406
|
+
let transaction = config.transaction;
|
|
1407
|
+
const computeLimitIndex = transaction.instructions.findIndex(isComputeUnitLimitInstruction);
|
|
1408
|
+
if (computeLimitIndex === -1 || shouldResetComputeUnits) {
|
|
1409
|
+
const unitsFromSimulation = await estimateComputeUnits(config.rpc, transaction);
|
|
1410
|
+
const estimatedUnits = unitsFromSimulation ? Math.ceil(unitsFromSimulation * multiplier) : DEFAULT_COMPUTE_UNIT_LIMIT;
|
|
1411
|
+
const units = Math.min(
|
|
1412
|
+
MAX_COMPUTE_UNIT_LIMIT,
|
|
1413
|
+
Math.max(DEFAULT_COMPUTE_UNIT_LIMIT, Math.max(1, estimatedUnits))
|
|
1414
|
+
);
|
|
1415
|
+
const instruction = getSetComputeUnitLimitInstruction({ units });
|
|
1416
|
+
if (computeLimitIndex === -1) {
|
|
1417
|
+
transaction = appendTransactionMessageInstruction(instruction, transaction);
|
|
1418
|
+
} else {
|
|
1419
|
+
const nextInstructions = [...transaction.instructions];
|
|
1420
|
+
nextInstructions.splice(computeLimitIndex, 1, instruction);
|
|
1421
|
+
transaction = Object.freeze({
|
|
1422
|
+
...transaction,
|
|
1423
|
+
instructions: Object.freeze(nextInstructions)
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
let transactionHasLifetime = transaction.lifetimeConstraint !== void 0;
|
|
1428
|
+
if (shouldResetBlockhash || !transactionHasLifetime) {
|
|
1429
|
+
const latest = await config.rpc.getLatestBlockhash().send();
|
|
1430
|
+
if (!transactionHasLifetime) {
|
|
1431
|
+
transaction = setTransactionMessageLifetimeUsingBlockhash(latest.value, transaction);
|
|
1432
|
+
} else if (shouldResetBlockhash) {
|
|
1433
|
+
transaction = Object.freeze({
|
|
1434
|
+
...transaction,
|
|
1435
|
+
lifetimeConstraint: latest.value
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
transactionHasLifetime = true;
|
|
1439
|
+
}
|
|
1440
|
+
if (config.logRequest) {
|
|
1441
|
+
config.logRequest({ base64WireTransaction: transactionToBase64(transaction) });
|
|
1442
|
+
}
|
|
1443
|
+
return transaction;
|
|
1444
|
+
}
|
|
1445
|
+
__name(prepareTransaction, "prepareTransaction");
|
|
1446
|
+
|
|
1447
|
+
// src/features/transactions.ts
|
|
1448
|
+
function toAddress(value) {
|
|
1449
|
+
return typeof value === "string" ? address(value) : value;
|
|
1450
|
+
}
|
|
1451
|
+
__name(toAddress, "toAddress");
|
|
1452
|
+
function hasSetComputeUnitLimitInstruction(instructions) {
|
|
1453
|
+
return instructions.some(
|
|
1454
|
+
(instruction) => isInstructionForProgram(instruction, COMPUTE_BUDGET_PROGRAM_ADDRESS) && isInstructionWithData(instruction) && instruction.data[0] === ComputeBudgetInstruction.SetComputeUnitLimit
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
__name(hasSetComputeUnitLimitInstruction, "hasSetComputeUnitLimitInstruction");
|
|
1458
|
+
function hasSetComputeUnitPriceInstruction(instructions) {
|
|
1459
|
+
return instructions.some(
|
|
1460
|
+
(instruction) => isInstructionForProgram(instruction, COMPUTE_BUDGET_PROGRAM_ADDRESS) && isInstructionWithData(instruction) && instruction.data[0] === ComputeBudgetInstruction.SetComputeUnitPrice
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
__name(hasSetComputeUnitPriceInstruction, "hasSetComputeUnitPriceInstruction");
|
|
1464
|
+
function instructionUsesAddressLookup(instruction) {
|
|
1465
|
+
if ("addressTableLookup" in instruction && instruction.addressTableLookup != null) {
|
|
1466
|
+
return true;
|
|
1467
|
+
}
|
|
1468
|
+
if ("addressTableLookups" in instruction && Array.isArray(instruction.addressTableLookups) && instruction.addressTableLookups.length > 0) {
|
|
1469
|
+
return true;
|
|
1470
|
+
}
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
__name(instructionUsesAddressLookup, "instructionUsesAddressLookup");
|
|
1474
|
+
function resolveVersion(requested, instructions) {
|
|
1475
|
+
if (requested && requested !== "auto") {
|
|
1476
|
+
return requested;
|
|
1477
|
+
}
|
|
1478
|
+
return instructions.some(instructionUsesAddressLookup) ? 0 : "legacy";
|
|
1479
|
+
}
|
|
1480
|
+
__name(resolveVersion, "resolveVersion");
|
|
1481
|
+
function normaliseCommitment(request, getFallbackCommitment) {
|
|
1482
|
+
return request.commitment ?? getFallbackCommitment();
|
|
1483
|
+
}
|
|
1484
|
+
__name(normaliseCommitment, "normaliseCommitment");
|
|
1485
|
+
function resolveFeePayerAddress(feePayer, authoritySigner) {
|
|
1486
|
+
if (!feePayer && !authoritySigner) {
|
|
1487
|
+
throw new Error("A fee payer must be provided via `feePayer` or `authority`.");
|
|
1488
|
+
}
|
|
1489
|
+
if (feePayer && typeof feePayer === "object" && "address" in feePayer) {
|
|
1490
|
+
return { address: feePayer.address, signer: feePayer };
|
|
1491
|
+
}
|
|
1492
|
+
if (feePayer) {
|
|
1493
|
+
const address4 = toAddress(feePayer);
|
|
1494
|
+
if (authoritySigner && authoritySigner.address === address4) {
|
|
1495
|
+
return { address: address4, signer: authoritySigner };
|
|
1496
|
+
}
|
|
1497
|
+
return { address: address4 };
|
|
1498
|
+
}
|
|
1499
|
+
if (!authoritySigner) {
|
|
1500
|
+
throw new Error("Unable to resolve authority signer for the fee payer.");
|
|
1501
|
+
}
|
|
1502
|
+
const authorityAddress = authoritySigner.address;
|
|
1503
|
+
return { address: authorityAddress, signer: authoritySigner };
|
|
1504
|
+
}
|
|
1505
|
+
__name(resolveFeePayerAddress, "resolveFeePayerAddress");
|
|
1506
|
+
function resolveComputeUnitLimit(request, instructions) {
|
|
1507
|
+
const value = request.computeUnitLimit;
|
|
1508
|
+
if (value === void 0 || hasSetComputeUnitLimitInstruction(instructions)) {
|
|
1509
|
+
return void 0;
|
|
1510
|
+
}
|
|
1511
|
+
return typeof value === "bigint" ? value : BigInt(Math.floor(value));
|
|
1512
|
+
}
|
|
1513
|
+
__name(resolveComputeUnitLimit, "resolveComputeUnitLimit");
|
|
1514
|
+
function resolveComputeUnitPrice(request, instructions) {
|
|
1515
|
+
if (request.computeUnitPrice === void 0 || hasSetComputeUnitPriceInstruction(instructions)) {
|
|
1516
|
+
return void 0;
|
|
1517
|
+
}
|
|
1518
|
+
if (typeof request.computeUnitPrice === "bigint") {
|
|
1519
|
+
return request.computeUnitPrice;
|
|
1520
|
+
}
|
|
1521
|
+
return BigInt(Math.floor(request.computeUnitPrice));
|
|
1522
|
+
}
|
|
1523
|
+
__name(resolveComputeUnitPrice, "resolveComputeUnitPrice");
|
|
1524
|
+
async function createTransactionRecipe(request, context) {
|
|
1525
|
+
if (!request.instructions.length) {
|
|
1526
|
+
throw new Error("Add at least one instruction before preparing a transaction.");
|
|
1527
|
+
}
|
|
1528
|
+
const { getFallbackCommitment, runtime } = context;
|
|
1529
|
+
request.abortSignal?.throwIfAborted();
|
|
1530
|
+
const commitment = normaliseCommitment(request, getFallbackCommitment);
|
|
1531
|
+
let authoritySigner;
|
|
1532
|
+
let mode = "partial";
|
|
1533
|
+
if (request.authority) {
|
|
1534
|
+
if (isWalletSession(request.authority)) {
|
|
1535
|
+
const { signer, mode: walletMode } = createWalletTransactionSigner(request.authority, { commitment });
|
|
1536
|
+
authoritySigner = signer;
|
|
1537
|
+
mode = walletMode;
|
|
1538
|
+
} else {
|
|
1539
|
+
authoritySigner = request.authority;
|
|
1540
|
+
mode = resolveSignerMode(authoritySigner);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
const { address: feePayer, signer: feePayerSigner } = resolveFeePayerAddress(request.feePayer, authoritySigner);
|
|
1544
|
+
if (mode === "send") {
|
|
1545
|
+
if (!feePayerSigner || !isTransactionSendingSigner(feePayerSigner)) {
|
|
1546
|
+
mode = "partial";
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
const baseInstructions = [...request.instructions];
|
|
1550
|
+
const version = resolveVersion(request.version, baseInstructions);
|
|
1551
|
+
const lifetime = request.lifetime ?? (await runtime.rpc.getLatestBlockhash({ commitment }).send({ abortSignal: request.abortSignal })).value;
|
|
1552
|
+
request.abortSignal?.throwIfAborted();
|
|
1553
|
+
const resolvedComputeUnitLimit = resolveComputeUnitLimit(request, baseInstructions);
|
|
1554
|
+
const computeUnitPrice = resolveComputeUnitPrice(request, baseInstructions);
|
|
1555
|
+
const prefixInstructions = [];
|
|
1556
|
+
if (resolvedComputeUnitLimit !== void 0) {
|
|
1557
|
+
prefixInstructions.push(getSetComputeUnitLimitInstruction({ units: Number(resolvedComputeUnitLimit) }));
|
|
1558
|
+
}
|
|
1559
|
+
if (computeUnitPrice !== void 0) {
|
|
1560
|
+
prefixInstructions.push(getSetComputeUnitPriceInstruction({ microLamports: Number(computeUnitPrice) }));
|
|
1561
|
+
}
|
|
1562
|
+
const instructionSequence = [...prefixInstructions, ...baseInstructions];
|
|
1563
|
+
const createMessage = /* @__PURE__ */ __name(async () => pipe(
|
|
1564
|
+
createTransactionMessage({ version }),
|
|
1565
|
+
(message) => feePayerSigner ? setTransactionMessageFeePayerSigner(feePayerSigner, message) : setTransactionMessageFeePayer(feePayer, message),
|
|
1566
|
+
(message) => setTransactionMessageLifetimeUsingBlockhash(lifetime, message)
|
|
1567
|
+
), "createMessage");
|
|
1568
|
+
return Object.freeze({
|
|
1569
|
+
commitment,
|
|
1570
|
+
computeUnitLimit: resolvedComputeUnitLimit,
|
|
1571
|
+
computeUnitPrice,
|
|
1572
|
+
createTransactionMessage: createMessage,
|
|
1573
|
+
feePayer,
|
|
1574
|
+
instructionPlan: getMessagePackerInstructionPlanFromInstructions(instructionSequence),
|
|
1575
|
+
instructions: Object.freeze(baseInstructions),
|
|
1576
|
+
lifetime,
|
|
1577
|
+
mode,
|
|
1578
|
+
version
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
__name(createTransactionRecipe, "createTransactionRecipe");
|
|
1582
|
+
function assertSingleTransactionPlan(plan) {
|
|
1583
|
+
if (plan.kind !== "single") {
|
|
1584
|
+
throw new Error("Transaction recipe produced a multi-transaction plan which is not supported.");
|
|
1585
|
+
}
|
|
1586
|
+
return plan;
|
|
1587
|
+
}
|
|
1588
|
+
__name(assertSingleTransactionPlan, "assertSingleTransactionPlan");
|
|
1589
|
+
function createTransactionHelper(runtime, getFallbackCommitment) {
|
|
1590
|
+
async function prepare(request) {
|
|
1591
|
+
const recipe = await createTransactionRecipe(request, { getFallbackCommitment, runtime });
|
|
1592
|
+
const planner = createTransactionPlanner({
|
|
1593
|
+
createTransactionMessage: recipe.createTransactionMessage
|
|
1594
|
+
});
|
|
1595
|
+
const plan = await planner(recipe.instructionPlan, { abortSignal: request.abortSignal });
|
|
1596
|
+
const singlePlan = assertSingleTransactionPlan(plan);
|
|
1597
|
+
const prepared = Object.freeze({
|
|
1598
|
+
commitment: recipe.commitment,
|
|
1599
|
+
computeUnitLimit: recipe.computeUnitLimit,
|
|
1600
|
+
computeUnitPrice: recipe.computeUnitPrice,
|
|
1601
|
+
feePayer: recipe.feePayer,
|
|
1602
|
+
instructions: recipe.instructions,
|
|
1603
|
+
lifetime: recipe.lifetime,
|
|
1604
|
+
message: singlePlan.message,
|
|
1605
|
+
mode: recipe.mode,
|
|
1606
|
+
plan,
|
|
1607
|
+
version: recipe.version
|
|
1608
|
+
});
|
|
1609
|
+
return prepared;
|
|
1610
|
+
}
|
|
1611
|
+
__name(prepare, "prepare");
|
|
1612
|
+
async function sign(prepared, options = {}) {
|
|
1613
|
+
return await signTransactionMessageWithSigners(prepared.message, {
|
|
1614
|
+
abortSignal: options.abortSignal,
|
|
1615
|
+
minContextSlot: options.minContextSlot
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
__name(sign, "sign");
|
|
1619
|
+
async function toWire(prepared, options = {}) {
|
|
1620
|
+
const signed = await sign(prepared, options);
|
|
1621
|
+
return getBase64EncodedWireTransaction(signed);
|
|
1622
|
+
}
|
|
1623
|
+
__name(toWire, "toWire");
|
|
1624
|
+
async function send(prepared, options = {}) {
|
|
1625
|
+
if (!prepared.plan || prepared.mode === "send") {
|
|
1626
|
+
return sendDirect(prepared, options);
|
|
1627
|
+
}
|
|
1628
|
+
return sendWithExecutor(prepared, options);
|
|
1629
|
+
}
|
|
1630
|
+
__name(send, "send");
|
|
1631
|
+
async function sendDirect(prepared, options) {
|
|
1632
|
+
const commitment = options.commitment ?? prepared.commitment;
|
|
1633
|
+
if (prepared.mode === "send") {
|
|
1634
|
+
const signatureBytes2 = await signAndSendTransactionMessageWithSigners(prepared.message, {
|
|
1635
|
+
abortSignal: options.abortSignal,
|
|
1636
|
+
minContextSlot: options.minContextSlot
|
|
1637
|
+
});
|
|
1638
|
+
const base58Decoder2 = getBase58Decoder();
|
|
1639
|
+
return signature(base58Decoder2.decode(signatureBytes2));
|
|
1640
|
+
}
|
|
1641
|
+
const signed = await sign(prepared, {
|
|
1642
|
+
abortSignal: options.abortSignal,
|
|
1643
|
+
minContextSlot: options.minContextSlot
|
|
1644
|
+
});
|
|
1645
|
+
const wire = getBase64EncodedWireTransaction(signed);
|
|
1646
|
+
const maxRetries = options.maxRetries === void 0 ? void 0 : typeof options.maxRetries === "bigint" ? options.maxRetries : BigInt(options.maxRetries);
|
|
1647
|
+
const response = await runtime.rpc.sendTransaction(wire, {
|
|
1648
|
+
encoding: "base64",
|
|
1649
|
+
maxRetries,
|
|
1650
|
+
preflightCommitment: commitment,
|
|
1651
|
+
skipPreflight: options.skipPreflight
|
|
1652
|
+
}).send({ abortSignal: options.abortSignal });
|
|
1653
|
+
return signature(response);
|
|
1654
|
+
}
|
|
1655
|
+
__name(sendDirect, "sendDirect");
|
|
1656
|
+
async function sendWithExecutor(prepared, options) {
|
|
1657
|
+
if (!prepared.plan) {
|
|
1658
|
+
return sendDirect(prepared, options);
|
|
1659
|
+
}
|
|
1660
|
+
const commitment = options.commitment ?? prepared.commitment;
|
|
1661
|
+
const maxRetries = options.maxRetries === void 0 ? void 0 : typeof options.maxRetries === "bigint" ? options.maxRetries : BigInt(options.maxRetries);
|
|
1662
|
+
let latestSignature = null;
|
|
1663
|
+
const executor = createTransactionPlanExecutor({
|
|
1664
|
+
async executeTransactionMessage(message, config = {}) {
|
|
1665
|
+
const signed = await signTransactionMessageWithSigners(message, {
|
|
1666
|
+
abortSignal: config.abortSignal ?? options.abortSignal,
|
|
1667
|
+
minContextSlot: options.minContextSlot
|
|
1668
|
+
});
|
|
1669
|
+
const wire = getBase64EncodedWireTransaction(signed);
|
|
1670
|
+
const response = await runtime.rpc.sendTransaction(wire, {
|
|
1671
|
+
encoding: "base64",
|
|
1672
|
+
maxRetries,
|
|
1673
|
+
preflightCommitment: commitment,
|
|
1674
|
+
skipPreflight: options.skipPreflight
|
|
1675
|
+
}).send({ abortSignal: config.abortSignal ?? options.abortSignal });
|
|
1676
|
+
latestSignature = signature(response);
|
|
1677
|
+
return { transaction: signed };
|
|
1678
|
+
}
|
|
1679
|
+
});
|
|
1680
|
+
await executor(prepared.plan, { abortSignal: options.abortSignal });
|
|
1681
|
+
if (!latestSignature) {
|
|
1682
|
+
throw new Error("Failed to resolve transaction signature.");
|
|
1683
|
+
}
|
|
1684
|
+
return latestSignature;
|
|
1685
|
+
}
|
|
1686
|
+
__name(sendWithExecutor, "sendWithExecutor");
|
|
1687
|
+
async function prepareAndSend(request, options = {}) {
|
|
1688
|
+
const { prepareTransaction: overrides, ...rest } = request;
|
|
1689
|
+
const prepared = await prepare(rest);
|
|
1690
|
+
if (overrides === false) {
|
|
1691
|
+
return send(prepared, options);
|
|
1692
|
+
}
|
|
1693
|
+
const prepareConfig = overrides ?? {};
|
|
1694
|
+
const tunedMessage = await prepareTransaction({
|
|
1695
|
+
blockhashReset: prepareConfig.blockhashReset ?? false,
|
|
1696
|
+
...prepareConfig,
|
|
1697
|
+
rpc: runtime.rpc,
|
|
1698
|
+
transaction: prepared.message
|
|
1699
|
+
});
|
|
1700
|
+
const tunedPrepared = Object.freeze({
|
|
1701
|
+
...prepared,
|
|
1702
|
+
message: tunedMessage,
|
|
1703
|
+
plan: singleTransactionPlan(tunedMessage)
|
|
1704
|
+
});
|
|
1705
|
+
return send(tunedPrepared, options);
|
|
1706
|
+
}
|
|
1707
|
+
__name(prepareAndSend, "prepareAndSend");
|
|
1708
|
+
return Object.freeze({
|
|
1709
|
+
prepare,
|
|
1710
|
+
sign,
|
|
1711
|
+
toWire,
|
|
1712
|
+
send,
|
|
1713
|
+
prepareAndSend
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
__name(createTransactionHelper, "createTransactionHelper");
|
|
1717
|
+
|
|
1718
|
+
// src/client/createClientHelpers.ts
|
|
1719
|
+
function withDefaultCommitment(config, getFallback, baseCommitment) {
|
|
1720
|
+
if (config.commitment !== void 0) {
|
|
1721
|
+
return config;
|
|
1722
|
+
}
|
|
1723
|
+
const commitment = baseCommitment ?? getFallback();
|
|
1724
|
+
return {
|
|
1725
|
+
...config,
|
|
1726
|
+
commitment
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
__name(withDefaultCommitment, "withDefaultCommitment");
|
|
1730
|
+
function wrapSolTransferHelper(helper, getFallback) {
|
|
1731
|
+
return {
|
|
1732
|
+
prepareTransfer: /* @__PURE__ */ __name((config) => helper.prepareTransfer(withDefaultCommitment(config, getFallback)), "prepareTransfer"),
|
|
1733
|
+
sendPreparedTransfer: helper.sendPreparedTransfer,
|
|
1734
|
+
sendTransfer: /* @__PURE__ */ __name((config, options) => helper.sendTransfer(withDefaultCommitment(config, getFallback), options), "sendTransfer")
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1737
|
+
__name(wrapSolTransferHelper, "wrapSolTransferHelper");
|
|
1738
|
+
function wrapSplTokenHelper(helper, getFallback, baseCommitment) {
|
|
1739
|
+
const resolveCommitment = /* @__PURE__ */ __name((commitment) => commitment ?? baseCommitment ?? getFallback(), "resolveCommitment");
|
|
1740
|
+
return {
|
|
1741
|
+
deriveAssociatedTokenAddress: helper.deriveAssociatedTokenAddress,
|
|
1742
|
+
fetchBalance: /* @__PURE__ */ __name((owner, commitment) => helper.fetchBalance(owner, resolveCommitment(commitment)), "fetchBalance"),
|
|
1743
|
+
prepareTransfer: /* @__PURE__ */ __name((config) => helper.prepareTransfer(withDefaultCommitment(config, getFallback, baseCommitment)), "prepareTransfer"),
|
|
1744
|
+
sendPreparedTransfer: helper.sendPreparedTransfer,
|
|
1745
|
+
sendTransfer: /* @__PURE__ */ __name((config, options) => helper.sendTransfer(withDefaultCommitment(config, getFallback, baseCommitment), options), "sendTransfer")
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
__name(wrapSplTokenHelper, "wrapSplTokenHelper");
|
|
1749
|
+
function normaliseConfigValue(value) {
|
|
1750
|
+
if (value === null || value === void 0) {
|
|
1751
|
+
return void 0;
|
|
1752
|
+
}
|
|
1753
|
+
if (typeof value === "string") {
|
|
1754
|
+
return value;
|
|
1755
|
+
}
|
|
1756
|
+
if (typeof value === "object" && "toString" in value) {
|
|
1757
|
+
return String(value.toString());
|
|
1758
|
+
}
|
|
1759
|
+
return JSON.stringify(value);
|
|
1760
|
+
}
|
|
1761
|
+
__name(normaliseConfigValue, "normaliseConfigValue");
|
|
1762
|
+
function serialiseSplConfig(config) {
|
|
1763
|
+
return JSON.stringify({
|
|
1764
|
+
associatedTokenProgram: normaliseConfigValue(config.associatedTokenProgram),
|
|
1765
|
+
commitment: normaliseConfigValue(config.commitment),
|
|
1766
|
+
decimals: config.decimals,
|
|
1767
|
+
mint: normaliseConfigValue(config.mint),
|
|
1768
|
+
tokenProgram: normaliseConfigValue(config.tokenProgram)
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
__name(serialiseSplConfig, "serialiseSplConfig");
|
|
1772
|
+
function createClientHelpers(runtime, store) {
|
|
1773
|
+
const getFallbackCommitment = /* @__PURE__ */ __name(() => store.getState().cluster.commitment, "getFallbackCommitment");
|
|
1774
|
+
const splTokenCache = /* @__PURE__ */ new Map();
|
|
1775
|
+
let solTransfer;
|
|
1776
|
+
let transaction;
|
|
1777
|
+
const getSolTransfer = /* @__PURE__ */ __name(() => {
|
|
1778
|
+
if (!solTransfer) {
|
|
1779
|
+
solTransfer = wrapSolTransferHelper(createSolTransferHelper(runtime), getFallbackCommitment);
|
|
1780
|
+
}
|
|
1781
|
+
return solTransfer;
|
|
1782
|
+
}, "getSolTransfer");
|
|
1783
|
+
const getTransaction = /* @__PURE__ */ __name(() => {
|
|
1784
|
+
if (!transaction) {
|
|
1785
|
+
transaction = createTransactionHelper(runtime, getFallbackCommitment);
|
|
1786
|
+
}
|
|
1787
|
+
return transaction;
|
|
1788
|
+
}, "getTransaction");
|
|
1789
|
+
function getSplTokenHelper(config) {
|
|
1790
|
+
const cacheKey = serialiseSplConfig(config);
|
|
1791
|
+
const cached = splTokenCache.get(cacheKey);
|
|
1792
|
+
if (cached) {
|
|
1793
|
+
return cached.scoped;
|
|
1794
|
+
}
|
|
1795
|
+
const helper = createSplTokenHelper(runtime, config);
|
|
1796
|
+
const scoped = wrapSplTokenHelper(helper, getFallbackCommitment, config.commitment);
|
|
1797
|
+
splTokenCache.set(cacheKey, {
|
|
1798
|
+
baseCommitment: config.commitment,
|
|
1799
|
+
scoped
|
|
1800
|
+
});
|
|
1801
|
+
return scoped;
|
|
1802
|
+
}
|
|
1803
|
+
__name(getSplTokenHelper, "getSplTokenHelper");
|
|
1804
|
+
const prepareTransactionWithRuntime = /* @__PURE__ */ __name((options) => prepareTransaction({
|
|
1805
|
+
...options,
|
|
1806
|
+
rpc: runtime.rpc
|
|
1807
|
+
}), "prepareTransactionWithRuntime");
|
|
1808
|
+
return Object.freeze({
|
|
1809
|
+
get solTransfer() {
|
|
1810
|
+
return getSolTransfer();
|
|
1811
|
+
},
|
|
1812
|
+
splToken: getSplTokenHelper,
|
|
1813
|
+
get transaction() {
|
|
1814
|
+
return getTransaction();
|
|
1815
|
+
},
|
|
1816
|
+
prepareTransaction: prepareTransactionWithRuntime
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
__name(createClientHelpers, "createClientHelpers");
|
|
1820
|
+
function createClusterStatus() {
|
|
1821
|
+
return { status: "idle" };
|
|
1822
|
+
}
|
|
1823
|
+
__name(createClusterStatus, "createClusterStatus");
|
|
1824
|
+
function createInitialClientState(config) {
|
|
1825
|
+
const { commitment, endpoint, websocketEndpoint } = config;
|
|
1826
|
+
const timestamp = Date.now();
|
|
1827
|
+
return deepFreeze({
|
|
1828
|
+
accounts: {},
|
|
1829
|
+
cluster: {
|
|
1830
|
+
commitment,
|
|
1831
|
+
endpoint,
|
|
1832
|
+
status: createClusterStatus(),
|
|
1833
|
+
websocketEndpoint
|
|
1834
|
+
},
|
|
1835
|
+
lastUpdatedAt: timestamp,
|
|
1836
|
+
subscriptions: {
|
|
1837
|
+
account: {},
|
|
1838
|
+
signature: {}
|
|
1839
|
+
},
|
|
1840
|
+
transactions: {},
|
|
1841
|
+
wallet: { status: "disconnected" }
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
__name(createInitialClientState, "createInitialClientState");
|
|
1845
|
+
function createClientStore(initialState) {
|
|
1846
|
+
return createStore(() => initialState);
|
|
1847
|
+
}
|
|
1848
|
+
__name(createClientStore, "createClientStore");
|
|
1849
|
+
function createDefaultClientStore(config) {
|
|
1850
|
+
return createClientStore(createInitialClientState(config));
|
|
1851
|
+
}
|
|
1852
|
+
__name(createDefaultClientStore, "createDefaultClientStore");
|
|
1853
|
+
|
|
1854
|
+
// src/client/watchers.ts
|
|
1855
|
+
function createWatchers({ logger: inputLogger, runtime, store }) {
|
|
1856
|
+
const logger = inputLogger ?? createLogger();
|
|
1857
|
+
function setSubscriptionStatus(kind, id, status) {
|
|
1858
|
+
store.setState((state) => ({
|
|
1859
|
+
...state,
|
|
1860
|
+
lastUpdatedAt: now(),
|
|
1861
|
+
subscriptions: {
|
|
1862
|
+
...state.subscriptions,
|
|
1863
|
+
[kind]: {
|
|
1864
|
+
...state.subscriptions[kind],
|
|
1865
|
+
[id]: status
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}));
|
|
1869
|
+
}
|
|
1870
|
+
__name(setSubscriptionStatus, "setSubscriptionStatus");
|
|
1871
|
+
function onAbort(kind, id) {
|
|
1872
|
+
setSubscriptionStatus(kind, id, { status: "inactive" });
|
|
1873
|
+
}
|
|
1874
|
+
__name(onAbort, "onAbort");
|
|
1875
|
+
function createSubscriptionHandle(kind, id, abortController) {
|
|
1876
|
+
function abort() {
|
|
1877
|
+
abortController.abort();
|
|
1878
|
+
onAbort(kind, id);
|
|
1879
|
+
}
|
|
1880
|
+
__name(abort, "abort");
|
|
1881
|
+
return { abort };
|
|
1882
|
+
}
|
|
1883
|
+
__name(createSubscriptionHandle, "createSubscriptionHandle");
|
|
1884
|
+
async function handleAccountNotifications(config, listener, abortController) {
|
|
1885
|
+
const commitment = config.commitment ?? store.getState().cluster.commitment;
|
|
1886
|
+
const plan = runtime.rpcSubscriptions.accountNotifications(config.address, { commitment });
|
|
1887
|
+
const key = config.address.toString();
|
|
1888
|
+
setSubscriptionStatus("account", key, { status: "activating" });
|
|
1889
|
+
abortController.signal.addEventListener("abort", () => onAbort("account", key));
|
|
1890
|
+
try {
|
|
1891
|
+
const iterator = await plan.subscribe({ abortSignal: abortController.signal });
|
|
1892
|
+
setSubscriptionStatus("account", key, { status: "active" });
|
|
1893
|
+
for await (const notification of iterator) {
|
|
1894
|
+
const lamports2 = notification.value?.lamports ?? null;
|
|
1895
|
+
const slot = notification.context?.slot ?? null;
|
|
1896
|
+
const entry = {
|
|
1897
|
+
address: config.address,
|
|
1898
|
+
data: notification.value?.data,
|
|
1899
|
+
error: void 0,
|
|
1900
|
+
fetching: false,
|
|
1901
|
+
lamports: lamports2,
|
|
1902
|
+
lastFetchedAt: now(),
|
|
1903
|
+
slot
|
|
1904
|
+
};
|
|
1905
|
+
listener(entry);
|
|
1906
|
+
store.setState((state) => ({
|
|
1907
|
+
...state,
|
|
1908
|
+
accounts: {
|
|
1909
|
+
...state.accounts,
|
|
1910
|
+
[key]: entry
|
|
1911
|
+
},
|
|
1912
|
+
lastUpdatedAt: now()
|
|
1913
|
+
}));
|
|
1914
|
+
}
|
|
1915
|
+
} catch (error) {
|
|
1916
|
+
if (!abortController.signal.aborted) {
|
|
1917
|
+
logger({
|
|
1918
|
+
data: { address: key, ...formatError(error) },
|
|
1919
|
+
level: "error",
|
|
1920
|
+
message: "account subscription failed"
|
|
1921
|
+
});
|
|
1922
|
+
setSubscriptionStatus("account", key, { error, status: "error" });
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
__name(handleAccountNotifications, "handleAccountNotifications");
|
|
1927
|
+
function watchAccount(config, listener) {
|
|
1928
|
+
const abortController = new AbortController();
|
|
1929
|
+
handleAccountNotifications(config, listener, abortController).catch((error) => {
|
|
1930
|
+
if (!abortController.signal.aborted) {
|
|
1931
|
+
logger({
|
|
1932
|
+
data: { address: config.address.toString(), ...formatError(error) },
|
|
1933
|
+
level: "error",
|
|
1934
|
+
message: "account watcher error"
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
});
|
|
1938
|
+
return createSubscriptionHandle("account", config.address.toString(), abortController);
|
|
1939
|
+
}
|
|
1940
|
+
__name(watchAccount, "watchAccount");
|
|
1941
|
+
function watchBalance(config, listener) {
|
|
1942
|
+
return watchAccount(config, (account) => {
|
|
1943
|
+
if (account.lamports !== null) {
|
|
1944
|
+
listener(account.lamports);
|
|
1945
|
+
}
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
__name(watchBalance, "watchBalance");
|
|
1949
|
+
async function handleSignatureNotifications(config, listener, abortController) {
|
|
1950
|
+
const commitment = config.commitment ?? store.getState().cluster.commitment;
|
|
1951
|
+
const plan = runtime.rpcSubscriptions.signatureNotifications(config.signature, {
|
|
1952
|
+
commitment,
|
|
1953
|
+
enableReceivedNotification: config.enableReceivedNotification
|
|
1954
|
+
});
|
|
1955
|
+
const key = config.signature.toString();
|
|
1956
|
+
setSubscriptionStatus("signature", key, { status: "activating" });
|
|
1957
|
+
abortController.signal.addEventListener("abort", () => onAbort("signature", key));
|
|
1958
|
+
try {
|
|
1959
|
+
const iterator = await plan.subscribe({ abortSignal: abortController.signal });
|
|
1960
|
+
setSubscriptionStatus("signature", key, { status: "active" });
|
|
1961
|
+
for await (const notification of iterator) {
|
|
1962
|
+
listener(notification);
|
|
1963
|
+
store.setState((state) => ({
|
|
1964
|
+
...state,
|
|
1965
|
+
lastUpdatedAt: now(),
|
|
1966
|
+
transactions: {
|
|
1967
|
+
...state.transactions,
|
|
1968
|
+
[key]: {
|
|
1969
|
+
lastUpdatedAt: now(),
|
|
1970
|
+
signature: config.signature,
|
|
1971
|
+
status: "waiting"
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
}));
|
|
1975
|
+
}
|
|
1976
|
+
} catch (error) {
|
|
1977
|
+
if (!abortController.signal.aborted) {
|
|
1978
|
+
logger({
|
|
1979
|
+
data: { signature: key, ...formatError(error) },
|
|
1980
|
+
level: "error",
|
|
1981
|
+
message: "signature subscription failed"
|
|
1982
|
+
});
|
|
1983
|
+
setSubscriptionStatus("signature", key, { error, status: "error" });
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
__name(handleSignatureNotifications, "handleSignatureNotifications");
|
|
1988
|
+
function watchSignature(config, listener) {
|
|
1989
|
+
const abortController = new AbortController();
|
|
1990
|
+
handleSignatureNotifications(config, listener, abortController).catch((error) => {
|
|
1991
|
+
if (!abortController.signal.aborted) {
|
|
1992
|
+
logger({
|
|
1993
|
+
data: { signature: config.signature.toString(), ...formatError(error) },
|
|
1994
|
+
level: "error",
|
|
1995
|
+
message: "signature watcher error"
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
});
|
|
1999
|
+
return createSubscriptionHandle("signature", config.signature.toString(), abortController);
|
|
2000
|
+
}
|
|
2001
|
+
__name(watchSignature, "watchSignature");
|
|
2002
|
+
return {
|
|
2003
|
+
watchAccount,
|
|
2004
|
+
watchBalance,
|
|
2005
|
+
watchSignature
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
__name(createWatchers, "createWatchers");
|
|
2009
|
+
|
|
2010
|
+
// src/client/createClient.ts
|
|
2011
|
+
function createClient(config) {
|
|
2012
|
+
const commitment = config.commitment ?? "confirmed";
|
|
2013
|
+
const websocketEndpoint = config.websocketEndpoint ?? config.endpoint;
|
|
2014
|
+
const initialState = createInitialClientState({
|
|
2015
|
+
commitment,
|
|
2016
|
+
endpoint: config.endpoint,
|
|
2017
|
+
websocketEndpoint
|
|
2018
|
+
});
|
|
2019
|
+
const store = config.createStore ? config.createStore(initialState) : createClientStore(initialState);
|
|
2020
|
+
const rpcClient = config.rpcClient ?? createSolanaRpcClient({
|
|
2021
|
+
commitment,
|
|
2022
|
+
endpoint: config.endpoint,
|
|
2023
|
+
websocketEndpoint
|
|
2024
|
+
});
|
|
2025
|
+
const runtime = {
|
|
2026
|
+
rpc: rpcClient.rpc,
|
|
2027
|
+
rpcSubscriptions: rpcClient.rpcSubscriptions
|
|
2028
|
+
};
|
|
2029
|
+
const connectors = createWalletRegistry(config.walletConnectors ?? []);
|
|
2030
|
+
const logger = createLogger(config.logger);
|
|
2031
|
+
const actions = createActions({ connectors, logger, runtime, store });
|
|
2032
|
+
const watchers = createWatchers({ logger, runtime, store });
|
|
2033
|
+
const helpers = createClientHelpers(runtime, store);
|
|
2034
|
+
store.setState((state) => ({
|
|
2035
|
+
...state,
|
|
2036
|
+
cluster: {
|
|
2037
|
+
...state.cluster,
|
|
2038
|
+
status: { status: "connecting" }
|
|
2039
|
+
},
|
|
2040
|
+
lastUpdatedAt: now()
|
|
2041
|
+
}));
|
|
2042
|
+
actions.setCluster(config.endpoint, { commitment, websocketEndpoint }).catch(
|
|
2043
|
+
(error) => logger({
|
|
2044
|
+
data: formatError(error),
|
|
2045
|
+
level: "error",
|
|
2046
|
+
message: "initial cluster setup failed"
|
|
2047
|
+
})
|
|
2048
|
+
);
|
|
2049
|
+
function destroy() {
|
|
2050
|
+
store.setState(() => initialState);
|
|
2051
|
+
}
|
|
2052
|
+
__name(destroy, "destroy");
|
|
2053
|
+
return {
|
|
2054
|
+
actions,
|
|
2055
|
+
config,
|
|
2056
|
+
connectors,
|
|
2057
|
+
destroy,
|
|
2058
|
+
get helpers() {
|
|
2059
|
+
return helpers;
|
|
2060
|
+
},
|
|
2061
|
+
runtime,
|
|
2062
|
+
store,
|
|
2063
|
+
get solTransfer() {
|
|
2064
|
+
return helpers.solTransfer;
|
|
2065
|
+
},
|
|
2066
|
+
get SolTransfer() {
|
|
2067
|
+
return helpers.solTransfer;
|
|
2068
|
+
},
|
|
2069
|
+
splToken: helpers.splToken,
|
|
2070
|
+
SplToken: helpers.splToken,
|
|
2071
|
+
SplHelper: helpers.splToken,
|
|
2072
|
+
get transaction() {
|
|
2073
|
+
return helpers.transaction;
|
|
2074
|
+
},
|
|
2075
|
+
prepareTransaction: helpers.prepareTransaction,
|
|
2076
|
+
watchers
|
|
2077
|
+
};
|
|
2078
|
+
}
|
|
2079
|
+
__name(createClient, "createClient");
|
|
2080
|
+
|
|
2081
|
+
// src/state/asyncState.ts
|
|
2082
|
+
function createInitialAsyncState() {
|
|
2083
|
+
return { status: "idle" };
|
|
2084
|
+
}
|
|
2085
|
+
__name(createInitialAsyncState, "createInitialAsyncState");
|
|
2086
|
+
function createAsyncState(status, payload = {}) {
|
|
2087
|
+
return {
|
|
2088
|
+
data: payload.data,
|
|
2089
|
+
error: payload.error,
|
|
2090
|
+
status
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
__name(createAsyncState, "createAsyncState");
|
|
2094
|
+
|
|
2095
|
+
// src/controllers/solTransferController.ts
|
|
2096
|
+
function ensureAuthority(input, resolveDefault) {
|
|
2097
|
+
const authority = input.authority ?? resolveDefault?.();
|
|
2098
|
+
if (!authority) {
|
|
2099
|
+
throw new Error("Connect a wallet or supply an `authority` before sending SOL transfers.");
|
|
2100
|
+
}
|
|
2101
|
+
return {
|
|
2102
|
+
...input,
|
|
2103
|
+
authority
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2106
|
+
__name(ensureAuthority, "ensureAuthority");
|
|
2107
|
+
function createSolTransferController(config) {
|
|
2108
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2109
|
+
const helper = config.helper;
|
|
2110
|
+
const authorityProvider = config.authorityProvider;
|
|
2111
|
+
let state = createInitialAsyncState();
|
|
2112
|
+
function notify() {
|
|
2113
|
+
for (const listener of listeners) {
|
|
2114
|
+
listener();
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
__name(notify, "notify");
|
|
2118
|
+
function setState(next) {
|
|
2119
|
+
state = next;
|
|
2120
|
+
notify();
|
|
2121
|
+
}
|
|
2122
|
+
__name(setState, "setState");
|
|
2123
|
+
async function send(config2, options) {
|
|
2124
|
+
const request = ensureAuthority(config2, authorityProvider);
|
|
2125
|
+
setState(createAsyncState("loading"));
|
|
2126
|
+
try {
|
|
2127
|
+
const signature4 = await helper.sendTransfer(request, options);
|
|
2128
|
+
setState(createAsyncState("success", { data: signature4 }));
|
|
2129
|
+
return signature4;
|
|
2130
|
+
} catch (error) {
|
|
2131
|
+
setState(createAsyncState("error", { error }));
|
|
2132
|
+
throw error;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
__name(send, "send");
|
|
2136
|
+
function subscribe(listener) {
|
|
2137
|
+
listeners.add(listener);
|
|
2138
|
+
return () => {
|
|
2139
|
+
listeners.delete(listener);
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
__name(subscribe, "subscribe");
|
|
2143
|
+
function reset() {
|
|
2144
|
+
setState(createInitialAsyncState());
|
|
2145
|
+
}
|
|
2146
|
+
__name(reset, "reset");
|
|
2147
|
+
return {
|
|
2148
|
+
getHelper: /* @__PURE__ */ __name(() => helper, "getHelper"),
|
|
2149
|
+
getState: /* @__PURE__ */ __name(() => state, "getState"),
|
|
2150
|
+
reset,
|
|
2151
|
+
send,
|
|
2152
|
+
subscribe
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
__name(createSolTransferController, "createSolTransferController");
|
|
2156
|
+
|
|
2157
|
+
// src/controllers/splTransferController.ts
|
|
2158
|
+
function ensureTransferConfig(input, resolveAuthority, resolveSourceOwner) {
|
|
2159
|
+
const authority = input.authority ?? resolveAuthority?.();
|
|
2160
|
+
if (!authority) {
|
|
2161
|
+
throw new Error("Connect a wallet or supply an `authority` before sending SPL tokens.");
|
|
2162
|
+
}
|
|
2163
|
+
const sourceOwner = input.sourceOwner ?? resolveSourceOwner?.();
|
|
2164
|
+
if (!sourceOwner) {
|
|
2165
|
+
throw new Error("Unable to resolve a source owner for the SPL token transfer.");
|
|
2166
|
+
}
|
|
2167
|
+
return {
|
|
2168
|
+
...input,
|
|
2169
|
+
authority,
|
|
2170
|
+
sourceOwner
|
|
2171
|
+
};
|
|
2172
|
+
}
|
|
2173
|
+
__name(ensureTransferConfig, "ensureTransferConfig");
|
|
2174
|
+
function createSplTransferController(config) {
|
|
2175
|
+
const helper = config.helper;
|
|
2176
|
+
const authorityProvider = config.authorityProvider;
|
|
2177
|
+
const sourceOwnerProvider = config.sourceOwnerProvider;
|
|
2178
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2179
|
+
let state = createInitialAsyncState();
|
|
2180
|
+
function notify() {
|
|
2181
|
+
for (const listener of listeners) {
|
|
2182
|
+
listener();
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
__name(notify, "notify");
|
|
2186
|
+
function setState(next) {
|
|
2187
|
+
state = next;
|
|
2188
|
+
notify();
|
|
2189
|
+
}
|
|
2190
|
+
__name(setState, "setState");
|
|
2191
|
+
async function send(config2, options) {
|
|
2192
|
+
const resolvedConfig = ensureTransferConfig(
|
|
2193
|
+
config2,
|
|
2194
|
+
config2.authority ? void 0 : authorityProvider,
|
|
2195
|
+
config2.sourceOwner ? void 0 : sourceOwnerProvider
|
|
2196
|
+
);
|
|
2197
|
+
setState(createAsyncState("loading"));
|
|
2198
|
+
try {
|
|
2199
|
+
const signature4 = await helper.sendTransfer(resolvedConfig, options);
|
|
2200
|
+
setState(createAsyncState("success", { data: signature4 }));
|
|
2201
|
+
return signature4;
|
|
2202
|
+
} catch (error) {
|
|
2203
|
+
setState(createAsyncState("error", { error }));
|
|
2204
|
+
throw error;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
__name(send, "send");
|
|
2208
|
+
function subscribe(listener) {
|
|
2209
|
+
listeners.add(listener);
|
|
2210
|
+
return () => {
|
|
2211
|
+
listeners.delete(listener);
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
2214
|
+
__name(subscribe, "subscribe");
|
|
2215
|
+
function reset() {
|
|
2216
|
+
setState(createInitialAsyncState());
|
|
2217
|
+
}
|
|
2218
|
+
__name(reset, "reset");
|
|
2219
|
+
return {
|
|
2220
|
+
getHelper: /* @__PURE__ */ __name(() => helper, "getHelper"),
|
|
2221
|
+
getState: /* @__PURE__ */ __name(() => state, "getState"),
|
|
2222
|
+
reset,
|
|
2223
|
+
send,
|
|
2224
|
+
subscribe
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
__name(createSplTransferController, "createSplTransferController");
|
|
2228
|
+
|
|
2229
|
+
// src/serialization/json.ts
|
|
2230
|
+
function bigintToJson(value) {
|
|
2231
|
+
return value.toString();
|
|
2232
|
+
}
|
|
2233
|
+
__name(bigintToJson, "bigintToJson");
|
|
2234
|
+
function bigintFromJson(value) {
|
|
2235
|
+
return toBigint2(value, "bigint");
|
|
2236
|
+
}
|
|
2237
|
+
__name(bigintFromJson, "bigintFromJson");
|
|
2238
|
+
function lamportsToJson(value) {
|
|
2239
|
+
return value.toString();
|
|
2240
|
+
}
|
|
2241
|
+
__name(lamportsToJson, "lamportsToJson");
|
|
2242
|
+
function lamportsFromJson(value) {
|
|
2243
|
+
return lamports(value, "lamports");
|
|
2244
|
+
}
|
|
2245
|
+
__name(lamportsFromJson, "lamportsFromJson");
|
|
2246
|
+
var COMMITMENT_PRIORITY = {
|
|
2247
|
+
processed: 0,
|
|
2248
|
+
confirmed: 1,
|
|
2249
|
+
finalized: 2
|
|
2250
|
+
};
|
|
2251
|
+
var SIGNATURE_STATUS_TIMEOUT_MS = 2e4;
|
|
2252
|
+
function normalizeSignature(input) {
|
|
2253
|
+
if (!input) {
|
|
2254
|
+
return void 0;
|
|
2255
|
+
}
|
|
2256
|
+
return typeof input === "string" ? signature(input) : input;
|
|
2257
|
+
}
|
|
2258
|
+
__name(normalizeSignature, "normalizeSignature");
|
|
2259
|
+
function deriveConfirmationStatus(status) {
|
|
2260
|
+
if (!status) {
|
|
2261
|
+
return null;
|
|
2262
|
+
}
|
|
2263
|
+
if (status.confirmationStatus === "processed" || status.confirmationStatus === "confirmed" || status.confirmationStatus === "finalized") {
|
|
2264
|
+
return status.confirmationStatus;
|
|
2265
|
+
}
|
|
2266
|
+
if (status.confirmations === null) {
|
|
2267
|
+
return "finalized";
|
|
2268
|
+
}
|
|
2269
|
+
if (typeof status.confirmations === "number" && status.confirmations > 0) {
|
|
2270
|
+
return "confirmed";
|
|
2271
|
+
}
|
|
2272
|
+
return "processed";
|
|
2273
|
+
}
|
|
2274
|
+
__name(deriveConfirmationStatus, "deriveConfirmationStatus");
|
|
2275
|
+
function confirmationMeetsCommitment(confirmation, target) {
|
|
2276
|
+
if (!confirmation) {
|
|
2277
|
+
return false;
|
|
2278
|
+
}
|
|
2279
|
+
return COMMITMENT_PRIORITY[confirmation] >= COMMITMENT_PRIORITY[target];
|
|
2280
|
+
}
|
|
2281
|
+
__name(confirmationMeetsCommitment, "confirmationMeetsCommitment");
|
|
2282
|
+
var MEMO_PROGRAM_ADDRESS = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
|
|
2283
|
+
function ensureNonMemoInstructionIndex(instructions) {
|
|
2284
|
+
const index = instructions.findIndex((instruction) => instruction.programAddress !== MEMO_PROGRAM_ADDRESS);
|
|
2285
|
+
if (instructions.length === 0 || index === -1) {
|
|
2286
|
+
throw new SolanaError(SOLANA_ERROR__INSTRUCTION_ERROR__GENERIC_ERROR, {
|
|
2287
|
+
cause: "At least one non-memo instruction is required.",
|
|
2288
|
+
index: instructions.length || index
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
return index;
|
|
2292
|
+
}
|
|
2293
|
+
__name(ensureNonMemoInstructionIndex, "ensureNonMemoInstructionIndex");
|
|
2294
|
+
function insertReferenceKey(reference, transaction) {
|
|
2295
|
+
return insertReferenceKeys([reference], transaction);
|
|
2296
|
+
}
|
|
2297
|
+
__name(insertReferenceKey, "insertReferenceKey");
|
|
2298
|
+
function insertReferenceKeys(references, transaction) {
|
|
2299
|
+
const index = ensureNonMemoInstructionIndex(transaction.instructions);
|
|
2300
|
+
const targetInstruction = transaction.instructions[index];
|
|
2301
|
+
const accounts = [
|
|
2302
|
+
...targetInstruction.accounts ?? [],
|
|
2303
|
+
...references.map((address4) => ({ address: address4, role: AccountRole.READONLY }))
|
|
2304
|
+
];
|
|
2305
|
+
const updatedInstructions = [...transaction.instructions];
|
|
2306
|
+
updatedInstructions.splice(index, 1, { ...targetInstruction, accounts });
|
|
2307
|
+
return Object.freeze({
|
|
2308
|
+
...transaction,
|
|
2309
|
+
instructions: Object.freeze(updatedInstructions)
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
__name(insertReferenceKeys, "insertReferenceKeys");
|
|
2313
|
+
|
|
2314
|
+
// src/transactions/transactionPoolController.ts
|
|
2315
|
+
function createStore2(initial) {
|
|
2316
|
+
let snapshot = initial;
|
|
2317
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2318
|
+
return {
|
|
2319
|
+
getSnapshot: /* @__PURE__ */ __name(() => snapshot, "getSnapshot"),
|
|
2320
|
+
setSnapshot(next) {
|
|
2321
|
+
snapshot = next;
|
|
2322
|
+
for (const listener of listeners) {
|
|
2323
|
+
listener();
|
|
2324
|
+
}
|
|
2325
|
+
},
|
|
2326
|
+
subscribe(listener) {
|
|
2327
|
+
listeners.add(listener);
|
|
2328
|
+
return () => {
|
|
2329
|
+
listeners.delete(listener);
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
};
|
|
2333
|
+
}
|
|
2334
|
+
__name(createStore2, "createStore");
|
|
2335
|
+
function freezeInstructions(list) {
|
|
2336
|
+
return Object.freeze([...list]);
|
|
2337
|
+
}
|
|
2338
|
+
__name(freezeInstructions, "freezeInstructions");
|
|
2339
|
+
function createTransactionPoolController(config) {
|
|
2340
|
+
const helper = config.helper;
|
|
2341
|
+
const initialInstructions = freezeInstructions(config.initialInstructions ?? []);
|
|
2342
|
+
const blockhashMaxAgeMs = config.blockhashMaxAgeMs ?? 3e4;
|
|
2343
|
+
let latestBlockhashCache;
|
|
2344
|
+
const instructionsStore = createStore2(initialInstructions);
|
|
2345
|
+
const preparedStore = createStore2(null);
|
|
2346
|
+
const prepareStateStore = createStore2(
|
|
2347
|
+
createInitialAsyncState()
|
|
2348
|
+
);
|
|
2349
|
+
const sendStateStore = createStore2(
|
|
2350
|
+
createInitialAsyncState()
|
|
2351
|
+
);
|
|
2352
|
+
function resetDerivedState() {
|
|
2353
|
+
preparedStore.setSnapshot(null);
|
|
2354
|
+
prepareStateStore.setSnapshot(createInitialAsyncState());
|
|
2355
|
+
sendStateStore.setSnapshot(createInitialAsyncState());
|
|
2356
|
+
}
|
|
2357
|
+
__name(resetDerivedState, "resetDerivedState");
|
|
2358
|
+
function commitInstructions(next) {
|
|
2359
|
+
instructionsStore.setSnapshot(freezeInstructions(next));
|
|
2360
|
+
resetDerivedState();
|
|
2361
|
+
}
|
|
2362
|
+
__name(commitInstructions, "commitInstructions");
|
|
2363
|
+
function addInstruction(instruction) {
|
|
2364
|
+
const next = [...instructionsStore.getSnapshot(), instruction];
|
|
2365
|
+
commitInstructions(next);
|
|
2366
|
+
}
|
|
2367
|
+
__name(addInstruction, "addInstruction");
|
|
2368
|
+
function addInstructions(instructionSet) {
|
|
2369
|
+
if (!instructionSet.length) {
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
const next = [...instructionsStore.getSnapshot(), ...instructionSet];
|
|
2373
|
+
commitInstructions(next);
|
|
2374
|
+
}
|
|
2375
|
+
__name(addInstructions, "addInstructions");
|
|
2376
|
+
function replaceInstructions(instructionSet) {
|
|
2377
|
+
commitInstructions(instructionSet);
|
|
2378
|
+
}
|
|
2379
|
+
__name(replaceInstructions, "replaceInstructions");
|
|
2380
|
+
function clearInstructions() {
|
|
2381
|
+
commitInstructions([]);
|
|
2382
|
+
}
|
|
2383
|
+
__name(clearInstructions, "clearInstructions");
|
|
2384
|
+
function removeInstruction(index) {
|
|
2385
|
+
const current = instructionsStore.getSnapshot();
|
|
2386
|
+
if (index < 0 || index >= current.length) {
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
const next = current.filter((_, ii) => ii !== index);
|
|
2390
|
+
commitInstructions(next);
|
|
2391
|
+
}
|
|
2392
|
+
__name(removeInstruction, "removeInstruction");
|
|
2393
|
+
function reset() {
|
|
2394
|
+
commitInstructions(initialInstructions);
|
|
2395
|
+
}
|
|
2396
|
+
__name(reset, "reset");
|
|
2397
|
+
function ensureInstructions(instructionList) {
|
|
2398
|
+
if (!instructionList.length) {
|
|
2399
|
+
throw new Error("Add at least one instruction before preparing a transaction.");
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
__name(ensureInstructions, "ensureInstructions");
|
|
2403
|
+
function resolveCachedLifetime() {
|
|
2404
|
+
if (!latestBlockhashCache) {
|
|
2405
|
+
return void 0;
|
|
2406
|
+
}
|
|
2407
|
+
if (Date.now() - latestBlockhashCache.updatedAt > blockhashMaxAgeMs) {
|
|
2408
|
+
return void 0;
|
|
2409
|
+
}
|
|
2410
|
+
return latestBlockhashCache.value;
|
|
2411
|
+
}
|
|
2412
|
+
__name(resolveCachedLifetime, "resolveCachedLifetime");
|
|
2413
|
+
async function prepare(options = {}) {
|
|
2414
|
+
const { instructions: overrideInstructions, ...rest } = options;
|
|
2415
|
+
const nextInstructions = overrideInstructions ?? instructionsStore.getSnapshot();
|
|
2416
|
+
ensureInstructions(nextInstructions);
|
|
2417
|
+
prepareStateStore.setSnapshot(createAsyncState("loading"));
|
|
2418
|
+
try {
|
|
2419
|
+
const cachedLifetime = rest.lifetime ?? resolveCachedLifetime();
|
|
2420
|
+
const restWithLifetime = cachedLifetime && !rest.lifetime ? { ...rest, lifetime: cachedLifetime } : rest;
|
|
2421
|
+
const prepared = await helper.prepare({
|
|
2422
|
+
...restWithLifetime,
|
|
2423
|
+
instructions: nextInstructions
|
|
2424
|
+
});
|
|
2425
|
+
preparedStore.setSnapshot(prepared);
|
|
2426
|
+
prepareStateStore.setSnapshot(createAsyncState("success", { data: prepared }));
|
|
2427
|
+
return prepared;
|
|
2428
|
+
} catch (error) {
|
|
2429
|
+
prepareStateStore.setSnapshot(createAsyncState("error", { error }));
|
|
2430
|
+
throw error;
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
__name(prepare, "prepare");
|
|
2434
|
+
function resolvePrepared(override) {
|
|
2435
|
+
const target = override ?? preparedStore.getSnapshot();
|
|
2436
|
+
if (!target) {
|
|
2437
|
+
throw new Error("Prepare a transaction before sending.");
|
|
2438
|
+
}
|
|
2439
|
+
return target;
|
|
2440
|
+
}
|
|
2441
|
+
__name(resolvePrepared, "resolvePrepared");
|
|
2442
|
+
function resolveLifetimeOptions(options) {
|
|
2443
|
+
if (options.lifetime) {
|
|
2444
|
+
return options;
|
|
2445
|
+
}
|
|
2446
|
+
const cachedLifetime = resolveCachedLifetime();
|
|
2447
|
+
if (!cachedLifetime) {
|
|
2448
|
+
return options;
|
|
2449
|
+
}
|
|
2450
|
+
return { ...options, lifetime: cachedLifetime };
|
|
2451
|
+
}
|
|
2452
|
+
__name(resolveLifetimeOptions, "resolveLifetimeOptions");
|
|
2453
|
+
async function send(options = {}) {
|
|
2454
|
+
const { prepared: overridePrepared, ...rest } = options;
|
|
2455
|
+
const target = resolvePrepared(overridePrepared);
|
|
2456
|
+
sendStateStore.setSnapshot(createAsyncState("loading"));
|
|
2457
|
+
try {
|
|
2458
|
+
const signature4 = await helper.send(target, rest);
|
|
2459
|
+
sendStateStore.setSnapshot(createAsyncState("success", { data: signature4 }));
|
|
2460
|
+
return signature4;
|
|
2461
|
+
} catch (error) {
|
|
2462
|
+
sendStateStore.setSnapshot(createAsyncState("error", { error }));
|
|
2463
|
+
throw error;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
__name(send, "send");
|
|
2467
|
+
async function prepareAndSend(request = {}, sendOptions) {
|
|
2468
|
+
const { instructions: overrideInstructions, ...rest } = request;
|
|
2469
|
+
const nextInstructions = overrideInstructions ?? instructionsStore.getSnapshot();
|
|
2470
|
+
ensureInstructions(nextInstructions);
|
|
2471
|
+
sendStateStore.setSnapshot(createAsyncState("loading"));
|
|
2472
|
+
try {
|
|
2473
|
+
const restWithLifetime = resolveLifetimeOptions(rest);
|
|
2474
|
+
const signature4 = await helper.prepareAndSend(
|
|
2475
|
+
{
|
|
2476
|
+
...restWithLifetime,
|
|
2477
|
+
instructions: nextInstructions
|
|
2478
|
+
},
|
|
2479
|
+
sendOptions
|
|
2480
|
+
);
|
|
2481
|
+
sendStateStore.setSnapshot(createAsyncState("success", { data: signature4 }));
|
|
2482
|
+
return signature4;
|
|
2483
|
+
} catch (error) {
|
|
2484
|
+
sendStateStore.setSnapshot(createAsyncState("error", { error }));
|
|
2485
|
+
throw error;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
__name(prepareAndSend, "prepareAndSend");
|
|
2489
|
+
function sign(options = {}) {
|
|
2490
|
+
const { prepared: overridePrepared, ...rest } = options;
|
|
2491
|
+
const target = resolvePrepared(overridePrepared);
|
|
2492
|
+
return helper.sign(target, rest);
|
|
2493
|
+
}
|
|
2494
|
+
__name(sign, "sign");
|
|
2495
|
+
function toWire(options = {}) {
|
|
2496
|
+
const { prepared: overridePrepared, ...rest } = options;
|
|
2497
|
+
const target = resolvePrepared(overridePrepared);
|
|
2498
|
+
return helper.toWire(target, rest);
|
|
2499
|
+
}
|
|
2500
|
+
__name(toWire, "toWire");
|
|
2501
|
+
function subscribeInstructions(listener) {
|
|
2502
|
+
return instructionsStore.subscribe(listener);
|
|
2503
|
+
}
|
|
2504
|
+
__name(subscribeInstructions, "subscribeInstructions");
|
|
2505
|
+
function subscribePrepared(listener) {
|
|
2506
|
+
return preparedStore.subscribe(listener);
|
|
2507
|
+
}
|
|
2508
|
+
__name(subscribePrepared, "subscribePrepared");
|
|
2509
|
+
function subscribePrepareState(listener) {
|
|
2510
|
+
return prepareStateStore.subscribe(listener);
|
|
2511
|
+
}
|
|
2512
|
+
__name(subscribePrepareState, "subscribePrepareState");
|
|
2513
|
+
function subscribeSendState(listener) {
|
|
2514
|
+
return sendStateStore.subscribe(listener);
|
|
2515
|
+
}
|
|
2516
|
+
__name(subscribeSendState, "subscribeSendState");
|
|
2517
|
+
function setLatestBlockhashCache(cache) {
|
|
2518
|
+
latestBlockhashCache = cache;
|
|
2519
|
+
}
|
|
2520
|
+
__name(setLatestBlockhashCache, "setLatestBlockhashCache");
|
|
2521
|
+
return {
|
|
2522
|
+
addInstruction,
|
|
2523
|
+
addInstructions,
|
|
2524
|
+
clearInstructions,
|
|
2525
|
+
get helper() {
|
|
2526
|
+
return helper;
|
|
2527
|
+
},
|
|
2528
|
+
getInstructions: instructionsStore.getSnapshot,
|
|
2529
|
+
getPrepareState: prepareStateStore.getSnapshot,
|
|
2530
|
+
getPrepared: preparedStore.getSnapshot,
|
|
2531
|
+
getSendState: sendStateStore.getSnapshot,
|
|
2532
|
+
getLatestBlockhashCache: /* @__PURE__ */ __name(() => latestBlockhashCache, "getLatestBlockhashCache"),
|
|
2533
|
+
prepare,
|
|
2534
|
+
prepareAndSend,
|
|
2535
|
+
removeInstruction,
|
|
2536
|
+
replaceInstructions,
|
|
2537
|
+
reset,
|
|
2538
|
+
send,
|
|
2539
|
+
setLatestBlockhashCache,
|
|
2540
|
+
sign,
|
|
2541
|
+
subscribeInstructions,
|
|
2542
|
+
subscribePrepareState,
|
|
2543
|
+
subscribePrepared,
|
|
2544
|
+
subscribeSendState,
|
|
2545
|
+
toWire
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
__name(createTransactionPoolController, "createTransactionPoolController");
|
|
2549
|
+
function toAddress2(addressLike) {
|
|
2550
|
+
return typeof addressLike === "string" ? address(addressLike) : addressLike;
|
|
2551
|
+
}
|
|
2552
|
+
__name(toAddress2, "toAddress");
|
|
2553
|
+
function toAddressString(addressLike) {
|
|
2554
|
+
return toAddress2(addressLike).toString();
|
|
2555
|
+
}
|
|
2556
|
+
__name(toAddressString, "toAddressString");
|
|
2557
|
+
|
|
2558
|
+
// src/utils/stableStringify.ts
|
|
2559
|
+
function stableStringify(value) {
|
|
2560
|
+
const result = JSON.stringify(value, (_key, candidate) => {
|
|
2561
|
+
if (typeof candidate === "bigint") {
|
|
2562
|
+
return { __type: "bigint", value: candidate.toString() };
|
|
2563
|
+
}
|
|
2564
|
+
if (candidate instanceof Uint8Array) {
|
|
2565
|
+
return Array.from(candidate);
|
|
2566
|
+
}
|
|
2567
|
+
return candidate;
|
|
2568
|
+
});
|
|
2569
|
+
return result ?? "undefined";
|
|
2570
|
+
}
|
|
2571
|
+
__name(stableStringify, "stableStringify");
|
|
2572
|
+
var base58Decoder = getBase58Decoder();
|
|
2573
|
+
var transactionDecoder = getTransactionDecoder();
|
|
2574
|
+
var transactionEncoder = getTransactionEncoder();
|
|
2575
|
+
function deriveConnectorId(wallet) {
|
|
2576
|
+
return wallet.name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
2577
|
+
}
|
|
2578
|
+
__name(deriveConnectorId, "deriveConnectorId");
|
|
2579
|
+
function getPrimaryAccount(accounts) {
|
|
2580
|
+
const primary = accounts[0];
|
|
2581
|
+
if (!primary) {
|
|
2582
|
+
throw new Error("Wallet returned no accounts.");
|
|
2583
|
+
}
|
|
2584
|
+
return primary;
|
|
2585
|
+
}
|
|
2586
|
+
__name(getPrimaryAccount, "getPrimaryAccount");
|
|
2587
|
+
function mapCommitment(commitment) {
|
|
2588
|
+
if (commitment === "processed" || commitment === "confirmed" || commitment === "finalized") {
|
|
2589
|
+
return commitment;
|
|
2590
|
+
}
|
|
2591
|
+
return void 0;
|
|
2592
|
+
}
|
|
2593
|
+
__name(mapCommitment, "mapCommitment");
|
|
2594
|
+
function toSessionAccount(walletAccount) {
|
|
2595
|
+
return {
|
|
2596
|
+
address: address(walletAccount.address),
|
|
2597
|
+
label: walletAccount.label,
|
|
2598
|
+
publicKey: new Uint8Array(walletAccount.publicKey)
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
__name(toSessionAccount, "toSessionAccount");
|
|
2602
|
+
function getChain(account) {
|
|
2603
|
+
const [preferred] = account.chains ?? [];
|
|
2604
|
+
return preferred;
|
|
2605
|
+
}
|
|
2606
|
+
__name(getChain, "getChain");
|
|
2607
|
+
async function disconnectWallet(wallet) {
|
|
2608
|
+
const disconnectFeature = wallet.features[StandardDisconnect];
|
|
2609
|
+
if (disconnectFeature) {
|
|
2610
|
+
await disconnectFeature.disconnect();
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
__name(disconnectWallet, "disconnectWallet");
|
|
2614
|
+
function createWalletStandardConnector(wallet, options = {}) {
|
|
2615
|
+
const metadata = {
|
|
2616
|
+
canAutoConnect: options.canAutoConnect ?? Boolean(wallet.features[StandardConnect]),
|
|
2617
|
+
icon: options.icon ?? wallet.icon,
|
|
2618
|
+
id: options.id ?? deriveConnectorId(wallet),
|
|
2619
|
+
name: options.name ?? wallet.name
|
|
2620
|
+
};
|
|
2621
|
+
async function connect(connectionOptions = {}) {
|
|
2622
|
+
const connectFeature = wallet.features[StandardConnect];
|
|
2623
|
+
const shouldConnectSilently = Boolean(connectionOptions.autoConnect);
|
|
2624
|
+
let walletAccounts = wallet.accounts;
|
|
2625
|
+
if (connectFeature) {
|
|
2626
|
+
const { accounts } = await connectFeature.connect({
|
|
2627
|
+
silent: shouldConnectSilently || void 0
|
|
2628
|
+
});
|
|
2629
|
+
if (accounts.length) {
|
|
2630
|
+
walletAccounts = accounts;
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
const primaryAccount = getPrimaryAccount(walletAccounts);
|
|
2634
|
+
const sessionAccount = toSessionAccount(primaryAccount);
|
|
2635
|
+
const signMessageFeature = wallet.features[SolanaSignMessage];
|
|
2636
|
+
const signTransactionFeature = wallet.features[SolanaSignTransaction];
|
|
2637
|
+
const signAndSendFeature = wallet.features[SolanaSignAndSendTransaction];
|
|
2638
|
+
const resolvedChain = options.defaultChain ?? getChain(primaryAccount);
|
|
2639
|
+
const signMessage = signMessageFeature ? async (message) => {
|
|
2640
|
+
const [output] = await signMessageFeature.signMessage({
|
|
2641
|
+
account: primaryAccount,
|
|
2642
|
+
message
|
|
2643
|
+
});
|
|
2644
|
+
return output.signature;
|
|
2645
|
+
} : void 0;
|
|
2646
|
+
const signTransaction = signTransactionFeature ? async (transaction) => {
|
|
2647
|
+
const wireBytes = new Uint8Array(transactionEncoder.encode(transaction));
|
|
2648
|
+
const request = resolvedChain ? {
|
|
2649
|
+
account: primaryAccount,
|
|
2650
|
+
chain: resolvedChain,
|
|
2651
|
+
transaction: wireBytes
|
|
2652
|
+
} : {
|
|
2653
|
+
account: primaryAccount,
|
|
2654
|
+
transaction: wireBytes
|
|
2655
|
+
};
|
|
2656
|
+
const [output] = await signTransactionFeature.signTransaction(request);
|
|
2657
|
+
return transactionDecoder.decode(output.signedTransaction);
|
|
2658
|
+
} : void 0;
|
|
2659
|
+
const sendTransaction = signAndSendFeature ? async (transaction, config) => {
|
|
2660
|
+
const wireBytes = new Uint8Array(transactionEncoder.encode(transaction));
|
|
2661
|
+
const chain = options.defaultChain ?? getChain(primaryAccount) ?? "solana:mainnet-beta";
|
|
2662
|
+
const [output] = await signAndSendFeature.signAndSendTransaction({
|
|
2663
|
+
account: primaryAccount,
|
|
2664
|
+
chain,
|
|
2665
|
+
options: {
|
|
2666
|
+
commitment: mapCommitment(config?.commitment)
|
|
2667
|
+
},
|
|
2668
|
+
transaction: wireBytes
|
|
2669
|
+
});
|
|
2670
|
+
return base58Decoder.decode(output.signature);
|
|
2671
|
+
} : void 0;
|
|
2672
|
+
async function disconnectSession() {
|
|
2673
|
+
await disconnectWallet(wallet);
|
|
2674
|
+
}
|
|
2675
|
+
__name(disconnectSession, "disconnectSession");
|
|
2676
|
+
return {
|
|
2677
|
+
account: sessionAccount,
|
|
2678
|
+
connector: metadata,
|
|
2679
|
+
disconnect: disconnectSession,
|
|
2680
|
+
sendTransaction,
|
|
2681
|
+
signMessage,
|
|
2682
|
+
signTransaction
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
__name(connect, "connect");
|
|
2686
|
+
async function disconnect() {
|
|
2687
|
+
await disconnectWallet(wallet);
|
|
2688
|
+
}
|
|
2689
|
+
__name(disconnect, "disconnect");
|
|
2690
|
+
function isSupported() {
|
|
2691
|
+
return typeof window !== "undefined";
|
|
2692
|
+
}
|
|
2693
|
+
__name(isSupported, "isSupported");
|
|
2694
|
+
return {
|
|
2695
|
+
...metadata,
|
|
2696
|
+
connect,
|
|
2697
|
+
disconnect,
|
|
2698
|
+
isSupported
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
__name(createWalletStandardConnector, "createWalletStandardConnector");
|
|
2702
|
+
function mapWalletToConnector(wallet, overrides) {
|
|
2703
|
+
return createWalletStandardConnector(wallet, overrides?.(wallet));
|
|
2704
|
+
}
|
|
2705
|
+
__name(mapWalletToConnector, "mapWalletToConnector");
|
|
2706
|
+
function getWalletStandardConnectors(options = {}) {
|
|
2707
|
+
const { get } = getWallets();
|
|
2708
|
+
const connectors = get().map((wallet) => mapWalletToConnector(wallet, options.overrides));
|
|
2709
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2710
|
+
return connectors.filter((connector) => {
|
|
2711
|
+
if (seen.has(connector.id)) {
|
|
2712
|
+
return false;
|
|
2713
|
+
}
|
|
2714
|
+
seen.add(connector.id);
|
|
2715
|
+
return true;
|
|
2716
|
+
});
|
|
2717
|
+
}
|
|
2718
|
+
__name(getWalletStandardConnectors, "getWalletStandardConnectors");
|
|
2719
|
+
function watchWalletStandardConnectors(onChange, options = {}) {
|
|
2720
|
+
const { get, on } = getWallets();
|
|
2721
|
+
const emit = /* @__PURE__ */ __name(() => {
|
|
2722
|
+
const connectors = get().map((wallet) => mapWalletToConnector(wallet, options.overrides));
|
|
2723
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2724
|
+
const deduplicated = connectors.filter((connector) => {
|
|
2725
|
+
if (seen.has(connector.id)) {
|
|
2726
|
+
return false;
|
|
2727
|
+
}
|
|
2728
|
+
seen.add(connector.id);
|
|
2729
|
+
return true;
|
|
2730
|
+
});
|
|
2731
|
+
onChange(deduplicated);
|
|
2732
|
+
}, "emit");
|
|
2733
|
+
emit();
|
|
2734
|
+
const offRegister = on("register", emit);
|
|
2735
|
+
const offUnregister = on("unregister", emit);
|
|
2736
|
+
return () => {
|
|
2737
|
+
offRegister();
|
|
2738
|
+
offUnregister();
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
__name(watchWalletStandardConnectors, "watchWalletStandardConnectors");
|
|
2742
|
+
|
|
2743
|
+
export { LAMPORTS_PER_SOL, SIGNATURE_STATUS_TIMEOUT_MS, applyRatio, assertDecimals, assertNonNegative, bigintFromJson, bigintToJson, checkedAdd, checkedDivide, checkedMultiply, checkedSubtract, confirmationMeetsCommitment, createAsyncState, createClient, createClientStore, createDefaultClientStore, createInitialAsyncState, createInitialClientState, createRatio, createSolTransferController, createSolTransferHelper, createSolanaRpcClient, createSplTokenHelper, createSplTransferController, createTokenAmount, createTransactionHelper, createTransactionPoolController, createTransactionRecipe, createWalletRegistry, createWalletStandardConnector, deriveConfirmationStatus, getWalletStandardConnectors, insertReferenceKey, insertReferenceKeys, lamports, lamportsFromJson, lamportsFromSol, lamportsMath, lamportsToJson, lamportsToSolString, normalizeSignature, pow10, prepareTransaction, stableStringify, toAddress2 as toAddress, toAddressString, toBigint2 as toBigint, transactionToBase64, transactionToBase64WithSigners, watchWalletStandardConnectors };
|
|
2744
|
+
//# sourceMappingURL=index.node.mjs.map
|
|
2745
|
+
//# sourceMappingURL=index.node.mjs.map
|