@solana/kora 0.2.1 → 0.3.0-beta.2

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.
@@ -1,10 +1,21 @@
1
- import { Config, EstimateTransactionFeeRequest, EstimateTransactionFeeResponse, GetBlockhashResponse, GetPayerSignerResponse, GetPaymentInstructionRequest, GetPaymentInstructionResponse, GetSupportedTokensResponse, KoraClientOptions, SignAndSendTransactionRequest, SignAndSendTransactionResponse, SignTransactionRequest, SignTransactionResponse, TransferTransactionRequest, TransferTransactionResponse } from './types/index.js';
1
+ import { Config, EstimateBundleFeeRequest, EstimateBundleFeeResponse, EstimateTransactionFeeRequest, EstimateTransactionFeeResponse, GetBlockhashResponse, GetPayerSignerResponse, GetPaymentInstructionRequest, GetPaymentInstructionResponse, GetSupportedTokensResponse, GetVersionResponse, KoraClientOptions, SignAndSendBundleRequest, SignAndSendBundleResponse, SignAndSendTransactionRequest, SignAndSendTransactionResponse, SignBundleRequest, SignBundleResponse, SignTransactionRequest, SignTransactionResponse } from './types/index.js';
2
2
  /**
3
3
  * Kora RPC client for interacting with the Kora paymaster service.
4
4
  *
5
- * @example
5
+ * Provides methods to estimate fees, sign transactions, and perform gasless transfers
6
+ * on Solana as specified by the Kora paymaster operator.
7
+ *
8
+ * @example Kora Initialization
6
9
  * ```typescript
7
- * const client = new KoraClient({ rpcUrl: 'http://localhost:8080' });
10
+ * const client = new KoraClient({
11
+ * rpcUrl: 'http://localhost:8080',
12
+ * // apiKey may be required by some operators
13
+ * // apiKey: 'your-api-key',
14
+ * // hmacSecret may be required by some operators
15
+ * // hmacSecret: 'your-hmac-secret'
16
+ * });
17
+ *
18
+ * // Sample usage: Get config
8
19
  * const config = await client.getConfig();
9
20
  * ```
10
21
  */
