@usearete/adapter-web3js 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arete
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # @usearete/adapter-web3js
2
+
3
+ An Arete [`WalletAdapter`](https://www.npmjs.com/package/@usearete/sdk) backed by [`@solana/web3.js`](https://github.com/solana-labs/solana-web3.js).
4
+
5
+ The adapter compiles static-key v0 transactions, signs once, submits once, and confirms without rebuilding or resubmitting. It also supports unsigned fee estimation and simulation for Arete operation inspection.
6
+
7
+ See the [transaction guide](../../../docs/src/content/docs/using-stacks/transactions.mdx)
8
+ for complete application setup, scopes, failure handling, and troubleshooting.
9
+
10
+ `transport: 'auto'` uses the connected Arete client's authenticated transaction transport per invocation. Standalone auto mode uses `connection` when provided. Use `transport: 'direct'` to require direct Solana RPC, or pass a `TransactionTransport` object. A resolved Arete operation never falls back to direct RPC after an error.
11
+
12
+ ```ts
13
+ const wallet = createWalletAdapter({ signer, transport: 'auto' })
14
+ const client = await Arete.connect(stack, { wallet })
15
+ await client.transaction(instructions)
16
+ ```
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install @usearete/adapter-web3js @solana/web3.js @usearete/sdk
22
+ ```
23
+
24
+ Node.js 18 or newer is supported. ESM and CommonJS entry points are included. Browser builds do not require an ambient `Buffer` global; the package imports its browser-compatible implementation explicitly.
25
+
26
+ ## Node Signer
27
+
28
+ ```ts
29
+ import { Connection, Keypair } from '@solana/web3.js';
30
+ import { Arete } from '@usearete/sdk';
31
+ import { createKeypairWalletAdapter } from '@usearete/adapter-web3js';
32
+ import { MY_STACK } from './generated/my-stack';
33
+
34
+ const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
35
+ const keypair = Keypair.fromSecretKey(/* secret key bytes */);
36
+ const wallet = createKeypairWalletAdapter({ connection, keypair });
37
+ const client = await Arete.connect(MY_STACK, { wallet });
38
+
39
+ const { signature, slot } = await client.instructions.buy({
40
+ amount: 1_000_000n,
41
+ maxSolCost: 100_000_000n,
42
+ mint: 'So11111111111111111111111111111111111111112',
43
+ });
44
+ ```
45
+
46
+ Configured `additionalSigners` are used when their addresses are required and are all published through `wallet.signerAddresses`. Per-send signers can be supplied through `send.signers` or `send.additionalSigners`.
47
+
48
+ ## Browser Wallets
49
+
50
+ `createWalletAdapter` accepts a wallet-adapter-style signer whose `signTransaction` method receives and returns a web3.js `VersionedTransaction`:
51
+
52
+ ```ts
53
+ const wallet = createWalletAdapter({
54
+ connection,
55
+ signer: {
56
+ publicKey,
57
+ signTransaction,
58
+ supportedTransactionVersions: walletAdapter.supportedTransactionVersions,
59
+ },
60
+ });
61
+ ```
62
+
63
+ In a React app using `@solana/wallet-adapter-react`, the `./react` subpath does this bridging for you:
64
+
65
+ ```tsx
66
+ import { useSolanaWalletAdapter } from '@usearete/adapter-web3js/react';
67
+ import { AreteProvider } from '@usearete/react';
68
+ import { APP_STREAM_STACK } from './generated/app-stack';
69
+
70
+ const publishableKey = import.meta.env.VITE_ARETE_PUBLISHABLE_KEY;
71
+ if (!publishableKey) throw new Error('VITE_ARETE_PUBLISHABLE_KEY is required');
72
+
73
+ function Shell({ children }) {
74
+ const wallet = useSolanaWalletAdapter(); // undefined until a wallet connects
75
+ return (
76
+ <AreteProvider
77
+ stack={APP_STREAM_STACK}
78
+ auth={{ publishableKey }}
79
+ wallet={wallet}
80
+ >
81
+ {children}
82
+ </AreteProvider>
83
+ );
84
+ }
85
+ ```
86
+
87
+ Hosted browser access requires the publishable key even when the app is only reading data. A wallet is required for signed operations, not for read-only viewing. `autoConnect` is omitted because its default is `true`; it controls only the initial connection, while `autoReconnect` independently defaults to `true` for recovery after an established connection is lost.
88
+
89
+ The wallet must be connected, expose a non-null `PublicKey`, and support transaction version `0`. If `supportedTransactionVersions` is `null` or excludes `0`, the adapter rejects before prompting or sending. If that property is omitted, the supplied `signTransaction` implementation is responsible for accepting v0 transactions.
90
+
91
+ Raw Wallet Standard `solana:signTransaction` features operate on byte-array request and response objects; they do not directly satisfy this interface. Bridge those feature calls to web3.js `VersionedTransaction` serialization/deserialization, or use a wallet-adapter integration that already exposes `signTransaction`.
92
+
93
+ Address lookup tables are not currently accepted by this adapter. Transactions use a v0 message with static account keys.
94
+
95
+ ## Inspection
96
+
97
+ Arete can inspect a prepared instruction or single-transaction operation without signing, submission, or a wallet prompt:
98
+
99
+ ```ts
100
+ const prepared = await client.operations.deploy.prepare(params);
101
+ const inspection = await client.inspectOperation(prepared, {
102
+ commitment: 'confirmed',
103
+ minContextSlot,
104
+ });
105
+
106
+ console.log(inspection.transaction.feeLamports);
107
+ console.log(inspection.transaction.logs);
108
+ console.log(inspection.transaction.computeUnitsConsumed);
109
+ console.log(inspection.transaction.contextSlot);
110
+ console.log(inspection.programError);
111
+ ```
112
+
113
+ Inspection compiles an unsigned v0 transaction, calls `getFeeForMessage`, and simulates with signature verification disabled. Arete core enriches simulation failures with the prepared operation's IDL error metadata. Multi-transaction flows are rejected by core rather than partially simulated.
114
+
115
+ ## Failure Outcomes
116
+
117
+ Adapter failures expose the structured outcome consumed by `getTransactionFailureOutcome`:
118
+
119
+ - `not-submitted`: build, missing signer, wallet rejection, unsupported v0 wallet, or definite preflight rejection.
120
+ - `submitted-unknown`: a signed transaction may have been submitted, but one status lookup could not prove the requested commitment.
121
+ - `chain-failed`: confirmation or the status lookup reports an on-chain error.
122
+
123
+ Known signatures and landed slots are preserved. After an uncertain send or confirmation error, the adapter performs one signature-status lookup and never sends the transaction again.
package/dist/index.cjs ADDED
@@ -0,0 +1,539 @@
1
+ 'use strict';
2
+
3
+ var bs58 = require('bs58');
4
+ var web3_js = require('@solana/web3.js');
5
+ var sdk = require('@usearete/sdk');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var bs58__default = /*#__PURE__*/_interopDefault(bs58);
10
+
11
+ /**
12
+ * @usearete/adapter-web3js
13
+ *
14
+ * An Arete WalletAdapter backed by @solana/web3.js. Transactions are compiled
15
+ * as v0 messages, signed once, submitted once, and then confirmed or
16
+ * classified without resubmission.
17
+ */
18
+ function connectionAccountLoader(connection) {
19
+ return {
20
+ async getAccount(address) {
21
+ const account = await connection.getAccountInfo(new web3_js.PublicKey(address), 'confirmed');
22
+ return account ? { data: new Uint8Array(account.data) } : null;
23
+ },
24
+ };
25
+ }
26
+ function toCommitment(level, fallback) {
27
+ return level ?? fallback;
28
+ }
29
+ function signerAddress(signer) {
30
+ return signer.publicKey.toBase58();
31
+ }
32
+ function collectRequiredSignerAddresses(instructions, feePayer) {
33
+ const required = new Set([feePayer.toBase58()]);
34
+ for (const instruction of instructions) {
35
+ for (const key of instruction.keys) {
36
+ if (key.isSigner) {
37
+ required.add(key.pubkey);
38
+ }
39
+ }
40
+ }
41
+ return required;
42
+ }
43
+ function indexLocalSigners(signers) {
44
+ const indexed = new Map();
45
+ for (const signer of signers) {
46
+ indexed.set(signerAddress(signer), signer);
47
+ }
48
+ return indexed;
49
+ }
50
+ function outcomeMessage(outcome) {
51
+ if (outcome.status === 'not-submitted') {
52
+ return `Transaction was not submitted during ${outcome.phase}`;
53
+ }
54
+ if (outcome.status === 'submitted-unknown') {
55
+ return `Transaction ${outcome.signature} was submitted but its status is unknown`;
56
+ }
57
+ return outcome.signature
58
+ ? `Transaction ${outcome.signature} failed on chain`
59
+ : 'Transaction failed on chain';
60
+ }
61
+ function transactionError(outcome, programError) {
62
+ const causeMessage = outcome.cause instanceof Error ? outcome.cause.message : undefined;
63
+ const error = new Error(causeMessage || outcomeMessage(outcome));
64
+ Object.defineProperties(error, {
65
+ name: { value: 'TransactionExecutionError', configurable: true },
66
+ cause: { value: outcome.cause, enumerable: true },
67
+ outcome: { value: outcome, enumerable: true },
68
+ signature: {
69
+ value: 'signature' in outcome ? outcome.signature : undefined,
70
+ enumerable: true,
71
+ },
72
+ slot: {
73
+ value: 'slot' in outcome ? outcome.slot : undefined,
74
+ enumerable: true,
75
+ },
76
+ programError: { value: programError, enumerable: true },
77
+ });
78
+ return error;
79
+ }
80
+ function customErrorCode(value, seen = new Set()) {
81
+ if (typeof value === 'string') {
82
+ const match = /custom program error:\s*0x([\da-f]+)/i.exec(value);
83
+ return match?.[1] ? Number.parseInt(match[1], 16) : undefined;
84
+ }
85
+ if (typeof value !== 'object' || value === null || seen.has(value)) {
86
+ return undefined;
87
+ }
88
+ seen.add(value);
89
+ if (Array.isArray(value)) {
90
+ for (const item of value) {
91
+ const code = customErrorCode(item, seen);
92
+ if (code !== undefined) {
93
+ return code;
94
+ }
95
+ }
96
+ return undefined;
97
+ }
98
+ const candidate = value;
99
+ if (Array.isArray(candidate.InstructionError)) {
100
+ const detail = candidate.InstructionError[1];
101
+ if (typeof detail === 'object' && detail !== null) {
102
+ const code = detail.Custom;
103
+ if (typeof code === 'number') {
104
+ return code;
105
+ }
106
+ }
107
+ }
108
+ if (typeof candidate.code === 'number') {
109
+ return candidate.code;
110
+ }
111
+ for (const key of [
112
+ 'cause',
113
+ 'error',
114
+ 'err',
115
+ 'value',
116
+ 'data',
117
+ 'message',
118
+ 'transactionMessage',
119
+ 'transactionLogs',
120
+ 'logs',
121
+ ]) {
122
+ const code = customErrorCode(candidate[key], seen);
123
+ if (code !== undefined) {
124
+ return code;
125
+ }
126
+ }
127
+ return undefined;
128
+ }
129
+ function parseProgramError(error) {
130
+ const code = customErrorCode(error);
131
+ return code === undefined
132
+ ? undefined
133
+ : {
134
+ code,
135
+ name: `CustomError${code}`,
136
+ message: `Unknown error with code ${code}`,
137
+ };
138
+ }
139
+ function signatureFromTransaction(transaction) {
140
+ const signature = transaction.signatures[0];
141
+ if (!signature || signature.every((byte) => byte === 0)) {
142
+ return undefined;
143
+ }
144
+ return bs58__default.default.encode(signature);
145
+ }
146
+ function hasAllRequiredSignatures(transaction) {
147
+ const required = transaction.message.header.numRequiredSignatures;
148
+ return transaction.signatures
149
+ .slice(0, required)
150
+ .every((signature) => signature.some((byte) => byte !== 0));
151
+ }
152
+ function commitmentRank(commitment) {
153
+ if (commitment === 'finalized' || commitment === 'max' || commitment === 'root') {
154
+ return 2;
155
+ }
156
+ if (commitment === 'confirmed'
157
+ || commitment === 'single'
158
+ || commitment === 'singleGossip') {
159
+ return 1;
160
+ }
161
+ return 0;
162
+ }
163
+ function statusRank(status) {
164
+ if (status.confirmationStatus === 'finalized' || status.confirmations === null) {
165
+ return 2;
166
+ }
167
+ if (status.confirmationStatus === 'confirmed' || (status.confirmations ?? 0) > 0) {
168
+ return 1;
169
+ }
170
+ return 0;
171
+ }
172
+ function encodeBase64(bytes) {
173
+ const bufferCtor = globalThis.Buffer;
174
+ if (bufferCtor)
175
+ return bufferCtor.from(bytes).toString('base64');
176
+ let binary = '';
177
+ for (const byte of bytes)
178
+ binary += String.fromCharCode(byte);
179
+ return btoa(binary);
180
+ }
181
+ function resolveTransport(selection, connection, context) {
182
+ if (typeof selection === 'object')
183
+ return { kind: 'arete', transport: selection };
184
+ if (selection === 'direct') {
185
+ if (!connection)
186
+ throw new Error('Web3.js direct transaction transport requires a Connection');
187
+ return { kind: 'direct', connection };
188
+ }
189
+ if (context?.transactionTransport)
190
+ return { kind: 'arete', transport: context.transactionTransport };
191
+ if (connection)
192
+ return { kind: 'direct', connection };
193
+ throw new Error('No transaction transport is available; connect through Arete or configure direct RPC');
194
+ }
195
+ async function pollAreteStatus(transport, signature, commitment, lastValidBlockHeight, options) {
196
+ const timeoutMs = options?.confirmationTimeoutMs ?? 60000;
197
+ const intervalMs = options?.statusPollIntervalMs ?? 500;
198
+ const deadline = Date.now() + timeoutMs;
199
+ let emptyStatusPolls = 0;
200
+ while (Date.now() <= deadline) {
201
+ const status = await transport.getSignatureStatus(signature, {
202
+ commitment: commitment,
203
+ searchTransactionHistory: true,
204
+ });
205
+ if (status?.err) {
206
+ throw transactionError({
207
+ status: 'chain-failed', phase: 'chain', signature,
208
+ slot: status.slot === null ? undefined : Number(status.slot),
209
+ programError: parseProgramError(status.err), cause: status.err,
210
+ });
211
+ }
212
+ if (status && commitmentRank(status.confirmationStatus) >= commitmentRank(commitment)) {
213
+ return { signature, slot: status.slot === null ? undefined : Number(status.slot) };
214
+ }
215
+ if (await transport.getBlockHeight({ commitment: commitment }) > lastValidBlockHeight) {
216
+ throw transactionError({
217
+ status: 'submitted-unknown', phase: 'confirmation', signature,
218
+ slot: status?.slot === null ? undefined : Number(status?.slot),
219
+ cause: new Error('Transaction blockhash expired before confirmation'),
220
+ });
221
+ }
222
+ emptyStatusPolls = status ? 0 : emptyStatusPolls + 1;
223
+ const delayMs = Math.min(intervalMs * (2 ** Math.min(emptyStatusPolls, 3)), 4000);
224
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
225
+ }
226
+ throw transactionError({
227
+ status: 'submitted-unknown', phase: 'confirmation', signature,
228
+ cause: new Error('Transaction confirmation timed out'),
229
+ });
230
+ }
231
+ async function resolveUncertainSubmission(connection, signature, commitment, phase, cause) {
232
+ let status = null;
233
+ try {
234
+ const response = await connection.getSignatureStatuses([signature], { searchTransactionHistory: true });
235
+ status = response.value[0] ?? null;
236
+ }
237
+ catch {
238
+ // The original submission/confirmation error remains the useful cause.
239
+ }
240
+ if (status?.err) {
241
+ throw transactionError({
242
+ status: 'chain-failed',
243
+ phase: 'chain',
244
+ signature,
245
+ slot: status.slot,
246
+ programError: parseProgramError(status.err),
247
+ cause,
248
+ });
249
+ }
250
+ if (status && statusRank(status) >= commitmentRank(commitment)) {
251
+ return { signature, slot: status.slot };
252
+ }
253
+ throw transactionError({
254
+ status: 'submitted-unknown',
255
+ phase,
256
+ signature,
257
+ slot: status?.slot,
258
+ cause,
259
+ });
260
+ }
261
+ /** Convert an Arete BuiltInstruction to a web3.js TransactionInstruction. */
262
+ function toTransactionInstruction(ix) {
263
+ return new web3_js.TransactionInstruction({
264
+ programId: new web3_js.PublicKey(ix.programId),
265
+ keys: ix.keys.map((key) => ({
266
+ pubkey: new web3_js.PublicKey(key.pubkey),
267
+ isSigner: key.isSigner,
268
+ isWritable: key.isWritable,
269
+ })),
270
+ // web3.js types this field as Buffer, but its transaction compiler consumes
271
+ // Uint8Array. Avoid importing the Node `buffer` builtin into browser apps.
272
+ data: Uint8Array.from(ix.data),
273
+ });
274
+ }
275
+ /** Convert a web3.js TransactionInstruction to an Arete BuiltInstruction. */
276
+ function fromTransactionInstruction(ix) {
277
+ return {
278
+ programId: ix.programId.toBase58(),
279
+ keys: ix.keys.map((key) => ({
280
+ pubkey: key.pubkey.toBase58(),
281
+ isSigner: key.isSigner,
282
+ isWritable: key.isWritable,
283
+ })),
284
+ data: new Uint8Array(ix.data),
285
+ };
286
+ }
287
+ /** Create a WalletAdapter from a connection and a v0-capable signer. */
288
+ function createWalletAdapter(config) {
289
+ const { signer } = config;
290
+ const configuredLocalSigners = config.additionalSigners ?? [];
291
+ const fallbackCommitment = config.defaultCommitment ?? 'confirmed';
292
+ const signerAddresses = [
293
+ signer.publicKey.toBase58(),
294
+ ...configuredLocalSigners.map(signerAddress),
295
+ ];
296
+ return {
297
+ publicKey: signer.publicKey.toBase58(),
298
+ signerAddresses: [...new Set(signerAddresses)],
299
+ async inspectTransaction(instructions, options, context) {
300
+ if (instructions.length === 0) {
301
+ throw new Error('inspectTransaction requires at least one instruction');
302
+ }
303
+ const commitment = options?.commitment ?? fallbackCommitment;
304
+ const feePayer = options?.feePayer ?? signer.publicKey;
305
+ const resolved = resolveTransport(config.transport, config.connection, context);
306
+ if (resolved.kind === 'arete') {
307
+ const latest = await resolved.transport.getLatestBlockhash({
308
+ commitment: commitment,
309
+ minContextSlot: options?.minContextSlot === undefined ? undefined : BigInt(options.minContextSlot),
310
+ });
311
+ const message = new web3_js.TransactionMessage({
312
+ payerKey: feePayer,
313
+ recentBlockhash: latest.blockhash,
314
+ instructions: instructions.map(toTransactionInstruction),
315
+ }).compileToV0Message();
316
+ const transaction = new web3_js.VersionedTransaction(message);
317
+ const [fee, simulation] = await Promise.all([
318
+ resolved.transport.getFeeForMessage(encodeBase64(message.serialize()), {
319
+ commitment: commitment,
320
+ minContextSlot: options?.minContextSlot === undefined ? undefined : BigInt(options.minContextSlot),
321
+ }),
322
+ resolved.transport.simulateTransaction(encodeBase64(transaction.serialize()), {
323
+ commitment: commitment,
324
+ minContextSlot: options?.minContextSlot === undefined ? undefined : BigInt(options.minContextSlot),
325
+ accounts: options?.accounts,
326
+ innerInstructions: options?.innerInstructions,
327
+ }),
328
+ ]);
329
+ return {
330
+ feeLamports: fee.feeLamports === null ? undefined : Number(fee.feeLamports),
331
+ feeContextSlot: Number(fee.contextSlot), logs: simulation.logs ?? undefined,
332
+ computeUnitsConsumed: simulation.unitsConsumed === undefined ? undefined : Number(simulation.unitsConsumed),
333
+ contextSlot: Number(simulation.contextSlot), error: simulation.err ?? undefined,
334
+ programError: parseProgramError(simulation.err),
335
+ };
336
+ }
337
+ const connection = resolved.connection;
338
+ const { blockhash } = await connection.getLatestBlockhash(commitment);
339
+ const message = new web3_js.TransactionMessage({
340
+ payerKey: feePayer,
341
+ recentBlockhash: blockhash,
342
+ instructions: instructions.map(toTransactionInstruction),
343
+ }).compileToV0Message();
344
+ const transaction = new web3_js.VersionedTransaction(message);
345
+ const [fee, simulation] = await Promise.all([
346
+ connection.getFeeForMessage(message, commitment),
347
+ connection.simulateTransaction(transaction, {
348
+ commitment,
349
+ sigVerify: false,
350
+ replaceRecentBlockhash: false,
351
+ minContextSlot: options?.minContextSlot,
352
+ innerInstructions: options?.innerInstructions,
353
+ accounts: options?.accounts
354
+ ? { encoding: 'base64', addresses: [...options.accounts] }
355
+ : undefined,
356
+ }),
357
+ ]);
358
+ return {
359
+ feeLamports: fee.value ?? undefined,
360
+ feeContextSlot: fee.context.slot,
361
+ logs: simulation.value.logs ?? undefined,
362
+ computeUnitsConsumed: simulation.value.unitsConsumed,
363
+ contextSlot: simulation.context.slot,
364
+ error: simulation.value.err ?? undefined,
365
+ programError: parseProgramError(simulation.value.err),
366
+ };
367
+ },
368
+ async signAndSend(instructions, options, context) {
369
+ const sendOptions = options;
370
+ let transaction;
371
+ let blockhash;
372
+ let lastValidBlockHeight;
373
+ let requiredSignerAddresses;
374
+ let localSigners;
375
+ const commitment = toCommitment(options?.confirmationLevel, fallbackCommitment);
376
+ let resolved;
377
+ try {
378
+ resolved = resolveTransport(config.transport, config.connection, context);
379
+ }
380
+ catch (cause) {
381
+ throw transactionError({ status: 'not-submitted', phase: 'build', cause });
382
+ }
383
+ const feePayer = sendOptions?.feePayer ?? signer;
384
+ const primarySignerAddress = signerAddress(signer);
385
+ try {
386
+ if (instructions.length === 0) {
387
+ throw new Error('signAndSend requires at least one instruction');
388
+ }
389
+ requiredSignerAddresses = collectRequiredSignerAddresses(instructions, feePayer.publicKey);
390
+ const localSignerMap = indexLocalSigners([
391
+ ...configuredLocalSigners,
392
+ ...(sendOptions?.signers ?? []),
393
+ ...(sendOptions?.additionalSigners ?? []),
394
+ ...(sendOptions?.feePayer ? [sendOptions.feePayer] : []),
395
+ ]);
396
+ const missingSignerAddresses = [...requiredSignerAddresses].filter((address) => address !== primarySignerAddress && !localSignerMap.has(address));
397
+ if (missingSignerAddresses.length > 0) {
398
+ throw new Error(`Missing signer(s) for transaction: ${missingSignerAddresses.join(', ')}`);
399
+ }
400
+ localSigners = [...requiredSignerAddresses]
401
+ .filter((address) => address !== primarySignerAddress)
402
+ .map((address) => localSignerMap.get(address))
403
+ .filter((candidate, index, all) => all.indexOf(candidate) === index);
404
+ const latestBlockhash = resolved.kind === 'arete'
405
+ ? await resolved.transport.getLatestBlockhash({ commitment: commitment })
406
+ : await resolved.connection.getLatestBlockhash(commitment);
407
+ blockhash = latestBlockhash.blockhash;
408
+ lastValidBlockHeight = Number(latestBlockhash.lastValidBlockHeight);
409
+ const message = new web3_js.TransactionMessage({
410
+ payerKey: feePayer.publicKey,
411
+ recentBlockhash: blockhash,
412
+ instructions: instructions.map(toTransactionInstruction),
413
+ }).compileToV0Message();
414
+ transaction = new web3_js.VersionedTransaction(message);
415
+ }
416
+ catch (cause) {
417
+ throw transactionError({ status: 'not-submitted', phase: 'build', cause });
418
+ }
419
+ try {
420
+ if (localSigners.length > 0) {
421
+ transaction.sign(localSigners);
422
+ }
423
+ if (requiredSignerAddresses.has(primarySignerAddress)) {
424
+ const supportedVersions = signer.supportedTransactionVersions;
425
+ if (supportedVersions === null || (supportedVersions && !supportedVersions.has(0))) {
426
+ throw new Error('The configured wallet does not support v0 VersionedTransaction signing');
427
+ }
428
+ const signed = await signer.signTransaction(transaction);
429
+ if (!signed || typeof signed.serialize !== 'function') {
430
+ throw new Error('The configured wallet did not return a signed v0 VersionedTransaction');
431
+ }
432
+ // Wallet adapters can use a different web3.js module instance, making
433
+ // instanceof checks reject otherwise valid signed transactions.
434
+ transaction = web3_js.VersionedTransaction.deserialize(signed.serialize());
435
+ }
436
+ if (!hasAllRequiredSignatures(transaction)) {
437
+ throw new Error('The configured signers did not provide every required signature');
438
+ }
439
+ }
440
+ catch (cause) {
441
+ throw transactionError({ status: 'not-submitted', phase: 'wallet', cause });
442
+ }
443
+ const localSignature = signatureFromTransaction(transaction);
444
+ if (resolved.kind === 'arete') {
445
+ let signature;
446
+ try {
447
+ const sent = await resolved.transport.sendTransaction(encodeBase64(transaction.serialize()), {
448
+ skipPreflight: options?.skipPreflight ?? false,
449
+ preflightCommitment: commitment,
450
+ });
451
+ signature = sent.signature;
452
+ }
453
+ catch (cause) {
454
+ if (cause instanceof sdk.TransactionTransportError && cause.submissionState === 'not_submitted') {
455
+ throw transactionError({ status: 'not-submitted', phase: 'send', cause });
456
+ }
457
+ throw transactionError({
458
+ status: 'submitted-unknown', phase: 'send',
459
+ signature: cause instanceof sdk.TransactionTransportError && cause.signature
460
+ ? cause.signature : localSignature,
461
+ cause,
462
+ });
463
+ }
464
+ try {
465
+ return await pollAreteStatus(resolved.transport, signature, commitment, BigInt(lastValidBlockHeight), options);
466
+ }
467
+ catch (cause) {
468
+ if (typeof cause === 'object' && cause !== null && 'outcome' in cause)
469
+ throw cause;
470
+ throw transactionError({
471
+ status: 'submitted-unknown', phase: 'confirmation', signature, cause,
472
+ });
473
+ }
474
+ }
475
+ const connection = resolved.connection;
476
+ let signature;
477
+ try {
478
+ signature = await connection.sendRawTransaction(transaction.serialize(), {
479
+ skipPreflight: options?.skipPreflight ?? false,
480
+ preflightCommitment: commitment,
481
+ });
482
+ }
483
+ catch (cause) {
484
+ if (cause instanceof web3_js.SendTransactionError) {
485
+ throw transactionError({ status: 'not-submitted', phase: 'send', cause }, parseProgramError(cause));
486
+ }
487
+ return resolveUncertainSubmission(connection, localSignature, commitment, 'send', cause);
488
+ }
489
+ try {
490
+ const confirmation = await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight }, commitment);
491
+ if (confirmation.value.err) {
492
+ throw transactionError({
493
+ status: 'chain-failed',
494
+ phase: 'chain',
495
+ signature,
496
+ slot: confirmation.context.slot,
497
+ programError: parseProgramError(confirmation.value.err),
498
+ cause: confirmation.value.err,
499
+ });
500
+ }
501
+ return { signature, slot: confirmation.context.slot };
502
+ }
503
+ catch (cause) {
504
+ if (typeof cause === 'object'
505
+ && cause !== null
506
+ && 'outcome' in cause
507
+ && cause.outcome?.status === 'chain-failed') {
508
+ throw cause;
509
+ }
510
+ return resolveUncertainSubmission(connection, signature, commitment, 'confirmation', cause);
511
+ }
512
+ },
513
+ };
514
+ }
515
+ /** Create a WalletAdapter backed by a local Keypair. */
516
+ function createKeypairWalletAdapter(config) {
517
+ const { connection, transport, keypair, additionalSigners, defaultCommitment } = config;
518
+ return createWalletAdapter({
519
+ connection,
520
+ transport,
521
+ additionalSigners,
522
+ defaultCommitment,
523
+ signer: {
524
+ publicKey: keypair.publicKey,
525
+ supportedTransactionVersions: new Set([0]),
526
+ async signTransaction(tx) {
527
+ tx.sign([keypair]);
528
+ return tx;
529
+ },
530
+ },
531
+ });
532
+ }
533
+
534
+ exports.connectionAccountLoader = connectionAccountLoader;
535
+ exports.createKeypairWalletAdapter = createKeypairWalletAdapter;
536
+ exports.createWalletAdapter = createWalletAdapter;
537
+ exports.fromTransactionInstruction = fromTransactionInstruction;
538
+ exports.toTransactionInstruction = toTransactionInstruction;
539
+ //# sourceMappingURL=index.cjs.map