@solana/kora 0.2.0 → 0.3.0-beta.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.
@@ -4,10 +4,10 @@ import { payer } from '@solana/kit-plugin-payer';
4
4
  import { rpc } from '@solana/kit-plugin-rpc';
5
5
  import { estimateAndUpdateProvisoryComputeUnitLimitFactory, estimateComputeUnitLimitFactory, } from '@solana-program/compute-budget';
6
6
  import { KoraClient } from '../client.js';
7
+ import { koraPlugin } from '../plugin.js';
7
8
  import { createKoraTransactionPlanExecutor } from './executor.js';
8
9
  import { buildPlaceholderPaymentInstruction, koraPaymentAddress } from './payment.js';
9
10
  import { buildComputeBudgetInstructions, createKoraTransactionPlanner } from './planner.js';
10
- import { koraPlugin } from './plugin.js';
11
11
  /**
12
12
  * Creates a Kora Kit client composed from Kit plugins.
13
13
  *
@@ -31,9 +31,14 @@ import { koraPlugin } from './plugin.js';
31
31
  * const result = await client.sendTransaction([myInstruction]);
32
32
  * ```
33
33
  */
34
+ // TODO: Bundle support — the plan/execute pipeline currently handles single transactions only.
35
+ // For Jito bundles, users must manually encode transactions and call `client.kora.signAndSendBundle()`.
36
+ // A future `createKitKoraBundleClient` (or a bundle-aware executor plugin) could extend this to
37
+ // plan multiple transaction messages and submit them as a single bundle.
34
38
  export async function createKitKoraClient(config) {
35
39
  const koraClient = new KoraClient({
36
40
  apiKey: config.apiKey,
41
+ getRecaptchaToken: config.getRecaptchaToken,
37
42
  hmacSecret: config.hmacSecret,
38
43
  rpcUrl: config.endpoint,
39
44
  });
@@ -58,7 +63,10 @@ export async function createKitKoraClient(config) {
58
63
  : undefined, resolveProvisoryComputeUnitLimit);
59
64
  return createEmptyClient()
60
65
  .use(rpc(config.rpcUrl))
61
- .use(koraPlugin({ apiKey: config.apiKey, endpoint: config.endpoint, hmacSecret: config.hmacSecret }))
66
+ .use(koraPlugin({
67
+ endpoint: config.endpoint,
68
+ koraClient,
69
+ }))
62
70
  .use(payer(payerSigner))
63
71
  .use(koraPaymentAddress(paymentAddr))
64
72
  .use(transactionPlannerPlugin(koraTransactionPlanner))
@@ -27,7 +27,7 @@ export async function buildPlaceholderPaymentInstruction(feePayerWallet, payment
27
27
  authority: feePayerWallet,
28
28
  destination: destinationTokenAccount,
29
29
  source: sourceTokenAccount,
30
- });
30
+ }, { programAddress: tokenProgram });
31
31
  return { destinationTokenAccount, instruction, sourceTokenAccount };
32
32
  }
33
33
  function isPlaceholderPaymentInstruction(ix, sourceTokenAccount, destinationTokenAccount, feePayerWallet, tokenProgramId) {
@@ -50,12 +50,13 @@ export function updatePaymentInstructionAmount(instructions, feePayerWallet, sou
50
50
  return ix;
51
51
  }
52
52
  replaced = true;
53
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ADDRESS;
53
54
  return getTransferInstruction({
54
55
  amount,
55
56
  authority: feePayerWallet,
56
57
  destination: destinationTokenAccount,
57
58
  source: sourceTokenAccount,
58
- });
59
+ }, { programAddress: tokenProgram });
59
60
  });