@@ -12,21 +23,215 @@ export declare class KoraClient {
12
23
  private rpcUrl;
13
24
  private apiKey?;
14
25
  private hmacSecret?;
15
- constructor({ rpcUrl, apiKey, hmacSecret }: KoraClientOptions);
26
+ private getRecaptchaToken?;
27
+ /**
28
+ * Creates a new Kora client instance.
29
+ * @param options - Client configuration options
30
+ * @param options.rpcUrl - The Kora RPC server URL
31
+ * @param options.apiKey - Optional API key for authentication
32
+ * @param options.hmacSecret - Optional HMAC secret for signature-based authentication
33
+ * @param options.getRecaptchaToken - Optional callback to get reCAPTCHA token for bot protection
34
+ */
35
+ constructor({ rpcUrl, apiKey, hmacSecret, getRecaptchaToken }: KoraClientOptions);
16
36
  private getHmacSignature;
17
37
  private getHeaders;
18
38
  private rpcRequest;
39
+ /**
40
+ * Retrieves the current Kora server configuration.
41
+ * @returns The server configuration including fee payer address and validation rules
42
+ * @throws {Error} When the RPC call fails
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const config = await client.getConfig();
47
+ * console.log('Fee payer:', config.fee_payer);
48
+ * console.log('Validation config:', JSON.stringify(config.validation_config, null, 2));
49
+ * ```
50
+ */
19
51
  getConfig(): Promise<Config>;
52
+ /**
53
+ * Retrieves the payer signer and payment destination from the Kora server.
54
+ * @returns Object containing the payer signer and payment destination
55
+ * @throws {Error} When the RPC call fails
56
+ *
57
+ * @example
58
+ */
20
59
  getPayerSigner(): Promise<GetPayerSignerResponse>;
60
+ /**
61
+ * Gets the latest blockhash from the Solana RPC that the Kora server is connected to.
62
+ * @returns Object containing the current blockhash
63
+ * @throws {Error} When the RPC call fails
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const { blockhash } = await client.getBlockhash();
68
+ * console.log('Current blockhash:', blockhash);
69
+ * ```
70
+ */
21
71
  getBlockhash(): Promise<GetBlockhashResponse>;
72
+ /**
73
+ * Gets the version of the Kora server.
74
+ * @returns Object containing the server version
75
+ * @throws {Error} When the RPC call fails
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const { version } = await client.getVersion();
80
+ * console.log('Server version:', version);
81
+ * ```
82
+ */
83
+ getVersion(): Promise<GetVersionResponse>;
84
+ /**
85
+ * Retrieves the list of tokens supported for fee payment.
86
+ * @returns Object containing an array of supported token mint addresses
87
+ * @throws {Error} When the RPC call fails
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const { tokens } = await client.getSupportedTokens();
92
+ * console.log('Supported tokens:', tokens);
93
+ * // Output: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', ...]
94
+ * ```
95
+ */
22
96
  getSupportedTokens(): Promise<GetSupportedTokensResponse>;
97
+ /**
98
+ * Estimates the transaction fee in both lamports and the specified token.
99
+ * @param request - Fee estimation request parameters
100
+ * @param request.transaction - Base64-encoded transaction to estimate fees for
101
+ * @param request.fee_token - Mint address of the token to calculate fees in
102
+ * @returns Fee amounts in both lamports and the specified token
103
+ * @throws {Error} When the RPC call fails, the transaction is invalid, or the token is not supported
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * const fees = await client.estimateTransactionFee({
108
+ * transaction: 'base64EncodedTransaction',
109
+ * fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
110
+ * });
111
+ * console.log('Fee in lamports:', fees.fee_in_lamports);
112
+ * console.log('Fee in USDC:', fees.fee_in_token);
113
+ * ```
114
+ */
23
115
  estimateTransactionFee(request: EstimateTransactionFeeRequest): Promise<EstimateTransactionFeeResponse>;
116
+ /**
117
+ * Estimates the bundle fee in both lamports and the specified token.
118
+ * @param request - Bundle fee estimation request parameters
119
+ * @param request.transactions - Array of base64-encoded transactions to estimate fees for
120
+ * @param request.fee_token - Mint address of the token to calculate fees in
121
+ * @returns Total fee amounts across all transactions in both lamports and the specified token
122
+ * @throws {Error} When the RPC call fails, the bundle is invalid, or the token is not supported
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const fees = await client.estimateBundleFee({
127
+ * transactions: ['base64EncodedTransaction1', 'base64EncodedTransaction2'],
128
+ * fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
129
+ * });
130
+ * console.log('Total fee in lamports:', fees.fee_in_lamports);
131
+ * console.log('Total fee in USDC:', fees.fee_in_token);
132
+ * ```
133
+ */
134
+ estimateBundleFee(request: EstimateBundleFeeRequest): Promise<EstimateBundleFeeResponse>;
135
+ /**
136
+ * Signs a transaction with the Kora fee payer without broadcasting it.
137
+ * @param request - Sign request parameters
138
+ * @param request.transaction - Base64-encoded transaction to sign
139
+ * @returns Signature and the signed transaction
140
+ * @throws {Error} When the RPC call fails or transaction validation fails
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const result = await client.signTransaction({
145
+ * transaction: 'base64EncodedTransaction'
146
+ * });
147
+ * console.log('Signature:', result.signature);
148
+ * console.log('Signed tx:', result.signed_transaction);
149
+ * ```
150
+ */
24
151
  signTransaction(request: SignTransactionRequest): Promise<SignTransactionResponse>;
152
+ /**
153
+ * Signs a transaction and immediately broadcasts it to the Solana network.
154
+ * @param request - Sign and send request parameters
155
+ * @param request.transaction - Base64-encoded transaction to sign and send
156
+ * @param request.respond_after - The lifecycle milestone to wait for before
157
+ * responding (defaults to `'confirmed'`): `'confirmed'` waits for on-chain confirmation,
158
+ * `'sent'` returns once the RPC node accepts the transaction, `'signed'` returns as soon
159
+ * as signing completes and broadcasts in the background (broadcast failures are logged
160
+ * server-side; rebroadcast the returned signed transaction if it never lands)
161
+ * @returns Signature and the signed transaction
162
+ * @throws {Error} When the RPC call fails, validation fails, or broadcast fails
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const result = await client.signAndSendTransaction({
167
+ * transaction: 'base64EncodedTransaction'
168
+ * });
169
+ * console.log('Transaction signature:', result.signature);
170
+ *
171
+ * // Lowest latency: return as soon as signing completes
172
+ * const fast = await client.signAndSendTransaction({
173
+ * transaction: 'base64EncodedTransaction',
174
+ * respond_after: 'signed'
175
+ * });
176
+ * ```
177
+ */
25
178
  signAndSendTransaction(request: SignAndSendTransactionRequest): Promise<SignAndSendTransactionResponse>;
26
- transferTransaction(request: TransferTransactionRequest): Promise<TransferTransactionResponse>;
27
179
  /**
28
- * Estimates the fee and builds a payment transfer instruction from the source wallet
29
- * to the Kora payment address. The server handles decimal conversion internally.
180
+ * Signs a bundle of transactions with the Kora fee payer without broadcasting.
181
+ * @param request - Sign bundle request parameters
182
+ * @param request.transactions - Array of base64-encoded transactions to sign
183
+ * @param request.signer_key - Optional signer address for the transactions
184
+ * @param request.sig_verify - Optional signature verification (defaults to false)
185
+ * @param request.sign_only_indices - Optional indices of transactions to sign (defaults to all)
186
+ * @returns Array of signed transactions and signer public key
187
+ * @throws {Error} When the RPC call fails or validation fails
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * const result = await client.signBundle({
192
+ * transactions: ['base64Tx1', 'base64Tx2']
193
+ * });
194
+ * console.log('Signed transactions:', result.signed_transactions);
195
+ * console.log('Signer:', result.signer_pubkey);
196
+ * ```
197
+ */
198
+ signBundle(request: SignBundleRequest): Promise<SignBundleResponse>;
199
+ /**
200
+ * Signs a bundle of transactions and sends them to Jito block engine.
201
+ * @param request - Sign and send bundle request parameters
202
+ * @param request.transactions - Array of base64-encoded transactions to sign and send
203
+ * @param request.signer_key - Optional signer address for the transactions
204
+ * @param request.sig_verify - Optional signature verification (defaults to false)
205
+ * @param request.sign_only_indices - Optional indices of transactions to sign (defaults to all)
206
+ * @returns Array of signed transactions, signer public key, and Jito bundle UUID
207
+ * @throws {Error} When the RPC call fails, validation fails, or Jito submission fails
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * const result = await client.signAndSendBundle({
212
+ * transactions: ['base64Tx1', 'base64Tx2']
213
+ * });
214
+ * console.log('Bundle UUID:', result.bundle_uuid);
215
+ * console.log('Signed transactions:', result.signed_transactions);
216
+ * ```
217
+ */
218
+ signAndSendBundle(request: SignAndSendBundleRequest): Promise<SignAndSendBundleResponse>;
219
+ /**
220
+ * Creates a payment instruction to append to a transaction for fee payment to the Kora paymaster.
221
+ *
222
+ * This method estimates the required fee and generates a token transfer instruction
223
+ * from the source wallet to the Kora payment address. The server handles decimal
224
+ * conversion internally, so the raw token amount is used directly.
225
+ *
226
+ * @param request - Payment instruction request parameters
227
+ * @param request.transaction - Base64-encoded transaction to estimate fees for
228
+ * @param request.fee_token - Mint address of the token to use for payment
229
+ * @param request.source_wallet - Public key of the wallet paying the fees
230
+ * @param request.token_program_id - Optional token program ID (defaults to TOKEN_PROGRAM_ADDRESS)
231
+ * @param request.signer_key - Optional signer address for the transaction
232
+ * @param request.sig_verify - Optional signer verification during transaction simulation (defaults to false)
233
+ * @returns Payment instruction details including the instruction, amount, and addresses
234
+ * @throws {Error} When the token is not supported, payment is not required, or invalid addresses are provided
30
235
  *
31
236
  * @example
32
237
  * ```typescript
@@ -1,13 +1,24 @@
1
1
  import { assertIsAddress, isTransactionSigner } from '@solana/kit';
2
2
  import { findAssociatedTokenPda, getTransferInstruction, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
3
3
  import crypto from 'crypto';
4
- import { getInstructionsFromBase64Message } from './utils/transaction.js';
4
+ import { KoraError } from './error.js';
5
5
  /**
6
6
  * Kora RPC client for interacting with the Kora paymaster service.
7
7
  *
8
- * @example
8
+ * Provides methods to estimate fees, sign transactions, and perform gasless transfers
9
+ * on Solana as specified by the Kora paymaster operator.
10
+ *
11
+ * @example Kora Initialization
9
12
  * ```typescript
10
- * const client = new KoraClient({ rpcUrl: 'http://localhost:8080' });
13
+ * const client = new KoraClient({
14
+ * rpcUrl: 'http://localhost:8080',
15
+ * // apiKey may be required by some operators
16
+ * // apiKey: 'your-api-key',
17
+ * // hmacSecret may be required by some operators
18
+ * // hmacSecret: 'your-hmac-secret'
19
+ * });
20
+ *
21
+ * // Sample usage: Get config
11
22
  * const config = await client.getConfig();
12
23
  * ```
13
24
  */
@@ -15,10 +26,20 @@ export class KoraClient {
15
26
  rpcUrl;
16
27
  apiKey;
17
28
  hmacSecret;
18
- constructor({ rpcUrl, apiKey, hmacSecret }) {
29
+ getRecaptchaToken;
30
+ /**
31
+ * Creates a new Kora client instance.
32
+ * @param options - Client configuration options
33
+ * @param options.rpcUrl - The Kora RPC server URL
34
+ * @param options.apiKey - Optional API key for authentication
35
+ * @param options.hmacSecret - Optional HMAC secret for signature-based authentication
36
+ * @param options.getRecaptchaToken - Optional callback to get reCAPTCHA token for bot protection
37
+ */
38
+ constructor({ rpcUrl, apiKey, hmacSecret, getRecaptchaToken }) {
19
39
  this.rpcUrl = rpcUrl;
20
40
  this.apiKey = apiKey;
21
41
  this.hmacSecret = hmacSecret;
42
+ this.getRecaptchaToken = getRecaptchaToken;
22
43
  }
23
44
  getHmacSignature({ timestamp, body }) {
24
45
  if (!this.hmacSecret) {
@@ -27,7 +48,7 @@ export class KoraClient {
27
48
  const message = timestamp + body;
28
49
  return crypto.createHmac('sha256', this.hmacSecret).update(message).digest('hex');
29
50
  }
30
- getHeaders({ body }) {
51
+ async getHeaders({ body }) {
31
52
  const headers = {};
32
53
  if (this.apiKey) {
33
54
  headers['x-api-key'] = this.apiKey;
@@ -38,6 +59,10 @@ export class KoraClient {
38
59
  headers['x-timestamp'] = timestamp;
39
60
  headers['x-hmac-signature'] = signature;
40
61
  }
62
+ if (this.getRecaptchaToken) {
63
+ const token = await Promise.resolve(this.getRecaptchaToken());
64
+ headers['x-recaptcha-token'] = token;
65
+ }
41
66
  return headers;
42
67
  }
43
68
  async rpcRequest(method, params) {
@@ -47,7 +72,7 @@ export class KoraClient {
47
72
  method,
48
73
  params,
49
74
  });
50
- const headers = this.getHeaders({ body });
75
+ const headers = await this.getHeaders({ body });
51
76
  const response = await fetch(this.rpcUrl, {
52
77
  body,
53
78
  headers: { ...headers, 'Content-Type': 'application/json' },
@@ -55,40 +80,229 @@ export class KoraClient {
55
80
  });
56
81
  const json = (await response.json());
57
82
  if (json.error) {
58
- const error = json.error;
59
- throw new Error(`RPC Error ${error.code}: ${error.message}`);
83
+ const { code, message, data } = json.error;
84
+ throw new KoraError(code, message, data);
60
85
  }
61
86
  return json.result;
62
87
  }
88
+ /**
89
+ * Retrieves the current Kora server configuration.
90
+ * @returns The server configuration including fee payer address and validation rules
91
+ * @throws {Error} When the RPC call fails
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const config = await client.getConfig();
96
+ * console.log('Fee payer:', config.fee_payer);
97
+ * console.log('Validation config:', JSON.stringify(config.validation_config, null, 2));
98
+ * ```
99
+ */
63
100
  async getConfig() {
64
101
  return await this.rpcRequest('getConfig', undefined);
65
102
  }
103
+ /**
104
+ * Retrieves the payer signer and payment destination from the Kora server.
105
+ * @returns Object containing the payer signer and payment destination
106
+ * @throws {Error} When the RPC call fails
107
+ *
108
+ * @example
109
+ */
66
110
  async getPayerSigner() {
67
111
  return await this.rpcRequest('getPayerSigner', undefined);
68
112
  }
113
+ /**
114
+ * Gets the latest blockhash from the Solana RPC that the Kora server is connected to.
115
+ * @returns Object containing the current blockhash
116
+ * @throws {Error} When the RPC call fails
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const { blockhash } = await client.getBlockhash();
121
+ * console.log('Current blockhash:', blockhash);
122
+ * ```
123
+ */
69
124
  async getBlockhash() {
70
125
  return await this.rpcRequest('getBlockhash', undefined);
71
126
  }
127
+ /**
128
+ * Gets the version of the Kora server.
129
+ * @returns Object containing the server version
130
+ * @throws {Error} When the RPC call fails
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const { version } = await client.getVersion();
135
+ * console.log('Server version:', version);
136
+ * ```
137
+ */
138
+ async getVersion() {
139
+ return await this.rpcRequest('getVersion', undefined);
140
+ }
141
+ /**
142
+ * Retrieves the list of tokens supported for fee payment.
143
+ * @returns Object containing an array of supported token mint addresses
144
+ * @throws {Error} When the RPC call fails
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const { tokens } = await client.getSupportedTokens();
149
+ * console.log('Supported tokens:', tokens);
150
+ * // Output: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', ...]
151
+ * ```
152
+ */
72
153
  async getSupportedTokens() {
73
154
  return await this.rpcRequest('getSupportedTokens', undefined);
74
155
  }
156
+ /**
157
+ * Estimates the transaction fee in both lamports and the specified token.
158
+ * @param request - Fee estimation request parameters
159
+ * @param request.transaction - Base64-encoded transaction to estimate fees for
160
+ * @param request.fee_token - Mint address of the token to calculate fees in
161
+ * @returns Fee amounts in both lamports and the specified token
162
+ * @throws {Error} When the RPC call fails, the transaction is invalid, or the token is not supported
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const fees = await client.estimateTransactionFee({
167
+ * transaction: 'base64EncodedTransaction',
168
+ * fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
169
+ * });
170
+ * console.log('Fee in lamports:', fees.fee_in_lamports);
171
+ * console.log('Fee in USDC:', fees.fee_in_token);
172
+ * ```
173
+ */
75
174
  async estimateTransactionFee(request) {
76
175
  return await this.rpcRequest('estimateTransactionFee', request);
77
176
  }
177
+ /**
178
+ * Estimates the bundle fee in both lamports and the specified token.
179
+ * @param request - Bundle fee estimation request parameters
180
+ * @param request.transactions - Array of base64-encoded transactions to estimate fees for
181
+ * @param request.fee_token - Mint address of the token to calculate fees in
182
+ * @returns Total fee amounts across all transactions in both lamports and the specified token
183
+ * @throws {Error} When the RPC call fails, the bundle is invalid, or the token is not supported
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const fees = await client.estimateBundleFee({
188
+ * transactions: ['base64EncodedTransaction1', 'base64EncodedTransaction2'],
189
+ * fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
190
+ * });
191
+ * console.log('Total fee in lamports:', fees.fee_in_lamports);
192
+ * console.log('Total fee in USDC:', fees.fee_in_token);
193
+ * ```
194
+ */
195
+ async estimateBundleFee(request) {
196
+ return await this.rpcRequest('estimateBundleFee', request);
197
+ }
198
+ /**
199
+ * Signs a transaction with the Kora fee payer without broadcasting it.
200
+ * @param request - Sign request parameters
201
+ * @param request.transaction - Base64-encoded transaction to sign
202
+ * @returns Signature and the signed transaction
203
+ * @throws {Error} When the RPC call fails or transaction validation fails
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * const result = await client.signTransaction({
208
+ * transaction: 'base64EncodedTransaction'
209
+ * });
210
+ * console.log('Signature:', result.signature);
211
+ * console.log('Signed tx:', result.signed_transaction);
212
+ * ```
213
+ */
78
214
  async signTransaction(request) {
79
215
  return await this.rpcRequest('signTransaction', request);
80
216
  }
217
+ /**
218
+ * Signs a transaction and immediately broadcasts it to the Solana network.
219
+ * @param request - Sign and send request parameters
220
+ * @param request.transaction - Base64-encoded transaction to sign and send
221
+ * @param request.respond_after - The lifecycle milestone to wait for before
222
+ * responding (defaults to `'confirmed'`): `'confirmed'` waits for on-chain confirmation,
223
+ * `'sent'` returns once the RPC node accepts the transaction, `'signed'` returns as soon
224
+ * as signing completes and broadcasts in the background (broadcast failures are logged
225
+ * server-side; rebroadcast the returned signed transaction if it never lands)
226
+ * @returns Signature and the signed transaction
227
+ * @throws {Error} When the RPC call fails, validation fails, or broadcast fails
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const result = await client.signAndSendTransaction({
232
+ * transaction: 'base64EncodedTransaction'
233
+ * });
234
+ * console.log('Transaction signature:', result.signature);
235
+ *
236
+ * // Lowest latency: return as soon as signing completes
237
+ * const fast = await client.signAndSendTransaction({
238
+ * transaction: 'base64EncodedTransaction',
239
+ * respond_after: 'signed'
240
+ * });
241
+ * ```
242
+ */
81
243
  async signAndSendTransaction(request) {
82
244
  return await this.rpcRequest('signAndSendTransaction', request);
83
245
  }
84
- async transferTransaction(request) {
85
- const response = await this.rpcRequest('transferTransaction', request);
86
- response.instructions = getInstructionsFromBase64Message(response.message || '');
87
- return response;
246
+ /**
247
+ * Signs a bundle of transactions with the Kora fee payer without broadcasting.
248
+ * @param request - Sign bundle request parameters
249
+ * @param request.transactions - Array of base64-encoded transactions to sign
250
+ * @param request.signer_key - Optional signer address for the transactions
251
+ * @param request.sig_verify - Optional signature verification (defaults to false)
252
+ * @param request.sign_only_indices - Optional indices of transactions to sign (defaults to all)
253
+ * @returns Array of signed transactions and signer public key
254
+ * @throws {Error} When the RPC call fails or validation fails
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * const result = await client.signBundle({
259
+ * transactions: ['base64Tx1', 'base64Tx2']
260
+ * });
261
+ * console.log('Signed transactions:', result.signed_transactions);
262
+ * console.log('Signer:', result.signer_pubkey);
263
+ * ```
264
+ */
265
+ async signBundle(request) {
266
+ return await this.rpcRequest('signBundle', request);
88
267
  }
89
268
  /**
90
- * Estimates the fee and builds a payment transfer instruction from the source wallet
91
- * to the Kora payment address. The server handles decimal conversion internally.
269
+ * Signs a bundle of transactions and sends them to Jito block engine.
270
+ * @param request - Sign and send bundle request parameters
271
+ * @param request.transactions - Array of base64-encoded transactions to sign and send
272
+ * @param request.signer_key - Optional signer address for the transactions
273
+ * @param request.sig_verify - Optional signature verification (defaults to false)
274
+ * @param request.sign_only_indices - Optional indices of transactions to sign (defaults to all)
275
+ * @returns Array of signed transactions, signer public key, and Jito bundle UUID
276
+ * @throws {Error} When the RPC call fails, validation fails, or Jito submission fails
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * const result = await client.signAndSendBundle({
281
+ * transactions: ['base64Tx1', 'base64Tx2']
282
+ * });
283
+ * console.log('Bundle UUID:', result.bundle_uuid);
284
+ * console.log('Signed transactions:', result.signed_transactions);
285
+ * ```
286
+ */
287
+ async signAndSendBundle(request) {
288
+ return await this.rpcRequest('signAndSendBundle', request);
289
+ }
290
+ /**
291
+ * Creates a payment instruction to append to a transaction for fee payment to the Kora paymaster.
292
+ *
293
+ * This method estimates the required fee and generates a token transfer instruction
294
+ * from the source wallet to the Kora payment address. The server handles decimal
295
+ * conversion internally, so the raw token amount is used directly.
296
+ *
297
+ * @param request - Payment instruction request parameters
298
+ * @param request.transaction - Base64-encoded transaction to estimate fees for
299
+ * @param request.fee_token - Mint address of the token to use for payment
300
+ * @param request.source_wallet - Public key of the wallet paying the fees
301
+ * @param request.token_program_id - Optional token program ID (defaults to TOKEN_PROGRAM_ADDRESS)
302
+ * @param request.signer_key - Optional signer address for the transaction
303
+ * @param request.sig_verify - Optional signer verification during transaction simulation (defaults to false)
304
+ * @returns Payment instruction details including the instruction, amount, and addresses
305
+ * @throws {Error} When the token is not supported, payment is not required, or invalid addresses are provided
92
306
  *
93
307
  * @example
94
308
  * ```typescript
@@ -101,8 +315,8 @@ export class KoraClient {
101
315
  * ```
102
316
  */
103
317
  async getPaymentInstruction({ transaction, fee_token, source_wallet, token_program_id = TOKEN_PROGRAM_ADDRESS, signer_key, sig_verify, }) {
104
- const sourceIsSigner = typeof source_wallet !== 'string' && isTransactionSigner(source_wallet);
105
- const walletAddress = sourceIsSigner ? source_wallet.address : source_wallet;
318
+ const isSigner = typeof source_wallet !== 'string' && isTransactionSigner(source_wallet);
319
+ const walletAddress = isSigner ? source_wallet.address : source_wallet;
106
320
  assertIsAddress(walletAddress);
107
321
  assertIsAddress(fee_token);
108
322
  assertIsAddress(token_program_id);
@@ -123,9 +337,12 @@ export class KoraClient {
123
337
  owner: payment_address,
124
338
  tokenProgram: token_program_id,
125
339
  });
340
+ if (fee_in_token === undefined) {
341
+ throw new Error('Fee token was specified but fee_in_token was not returned from server');
342
+ }
126
343
  const paymentInstruction = getTransferInstruction({
127
344
  amount: fee_in_token,
128
- authority: sourceIsSigner ? source_wallet : walletAddress,
345
+ authority: isSigner ? source_wallet : walletAddress,
129
346
  destination: destinationTokenAccount,
130
347
  source: sourceTokenAccount,
131
348
  });
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Stable numeric error codes for RPC responses following JSON-RPC 2.0 spec (-32000 to -32099 for server errors).
3
+ */
4
+ export declare enum KoraErrorCode {
5
+ InvalidTransaction = -32000,
6
+ ValidationError = -32001,
7
+ UnsupportedFeeToken = -32002,
8
+ InsufficientFunds = -32003,
9
+ InvalidRequest = -32004,
10
+ FeeEstimationFailed = -32005,
11
+ TransactionExecutionFailed = -32006,
12
+ SigningError = -32020,
13
+ RateLimitExceeded = -32030,
14
+ UsageLimitExceeded = -32031,
15
+ Unauthorized = -32032,
16
+ SwapError = -32040,
17
+ TokenOperationError = -32041,
18
+ AccountNotFound = -32050,
19
+ JitoError = -32060,
20
+ RecaptchaError = -32061,
21
+ InternalServerError = -32090,
22
+ ConfigError = -32091,
23
+ SerializationError = -32092,
24
+ RpcError = -32093
25
+ }
26
+ /**
27
+ * Structured data returned in the JSON-RPC error object's `data` field.
28
+ */
29
+ export interface KoraErrorData {
30
+ error_type: string;
31
+ }
32
+ /**
33
+ * Represents a structured error returned by the Kora paymaster service.
34
+ */
35
+ export declare class KoraError extends Error {
36
+ /** The stable numeric error code */
37
+ readonly code: KoraErrorCode;
38
+ /** Optional structured data about the error */
39
+ readonly data?: KoraErrorData;
40
+ constructor(code?: number, message?: string, data?: KoraErrorData);
41
+ }