@solana/kora 0.2.0-beta.2 → 0.2.0-beta.3

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,5 +1,5 @@
1
- import { KoraClient } from '../src/client.js';
2
1
  import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
2
+ import { KoraClient } from '../src/client.js';
3
3
  import { getInstructionsFromBase64Message } from '../src/utils/transaction.js';
4
4
  // Mock fetch globally
5
5
  const mockFetch = jest.fn();
@@ -11,8 +11,8 @@ describe('KoraClient Unit Tests', () => {
11
11
  const mockSuccessfulResponse = (result) => {
12
12
  mockFetch.mockResolvedValueOnce({
13
13
  json: jest.fn().mockResolvedValueOnce({
14
- jsonrpc: '2.0',
15
14
  id: 1,
15
+ jsonrpc: '2.0',
16
16
  result,
17
17
  }),
18
18
  });
@@ -20,24 +20,24 @@ describe('KoraClient Unit Tests', () => {
20
20
  const mockErrorResponse = (error) => {
21
21
  mockFetch.mockResolvedValueOnce({
22
22
  json: jest.fn().mockResolvedValueOnce({
23
- jsonrpc: '2.0',
24
- id: 1,
25
23
  error,
24
+ id: 1,
25
+ jsonrpc: '2.0',
26
26
  }),
27
27
  });
28
28
  };
29
29
  const expectRpcCall = (method, params = undefined) => {
30
30
  expect(mockFetch).toHaveBeenCalledWith(mockRpcUrl, {
31
- method: 'POST',
32
- headers: {
33
- 'Content-Type': 'application/json',
34
- },
35
31
  body: JSON.stringify({
36
- jsonrpc: '2.0',
37
32
  id: 1,
33
+ jsonrpc: '2.0',
38
34
  method,
39
35
  params,
40
36
  }),
37
+ headers: {
38
+ 'Content-Type': 'application/json',
39
+ },
40
+ method: 'POST',
41
41
  });
42
42
  };
43
43
  const testSuccessfulRpcMethod = async (methodName, clientMethod, expectedResult, params = undefined) => {
@@ -78,81 +78,81 @@ describe('KoraClient Unit Tests', () => {
78
78
  describe('getConfig', () => {
79
79
  it('should return configuration', async () => {
80
80
  const mockConfig = {
81
+ enabled_methods: {
82
+ estimate_bundle_fee: true,
83
+ estimate_transaction_fee: true,
84
+ get_blockhash: true,
85
+ get_config: true,
86
+ get_payer_signer: true,
87
+ get_supported_tokens: true,
88
+ get_version: true,
89
+ liveness: true,
90
+ sign_and_send_bundle: true,
91
+ sign_and_send_transaction: true,
92
+ sign_bundle: true,
93
+ sign_transaction: true,
94
+ transfer_transaction: true,
95
+ },
81
96
  fee_payers: ['test_fee_payer_address'],
82
97
  validation_config: {
83
- max_allowed_lamports: 1000000,
84
- max_signatures: 10,
85
- price_source: 'Jupiter',
86
98
  allowed_programs: ['program1', 'program2'],
87
- allowed_tokens: ['token1', 'token2'],
88
99
  allowed_spl_paid_tokens: ['spl_token1'],
100
+ allowed_tokens: ['token1', 'token2'],
89
101
  disallowed_accounts: ['account1'],
90
102
  fee_payer_policy: {
91
- system: {
103
+ spl_token: {
104
+ allow_approve: true,
105
+ allow_burn: true,
106
+ allow_close_account: true,
107
+ allow_freeze_account: true,
108
+ allow_initialize_account: true,
109
+ allow_initialize_mint: true,
110
+ allow_initialize_multisig: true,
111
+ allow_mint_to: true,
112
+ allow_revoke: true,
113
+ allow_set_authority: true,
114
+ allow_thaw_account: true,
92
115
  allow_transfer: true,
116
+ },
117
+ system: {
118
+ allow_allocate: true,
93
119
  allow_assign: true,
94
120
  allow_create_account: true,
95
- allow_allocate: true,
121
+ allow_transfer: true,
96
122
  nonce: {
97
- allow_initialize: true,
98
123
  allow_advance: true,
99
124
  allow_authorize: true,
125
+ allow_initialize: true,
100
126
  allow_withdraw: true,
101
127
  },
102
128
  },
103
- spl_token: {
104
- allow_transfer: true,
129
+ token_2022: {
130
+ allow_approve: true,
105
131
  allow_burn: true,
106
132
  allow_close_account: true,
107
- allow_approve: true,
108
- allow_revoke: true,
109
- allow_set_authority: true,
110
- allow_mint_to: true,
111
- allow_initialize_mint: true,
133
+ allow_freeze_account: true,
112
134
  allow_initialize_account: true,
135
+ allow_initialize_mint: true,
113
136
  allow_initialize_multisig: true,
114
- allow_freeze_account: true,
115
- allow_thaw_account: true,
116
- },
117
- token_2022: {
118
- allow_transfer: false,
119
- allow_burn: true,
120
- allow_close_account: true,
121
- allow_approve: true,
137
+ allow_mint_to: true,
122
138
  allow_revoke: true,
123
139
  allow_set_authority: true,
124
- allow_mint_to: true,
125
- allow_initialize_mint: true,
126
- allow_initialize_account: true,
127
- allow_initialize_multisig: true,
128
- allow_freeze_account: true,
129
140
  allow_thaw_account: true,
141
+ allow_transfer: false,
130
142
  },
131
143
  },
144
+ max_allowed_lamports: 1000000,
145
+ max_signatures: 10,
132
146
  price: {
133
- type: 'margin',
134
147
  margin: 0.1,
148
+ type: 'margin',
135
149
  },
150
+ price_source: 'Jupiter',
136
151
  token2022: {
137
- blocked_mint_extensions: ['extension1', 'extension2'],
138
152
  blocked_account_extensions: ['account_extension1', 'account_extension2'],
153
+ blocked_mint_extensions: ['extension1', 'extension2'],
139
154
  },
140
155
  },
141
- enabled_methods: {
142
- liveness: true,
143
- estimate_transaction_fee: true,
144
- estimate_bundle_fee: true,
145
- get_supported_tokens: true,
146
- get_payer_signer: true,
147
- sign_transaction: true,
148
- sign_and_send_transaction: true,
149
- transfer_transaction: true,
150
- get_blockhash: true,
151
- get_config: true,
152
- get_version: true,
153
- sign_and_send_bundle: true,
154
- sign_bundle: true,
155
- },
156
156
  };
157
157
  await testSuccessfulRpcMethod('getConfig', () => client.getConfig(), mockConfig);
158
158
  });
@@ -184,15 +184,15 @@ describe('KoraClient Unit Tests', () => {
184
184
  describe('getPayerSigner', () => {
185
185
  it('should return payer signer and payment destination', async () => {
186
186
  const mockResponse = {
187
- signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
188
187
  payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
188
+ signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
189
189
  };
190
190
  await testSuccessfulRpcMethod('getPayerSigner', () => client.getPayerSigner(), mockResponse);
191
191
  });
192
192
  it('should return same address for signer and payment_destination when no separate paymaster', async () => {
193
193
  const mockResponse = {
194
- signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
195
194
  payment_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
195
+ signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
196
196
  };
197
197
  await testSuccessfulRpcMethod('getPayerSigner', () => client.getPayerSigner(), mockResponse);
198
198
  expect(mockResponse.signer_address).toBe(mockResponse.payment_address);
@@ -201,14 +201,14 @@ describe('KoraClient Unit Tests', () => {
201
201
  describe('estimateTransactionFee', () => {
202
202
  it('should estimate transaction fee', async () => {
203
203
  const request = {
204
- transaction: 'base64_encoded_transaction',
205
204
  fee_token: 'SOL',
205
+ transaction: 'base64_encoded_transaction',
206
206
  };
207
207
  const mockResponse = {
208
208
  fee_in_lamports: 5000,
209
209
  fee_in_token: 25,
210
- signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
211
210
  payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
211
+ signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
212
212
  };
213
213
  await testSuccessfulRpcMethod('estimateTransactionFee', () => client.estimateTransactionFee(request), mockResponse, request);
214
214
  });
@@ -264,9 +264,9 @@ describe('KoraClient Unit Tests', () => {
264
264
  transactions: ['base64_tx_1', 'base64_tx_2'],
265
265
  };
266
266
  const mockResponse = {
267
+ bundle_uuid: 'test-bundle-uuid-123',
267
268
  signed_transactions: ['base64_signed_tx_1', 'base64_signed_tx_2'],
268
269
  signer_pubkey: 'test_signer_pubkey',
269
- bundle_uuid: 'test-bundle-uuid-123',
270
270
  };
271
271
  await testSuccessfulRpcMethod('signAndSendBundle', () => client.signAndSendBundle(request), mockResponse, request);
272
272
  });
@@ -279,116 +279,98 @@ describe('KoraClient Unit Tests', () => {
279
279
  await expect(client.signAndSendBundle(request)).rejects.toThrow('RPC Error -32000: Jito submission failed');
280
280
  });
281
281
  });
282
- describe('transferTransaction (DEPRECATED)', () => {
283
- it('should create transfer transaction', async () => {
284
- const request = {
285
- amount: 1000000,
286
- token: 'SOL',
287
- source: 'source_address',
288
- destination: 'destination_address',
289
- };
290
- const mockResponse = {
291
- transaction: 'base64_encoded_transaction',
292
- message: 'Transfer transaction created',
293
- blockhash: 'test_blockhash',
294
- signer_pubkey: 'test_signer_pubkey',
295
- instructions: [],
296
- };
297
- await testSuccessfulRpcMethod('transferTransaction', () => client.transferTransaction(request), mockResponse, request);
298
- });
299
- });
300
282
  describe('getPaymentInstruction', () => {
301
- const mockConfig = {
283
+ const _mockConfig = {
284
+ enabled_methods: {
285
+ estimate_bundle_fee: true,
286
+ estimate_transaction_fee: true,
287
+ get_blockhash: true,
288
+ get_config: true,
289
+ get_payer_signer: true,
290
+ get_supported_tokens: true,
291
+ get_version: true,
292
+ liveness: true,
293
+ sign_and_send_bundle: true,
294
+ sign_and_send_transaction: true,
295
+ sign_bundle: true,
296
+ sign_transaction: true,
297
+ transfer_transaction: true,
298
+ },
302
299
  fee_payers: ['11111111111111111111111111111111'],
303
300
  validation_config: {
304
- max_allowed_lamports: 1000000,
305
- max_signatures: 10,
306
- price_source: 'Jupiter',
307
301
  allowed_programs: ['program1'],
308
- allowed_tokens: ['token1'],
309
302
  allowed_spl_paid_tokens: ['4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'],
303
+ allowed_tokens: ['token1'],
310
304
  disallowed_accounts: [],
311
305
  fee_payer_policy: {
312
- system: {
306
+ spl_token: {
307
+ allow_approve: true,
308
+ allow_burn: true,
309
+ allow_close_account: true,
310
+ allow_freeze_account: true,
311
+ allow_initialize_account: true,
312
+ allow_initialize_mint: true,
313
+ allow_initialize_multisig: true,
314
+ allow_mint_to: true,
315
+ allow_revoke: true,
316
+ allow_set_authority: true,
317
+ allow_thaw_account: true,
313
318
  allow_transfer: true,
319
+ },
320
+ system: {
321
+ allow_allocate: true,
314
322
  allow_assign: true,
315
323
  allow_create_account: true,
316
- allow_allocate: true,
324
+ allow_transfer: true,
317
325
  nonce: {
318
- allow_initialize: true,
319
326
  allow_advance: true,
320
327
  allow_authorize: true,
328
+ allow_initialize: true,
321
329
  allow_withdraw: true,
322
330
  },
323
331
  },
324
- spl_token: {
325
- allow_transfer: true,
332
+ token_2022: {
333
+ allow_approve: true,
326
334
  allow_burn: true,
327
335
  allow_close_account: true,
328
- allow_approve: true,
329
- allow_revoke: true,
330
- allow_set_authority: true,
331
- allow_mint_to: true,
332
- allow_initialize_mint: true,
336
+ allow_freeze_account: true,
333
337
  allow_initialize_account: true,
338
+ allow_initialize_mint: true,
334
339
  allow_initialize_multisig: true,
335
- allow_freeze_account: true,
336
- allow_thaw_account: true,
337
- },
338
- token_2022: {
339
- allow_transfer: true,
340
- allow_burn: true,
341
- allow_close_account: true,
342
- allow_approve: true,
340
+ allow_mint_to: true,
343
341
  allow_revoke: true,
344
342
  allow_set_authority: true,
345
- allow_mint_to: true,
346
- allow_initialize_mint: true,
347
- allow_initialize_account: true,
348
- allow_initialize_multisig: true,
349
- allow_freeze_account: true,
350
343
  allow_thaw_account: true,
344
+ allow_transfer: true,
351
345
  },
352
346
  },
347
+ max_allowed_lamports: 1000000,
348
+ max_signatures: 10,
353
349
  price: {
354
- type: 'margin',
355
350
  margin: 0.1,
351
+ type: 'margin',
356
352
  },
353
+ price_source: 'Jupiter',
357
354
  token2022: {
358
- blocked_mint_extensions: [],
359
355
  blocked_account_extensions: [],
356
+ blocked_mint_extensions: [],
360
357
  },
361
358
  },
362
- enabled_methods: {
363
- liveness: true,
364
- estimate_transaction_fee: true,
365
- estimate_bundle_fee: true,
366
- get_supported_tokens: true,
367
- get_payer_signer: true,
368
- sign_transaction: true,
369
- sign_and_send_transaction: true,
370
- transfer_transaction: true,
371
- get_blockhash: true,
372
- get_config: true,
373
- get_version: true,
374
- sign_and_send_bundle: true,
375
- sign_bundle: true,
376
- },
377
359
  };
378
360
  const mockFeeEstimate = {
379
361
  fee_in_lamports: 5000,
380
362
  fee_in_token: 50000,
381
- signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
382
363
  payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
364
+ signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
383
365
  };
384
366
  // Create a mock base64-encoded transaction
385
367
  // This is a minimal valid transaction structure
386
368
  const mockTransactionBase64 = 'Aoq7ymA5OGP+gmDXiY5m3cYXlY2Rz/a/gFjOgt9ZuoCS7UzuiGGaEnW2OOtvHvMQHkkD7Z4LRF5B63ftu+1oZwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgECB1urjQEjgFgzqYhJ8IXJeSg4cJP1j1g2CJstOQTDchOKUzqH3PxgGW3c4V3vZV05A5Y30/MggOBs0Kd00s1JEwg5TaEeaV4+KL2y7fXIAuf6cN0ZQitbhY+G9ExtBSChspOXPgNcy9pYpETe4bmB+fg4bfZx1tnicA/kIyyubczAmbcIKIuniNOOQYG2ggKCz8NjEsHVezrWMatndu1wk6J5miGP26J6Vwp31AljiAajAFuP0D9mWJwSeFuA7J5rPwbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpd/O36SW02zRtNtqk6GFeip2+yBQsVTeSbLL4rWJRkd4CBgQCBQQBCgxAQg8AAAAAAAYGBAIFAwEKDBAnAAAAAAAABg==';
387
369
  const validRequest = {
388
- transaction: mockTransactionBase64,
389
370
  fee_token: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
390
371
  source_wallet: '11111111111111111111111111111111',
391
372
  token_program_id: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
373
+ transaction: mockTransactionBase64,
392
374
  };
393
375
  beforeEach(() => {
394
376
  // Mock console.log to avoid noise in tests
@@ -401,16 +383,17 @@ describe('KoraClient Unit Tests', () => {
401
383
  // Mock estimateTransactionFee call
402
384
  mockFetch.mockResolvedValueOnce({
403
385
  json: jest.fn().mockResolvedValueOnce({
404
- jsonrpc: '2.0',
405
386
  id: 1,
387
+ jsonrpc: '2.0',
406
388
  result: mockFeeEstimate,
407
389
  }),
408
390
  });
409
391
  const result = await client.getPaymentInstruction(validRequest);
410
392
  expect(result).toEqual({
411
393
  original_transaction: validRequest.transaction,
394
+ payment_address: mockFeeEstimate.payment_address,
395
+ payment_amount: mockFeeEstimate.fee_in_token,
412
396
  payment_instruction: expect.objectContaining({
413
- programAddress: TOKEN_PROGRAM_ADDRESS,
414
397
  accounts: [
415
398
  expect.objectContaining({
416
399
  role: 1, // writable
@@ -419,44 +402,44 @@ describe('KoraClient Unit Tests', () => {
419
402
  role: 1, // writable
420
403
  }), // Destination token account
421
404
  expect.objectContaining({
422
- role: 2, // readonly-signer
405
+ // readonly-signer
423
406
  address: validRequest.source_wallet,
407
+ role: 2,
424
408
  signer: expect.objectContaining({
425
409
  address: validRequest.source_wallet,
426
410
  }),
427
411
  }), // Authority
428
412
  ],
429
413
  data: expect.any(Uint8Array),
414
+ programAddress: TOKEN_PROGRAM_ADDRESS,
430
415
  }),
431
- payment_amount: mockFeeEstimate.fee_in_token,
432
416
  payment_token: validRequest.fee_token,
433
- payment_address: mockFeeEstimate.payment_address,
434
417
  signer_address: mockFeeEstimate.signer_pubkey,
435
418
  });
436
419
  // Verify only estimateTransactionFee was called
437
420
  expect(mockFetch).toHaveBeenCalledTimes(1);
438
421
  expect(mockFetch).toHaveBeenCalledWith(mockRpcUrl, {
439
- method: 'POST',
440
- headers: {
441
- 'Content-Type': 'application/json',
442
- },
443
422
  body: JSON.stringify({
444
- jsonrpc: '2.0',
445
423
  id: 1,
424
+ jsonrpc: '2.0',
446
425
  method: 'estimateTransactionFee',
447
426
  params: {
448
- transaction: validRequest.transaction,
449
427
  fee_token: validRequest.fee_token,
428
+ transaction: validRequest.transaction,
450
429
  },
451
430
  }),
431
+ headers: {
432
+ 'Content-Type': 'application/json',
433
+ },
434
+ method: 'POST',
452
435
  });
453
436
  });
454
437
  it('should handle fixed pricing configuration', async () => {
455
438
  // Mock estimateTransactionFee call
456
439
  mockFetch.mockResolvedValueOnce({
457
440
  json: jest.fn().mockResolvedValueOnce({
458
- jsonrpc: '2.0',
459
441
  id: 1,
442
+ jsonrpc: '2.0',
460
443
  result: mockFeeEstimate,
461
444
  }),
462
445
  });
@@ -479,9 +462,9 @@ describe('KoraClient Unit Tests', () => {
479
462
  const mockError = { code: -32602, message: 'Invalid transaction' };
480
463
  mockFetch.mockResolvedValueOnce({
481
464
  json: jest.fn().mockResolvedValueOnce({
482
- jsonrpc: '2.0',
483
- id: 1,
484
465
  error: mockError,
466
+ id: 1,
467
+ jsonrpc: '2.0',
485
468
  }),
486
469
  });
487
470
  await expect(client.getPaymentInstruction(validRequest)).rejects.toThrow('RPC Error -32602: Invalid transaction');
@@ -493,18 +476,18 @@ describe('KoraClient Unit Tests', () => {
493
476
  it('should return correct payment details in response', async () => {
494
477
  mockFetch.mockResolvedValueOnce({
495
478
  json: jest.fn().mockResolvedValueOnce({
496
- jsonrpc: '2.0',
497
479
  id: 1,
480
+ jsonrpc: '2.0',
498
481
  result: mockFeeEstimate,
499
482
  }),
500
483
  });
501
484
  const result = await client.getPaymentInstruction(validRequest);
502
485
  expect(result).toMatchObject({
503
486
  original_transaction: validRequest.transaction,
504
- payment_instruction: expect.any(Object),
487
+ payment_address: mockFeeEstimate.payment_address,
505
488
  payment_amount: mockFeeEstimate.fee_in_token,
489
+ payment_instruction: expect.any(Object),
506
490
  payment_token: validRequest.fee_token,
507
- payment_address: mockFeeEstimate.payment_address,
508
491
  signer_address: mockFeeEstimate.signer_pubkey,
509
492
  });
510
493
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/kora",
3
- "version": "0.2.0-beta.2",
3
+ "version": "0.2.0-beta.3",
4
4
  "description": "TypeScript SDK for Kora RPC",
5
5
  "main": "dist/src/index.js",
6
6
  "type": "module",
@@ -24,7 +24,8 @@
24
24
  "@solana-program/compute-budget": "^0.11.0",
25
25
  "@solana-program/system": "^0.10.0",
26
26
  "@solana-program/token": "^0.9.0",
27
- "@solana/kit": "^5.1.0",
27
+ "@solana/eslint-config-solana": "^6.0.0",
28
+ "@solana/kit": "^5.4.0",
28
29
  "@solana/prettier-config-solana": "^0.0.6",
29
30
  "@types/jest": "^29.5.12",
30
31
  "@types/node": "^20.17.27",
@@ -55,7 +56,7 @@
55
56
  "test:ci:integration": "node scripts/test-with-validator.js",
56
57
  "test:ci:integration:auth": "ENABLE_AUTH=true node scripts/test-with-validator.js",
57
58
  "test:ci:unit": "jest test/unit.test.ts",
58
- "lint": "eslint src --ext .ts",
59
+ "lint": "eslint src test",
59
60
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
60
61
  "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
61
62
  "type-check": "tsc --noEmit",