@solana/kora 0.1.0 → 0.1.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.
- package/README.md +29 -27
- package/dist/src/client.js +0 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/plugin.d.ts +73 -0
- package/dist/src/plugin.js +148 -0
- package/dist/src/types/index.d.ts +115 -0
- package/dist/test/plugin.test.d.ts +1 -0
- package/dist/test/plugin.test.js +386 -0
- package/dist/test/setup.js +3 -1
- package/package.json +12 -7
package/README.md
CHANGED
|
@@ -1,8 +1,35 @@
|
|
|
1
1
|
# Kora TypeScript SDK
|
|
2
2
|
|
|
3
|
-
A TypeScript SDK for interacting with the Kora RPC server. This SDK provides a type-safe interface to all Kora RPC methods.
|
|
3
|
+
A TypeScript SDK for interacting with the Kora RPC server. This SDK provides a type-safe interface to all Kora RPC methods (requires a Kora RPC server to be running).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pnpm install @solana/kora
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { KoraClient } from '@solana/kora';
|
|
16
|
+
|
|
17
|
+
// Initialize the client with your RPC endpoint
|
|
18
|
+
const client = new KoraClient({ rpcUrl: 'http://localhost:8080' });
|
|
19
|
+
|
|
20
|
+
// Example: Get Kora to sign a transaction
|
|
21
|
+
const result = await client.signTransaction({
|
|
22
|
+
transaction: 'myBase64EncodedTransaction'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Access the signed transaction (base64 encoded)
|
|
26
|
+
console.log('Signed transaction:', result.signed_transaction);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**[→ API Reference](https://launch.solana.com/docs/kora/json-rpc-api)**
|
|
30
|
+
**[→ Quick Start](https://launch.solana.com/docs/kora/getting-started/quick-start)**
|
|
31
|
+
|
|
32
|
+
## Local Development
|
|
6
33
|
|
|
7
34
|
### Building from Source
|
|
8
35
|
|
|
@@ -33,28 +60,3 @@ pnpm test:ci:integration
|
|
|
33
60
|
|
|
34
61
|
This will start a local test validator and run all tests.
|
|
35
62
|
|
|
36
|
-
|
|
37
|
-
## Quick Start
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
import { KoraClient } from '@solana/kora';
|
|
41
|
-
|
|
42
|
-
// Initialize the client with your RPC endpoint
|
|
43
|
-
const client = new KoraClient({ rpcUrl: 'http://localhost:8080' });
|
|
44
|
-
|
|
45
|
-
// Example: Transfer tokens
|
|
46
|
-
const result = await client.transferTransaction({
|
|
47
|
-
amount: 1000000, // 1 USDC (6 decimals)
|
|
48
|
-
token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC mint
|
|
49
|
-
source: "sourceAddress",
|
|
50
|
-
destination: "destinationAddress"
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Access the base64 encoded transaction, base64 encoded message, and parsed instructions directly
|
|
54
|
-
console.log('Transaction:', result.transaction);
|
|
55
|
-
console.log('Message:', result.message);
|
|
56
|
-
console.log('Instructions:', result.instructions);
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
**[→ API Reference](https://launch.solana.com/docs/kora/json-rpc-api)**
|
|
60
|
-
**[→ Quick Start](https://launch.solana.com/docs/kora/getting-started/quick-start)**
|
package/dist/src/client.js
CHANGED
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { KoraPluginConfig, KitPayerSignerResponse, KitBlockhashResponse, KitSupportedTokensResponse, KitEstimateFeeResponse, KitSignTransactionResponse, KitSignAndSendTransactionResponse, KitTransferTransactionResponse, KitPaymentInstructionResponse, KitConfigResponse, EstimateTransactionFeeRequest, SignTransactionRequest, SignAndSendTransactionRequest, TransferTransactionRequest, GetPaymentInstructionRequest } 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
|
+
* Retrieves the current Kora server configuration with Kit-typed addresses.
|
|
36
|
+
*/
|
|
37
|
+
getConfig(): Promise<KitConfigResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* Retrieves the payer signer and payment destination with Kit-typed addresses.
|
|
40
|
+
*/
|
|
41
|
+
getPayerSigner(): Promise<KitPayerSignerResponse>;
|
|
42
|
+
/**
|
|
43
|
+
* Gets the latest blockhash with Kit Blockhash type.
|
|
44
|
+
*/
|
|
45
|
+
getBlockhash(): Promise<KitBlockhashResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Retrieves the list of tokens supported for fee payment with Kit-typed addresses.
|
|
48
|
+
*/
|
|
49
|
+
getSupportedTokens(): Promise<KitSupportedTokensResponse>;
|
|
50
|
+
/**
|
|
51
|
+
* Estimates the transaction fee with Kit-typed addresses.
|
|
52
|
+
*/
|
|
53
|
+
estimateTransactionFee(request: EstimateTransactionFeeRequest): Promise<KitEstimateFeeResponse>;
|
|
54
|
+
/**
|
|
55
|
+
* Signs a transaction with Kit-typed response.
|
|
56
|
+
*/
|
|
57
|
+
signTransaction(request: SignTransactionRequest): Promise<KitSignTransactionResponse>;
|
|
58
|
+
/**
|
|
59
|
+
* Signs and sends a transaction with Kit-typed response.
|
|
60
|
+
*/
|
|
61
|
+
signAndSendTransaction(request: SignAndSendTransactionRequest): Promise<KitSignAndSendTransactionResponse>;
|
|
62
|
+
/**
|
|
63
|
+
* Creates a token transfer transaction with Kit-typed response.
|
|
64
|
+
*/
|
|
65
|
+
transferTransaction(request: TransferTransactionRequest): Promise<KitTransferTransactionResponse>;
|
|
66
|
+
/**
|
|
67
|
+
* Creates a payment instruction with Kit-typed response.
|
|
68
|
+
*/
|
|
69
|
+
getPaymentInstruction(request: GetPaymentInstructionRequest): Promise<KitPaymentInstructionResponse>;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
/** Type representing the Kora API exposed by the plugin */
|
|
73
|
+
export type KoraApi = ReturnType<ReturnType<typeof koraPlugin>>['kora'];
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { address, blockhash } from '@solana/kit';
|
|
2
|
+
import { KoraClient } from './client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a Kora Kit plugin that adds Kora paymaster functionality to a Kit client.
|
|
5
|
+
*
|
|
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
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { createEmptyClient } from '@solana/kit';
|
|
20
|
+
* import { koraPlugin } from '@solana/kora';
|
|
21
|
+
*
|
|
22
|
+
* const client = createEmptyClient()
|
|
23
|
+
* .use(koraPlugin({ endpoint: 'https://kora.example.com' }));
|
|
24
|
+
*
|
|
25
|
+
* // All responses have Kit-typed fields
|
|
26
|
+
* const config = await client.kora.getConfig();
|
|
27
|
+
* // config.fee_payers is Address[] not string[]
|
|
28
|
+
*
|
|
29
|
+
* const { signer_pubkey } = await client.kora.signTransaction({ transaction: tx });
|
|
30
|
+
* // signer_pubkey is Address not string
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function koraPlugin(config) {
|
|
34
|
+
const client = new KoraClient({
|
|
35
|
+
rpcUrl: config.endpoint,
|
|
36
|
+
apiKey: config.apiKey,
|
|
37
|
+
hmacSecret: config.hmacSecret,
|
|
38
|
+
});
|
|
39
|
+
return (c) => ({
|
|
40
|
+
...c,
|
|
41
|
+
kora: {
|
|
42
|
+
/**
|
|
43
|
+
* Retrieves the current Kora server configuration with Kit-typed addresses.
|
|
44
|
+
*/
|
|
45
|
+
async getConfig() {
|
|
46
|
+
const result = await client.getConfig();
|
|
47
|
+
return {
|
|
48
|
+
fee_payers: result.fee_payers.map(addr => address(addr)),
|
|
49
|
+
validation_config: {
|
|
50
|
+
...result.validation_config,
|
|
51
|
+
allowed_programs: result.validation_config.allowed_programs.map(addr => address(addr)),
|
|
52
|
+
allowed_tokens: result.validation_config.allowed_tokens.map(addr => address(addr)),
|
|
53
|
+
allowed_spl_paid_tokens: result.validation_config.allowed_spl_paid_tokens.map(addr => address(addr)),
|
|
54
|
+
disallowed_accounts: result.validation_config.disallowed_accounts.map(addr => address(addr)),
|
|
55
|
+
},
|
|
56
|
+
enabled_methods: result.enabled_methods,
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* Retrieves the payer signer and payment destination with Kit-typed addresses.
|
|
61
|
+
*/
|
|
62
|
+
async getPayerSigner() {
|
|
63
|
+
const result = await client.getPayerSigner();
|
|
64
|
+
return {
|
|
65
|
+
signer_address: address(result.signer_address),
|
|
66
|
+
payment_address: address(result.payment_address),
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* Gets the latest blockhash with Kit Blockhash type.
|
|
71
|
+
*/
|
|
72
|
+
async getBlockhash() {
|
|
73
|
+
const result = await client.getBlockhash();
|
|
74
|
+
return {
|
|
75
|
+
blockhash: blockhash(result.blockhash),
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Retrieves the list of tokens supported for fee payment with Kit-typed addresses.
|
|
80
|
+
*/
|
|
81
|
+
async getSupportedTokens() {
|
|
82
|
+
const result = await client.getSupportedTokens();
|
|
83
|
+
return {
|
|
84
|
+
tokens: result.tokens.map(addr => address(addr)),
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Estimates the transaction fee with Kit-typed addresses.
|
|
89
|
+
*/
|
|
90
|
+
async estimateTransactionFee(request) {
|
|
91
|
+
const result = await client.estimateTransactionFee(request);
|
|
92
|
+
return {
|
|
93
|
+
fee_in_lamports: result.fee_in_lamports,
|
|
94
|
+
fee_in_token: result.fee_in_token,
|
|
95
|
+
signer_pubkey: address(result.signer_pubkey),
|
|
96
|
+
payment_address: address(result.payment_address),
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
/**
|
|
100
|
+
* Signs a transaction with Kit-typed response.
|
|
101
|
+
*/
|
|
102
|
+
async signTransaction(request) {
|
|
103
|
+
const result = await client.signTransaction(request);
|
|
104
|
+
return {
|
|
105
|
+
signed_transaction: result.signed_transaction,
|
|
106
|
+
signer_pubkey: address(result.signer_pubkey),
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* Signs and sends a transaction with Kit-typed response.
|
|
111
|
+
*/
|
|
112
|
+
async signAndSendTransaction(request) {
|
|
113
|
+
const result = await client.signAndSendTransaction(request);
|
|
114
|
+
return {
|
|
115
|
+
signed_transaction: result.signed_transaction,
|
|
116
|
+
signer_pubkey: address(result.signer_pubkey),
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* Creates a token transfer transaction with Kit-typed response.
|
|
121
|
+
*/
|
|
122
|
+
async transferTransaction(request) {
|
|
123
|
+
const result = await client.transferTransaction(request);
|
|
124
|
+
return {
|
|
125
|
+
transaction: result.transaction,
|
|
126
|
+
message: result.message,
|
|
127
|
+
blockhash: blockhash(result.blockhash),
|
|
128
|
+
signer_pubkey: address(result.signer_pubkey),
|
|
129
|
+
instructions: result.instructions,
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* Creates a payment instruction with Kit-typed response.
|
|
134
|
+
*/
|
|
135
|
+
async getPaymentInstruction(request) {
|
|
136
|
+
const result = await client.getPaymentInstruction(request);
|
|
137
|
+
return {
|
|
138
|
+
original_transaction: result.original_transaction,
|
|
139
|
+
payment_instruction: result.payment_instruction,
|
|
140
|
+
payment_amount: result.payment_amount,
|
|
141
|
+
payment_token: address(result.payment_token),
|
|
142
|
+
payment_address: address(result.payment_address),
|
|
143
|
+
signer_address: address(result.signer_address),
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
@@ -381,3 +381,118 @@ export interface KoraClientOptions {
|
|
|
381
381
|
/** Optional HMAC secret for signature-based authentication */
|
|
382
382
|
hmacSecret?: string;
|
|
383
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* Plugin Types - Kit-typed responses for the Kora plugin
|
|
386
|
+
*/
|
|
387
|
+
import type { Address, Blockhash, Instruction as KitInstruction, Base64EncodedWireTransaction } from '@solana/kit';
|
|
388
|
+
/** Configuration options for the Kora Kit plugin */
|
|
389
|
+
export interface KoraPluginConfig {
|
|
390
|
+
/** Kora RPC endpoint URL */
|
|
391
|
+
endpoint: string;
|
|
392
|
+
/** Optional API key for authentication */
|
|
393
|
+
apiKey?: string;
|
|
394
|
+
/** Optional HMAC secret for signature-based authentication */
|
|
395
|
+
hmacSecret?: string;
|
|
396
|
+
}
|
|
397
|
+
/** Plugin response for getPayerSigner with Kit Address types */
|
|
398
|
+
export interface KitPayerSignerResponse {
|
|
399
|
+
/** Public key of the payer signer */
|
|
400
|
+
signer_address: Address;
|
|
401
|
+
/** Public key of the payment destination */
|
|
402
|
+
payment_address: Address;
|
|
403
|
+
}
|
|
404
|
+
/** Plugin response for getBlockhash with Kit Blockhash type */
|
|
405
|
+
export interface KitBlockhashResponse {
|
|
406
|
+
/** Base58-encoded blockhash */
|
|
407
|
+
blockhash: Blockhash;
|
|
408
|
+
}
|
|
409
|
+
/** Plugin response for getSupportedTokens with Kit Address types */
|
|
410
|
+
export interface KitSupportedTokensResponse {
|
|
411
|
+
/** Array of supported token mint addresses */
|
|
412
|
+
tokens: Address[];
|
|
413
|
+
}
|
|
414
|
+
/** Plugin response for estimateTransactionFee with Kit Address types */
|
|
415
|
+
export interface KitEstimateFeeResponse {
|
|
416
|
+
/** Transaction fee in lamports */
|
|
417
|
+
fee_in_lamports: number;
|
|
418
|
+
/** Transaction fee in the requested token */
|
|
419
|
+
fee_in_token: number;
|
|
420
|
+
/** Public key of the signer used to estimate the fee */
|
|
421
|
+
signer_pubkey: Address;
|
|
422
|
+
/** Public key of the payment destination */
|
|
423
|
+
payment_address: Address;
|
|
424
|
+
}
|
|
425
|
+
/** Plugin response for signTransaction with Kit types */
|
|
426
|
+
export interface KitSignTransactionResponse {
|
|
427
|
+
/** Base64-encoded signed transaction */
|
|
428
|
+
signed_transaction: Base64EncodedWireTransaction;
|
|
429
|
+
/** Public key of the signer used to sign the transaction */
|
|
430
|
+
signer_pubkey: Address;
|
|
431
|
+
}
|
|
432
|
+
/** Plugin response for signAndSendTransaction with Kit types */
|
|
433
|
+
export interface KitSignAndSendTransactionResponse {
|
|
434
|
+
/** Base64-encoded signed transaction */
|
|
435
|
+
signed_transaction: Base64EncodedWireTransaction;
|
|
436
|
+
/** Public key of the signer used to send the transaction */
|
|
437
|
+
signer_pubkey: Address;
|
|
438
|
+
}
|
|
439
|
+
/** Plugin response for transferTransaction with Kit types */
|
|
440
|
+
export interface KitTransferTransactionResponse {
|
|
441
|
+
/** Base64-encoded signed transaction */
|
|
442
|
+
transaction: Base64EncodedWireTransaction;
|
|
443
|
+
/** Base64-encoded message */
|
|
444
|
+
message: string;
|
|
445
|
+
/** Recent blockhash used in the transaction */
|
|
446
|
+
blockhash: Blockhash;
|
|
447
|
+
/** Public key of the signer used to send the transaction */
|
|
448
|
+
signer_pubkey: Address;
|
|
449
|
+
/** Parsed instructions from the transaction message */
|
|
450
|
+
instructions: KitInstruction[];
|
|
451
|
+
}
|
|
452
|
+
/** Plugin response for getPaymentInstruction with Kit types */
|
|
453
|
+
export interface KitPaymentInstructionResponse {
|
|
454
|
+
/** Base64-encoded original transaction */
|
|
455
|
+
original_transaction: Base64EncodedWireTransaction;
|
|
456
|
+
/** Payment instruction */
|
|
457
|
+
payment_instruction: KitInstruction;
|
|
458
|
+
/** Payment amount in the requested token */
|
|
459
|
+
payment_amount: number;
|
|
460
|
+
/** Mint address of the token used for payment */
|
|
461
|
+
payment_token: Address;
|
|
462
|
+
/** Public key of the payment destination */
|
|
463
|
+
payment_address: Address;
|
|
464
|
+
/** Public key of the payer signer */
|
|
465
|
+
signer_address: Address;
|
|
466
|
+
}
|
|
467
|
+
/** Plugin response for getConfig with Kit Address types */
|
|
468
|
+
export interface KitConfigResponse {
|
|
469
|
+
/** Array of public keys of the fee payer accounts (signer pool) */
|
|
470
|
+
fee_payers: Address[];
|
|
471
|
+
/** Validation rules and constraints */
|
|
472
|
+
validation_config: KitValidationConfig;
|
|
473
|
+
/** Enabled methods */
|
|
474
|
+
enabled_methods: EnabledMethods;
|
|
475
|
+
}
|
|
476
|
+
/** Plugin validation config with Kit Address types */
|
|
477
|
+
export interface KitValidationConfig {
|
|
478
|
+
/** Maximum allowed transaction value in lamports */
|
|
479
|
+
max_allowed_lamports: number;
|
|
480
|
+
/** Maximum number of signatures allowed per transaction */
|
|
481
|
+
max_signatures: number;
|
|
482
|
+
/** Price oracle source for token conversions */
|
|
483
|
+
price_source: PriceSource;
|
|
484
|
+
/** List of allowed Solana program IDs */
|
|
485
|
+
allowed_programs: Address[];
|
|
486
|
+
/** List of allowed token mint addresses for fee payment */
|
|
487
|
+
allowed_tokens: Address[];
|
|
488
|
+
/** List of SPL tokens accepted for paid transactions */
|
|
489
|
+
allowed_spl_paid_tokens: Address[];
|
|
490
|
+
/** List of blocked account addresses */
|
|
491
|
+
disallowed_accounts: Address[];
|
|
492
|
+
/** Policy controlling fee payer permissions */
|
|
493
|
+
fee_payer_policy: FeePayerPolicy;
|
|
494
|
+
/** Pricing model configuration */
|
|
495
|
+
price: PriceConfig;
|
|
496
|
+
/** Token2022 configuration */
|
|
497
|
+
token2022: Token2022Config;
|
|
498
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { createEmptyClient } from '@solana/kit';
|
|
2
|
+
import { koraPlugin } from '../src/plugin.js';
|
|
3
|
+
// Mock fetch globally
|
|
4
|
+
const mockFetch = jest.fn();
|
|
5
|
+
global.fetch = mockFetch;
|
|
6
|
+
describe('Kora Kit Plugin', () => {
|
|
7
|
+
const mockEndpoint = 'http://localhost:8080';
|
|
8
|
+
const mockConfig = {
|
|
9
|
+
endpoint: mockEndpoint,
|
|
10
|
+
};
|
|
11
|
+
// Helper to mock successful RPC response
|
|
12
|
+
const mockSuccessfulResponse = (result) => {
|
|
13
|
+
mockFetch.mockResolvedValueOnce({
|
|
14
|
+
json: jest.fn().mockResolvedValueOnce({
|
|
15
|
+
jsonrpc: '2.0',
|
|
16
|
+
id: 1,
|
|
17
|
+
result,
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
// Helper to mock error response
|
|
22
|
+
const mockErrorResponse = (error) => {
|
|
23
|
+
mockFetch.mockResolvedValueOnce({
|
|
24
|
+
json: jest.fn().mockResolvedValueOnce({
|
|
25
|
+
jsonrpc: '2.0',
|
|
26
|
+
id: 1,
|
|
27
|
+
error,
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
mockFetch.mockClear();
|
|
33
|
+
});
|
|
34
|
+
describe('Plugin Composition', () => {
|
|
35
|
+
it('should add kora property to client', () => {
|
|
36
|
+
const baseClient = { existing: 'property' };
|
|
37
|
+
const plugin = koraPlugin(mockConfig);
|
|
38
|
+
const enhanced = plugin(baseClient);
|
|
39
|
+
expect(enhanced.existing).toBe('property');
|
|
40
|
+
expect(enhanced.kora).toBeDefined();
|
|
41
|
+
expect(typeof enhanced.kora.getConfig).toBe('function');
|
|
42
|
+
expect(typeof enhanced.kora.getPayerSigner).toBe('function');
|
|
43
|
+
expect(typeof enhanced.kora.getBlockhash).toBe('function');
|
|
44
|
+
expect(typeof enhanced.kora.getSupportedTokens).toBe('function');
|
|
45
|
+
expect(typeof enhanced.kora.estimateTransactionFee).toBe('function');
|
|
46
|
+
expect(typeof enhanced.kora.signTransaction).toBe('function');
|
|
47
|
+
expect(typeof enhanced.kora.signAndSendTransaction).toBe('function');
|
|
48
|
+
expect(typeof enhanced.kora.transferTransaction).toBe('function');
|
|
49
|
+
expect(typeof enhanced.kora.getPaymentInstruction).toBe('function');
|
|
50
|
+
});
|
|
51
|
+
it('should work with empty client object', () => {
|
|
52
|
+
const plugin = koraPlugin(mockConfig);
|
|
53
|
+
const enhanced = plugin({});
|
|
54
|
+
expect(enhanced.kora).toBeDefined();
|
|
55
|
+
});
|
|
56
|
+
it('should support authentication options', () => {
|
|
57
|
+
const authConfig = {
|
|
58
|
+
endpoint: mockEndpoint,
|
|
59
|
+
apiKey: 'test-api-key',
|
|
60
|
+
hmacSecret: 'test-hmac-secret',
|
|
61
|
+
};
|
|
62
|
+
const plugin = koraPlugin(authConfig);
|
|
63
|
+
const enhanced = plugin({});
|
|
64
|
+
expect(enhanced.kora).toBeDefined();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('Type Casting', () => {
|
|
68
|
+
let kora;
|
|
69
|
+
beforeEach(() => {
|
|
70
|
+
const plugin = koraPlugin(mockConfig);
|
|
71
|
+
const client = plugin({});
|
|
72
|
+
kora = client.kora;
|
|
73
|
+
});
|
|
74
|
+
describe('getConfig', () => {
|
|
75
|
+
it('should return Kit-typed Address arrays', async () => {
|
|
76
|
+
const rawResponse = {
|
|
77
|
+
fee_payers: ['DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7'],
|
|
78
|
+
validation_config: {
|
|
79
|
+
max_allowed_lamports: 1000000,
|
|
80
|
+
max_signatures: 10,
|
|
81
|
+
price_source: 'Jupiter',
|
|
82
|
+
allowed_programs: ['11111111111111111111111111111111'],
|
|
83
|
+
allowed_tokens: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'],
|
|
84
|
+
allowed_spl_paid_tokens: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'],
|
|
85
|
+
disallowed_accounts: [],
|
|
86
|
+
fee_payer_policy: {
|
|
87
|
+
system: {
|
|
88
|
+
allow_transfer: true,
|
|
89
|
+
allow_assign: true,
|
|
90
|
+
allow_create_account: true,
|
|
91
|
+
allow_allocate: true,
|
|
92
|
+
nonce: {
|
|
93
|
+
allow_initialize: true,
|
|
94
|
+
allow_advance: true,
|
|
95
|
+
allow_authorize: true,
|
|
96
|
+
allow_withdraw: true,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
spl_token: {
|
|
100
|
+
allow_transfer: true,
|
|
101
|
+
allow_burn: true,
|
|
102
|
+
allow_close_account: true,
|
|
103
|
+
allow_approve: true,
|
|
104
|
+
allow_revoke: true,
|
|
105
|
+
allow_set_authority: true,
|
|
106
|
+
allow_mint_to: true,
|
|
107
|
+
allow_freeze_account: true,
|
|
108
|
+
allow_thaw_account: true,
|
|
109
|
+
},
|
|
110
|
+
token_2022: {
|
|
111
|
+
allow_transfer: true,
|
|
112
|
+
allow_burn: true,
|
|
113
|
+
allow_close_account: true,
|
|
114
|
+
allow_approve: true,
|
|
115
|
+
allow_revoke: true,
|
|
116
|
+
allow_set_authority: true,
|
|
117
|
+
allow_mint_to: true,
|
|
118
|
+
allow_freeze_account: true,
|
|
119
|
+
allow_thaw_account: true,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
price: { type: 'margin', margin: 0.1 },
|
|
123
|
+
token2022: {
|
|
124
|
+
blocked_mint_extensions: [],
|
|
125
|
+
blocked_account_extensions: [],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
enabled_methods: {
|
|
129
|
+
liveness: true,
|
|
130
|
+
estimate_transaction_fee: true,
|
|
131
|
+
get_supported_tokens: true,
|
|
132
|
+
sign_transaction: true,
|
|
133
|
+
sign_and_send_transaction: true,
|
|
134
|
+
transfer_transaction: true,
|
|
135
|
+
get_blockhash: true,
|
|
136
|
+
get_config: true,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
mockSuccessfulResponse(rawResponse);
|
|
140
|
+
const result = await kora.getConfig();
|
|
141
|
+
// Verify type casting - these should be Address types
|
|
142
|
+
expect(result.fee_payers).toHaveLength(1);
|
|
143
|
+
expect(result.fee_payers[0]).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
144
|
+
expect(result.validation_config.allowed_programs).toHaveLength(1);
|
|
145
|
+
expect(result.validation_config.allowed_programs[0]).toBe('11111111111111111111111111111111');
|
|
146
|
+
expect(result.validation_config.allowed_tokens).toHaveLength(1);
|
|
147
|
+
expect(result.validation_config.allowed_tokens[0]).toBe('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
describe('getPayerSigner', () => {
|
|
151
|
+
it('should return Kit-typed Address fields', async () => {
|
|
152
|
+
const rawResponse = {
|
|
153
|
+
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
154
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
155
|
+
};
|
|
156
|
+
mockSuccessfulResponse(rawResponse);
|
|
157
|
+
const result = await kora.getPayerSigner();
|
|
158
|
+
// Type assertion - these should be Address types
|
|
159
|
+
const signerAddr = result.signer_address;
|
|
160
|
+
const paymentAddr = result.payment_address;
|
|
161
|
+
expect(signerAddr).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
162
|
+
expect(paymentAddr).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('getBlockhash', () => {
|
|
166
|
+
it('should return Kit-typed Blockhash field', async () => {
|
|
167
|
+
const rawResponse = {
|
|
168
|
+
blockhash: '4NxM2D4kQcipkzMWBWQME5YSVnj5kT8QKA7rvb3rKLvE',
|
|
169
|
+
};
|
|
170
|
+
mockSuccessfulResponse(rawResponse);
|
|
171
|
+
const result = await kora.getBlockhash();
|
|
172
|
+
// Type assertion - should be Blockhash type
|
|
173
|
+
const hash = result.blockhash;
|
|
174
|
+
expect(hash).toBe('4NxM2D4kQcipkzMWBWQME5YSVnj5kT8QKA7rvb3rKLvE');
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
describe('getSupportedTokens', () => {
|
|
178
|
+
it('should return Kit-typed Address array', async () => {
|
|
179
|
+
const rawResponse = {
|
|
180
|
+
tokens: [
|
|
181
|
+
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
182
|
+
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
mockSuccessfulResponse(rawResponse);
|
|
186
|
+
const result = await kora.getSupportedTokens();
|
|
187
|
+
// Type assertion - these should be Address types
|
|
188
|
+
expect(result.tokens).toHaveLength(2);
|
|
189
|
+
const token0 = result.tokens[0];
|
|
190
|
+
const token1 = result.tokens[1];
|
|
191
|
+
expect(token0).toBe('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
192
|
+
expect(token1).toBe('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB');
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
describe('estimateTransactionFee', () => {
|
|
196
|
+
it('should return Kit-typed Address fields', async () => {
|
|
197
|
+
const rawResponse = {
|
|
198
|
+
fee_in_lamports: 5000,
|
|
199
|
+
fee_in_token: 50,
|
|
200
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
201
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
202
|
+
};
|
|
203
|
+
mockSuccessfulResponse(rawResponse);
|
|
204
|
+
const result = await kora.estimateTransactionFee({
|
|
205
|
+
transaction: 'base64EncodedTransaction',
|
|
206
|
+
fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
207
|
+
});
|
|
208
|
+
// Type assertions
|
|
209
|
+
const signerPubkey = result.signer_pubkey;
|
|
210
|
+
const paymentAddr = result.payment_address;
|
|
211
|
+
expect(result.fee_in_lamports).toBe(5000);
|
|
212
|
+
expect(result.fee_in_token).toBe(50);
|
|
213
|
+
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
214
|
+
expect(paymentAddr).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
describe('signTransaction', () => {
|
|
218
|
+
it('should return Kit-typed response with Base64EncodedWireTransaction', async () => {
|
|
219
|
+
const rawResponse = {
|
|
220
|
+
signed_transaction: 'base64SignedTransaction',
|
|
221
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
222
|
+
};
|
|
223
|
+
mockSuccessfulResponse(rawResponse);
|
|
224
|
+
const result = await kora.signTransaction({
|
|
225
|
+
transaction: 'base64EncodedTransaction',
|
|
226
|
+
});
|
|
227
|
+
// Type assertions - verify Kit types
|
|
228
|
+
const signedTx = result.signed_transaction;
|
|
229
|
+
const signerPubkey = result.signer_pubkey;
|
|
230
|
+
expect(signedTx).toBe('base64SignedTransaction');
|
|
231
|
+
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
describe('signAndSendTransaction', () => {
|
|
235
|
+
it('should return Kit-typed response with Base64EncodedWireTransaction', async () => {
|
|
236
|
+
const rawResponse = {
|
|
237
|
+
signed_transaction: 'base64SignedTransaction',
|
|
238
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
239
|
+
};
|
|
240
|
+
mockSuccessfulResponse(rawResponse);
|
|
241
|
+
const result = await kora.signAndSendTransaction({
|
|
242
|
+
transaction: 'base64EncodedTransaction',
|
|
243
|
+
});
|
|
244
|
+
// Type assertions - verify Kit types
|
|
245
|
+
const signedTx = result.signed_transaction;
|
|
246
|
+
const signerPubkey = result.signer_pubkey;
|
|
247
|
+
expect(signedTx).toBe('base64SignedTransaction');
|
|
248
|
+
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
describe('transferTransaction', () => {
|
|
252
|
+
it('should return Kit-typed response with Base64EncodedWireTransaction and Blockhash', async () => {
|
|
253
|
+
const rawResponse = {
|
|
254
|
+
transaction: 'base64Transaction',
|
|
255
|
+
message: 'base64Message',
|
|
256
|
+
blockhash: '4NxM2D4kQcipkzMWBWQME5YSVnj5kT8QKA7rvb3rKLvE',
|
|
257
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
258
|
+
instructions: [],
|
|
259
|
+
};
|
|
260
|
+
mockSuccessfulResponse(rawResponse);
|
|
261
|
+
const result = await kora.transferTransaction({
|
|
262
|
+
amount: 1000000,
|
|
263
|
+
token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
264
|
+
source: 'sourceWallet',
|
|
265
|
+
destination: 'destWallet',
|
|
266
|
+
});
|
|
267
|
+
// Type assertions - verify Kit types
|
|
268
|
+
const tx = result.transaction;
|
|
269
|
+
const hash = result.blockhash;
|
|
270
|
+
const signerPubkey = result.signer_pubkey;
|
|
271
|
+
expect(tx).toBe('base64Transaction');
|
|
272
|
+
expect(result.message).toBe('base64Message');
|
|
273
|
+
expect(hash).toBe('4NxM2D4kQcipkzMWBWQME5YSVnj5kT8QKA7rvb3rKLvE');
|
|
274
|
+
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
275
|
+
expect(result.instructions).toEqual([]);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
describe('getPaymentInstruction', () => {
|
|
279
|
+
it('should return Kit-typed response with Base64EncodedWireTransaction and Address fields', async () => {
|
|
280
|
+
const mockFeeEstimate = {
|
|
281
|
+
fee_in_lamports: 5000,
|
|
282
|
+
fee_in_token: 50000,
|
|
283
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
284
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
285
|
+
};
|
|
286
|
+
const testTx = 'Aoq7ymA5OGP+gmDXiY5m3cYXlY2Rz/a/gFjOgt9ZuoCS7UzuiGGaEnW2OOtvHvMQHkkD7Z4LRF5B63ftu+1oZwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgECB1urjQEjgFgzqYhJ8IXJeSg4cJP1j1g2CJstOQTDchOKUzqH3PxgGW3c4V3vZV05A5Y30/MggOBs0Kd00s1JEwg5TaEeaV4+KL2y7fXIAuf6cN0ZQitbhY+G9ExtBSChspOXPgNcy9pYpETe4bmB+fg4bfZx1tnicA/kIyyubczAmbcIKIuniNOOQYG2ggKCz8NjEsHVezrWMatndu1wk6J5miGP26J6Vwp31AljiAajAFuP0D9mWJwSeFuA7J5rPwbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpd/O36SW02zRtNtqk6GFeip2+yBQsVTeSbLL4rWJRkd4CBgQCBQQBCgxAQg8AAAAAAAYGBAIFAwEKDBAnAAAAAAAABg==';
|
|
287
|
+
mockSuccessfulResponse(mockFeeEstimate);
|
|
288
|
+
const result = await kora.getPaymentInstruction({
|
|
289
|
+
transaction: testTx,
|
|
290
|
+
fee_token: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
|
|
291
|
+
source_wallet: '11111111111111111111111111111111',
|
|
292
|
+
token_program_id: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
|
|
293
|
+
});
|
|
294
|
+
// Type assertions - verify Kit types
|
|
295
|
+
const originalTx = result.original_transaction;
|
|
296
|
+
const paymentToken = result.payment_token;
|
|
297
|
+
const paymentAddr = result.payment_address;
|
|
298
|
+
const signerAddr = result.signer_address;
|
|
299
|
+
expect(originalTx).toBe(testTx);
|
|
300
|
+
expect(paymentToken).toBe('4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU');
|
|
301
|
+
expect(paymentAddr).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
302
|
+
expect(signerAddr).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
303
|
+
expect(result.payment_amount).toBe(50000);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
describe('Error Handling', () => {
|
|
308
|
+
let kora;
|
|
309
|
+
beforeEach(() => {
|
|
310
|
+
const plugin = koraPlugin(mockConfig);
|
|
311
|
+
const client = plugin({});
|
|
312
|
+
kora = client.kora;
|
|
313
|
+
});
|
|
314
|
+
it('should propagate RPC errors', async () => {
|
|
315
|
+
mockErrorResponse({ code: -32601, message: 'Method not found' });
|
|
316
|
+
await expect(kora.getConfig()).rejects.toThrow('RPC Error -32601: Method not found');
|
|
317
|
+
});
|
|
318
|
+
it('should propagate network errors', async () => {
|
|
319
|
+
mockFetch.mockRejectedValueOnce(new Error('Network error'));
|
|
320
|
+
await expect(kora.getConfig()).rejects.toThrow('Network error');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
describe('KoraApi Type Export', () => {
|
|
324
|
+
it('should export KoraApi type correctly', () => {
|
|
325
|
+
// This test verifies the KoraApi type is correctly exported
|
|
326
|
+
const plugin = koraPlugin(mockConfig);
|
|
327
|
+
const client = plugin({});
|
|
328
|
+
// Type check - assign to KoraApi type
|
|
329
|
+
const api = client.kora;
|
|
330
|
+
expect(api).toBeDefined();
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
describe('createEmptyClient Integration', () => {
|
|
334
|
+
it('should initialize kora property on Kit client', () => {
|
|
335
|
+
const client = createEmptyClient().use(koraPlugin(mockConfig));
|
|
336
|
+
expect(client).toHaveProperty('kora');
|
|
337
|
+
expect(client.kora).toBeDefined();
|
|
338
|
+
});
|
|
339
|
+
it('should expose all Kora RPC methods', () => {
|
|
340
|
+
const client = createEmptyClient().use(koraPlugin(mockConfig));
|
|
341
|
+
expect(typeof client.kora.getConfig).toBe('function');
|
|
342
|
+
expect(typeof client.kora.getPayerSigner).toBe('function');
|
|
343
|
+
expect(typeof client.kora.getBlockhash).toBe('function');
|
|
344
|
+
expect(typeof client.kora.getSupportedTokens).toBe('function');
|
|
345
|
+
expect(typeof client.kora.estimateTransactionFee).toBe('function');
|
|
346
|
+
expect(typeof client.kora.signTransaction).toBe('function');
|
|
347
|
+
expect(typeof client.kora.signAndSendTransaction).toBe('function');
|
|
348
|
+
expect(typeof client.kora.transferTransaction).toBe('function');
|
|
349
|
+
expect(typeof client.kora.getPaymentInstruction).toBe('function');
|
|
350
|
+
});
|
|
351
|
+
it('should work with authentication config', () => {
|
|
352
|
+
const authConfig = {
|
|
353
|
+
endpoint: mockEndpoint,
|
|
354
|
+
apiKey: 'test-api-key',
|
|
355
|
+
hmacSecret: 'test-hmac-secret',
|
|
356
|
+
};
|
|
357
|
+
const client = createEmptyClient().use(koraPlugin(authConfig));
|
|
358
|
+
expect(client.kora).toBeDefined();
|
|
359
|
+
expect(typeof client.kora.getConfig).toBe('function');
|
|
360
|
+
});
|
|
361
|
+
it('should compose with other plugins', () => {
|
|
362
|
+
// Simulate another plugin that adds a different property
|
|
363
|
+
const otherPlugin = (c) => ({
|
|
364
|
+
...c,
|
|
365
|
+
other: { foo: () => 'bar' },
|
|
366
|
+
});
|
|
367
|
+
const client = createEmptyClient().use(koraPlugin(mockConfig)).use(otherPlugin);
|
|
368
|
+
// Both plugins should be available
|
|
369
|
+
expect(client.kora).toBeDefined();
|
|
370
|
+
expect(client.other).toBeDefined();
|
|
371
|
+
expect(typeof client.kora.getConfig).toBe('function');
|
|
372
|
+
expect(client.other.foo()).toBe('bar');
|
|
373
|
+
});
|
|
374
|
+
it('should call RPC methods correctly', async () => {
|
|
375
|
+
const mockResponse = {
|
|
376
|
+
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
377
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
378
|
+
};
|
|
379
|
+
mockSuccessfulResponse(mockResponse);
|
|
380
|
+
const client = createEmptyClient().use(koraPlugin(mockConfig));
|
|
381
|
+
const result = await client.kora.getPayerSigner();
|
|
382
|
+
expect(result.signer_address).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
383
|
+
expect(result.payment_address).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
});
|
package/dist/test/setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getCreateAccountInstruction } from '@solana-program/system';
|
|
2
2
|
import { findAssociatedTokenPda, getCreateAssociatedTokenIdempotentInstructionAsync, getInitializeMintInstruction, getMintSize, getMintToInstruction, TOKEN_PROGRAM_ADDRESS, } from '@solana-program/token';
|
|
3
|
-
import { airdropFactory, createSolanaRpc, createSolanaRpcSubscriptions, lamports, sendAndConfirmTransactionFactory, pipe, createTransactionMessage, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageFeePayerSigner, appendTransactionMessageInstructions, signTransactionMessageWithSigners, getSignatureFromTransaction, assertIsAddress, createKeyPairSignerFromBytes, getBase58Encoder, } from '@solana/kit';
|
|
3
|
+
import { airdropFactory, createSolanaRpc, createSolanaRpcSubscriptions, lamports, sendAndConfirmTransactionFactory, pipe, createTransactionMessage, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageFeePayerSigner, appendTransactionMessageInstructions, signTransactionMessageWithSigners, getSignatureFromTransaction, assertIsAddress, createKeyPairSignerFromBytes, getBase58Encoder, assertIsSendableTransaction, assertIsTransactionWithBlockhashLifetime, } from '@solana/kit';
|
|
4
4
|
import { updateOrAppendSetComputeUnitLimitInstruction, updateOrAppendSetComputeUnitPriceInstruction, MAX_COMPUTE_UNIT_LIMIT, } from '@solana-program/compute-budget';
|
|
5
5
|
import { config } from 'dotenv';
|
|
6
6
|
import path from 'path';
|
|
@@ -94,6 +94,8 @@ const createDefaultTransaction = async (client, feePayer, computeLimit = MAX_COM
|
|
|
94
94
|
const signAndSendTransaction = async (client, transactionMessage, commitment) => {
|
|
95
95
|
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
|
|
96
96
|
const signature = getSignatureFromTransaction(signedTransaction);
|
|
97
|
+
assertIsSendableTransaction(signedTransaction);
|
|
98
|
+
assertIsTransactionWithBlockhashLifetime(signedTransaction);
|
|
97
99
|
await sendAndConfirmTransactionFactory(client)(signedTransaction, { commitment, skipPreflight: true });
|
|
98
100
|
return signature;
|
|
99
101
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/kora",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "TypeScript SDK for Kora RPC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -16,12 +16,16 @@
|
|
|
16
16
|
],
|
|
17
17
|
"author": "",
|
|
18
18
|
"license": "MIT",
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"@solana-program/token": "^0.9.0",
|
|
21
|
+
"@solana/kit": "^5.0.0"
|
|
22
|
+
},
|
|
19
23
|
"devDependencies": {
|
|
20
|
-
"@solana-program/compute-budget": "^0.
|
|
21
|
-
"@solana-program/system": "^0.
|
|
22
|
-
"@solana-program/token": "^0.
|
|
23
|
-
"@solana/kit": "^
|
|
24
|
-
"@solana/prettier-config-solana": "^0.0.
|
|
24
|
+
"@solana-program/compute-budget": "^0.11.0",
|
|
25
|
+
"@solana-program/system": "^0.10.0",
|
|
26
|
+
"@solana-program/token": "^0.9.0",
|
|
27
|
+
"@solana/kit": "^5.4.0",
|
|
28
|
+
"@solana/prettier-config-solana": "^0.0.6",
|
|
25
29
|
"@types/jest": "^29.5.12",
|
|
26
30
|
"@types/node": "^20.17.27",
|
|
27
31
|
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
@@ -34,7 +38,8 @@
|
|
|
34
38
|
"ts-node": "^10.9.2",
|
|
35
39
|
"typedoc": "^0.28.9",
|
|
36
40
|
"typedoc-plugin-markdown": "^4.8.0",
|
|
37
|
-
"typescript": "^5.3.3"
|
|
41
|
+
"typescript": "^5.3.3",
|
|
42
|
+
"ws": "^8.18.3"
|
|
38
43
|
},
|
|
39
44
|
"scripts": {
|
|
40
45
|
"build": "tsc",
|