@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.
- package/dist/src/client.d.ts +212 -7
- package/dist/src/client.js +234 -17
- package/dist/src/error.d.ts +41 -0
- package/dist/src/error.js +54 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/kit/executor.d.ts +2 -2
- package/dist/src/kit/executor.js +20 -7
- package/dist/src/kit/index.d.ts +85 -25
- package/dist/src/kit/index.js +79 -49
- package/dist/src/kit/payment.js +3 -2
- package/dist/src/kit/planner.d.ts +2 -2
- package/dist/src/plugin.d.ts +85 -0
- package/dist/src/plugin.js +179 -0
- package/dist/src/types/index.d.ts +200 -80
- package/dist/test/auth-setup.js +4 -4
- package/dist/test/integration.test.js +223 -298
- package/dist/test/kit-client.test.js +66 -3
- package/dist/test/plugin.test.js +169 -79
- package/dist/test/setup.d.ts +8 -15
- package/dist/test/setup.js +76 -153
- package/dist/test/unit.test.js +365 -161
- package/package.json +37 -34
- package/dist/src/kit/plugin.d.ts +0 -31
- package/dist/src/kit/plugin.js +0 -107
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { createKitKoraClient } from '../src/kit/index.js';
|
|
2
|
-
import { address, createNoopSigner } from '@solana/kit';
|
|
1
|
+
import { createKitKoraClient, kora } from '../src/kit/index.js';
|
|
2
|
+
import { address, createClient, createNoopSigner } from '@solana/kit';
|
|
3
|
+
import { identity, signer } from '@solana/kit-plugin-signer';
|
|
3
4
|
// Mock fetch globally
|
|
4
5
|
const mockFetch = jest.fn();
|
|
5
6
|
global.fetch = mockFetch;
|
|
@@ -80,7 +81,7 @@ describe('createKitKoraClient', () => {
|
|
|
80
81
|
rpcUrl: MOCK_RPC_URL,
|
|
81
82
|
feeToken: MOCK_FEE_TOKEN,
|
|
82
83
|
feePayerWallet: MOCK_WALLET,
|
|
83
|
-
})).rejects.toThrow('
|
|
84
|
+
})).rejects.toThrow('Kora Error -32000: Server error');
|
|
84
85
|
});
|
|
85
86
|
it('should expose kora namespace for raw RPC access', async () => {
|
|
86
87
|
mockRpcResponse({
|
|
@@ -324,6 +325,24 @@ describe('createKitKoraClient', () => {
|
|
|
324
325
|
const headers = mockFetch.mock.calls[0][1].headers;
|
|
325
326
|
expect(headers['x-api-key']).toBe('test-api-key');
|
|
326
327
|
});
|
|
328
|
+
it('should pass getRecaptchaToken to underlying KoraClient', async () => {
|
|
329
|
+
const mockGetToken = jest.fn().mockResolvedValue('test-recaptcha-token');
|
|
330
|
+
mockRpcResponse({
|
|
331
|
+
signer_address: MOCK_PAYER_ADDRESS,
|
|
332
|
+
payment_address: MOCK_PAYMENT_ADDRESS,
|
|
333
|
+
});
|
|
334
|
+
await createKitKoraClient({
|
|
335
|
+
endpoint: MOCK_ENDPOINT,
|
|
336
|
+
rpcUrl: MOCK_RPC_URL,
|
|
337
|
+
feeToken: MOCK_FEE_TOKEN,
|
|
338
|
+
feePayerWallet: MOCK_WALLET,
|
|
339
|
+
getRecaptchaToken: mockGetToken,
|
|
340
|
+
});
|
|
341
|
+
// The init call should include the reCAPTCHA token header
|
|
342
|
+
expect(mockGetToken).toHaveBeenCalledTimes(1);
|
|
343
|
+
const headers = mockFetch.mock.calls[0][1].headers;
|
|
344
|
+
expect(headers['x-recaptcha-token']).toBe('test-recaptcha-token');
|
|
345
|
+
});
|
|
327
346
|
});
|
|
328
347
|
describe('Token-2022 support', () => {
|
|
329
348
|
it('should accept tokenProgramId in config', async () => {
|
|
@@ -471,3 +490,47 @@ describe('createKitKoraClient', () => {
|
|
|
471
490
|
});
|
|
472
491
|
});
|
|
473
492
|
});
|
|
493
|
+
describe('kora() bundle plugin', () => {
|
|
494
|
+
beforeEach(() => {
|
|
495
|
+
mockFetch.mockClear();
|
|
496
|
+
});
|
|
497
|
+
afterEach(() => {
|
|
498
|
+
jest.resetAllMocks();
|
|
499
|
+
});
|
|
500
|
+
it('composes with identity() and exposes the same surface as the wrapper', async () => {
|
|
501
|
+
mockRpcResponse({
|
|
502
|
+
signer_address: MOCK_PAYER_ADDRESS,
|
|
503
|
+
payment_address: MOCK_PAYMENT_ADDRESS,
|
|
504
|
+
});
|
|
505
|
+
const client = await createClient()
|
|
506
|
+
.use(identity(MOCK_WALLET))
|
|
507
|
+
.use(kora({
|
|
508
|
+
endpoint: MOCK_ENDPOINT,
|
|
509
|
+
rpcUrl: MOCK_RPC_URL,
|
|
510
|
+
feeToken: MOCK_FEE_TOKEN,
|
|
511
|
+
}));
|
|
512
|
+
expect(client.identity.address).toBe(MOCK_WALLET_ADDRESS);
|
|
513
|
+
expect(client.payer.address).toBe(MOCK_PAYER_ADDRESS);
|
|
514
|
+
expect(client.paymentAddress).toBe(MOCK_PAYMENT_ADDRESS);
|
|
515
|
+
expect(typeof client.sendTransaction).toBe('function');
|
|
516
|
+
expect(typeof client.planTransaction).toBe('function');
|
|
517
|
+
expect(client.kora).toBeDefined();
|
|
518
|
+
});
|
|
519
|
+
// TODO: re-enable once @solana/kit supports overriding an already-set field on an
|
|
520
|
+
// extended client.
|
|
521
|
+
it.skip('overrides client.payer when the caller used signer() (sets identity + payer)', async () => {
|
|
522
|
+
mockRpcResponse({
|
|
523
|
+
signer_address: MOCK_PAYER_ADDRESS,
|
|
524
|
+
payment_address: MOCK_PAYMENT_ADDRESS,
|
|
525
|
+
});
|
|
526
|
+
const client = await createClient()
|
|
527
|
+
.use(signer(MOCK_WALLET))
|
|
528
|
+
.use(kora({
|
|
529
|
+
endpoint: MOCK_ENDPOINT,
|
|
530
|
+
rpcUrl: MOCK_RPC_URL,
|
|
531
|
+
feeToken: MOCK_FEE_TOKEN,
|
|
532
|
+
}));
|
|
533
|
+
expect(client.identity.address).toBe(MOCK_WALLET_ADDRESS);
|
|
534
|
+
expect(client.payer.address).toBe(MOCK_PAYER_ADDRESS);
|
|
535
|
+
});
|
|
536
|
+
});
|
package/dist/test/plugin.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { koraPlugin } from '../src/
|
|
1
|
+
import { createClient } from '@solana/kit';
|
|
2
|
+
import { koraPlugin } from '../src/plugin.js';
|
|
3
3
|
// Mock fetch globally
|
|
4
4
|
const mockFetch = jest.fn();
|
|
5
5
|
global.fetch = mockFetch;
|
|
@@ -12,8 +12,8 @@ describe('Kora Kit Plugin', () => {
|
|
|
12
12
|
const mockSuccessfulResponse = (result) => {
|
|
13
13
|
mockFetch.mockResolvedValueOnce({
|
|
14
14
|
json: jest.fn().mockResolvedValueOnce({
|
|
15
|
-
jsonrpc: '2.0',
|
|
16
15
|
id: 1,
|
|
16
|
+
jsonrpc: '2.0',
|
|
17
17
|
result,
|
|
18
18
|
}),
|
|
19
19
|
});
|
|
@@ -22,9 +22,9 @@ describe('Kora Kit Plugin', () => {
|
|
|
22
22
|
const mockErrorResponse = (error) => {
|
|
23
23
|
mockFetch.mockResolvedValueOnce({
|
|
24
24
|
json: jest.fn().mockResolvedValueOnce({
|
|
25
|
-
jsonrpc: '2.0',
|
|
26
|
-
id: 1,
|
|
27
25
|
error,
|
|
26
|
+
id: 1,
|
|
27
|
+
jsonrpc: '2.0',
|
|
28
28
|
}),
|
|
29
29
|
});
|
|
30
30
|
};
|
|
@@ -41,11 +41,14 @@ describe('Kora Kit Plugin', () => {
|
|
|
41
41
|
expect(typeof enhanced.kora.getConfig).toBe('function');
|
|
42
42
|
expect(typeof enhanced.kora.getPayerSigner).toBe('function');
|
|
43
43
|
expect(typeof enhanced.kora.getBlockhash).toBe('function');
|
|
44
|
+
expect(typeof enhanced.kora.getVersion).toBe('function');
|
|
44
45
|
expect(typeof enhanced.kora.getSupportedTokens).toBe('function');
|
|
45
46
|
expect(typeof enhanced.kora.estimateTransactionFee).toBe('function');
|
|
47
|
+
expect(typeof enhanced.kora.estimateBundleFee).toBe('function');
|
|
46
48
|
expect(typeof enhanced.kora.signTransaction).toBe('function');
|
|
47
49
|
expect(typeof enhanced.kora.signAndSendTransaction).toBe('function');
|
|
48
|
-
expect(typeof enhanced.kora.
|
|
50
|
+
expect(typeof enhanced.kora.signBundle).toBe('function');
|
|
51
|
+
expect(typeof enhanced.kora.signAndSendBundle).toBe('function');
|
|
49
52
|
expect(typeof enhanced.kora.getPaymentInstruction).toBe('function');
|
|
50
53
|
});
|
|
51
54
|
it('should work with empty client object', () => {
|
|
@@ -55,8 +58,8 @@ describe('Kora Kit Plugin', () => {
|
|
|
55
58
|
});
|
|
56
59
|
it('should support authentication options', () => {
|
|
57
60
|
const authConfig = {
|
|
58
|
-
endpoint: mockEndpoint,
|
|
59
61
|
apiKey: 'test-api-key',
|
|
62
|
+
endpoint: mockEndpoint,
|
|
60
63
|
hmacSecret: 'test-hmac-secret',
|
|
61
64
|
};
|
|
62
65
|
const plugin = koraPlugin(authConfig);
|
|
@@ -74,67 +77,67 @@ describe('Kora Kit Plugin', () => {
|
|
|
74
77
|
describe('getConfig', () => {
|
|
75
78
|
it('should return Kit-typed Address arrays', async () => {
|
|
76
79
|
const rawResponse = {
|
|
80
|
+
enabled_methods: {
|
|
81
|
+
estimate_transaction_fee: true,
|
|
82
|
+
get_blockhash: true,
|
|
83
|
+
get_config: true,
|
|
84
|
+
get_supported_tokens: true,
|
|
85
|
+
liveness: true,
|
|
86
|
+
sign_and_send_transaction: true,
|
|
87
|
+
sign_transaction: true,
|
|
88
|
+
transfer_transaction: true,
|
|
89
|
+
},
|
|
77
90
|
fee_payers: ['DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7'],
|
|
78
91
|
validation_config: {
|
|
79
|
-
max_allowed_lamports: 1000000,
|
|
80
|
-
max_signatures: 10,
|
|
81
|
-
price_source: 'Jupiter',
|
|
82
92
|
allowed_programs: ['11111111111111111111111111111111'],
|
|
83
|
-
allowed_tokens: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'],
|
|
84
93
|
allowed_spl_paid_tokens: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'],
|
|
94
|
+
allowed_tokens: ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'],
|
|
85
95
|
disallowed_accounts: [],
|
|
86
96
|
fee_payer_policy: {
|
|
87
|
-
|
|
97
|
+
spl_token: {
|
|
98
|
+
allow_approve: true,
|
|
99
|
+
allow_burn: true,
|
|
100
|
+
allow_close_account: true,
|
|
101
|
+
allow_freeze_account: true,
|
|
102
|
+
allow_mint_to: true,
|
|
103
|
+
allow_revoke: true,
|
|
104
|
+
allow_set_authority: true,
|
|
105
|
+
allow_thaw_account: true,
|
|
88
106
|
allow_transfer: true,
|
|
107
|
+
},
|
|
108
|
+
system: {
|
|
109
|
+
allow_allocate: true,
|
|
89
110
|
allow_assign: true,
|
|
90
111
|
allow_create_account: true,
|
|
91
|
-
|
|
112
|
+
allow_transfer: true,
|
|
92
113
|
nonce: {
|
|
93
|
-
allow_initialize: true,
|
|
94
114
|
allow_advance: true,
|
|
95
115
|
allow_authorize: true,
|
|
116
|
+
allow_initialize: true,
|
|
96
117
|
allow_withdraw: true,
|
|
97
118
|
},
|
|
98
119
|
},
|
|
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
120
|
token_2022: {
|
|
111
|
-
|
|
121
|
+
allow_approve: true,
|
|
112
122
|
allow_burn: true,
|
|
113
123
|
allow_close_account: true,
|
|
114
|
-
|
|
124
|
+
allow_freeze_account: true,
|
|
125
|
+
allow_mint_to: true,
|
|
115
126
|
allow_revoke: true,
|
|
116
127
|
allow_set_authority: true,
|
|
117
|
-
allow_mint_to: true,
|
|
118
|
-
allow_freeze_account: true,
|
|
119
128
|
allow_thaw_account: true,
|
|
129
|
+
allow_transfer: true,
|
|
120
130
|
},
|
|
121
131
|
},
|
|
122
|
-
|
|
132
|
+
max_allowed_lamports: 1000000,
|
|
133
|
+
max_signatures: 10,
|
|
134
|
+
price: { margin: 0.1, type: 'margin' },
|
|
135
|
+
price_source: 'Jupiter',
|
|
123
136
|
token2022: {
|
|
124
|
-
blocked_mint_extensions: [],
|
|
125
137
|
blocked_account_extensions: [],
|
|
138
|
+
blocked_mint_extensions: [],
|
|
126
139
|
},
|
|
127
140
|
},
|
|
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
141
|
};
|
|
139
142
|
mockSuccessfulResponse(rawResponse);
|
|
140
143
|
const result = await kora.getConfig();
|
|
@@ -146,12 +149,47 @@ describe('Kora Kit Plugin', () => {
|
|
|
146
149
|
expect(result.validation_config.allowed_tokens).toHaveLength(1);
|
|
147
150
|
expect(result.validation_config.allowed_tokens[0]).toBe('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
148
151
|
});
|
|
152
|
+
it('should pass through the "All" wildcard for allowed_programs without crashing', async () => {
|
|
153
|
+
// Regression: ProgramsConfig::All serializes as the string "All" on the wire,
|
|
154
|
+
// which would crash the kit wrapper if it called .map() unconditionally.
|
|
155
|
+
const rawResponse = {
|
|
156
|
+
enabled_methods: {
|
|
157
|
+
estimate_transaction_fee: true,
|
|
158
|
+
get_blockhash: true,
|
|
159
|
+
get_config: true,
|
|
160
|
+
get_supported_tokens: true,
|
|
161
|
+
liveness: true,
|
|
162
|
+
sign_and_send_transaction: true,
|
|
163
|
+
sign_transaction: true,
|
|
164
|
+
transfer_transaction: true,
|
|
165
|
+
},
|
|
166
|
+
fee_payers: ['DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7'],
|
|
167
|
+
validation_config: {
|
|
168
|
+
allowed_programs: 'All',
|
|
169
|
+
allowed_spl_paid_tokens: [],
|
|
170
|
+
allowed_tokens: [],
|
|
171
|
+
disallowed_accounts: [],
|
|
172
|
+
fee_payer_policy: {},
|
|
173
|
+
max_allowed_lamports: 1000000,
|
|
174
|
+
max_signatures: 10,
|
|
175
|
+
price: { margin: 0.1, type: 'margin' },
|
|
176
|
+
price_source: 'Jupiter',
|
|
177
|
+
token2022: {
|
|
178
|
+
blocked_account_extensions: [],
|
|
179
|
+
blocked_mint_extensions: [],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
mockSuccessfulResponse(rawResponse);
|
|
184
|
+
const result = await kora.getConfig();
|
|
185
|
+
expect(result.validation_config.allowed_programs).toBe('All');
|
|
186
|
+
});
|
|
149
187
|
});
|
|
150
188
|
describe('getPayerSigner', () => {
|
|
151
189
|
it('should return Kit-typed Address fields', async () => {
|
|
152
190
|
const rawResponse = {
|
|
153
|
-
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
154
191
|
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
192
|
+
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
155
193
|
};
|
|
156
194
|
mockSuccessfulResponse(rawResponse);
|
|
157
195
|
const result = await kora.getPayerSigner();
|
|
@@ -174,6 +212,16 @@ describe('Kora Kit Plugin', () => {
|
|
|
174
212
|
expect(hash).toBe('4NxM2D4kQcipkzMWBWQME5YSVnj5kT8QKA7rvb3rKLvE');
|
|
175
213
|
});
|
|
176
214
|
});
|
|
215
|
+
describe('getVersion', () => {
|
|
216
|
+
it('should return version string', async () => {
|
|
217
|
+
const rawResponse = {
|
|
218
|
+
version: '2.0.0',
|
|
219
|
+
};
|
|
220
|
+
mockSuccessfulResponse(rawResponse);
|
|
221
|
+
const result = await kora.getVersion();
|
|
222
|
+
expect(result.version).toBe('2.0.0');
|
|
223
|
+
});
|
|
224
|
+
});
|
|
177
225
|
describe('getSupportedTokens', () => {
|
|
178
226
|
it('should return Kit-typed Address array', async () => {
|
|
179
227
|
const rawResponse = {
|
|
@@ -197,13 +245,13 @@ describe('Kora Kit Plugin', () => {
|
|
|
197
245
|
const rawResponse = {
|
|
198
246
|
fee_in_lamports: 5000,
|
|
199
247
|
fee_in_token: 50,
|
|
200
|
-
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
201
248
|
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
249
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
202
250
|
};
|
|
203
251
|
mockSuccessfulResponse(rawResponse);
|
|
204
252
|
const result = await kora.estimateTransactionFee({
|
|
205
|
-
transaction: 'base64EncodedTransaction',
|
|
206
253
|
fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
254
|
+
transaction: 'base64EncodedTransaction',
|
|
207
255
|
});
|
|
208
256
|
// Type assertions
|
|
209
257
|
const signerPubkey = result.signer_pubkey;
|
|
@@ -214,6 +262,28 @@ describe('Kora Kit Plugin', () => {
|
|
|
214
262
|
expect(paymentAddr).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
215
263
|
});
|
|
216
264
|
});
|
|
265
|
+
describe('estimateBundleFee', () => {
|
|
266
|
+
it('should return Kit-typed Address fields for bundle', async () => {
|
|
267
|
+
const rawResponse = {
|
|
268
|
+
fee_in_lamports: 15000,
|
|
269
|
+
fee_in_token: 150,
|
|
270
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
271
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
272
|
+
};
|
|
273
|
+
mockSuccessfulResponse(rawResponse);
|
|
274
|
+
const result = await kora.estimateBundleFee({
|
|
275
|
+
fee_token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
276
|
+
transactions: ['base64Tx1', 'base64Tx2', 'base64Tx3'],
|
|
277
|
+
});
|
|
278
|
+
// Type assertions
|
|
279
|
+
const signerPubkey = result.signer_pubkey;
|
|
280
|
+
const paymentAddr = result.payment_address;
|
|
281
|
+
expect(result.fee_in_lamports).toBe(15000);
|
|
282
|
+
expect(result.fee_in_token).toBe(150);
|
|
283
|
+
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
284
|
+
expect(paymentAddr).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
217
287
|
describe('signTransaction', () => {
|
|
218
288
|
it('should return Kit-typed response with Base64EncodedWireTransaction', async () => {
|
|
219
289
|
const rawResponse = {
|
|
@@ -232,9 +302,11 @@ describe('Kora Kit Plugin', () => {
|
|
|
232
302
|
});
|
|
233
303
|
});
|
|
234
304
|
describe('signAndSendTransaction', () => {
|
|
235
|
-
it('should return Kit-typed response with Base64EncodedWireTransaction', async () => {
|
|
305
|
+
it('should return Kit-typed response with Signature and Base64EncodedWireTransaction', async () => {
|
|
306
|
+
// Use a valid base58 signature (88 characters, valid base58 alphabet)
|
|
307
|
+
const mockSignature = '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW';
|
|
236
308
|
const rawResponse = {
|
|
237
|
-
signature:
|
|
309
|
+
signature: mockSignature,
|
|
238
310
|
signed_transaction: 'base64SignedTransaction',
|
|
239
311
|
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
240
312
|
};
|
|
@@ -243,37 +315,52 @@ describe('Kora Kit Plugin', () => {
|
|
|
243
315
|
transaction: 'base64EncodedTransaction',
|
|
244
316
|
});
|
|
245
317
|
// Type assertions - verify Kit types
|
|
318
|
+
const sig = result.signature;
|
|
246
319
|
const signedTx = result.signed_transaction;
|
|
247
320
|
const signerPubkey = result.signer_pubkey;
|
|
321
|
+
expect(sig).toBe(mockSignature);
|
|
248
322
|
expect(signedTx).toBe('base64SignedTransaction');
|
|
249
323
|
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
250
324
|
});
|
|
251
325
|
});
|
|
252
|
-
describe('
|
|
253
|
-
it('should return Kit-typed response with Base64EncodedWireTransaction
|
|
326
|
+
describe('signBundle', () => {
|
|
327
|
+
it('should return Kit-typed response with Base64EncodedWireTransaction array', async () => {
|
|
254
328
|
const rawResponse = {
|
|
255
|
-
|
|
256
|
-
message: 'base64Message',
|
|
257
|
-
blockhash: '4NxM2D4kQcipkzMWBWQME5YSVnj5kT8QKA7rvb3rKLvE',
|
|
329
|
+
signed_transactions: ['base64SignedTx1', 'base64SignedTx2'],
|
|
258
330
|
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
259
|
-
instructions: [],
|
|
260
331
|
};
|
|
261
332
|
mockSuccessfulResponse(rawResponse);
|
|
262
|
-
const result = await kora.
|
|
263
|
-
|
|
264
|
-
token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
265
|
-
source: 'sourceWallet',
|
|
266
|
-
destination: 'destWallet',
|
|
333
|
+
const result = await kora.signBundle({
|
|
334
|
+
transactions: ['base64Tx1', 'base64Tx2'],
|
|
267
335
|
});
|
|
268
336
|
// Type assertions - verify Kit types
|
|
269
|
-
const
|
|
270
|
-
const hash = result.blockhash;
|
|
337
|
+
const signedTxs = result.signed_transactions;
|
|
271
338
|
const signerPubkey = result.signer_pubkey;
|
|
272
|
-
expect(
|
|
273
|
-
expect(
|
|
274
|
-
expect(
|
|
339
|
+
expect(signedTxs).toHaveLength(2);
|
|
340
|
+
expect(signedTxs[0]).toBe('base64SignedTx1');
|
|
341
|
+
expect(signedTxs[1]).toBe('base64SignedTx2');
|
|
275
342
|
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
276
|
-
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
describe('signAndSendBundle', () => {
|
|
346
|
+
it('should return Kit-typed response with Base64EncodedWireTransaction array and bundle UUID', async () => {
|
|
347
|
+
const rawResponse = {
|
|
348
|
+
bundle_uuid: 'jito-bundle-uuid-12345',
|
|
349
|
+
signed_transactions: ['base64SignedTx1', 'base64SignedTx2'],
|
|
350
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
351
|
+
};
|
|
352
|
+
mockSuccessfulResponse(rawResponse);
|
|
353
|
+
const result = await kora.signAndSendBundle({
|
|
354
|
+
transactions: ['base64Tx1', 'base64Tx2'],
|
|
355
|
+
});
|
|
356
|
+
// Type assertions - verify Kit types
|
|
357
|
+
const signedTxs = result.signed_transactions;
|
|
358
|
+
const signerPubkey = result.signer_pubkey;
|
|
359
|
+
expect(signedTxs).toHaveLength(2);
|
|
360
|
+
expect(signedTxs[0]).toBe('base64SignedTx1');
|
|
361
|
+
expect(signedTxs[1]).toBe('base64SignedTx2');
|
|
362
|
+
expect(signerPubkey).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
363
|
+
expect(result.bundle_uuid).toBe('jito-bundle-uuid-12345');
|
|
277
364
|
});
|
|
278
365
|
});
|
|
279
366
|
describe('getPaymentInstruction', () => {
|
|
@@ -281,16 +368,16 @@ describe('Kora Kit Plugin', () => {
|
|
|
281
368
|
const mockFeeEstimate = {
|
|
282
369
|
fee_in_lamports: 5000,
|
|
283
370
|
fee_in_token: 50000,
|
|
284
|
-
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
285
371
|
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
372
|
+
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
286
373
|
};
|
|
287
374
|
const testTx = 'Aoq7ymA5OGP+gmDXiY5m3cYXlY2Rz/a/gFjOgt9ZuoCS7UzuiGGaEnW2OOtvHvMQHkkD7Z4LRF5B63ftu+1oZwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgECB1urjQEjgFgzqYhJ8IXJeSg4cJP1j1g2CJstOQTDchOKUzqH3PxgGW3c4V3vZV05A5Y30/MggOBs0Kd00s1JEwg5TaEeaV4+KL2y7fXIAuf6cN0ZQitbhY+G9ExtBSChspOXPgNcy9pYpETe4bmB+fg4bfZx1tnicA/kIyyubczAmbcIKIuniNOOQYG2ggKCz8NjEsHVezrWMatndu1wk6J5miGP26J6Vwp31AljiAajAFuP0D9mWJwSeFuA7J5rPwbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpd/O36SW02zRtNtqk6GFeip2+yBQsVTeSbLL4rWJRkd4CBgQCBQQBCgxAQg8AAAAAAAYGBAIFAwEKDBAnAAAAAAAABg==';
|
|
288
375
|
mockSuccessfulResponse(mockFeeEstimate);
|
|
289
376
|
const result = await kora.getPaymentInstruction({
|
|
290
|
-
transaction: testTx,
|
|
291
377
|
fee_token: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
|
|
292
378
|
source_wallet: '11111111111111111111111111111111',
|
|
293
379
|
token_program_id: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
|
|
380
|
+
transaction: testTx,
|
|
294
381
|
});
|
|
295
382
|
// Type assertions - verify Kit types
|
|
296
383
|
const originalTx = result.original_transaction;
|
|
@@ -314,48 +401,51 @@ describe('Kora Kit Plugin', () => {
|
|
|
314
401
|
});
|
|
315
402
|
it('should propagate RPC errors', async () => {
|
|
316
403
|
mockErrorResponse({ code: -32601, message: 'Method not found' });
|
|
317
|
-
await expect(kora.getConfig()).rejects.toThrow('
|
|
404
|
+
await expect(kora.getConfig()).rejects.toThrow('Kora Error -32601: Method not found');
|
|
318
405
|
});
|
|
319
406
|
it('should propagate network errors', async () => {
|
|
320
407
|
mockFetch.mockRejectedValueOnce(new Error('Network error'));
|
|
321
408
|
await expect(kora.getConfig()).rejects.toThrow('Network error');
|
|
322
409
|
});
|
|
323
410
|
});
|
|
324
|
-
describe('
|
|
325
|
-
it('should export
|
|
326
|
-
// This test verifies the
|
|
411
|
+
describe('KoraApi Type Export', () => {
|
|
412
|
+
it('should export KoraApi type correctly', () => {
|
|
413
|
+
// This test verifies the KoraApi type is correctly exported
|
|
327
414
|
const plugin = koraPlugin(mockConfig);
|
|
328
415
|
const client = plugin({});
|
|
329
|
-
// Type check - assign to
|
|
416
|
+
// Type check - assign to KoraApi type
|
|
330
417
|
const api = client.kora;
|
|
331
418
|
expect(api).toBeDefined();
|
|
332
419
|
});
|
|
333
420
|
});
|
|
334
|
-
describe('
|
|
421
|
+
describe('createClient Integration', () => {
|
|
335
422
|
it('should initialize kora property on Kit client', () => {
|
|
336
|
-
const client =
|
|
423
|
+
const client = createClient().use(koraPlugin(mockConfig));
|
|
337
424
|
expect(client).toHaveProperty('kora');
|
|
338
425
|
expect(client.kora).toBeDefined();
|
|
339
426
|
});
|
|
340
427
|
it('should expose all Kora RPC methods', () => {
|
|
341
|
-
const client =
|
|
428
|
+
const client = createClient().use(koraPlugin(mockConfig));
|
|
342
429
|
expect(typeof client.kora.getConfig).toBe('function');
|
|
343
430
|
expect(typeof client.kora.getPayerSigner).toBe('function');
|
|
344
431
|
expect(typeof client.kora.getBlockhash).toBe('function');
|
|
432
|
+
expect(typeof client.kora.getVersion).toBe('function');
|
|
345
433
|
expect(typeof client.kora.getSupportedTokens).toBe('function');
|
|
346
434
|
expect(typeof client.kora.estimateTransactionFee).toBe('function');
|
|
435
|
+
expect(typeof client.kora.estimateBundleFee).toBe('function');
|
|
347
436
|
expect(typeof client.kora.signTransaction).toBe('function');
|
|
348
437
|
expect(typeof client.kora.signAndSendTransaction).toBe('function');
|
|
349
|
-
expect(typeof client.kora.
|
|
438
|
+
expect(typeof client.kora.signBundle).toBe('function');
|
|
439
|
+
expect(typeof client.kora.signAndSendBundle).toBe('function');
|
|
350
440
|
expect(typeof client.kora.getPaymentInstruction).toBe('function');
|
|
351
441
|
});
|
|
352
442
|
it('should work with authentication config', () => {
|
|
353
443
|
const authConfig = {
|
|
354
|
-
endpoint: mockEndpoint,
|
|
355
444
|
apiKey: 'test-api-key',
|
|
445
|
+
endpoint: mockEndpoint,
|
|
356
446
|
hmacSecret: 'test-hmac-secret',
|
|
357
447
|
};
|
|
358
|
-
const client =
|
|
448
|
+
const client = createClient().use(koraPlugin(authConfig));
|
|
359
449
|
expect(client.kora).toBeDefined();
|
|
360
450
|
expect(typeof client.kora.getConfig).toBe('function');
|
|
361
451
|
});
|
|
@@ -365,7 +455,7 @@ describe('Kora Kit Plugin', () => {
|
|
|
365
455
|
...c,
|
|
366
456
|
other: { foo: () => 'bar' },
|
|
367
457
|
});
|
|
368
|
-
const client =
|
|
458
|
+
const client = createClient().use(koraPlugin(mockConfig)).use(otherPlugin);
|
|
369
459
|
// Both plugins should be available
|
|
370
460
|
expect(client.kora).toBeDefined();
|
|
371
461
|
expect(client.other).toBeDefined();
|
|
@@ -374,11 +464,11 @@ describe('Kora Kit Plugin', () => {
|
|
|
374
464
|
});
|
|
375
465
|
it('should call RPC methods correctly', async () => {
|
|
376
466
|
const mockResponse = {
|
|
377
|
-
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
378
467
|
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
468
|
+
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
379
469
|
};
|
|
380
470
|
mockSuccessfulResponse(mockResponse);
|
|
381
|
-
const client =
|
|
471
|
+
const client = createClient().use(koraPlugin(mockConfig));
|
|
382
472
|
const result = await client.kora.getPayerSigner();
|
|
383
473
|
expect(result.signer_address).toBe('DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
|
384
474
|
expect(result.payment_address).toBe('PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7');
|
package/dist/test/setup.d.ts
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Address, KeyPairSigner } from '@solana/kit';
|
|
2
2
|
import { KoraClient } from '../src/index.js';
|
|
3
3
|
interface TestSuite {
|
|
4
|
+
destinationAddress: Address<string>;
|
|
5
|
+
koraAddress: Address<string>;
|
|
4
6
|
koraClient: KoraClient;
|
|
5
7
|
koraRpcUrl: string;
|
|
6
8
|
testWallet: KeyPairSigner<string>;
|
|
7
9
|
usdcMint: Address<string>;
|
|
8
|
-
destinationAddress: Address<string>;
|
|
9
|
-
koraAddress: Address<string>;
|
|
10
|
-
authConfig?: {
|
|
11
|
-
apiKey: string;
|
|
12
|
-
hmacSecret: string;
|
|
13
|
-
};
|
|
14
10
|
}
|
|
15
11
|
export declare function loadEnvironmentVariables(): {
|
|
16
|
-
|
|
12
|
+
destinationAddress: Address<string>;
|
|
17
13
|
koraAddress: Address<string>;
|
|
14
|
+
koraRpcUrl: string;
|
|
18
15
|
koraSignerType: string;
|
|
19
|
-
commitment: Commitment;
|
|
20
|
-
tokenDecimals: number;
|
|
21
|
-
tokenDropAmount: number;
|
|
22
16
|
solDropAmount: bigint;
|
|
23
|
-
solanaRpcUrl: string;
|
|
24
|
-
solanaWsUrl: string;
|
|
25
|
-
testWalletSecret: string;
|
|
26
17
|
testUsdcMintSecret: string;
|
|
27
|
-
|
|
18
|
+
testWalletSecret: string;
|
|
19
|
+
tokenDecimals: number;
|
|
20
|
+
tokenDropAmount: number;
|
|
28
21
|
};
|
|
29
22
|
declare function setupTestSuite(): Promise<TestSuite>;
|
|
30
23
|
export default setupTestSuite;
|