60
61
  if (!replaced) {
61
62
  throw new Error('Failed to update payment instruction: no matching placeholder transfer instruction found. ' +
@@ -0,0 +1,85 @@
1
+ import type { EstimateBundleFeeRequest, EstimateTransactionFeeRequest, GetPaymentInstructionRequest, GetVersionResponse, KitBlockhashResponse, KitConfigResponse, KitEstimateBundleFeeResponse, KitEstimateFeeResponse, KitPayerSignerResponse, KitPaymentInstructionResponse, KitSignAndSendBundleResponse, KitSignAndSendTransactionResponse, KitSignBundleResponse, KitSignTransactionResponse, KitSupportedTokensResponse, KoraPluginConfig, SignAndSendBundleRequest, SignAndSendTransactionRequest, SignBundleRequest, SignTransactionRequest } from './types/index.js';
2
+ /**
3
+ * Creates a Kora Kit plugin that adds Kora paymaster functionality to a Kit client.
4
+ *
5
+ * The plugin exposes all Kora RPC methods with Kit-typed responses (Address, Blockhash).
6
+ *
7
+ * **Note:** The plugin pattern with `createEmptyClient().use()` requires `@solana/kit` v5.4.0+.
8
+ * For older kit versions, use `KoraClient` directly instead.
9
+ *
10
+ * @param config - Plugin configuration
11
+ * @param config.endpoint - Kora RPC endpoint URL
12
+ * @param config.apiKey - Optional API key for authentication
13
+ * @param config.hmacSecret - Optional HMAC secret for signature-based authentication
14
+ * @returns A Kit plugin function that adds `.kora` to the client
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { createEmptyClient } from '@solana/kit';
19
+ * import { koraPlugin } from '@solana/kora';
20
+ *
21
+ * const client = createEmptyClient()
22
+ * .use(koraPlugin({ endpoint: 'https://kora.example.com' }));
23
+ *
24
+ * // All responses have Kit-typed fields
25
+ * const config = await client.kora.getConfig();
26
+ * // config.fee_payers is Address[] not string[]
27
+ *
28
+ * const { signer_pubkey } = await client.kora.signTransaction({ transaction: tx });
29
+ * // signer_pubkey is Address not string
30
+ * ```
31
+ */
32
+ export declare function koraPlugin(config: KoraPluginConfig): <T extends object>(c: T) => T & {
33
+ kora: {
34
+ /**
35
+ * Estimates the bundle fee with Kit-typed addresses.
36
+ */
37
+ estimateBundleFee(request: EstimateBundleFeeRequest): Promise<KitEstimateBundleFeeResponse>;
38
+ /**
39
+ * Estimates the transaction fee with Kit-typed addresses.
40
+ */
41
+ estimateTransactionFee(request: EstimateTransactionFeeRequest): Promise<KitEstimateFeeResponse>;
42
+ /**
43
+ * Gets the latest blockhash with Kit Blockhash type.
44
+ */
45
+ getBlockhash(): Promise<KitBlockhashResponse>;
46
+ /**
47
+ * Retrieves the current Kora server configuration with Kit-typed addresses.
48
+ */
49
+ getConfig(): Promise<KitConfigResponse>;
50
+ /**
51
+ * Retrieves the payer signer and payment destination with Kit-typed addresses.
52
+ */
53
+ getPayerSigner(): Promise<KitPayerSignerResponse>;
54
+ /**
55
+ * Creates a payment instruction with Kit-typed response.
56
+ */
57
+ getPaymentInstruction(request: GetPaymentInstructionRequest): Promise<KitPaymentInstructionResponse>;
58
+ /**
59
+ * Retrieves the list of tokens supported for fee payment with Kit-typed addresses.
60
+ */
61
+ getSupportedTokens(): Promise<KitSupportedTokensResponse>;
62
+ /**
63
+ * Gets the version of the Kora server.
64
+ */
65
+ getVersion(): Promise<GetVersionResponse>;
66
+ /**
67
+ * Signs and sends a bundle of transactions via Jito with Kit-typed response.
68
+ */
69
+ signAndSendBundle(request: SignAndSendBundleRequest): Promise<KitSignAndSendBundleResponse>;
70
+ /**
71
+ * Signs and sends a transaction with Kit-typed response.
72
+ */
73
+ signAndSendTransaction(request: SignAndSendTransactionRequest): Promise<KitSignAndSendTransactionResponse>;
74
+ /**
75
+ * Signs a bundle of transactions with Kit-typed response.
76
+ */
77
+ signBundle(request: SignBundleRequest): Promise<KitSignBundleResponse>;
78
+ /**
79
+ * Signs a transaction with Kit-typed response.
80
+ */
81
+ signTransaction(request: SignTransactionRequest): Promise<KitSignTransactionResponse>;
82
+ };
83
+ };
84
+ /** Type representing the Kora API exposed by the plugin */
85
+ export type KoraApi = ReturnType<ReturnType<typeof koraPlugin>>['kora'];
@@ -1,29 +1,61 @@
1
1
  import { address, blockhash, signature } from '@solana/kit';
2
- import { KoraClient } from '../client.js';
2
+ import { KoraClient } from './client.js';
3
3
  /**
4
- * Kit plugin that adds `.kora` namespace with all Kora RPC methods.
5
- * Responses are cast to Kit types (Address, Blockhash, Signature).
4
+ * Creates a Kora Kit plugin that adds Kora paymaster functionality to a Kit client.
6
5
  *
7
- * Requires `@solana/kit` v5.4.0+ for the `createEmptyClient().use()` pattern.
6
+ * The plugin exposes all Kora RPC methods with Kit-typed responses (Address, Blockhash).
7
+ *
8
+ * **Note:** The plugin pattern with `createEmptyClient().use()` requires `@solana/kit` v5.4.0+.
9
+ * For older kit versions, use `KoraClient` directly instead.
10
+ *
11
+ * @param config - Plugin configuration
12
+ * @param config.endpoint - Kora RPC endpoint URL
13
+ * @param config.apiKey - Optional API key for authentication
14
+ * @param config.hmacSecret - Optional HMAC secret for signature-based authentication
15
+ * @returns A Kit plugin function that adds `.kora` to the client
8
16
  *
9
17
  * @example
10
18
  * ```typescript
19
+ * import { createEmptyClient } from '@solana/kit';
20
+ * import { koraPlugin } from '@solana/kora';
21
+ *
11
22
  * const client = createEmptyClient()
12
23
  * .use(koraPlugin({ endpoint: 'https://kora.example.com' }));
13
24
  *
25
+ * // All responses have Kit-typed fields
14
26
  * const config = await client.kora.getConfig();
27
+ * // config.fee_payers is Address[] not string[]
28
+ *
15
29
  * const { signer_pubkey } = await client.kora.signTransaction({ transaction: tx });
30
+ * // signer_pubkey is Address not string
16
31
  * ```
17
32
  */
18
33
  export function koraPlugin(config) {
19
- const client = new KoraClient({
20
- apiKey: config.apiKey,
21
- hmacSecret: config.hmacSecret,
22
- rpcUrl: config.endpoint,
23
- });
34
+ const client = config.koraClient ??
35
+ new KoraClient({
36
+ apiKey: config.apiKey,
37
+ getRecaptchaToken: config.getRecaptchaToken,
38
+ hmacSecret: config.hmacSecret,
39
+ rpcUrl: config.endpoint,
40
+ });
24
41
  return (c) => ({
25
42
  ...c,
26
43
  kora: {
44
+ /**
45
+ * Estimates the bundle fee with Kit-typed addresses.
46
+ */
47
+ async estimateBundleFee(request) {
48
+ const result = await client.estimateBundleFee(request);
49
+ return {
50
+ fee_in_lamports: result.fee_in_lamports,
51
+ fee_in_token: result.fee_in_token,
52
+ payment_address: address(result.payment_address),
53
+ signer_pubkey: address(result.signer_pubkey),
54
+ };
55
+ },
56
+ /**
57
+ * Estimates the transaction fee with Kit-typed addresses.
58
+ */
27
59
  async estimateTransactionFee(request) {
28
60
  const result = await client.estimateTransactionFee(request);
29
61
  return {
@@ -33,12 +65,18 @@ export function koraPlugin(config) {
33
65
  signer_pubkey: address(result.signer_pubkey),
34
66
  };
35
67
  },
68
+ /**
69
+ * Gets the latest blockhash with Kit Blockhash type.
70
+ */
36
71
  async getBlockhash() {
37
72
  const result = await client.getBlockhash();
38
73
  return {
39
74
  blockhash: blockhash(result.blockhash),
40
75
  };
41
76
  },
77
+ /**
78
+ * Retrieves the current Kora server configuration with Kit-typed addresses.
79
+ */
42
80
  async getConfig() {
43
81
  const result = await client.getConfig();
44
82
  return {
@@ -53,6 +91,9 @@ export function koraPlugin(config) {
53
91
  },
54
92
  };
55
93
  },
94
+ /**
95
+ * Retrieves the payer signer and payment destination with Kit-typed addresses.
96
+ */
56
97
  async getPayerSigner() {
57
98
  const result = await client.getPayerSigner();
58
99
  return {
@@ -60,6 +101,9 @@ export function koraPlugin(config) {
60
101
  signer_address: address(result.signer_address),
61
102
  };
62
103
  },
104
+ /**
105
+ * Creates a payment instruction with Kit-typed response.
106
+ */
63
107
  async getPaymentInstruction(request) {
64
108
  const result = await client.getPaymentInstruction(request);
65
109
  return {
@@ -71,12 +115,35 @@ export function koraPlugin(config) {
71
115
  signer_address: address(result.signer_address),
72
116
  };
73
117
  },
118
+ /**
119
+ * Retrieves the list of tokens supported for fee payment with Kit-typed addresses.
120
+ */
74
121
  async getSupportedTokens() {
75
122
  const result = await client.getSupportedTokens();
76
123
  return {
77
124
  tokens: result.tokens.map(addr => address(addr)),
78
125
  };
79
126
  },
127
+ /**
128
+ * Gets the version of the Kora server.
129
+ */
130
+ async getVersion() {
131
+ return await client.getVersion();
132
+ },
133
+ /**
134
+ * Signs and sends a bundle of transactions via Jito with Kit-typed response.
135
+ */
136
+ async signAndSendBundle(request) {
137
+ const result = await client.signAndSendBundle(request);
138
+ return {
139
+ bundle_uuid: result.bundle_uuid,
140
+ signed_transactions: result.signed_transactions,
141
+ signer_pubkey: address(result.signer_pubkey),
142
+ };
143
+ },
144
+ /**
145
+ * Signs and sends a transaction with Kit-typed response.
146
+ */
80
147
  async signAndSendTransaction(request) {
81
148
  const result = await client.signAndSendTransaction(request);
82
149
  return {
@@ -85,21 +152,24 @@ export function koraPlugin(config) {
85
152
  signer_pubkey: address(result.signer_pubkey),
86
153
  };
87
154
  },
88
- async signTransaction(request) {
89
- const result = await client.signTransaction(request);
155
+ /**
156
+ * Signs a bundle of transactions with Kit-typed response.
157
+ */
158
+ async signBundle(request) {
159
+ const result = await client.signBundle(request);
90
160
  return {
91
- signed_transaction: result.signed_transaction,
161
+ signed_transactions: result.signed_transactions,
92
162
  signer_pubkey: address(result.signer_pubkey),
93
163
  };
94
164
  },
95
- async transferTransaction(request) {
96
- const result = await client.transferTransaction(request);
165
+ /**
166
+ * Signs a transaction with Kit-typed response.
167
+ */
168
+ async signTransaction(request) {
169
+ const result = await client.signTransaction(request);
97
170
  return {
98
- blockhash: blockhash(result.blockhash),
99
- instructions: result.instructions,
100
- message: result.message,
171
+ signed_transaction: result.signed_transaction,
101
172
  signer_pubkey: address(result.signer_pubkey),
102
- transaction: result.transaction,
103
173
  };
104
174
  },
105
175
  },