@solana/kora 0.2.0-beta.3 → 0.2.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.
- package/README.md +29 -27
- package/dist/src/client.d.ts +6 -198
- package/dist/src/client.js +12 -208
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +2 -1
- package/dist/src/kit/executor.d.ts +7 -0
- package/dist/src/kit/executor.js +55 -0
- package/dist/src/kit/index.d.ts +50 -0
- package/dist/src/kit/index.js +67 -0
- package/dist/src/kit/payment.d.ts +18 -0
- package/dist/src/kit/payment.js +69 -0
- package/dist/src/kit/planner.d.ts +4 -0
- package/dist/src/kit/planner.js +23 -0
- package/dist/src/kit/plugin.d.ts +31 -0
- package/dist/src/{plugin.js → kit/plugin.js} +13 -81
- package/dist/src/types/index.d.ts +89 -145
- package/dist/test/auth-setup.js +4 -4
- package/dist/test/integration.test.js +322 -172
- package/dist/test/kit-client.test.d.ts +1 -0
- package/dist/test/kit-client.test.js +473 -0
- package/dist/test/plugin.test.js +71 -126
- package/dist/test/setup.d.ts +13 -9
- package/dist/test/setup.js +36 -38
- package/dist/test/unit.test.js +141 -147
- package/package.json +31 -13
- package/dist/src/plugin.d.ts +0 -85
package/dist/test/unit.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
2
1
|
import { KoraClient } from '../src/client.js';
|
|
2
|
+
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
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
|
-
id: 1,
|
|
15
14
|
jsonrpc: '2.0',
|
|
15
|
+
id: 1,
|
|
16
16
|
result,
|
|
17
17
|
}),
|
|
18
18
|
});
|
|
@@ -20,9 +20,9 @@ describe('KoraClient Unit Tests', () => {
|
|
|
20
20
|
const mockErrorResponse = (error) => {
|
|
21
21
|
mockFetch.mockResolvedValueOnce({
|
|
22
22
|
json: jest.fn().mockResolvedValueOnce({
|
|
23
|
-
error,
|
|
24
|
-
id: 1,
|
|
25
23
|
jsonrpc: '2.0',
|
|
24
|
+
id: 1,
|
|
25
|
+
error,
|
|
26
26
|
}),
|
|
27
27
|
});
|
|
28
28
|
};
|
|
@@ -78,81 +78,70 @@ 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
|
-
},
|
|
96
81
|
fee_payers: ['test_fee_payer_address'],
|
|
97
82
|
validation_config: {
|
|
83
|
+
max_allowed_lamports: 1000000,
|
|
84
|
+
max_signatures: 10,
|
|
85
|
+
price_source: 'Jupiter',
|
|
98
86
|
allowed_programs: ['program1', 'program2'],
|
|
99
|
-
allowed_spl_paid_tokens: ['spl_token1'],
|
|
100
87
|
allowed_tokens: ['token1', 'token2'],
|
|
88
|
+
allowed_spl_paid_tokens: ['spl_token1'],
|
|
101
89
|
disallowed_accounts: ['account1'],
|
|
102
90
|
fee_payer_policy: {
|
|
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,
|
|
115
|
-
allow_transfer: true,
|
|
116
|
-
},
|
|
117
91
|
system: {
|
|
118
|
-
|
|
92
|
+
allow_transfer: true,
|
|
119
93
|
allow_assign: true,
|
|
120
94
|
allow_create_account: true,
|
|
121
|
-
|
|
95
|
+
allow_allocate: true,
|
|
122
96
|
nonce: {
|
|
97
|
+
allow_initialize: true,
|
|
123
98
|
allow_advance: true,
|
|
124
99
|
allow_authorize: true,
|
|
125
|
-
allow_initialize: true,
|
|
126
100
|
allow_withdraw: true,
|
|
127
101
|
},
|
|
128
102
|
},
|
|
129
|
-
|
|
130
|
-
|
|
103
|
+
spl_token: {
|
|
104
|
+
allow_transfer: true,
|
|
131
105
|
allow_burn: true,
|
|
132
106
|
allow_close_account: true,
|
|
133
|
-
|
|
134
|
-
allow_initialize_account: true,
|
|
135
|
-
allow_initialize_mint: true,
|
|
136
|
-
allow_initialize_multisig: true,
|
|
137
|
-
allow_mint_to: true,
|
|
107
|
+
allow_approve: true,
|
|
138
108
|
allow_revoke: true,
|
|
139
109
|
allow_set_authority: true,
|
|
110
|
+
allow_mint_to: true,
|
|
111
|
+
allow_freeze_account: true,
|
|
140
112
|
allow_thaw_account: true,
|
|
113
|
+
},
|
|
114
|
+
token_2022: {
|
|
141
115
|
allow_transfer: false,
|
|
116
|
+
allow_burn: true,
|
|
117
|
+
allow_close_account: true,
|
|
118
|
+
allow_approve: true,
|
|
119
|
+
allow_revoke: true,
|
|
120
|
+
allow_set_authority: true,
|
|
121
|
+
allow_mint_to: true,
|
|
122
|
+
allow_freeze_account: true,
|
|
123
|
+
allow_thaw_account: true,
|
|
142
124
|
},
|
|
143
125
|
},
|
|
144
|
-
max_allowed_lamports: 1000000,
|
|
145
|
-
max_signatures: 10,
|
|
146
126
|
price: {
|
|
147
|
-
margin: 0.1,
|
|
148
127
|
type: 'margin',
|
|
128
|
+
margin: 0.1,
|
|
149
129
|
},
|
|
150
|
-
price_source: 'Jupiter',
|
|
151
130
|
token2022: {
|
|
152
|
-
blocked_account_extensions: ['account_extension1', 'account_extension2'],
|
|
153
131
|
blocked_mint_extensions: ['extension1', 'extension2'],
|
|
132
|
+
blocked_account_extensions: ['account_extension1', 'account_extension2'],
|
|
154
133
|
},
|
|
155
134
|
},
|
|
135
|
+
enabled_methods: {
|
|
136
|
+
liveness: true,
|
|
137
|
+
estimate_transaction_fee: true,
|
|
138
|
+
get_supported_tokens: true,
|
|
139
|
+
sign_transaction: true,
|
|
140
|
+
sign_and_send_transaction: true,
|
|
141
|
+
transfer_transaction: true,
|
|
142
|
+
get_blockhash: true,
|
|
143
|
+
get_config: true,
|
|
144
|
+
},
|
|
156
145
|
};
|
|
157
146
|
await testSuccessfulRpcMethod('getConfig', () => client.getConfig(), mockConfig);
|
|
158
147
|
});
|
|
@@ -165,14 +154,6 @@ describe('KoraClient Unit Tests', () => {
|
|
|
165
154
|
await testSuccessfulRpcMethod('getBlockhash', () => client.getBlockhash(), mockResponse);
|
|
166
155
|
});
|
|
167
156
|
});
|
|
168
|
-
describe('getVersion', () => {
|
|
169
|
-
it('should return server version', async () => {
|
|
170
|
-
const mockResponse = {
|
|
171
|
-
version: '2.1.0-beta.0',
|
|
172
|
-
};
|
|
173
|
-
await testSuccessfulRpcMethod('getVersion', () => client.getVersion(), mockResponse);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
157
|
describe('getSupportedTokens', () => {
|
|
177
158
|
it('should return supported tokens list', async () => {
|
|
178
159
|
const mockResponse = {
|
|
@@ -184,15 +165,15 @@ describe('KoraClient Unit Tests', () => {
|
|
|
184
165
|
describe('getPayerSigner', () => {
|
|
185
166
|
it('should return payer signer and payment destination', async () => {
|
|
186
167
|
const mockResponse = {
|
|
187
|
-
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
188
168
|
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
169
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
189
170
|
};
|
|
190
171
|
await testSuccessfulRpcMethod('getPayerSigner', () => client.getPayerSigner(), mockResponse);
|
|
191
172
|
});
|
|
192
173
|
it('should return same address for signer and payment_destination when no separate paymaster', async () => {
|
|
193
174
|
const mockResponse = {
|
|
194
|
-
payment_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
195
175
|
signer_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
176
|
+
payment_address: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
196
177
|
};
|
|
197
178
|
await testSuccessfulRpcMethod('getPayerSigner', () => client.getPayerSigner(), mockResponse);
|
|
198
179
|
expect(mockResponse.signer_address).toBe(mockResponse.payment_address);
|
|
@@ -201,14 +182,14 @@ describe('KoraClient Unit Tests', () => {
|
|
|
201
182
|
describe('estimateTransactionFee', () => {
|
|
202
183
|
it('should estimate transaction fee', async () => {
|
|
203
184
|
const request = {
|
|
204
|
-
fee_token: 'SOL',
|
|
205
185
|
transaction: 'base64_encoded_transaction',
|
|
186
|
+
fee_token: 'SOL',
|
|
206
187
|
};
|
|
207
188
|
const mockResponse = {
|
|
208
189
|
fee_in_lamports: 5000,
|
|
209
190
|
fee_in_token: 25,
|
|
210
|
-
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
211
191
|
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
192
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
212
193
|
};
|
|
213
194
|
await testSuccessfulRpcMethod('estimateTransactionFee', () => client.estimateTransactionFee(request), mockResponse, request);
|
|
214
195
|
});
|
|
@@ -238,139 +219,148 @@ describe('KoraClient Unit Tests', () => {
|
|
|
238
219
|
await testSuccessfulRpcMethod('signAndSendTransaction', () => client.signAndSendTransaction(request), mockResponse, request);
|
|
239
220
|
});
|
|
240
221
|
});
|
|
241
|
-
describe('
|
|
242
|
-
it('should
|
|
222
|
+
describe('transferTransaction', () => {
|
|
223
|
+
it('should create transfer transaction', async () => {
|
|
243
224
|
const request = {
|
|
244
|
-
|
|
225
|
+
amount: 1000000,
|
|
226
|
+
token: 'SOL',
|
|
227
|
+
source: 'source_address',
|
|
228
|
+
destination: 'destination_address',
|
|
245
229
|
};
|
|
246
230
|
const mockResponse = {
|
|
247
|
-
|
|
231
|
+
transaction: 'base64_encoded_transaction',
|
|
232
|
+
message: 'Transfer transaction created',
|
|
233
|
+
blockhash: 'test_blockhash',
|
|
248
234
|
signer_pubkey: 'test_signer_pubkey',
|
|
235
|
+
instructions: [],
|
|
249
236
|
};
|
|
250
|
-
await testSuccessfulRpcMethod('
|
|
251
|
-
});
|
|
252
|
-
it('should handle RPC error', async () => {
|
|
253
|
-
const request = {
|
|
254
|
-
transactions: ['base64_tx_1'],
|
|
255
|
-
};
|
|
256
|
-
const mockError = { code: -32000, message: 'Bundle validation failed' };
|
|
257
|
-
mockErrorResponse(mockError);
|
|
258
|
-
await expect(client.signBundle(request)).rejects.toThrow('RPC Error -32000: Bundle validation failed');
|
|
237
|
+
await testSuccessfulRpcMethod('transferTransaction', () => client.transferTransaction(request), mockResponse, request);
|
|
259
238
|
});
|
|
260
|
-
|
|
261
|
-
describe('signAndSendBundle', () => {
|
|
262
|
-
it('should sign and send bundle of transactions', async () => {
|
|
239
|
+
it('should parse instructions from transfer transaction message', async () => {
|
|
263
240
|
const request = {
|
|
264
|
-
|
|
241
|
+
amount: 1000000,
|
|
242
|
+
token: 'SOL',
|
|
243
|
+
source: 'source_address',
|
|
244
|
+
destination: 'destination_address',
|
|
265
245
|
};
|
|
246
|
+
// This is a real base64 encoded message for testing
|
|
247
|
+
// In production, this would come from the RPC response
|
|
248
|
+
const mockMessage = 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQABAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDAAEMAgAAAAEAAAAAAAAA';
|
|
266
249
|
const mockResponse = {
|
|
267
|
-
|
|
268
|
-
|
|
250
|
+
transaction: 'base64_encoded_transaction',
|
|
251
|
+
message: mockMessage,
|
|
252
|
+
blockhash: 'test_blockhash',
|
|
269
253
|
signer_pubkey: 'test_signer_pubkey',
|
|
254
|
+
instructions: [],
|
|
270
255
|
};
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
256
|
+
mockSuccessfulResponse(mockResponse);
|
|
257
|
+
const result = await client.transferTransaction(request);
|
|
258
|
+
expect(result.instructions).toBeDefined();
|
|
259
|
+
expect(Array.isArray(result.instructions)).toBe(true);
|
|
260
|
+
// The instructions array should be populated from the parsed message
|
|
261
|
+
expect(result.instructions).not.toBeNull();
|
|
262
|
+
});
|
|
263
|
+
it('should handle transfer transaction with empty message gracefully', async () => {
|
|
274
264
|
const request = {
|
|
275
|
-
|
|
265
|
+
amount: 1000000,
|
|
266
|
+
token: 'SOL',
|
|
267
|
+
source: 'source_address',
|
|
268
|
+
destination: 'destination_address',
|
|
276
269
|
};
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
270
|
+
const mockResponse = {
|
|
271
|
+
transaction: 'base64_encoded_transaction',
|
|
272
|
+
message: '',
|
|
273
|
+
blockhash: 'test_blockhash',
|
|
274
|
+
signer_pubkey: 'test_signer_pubkey',
|
|
275
|
+
instructions: [],
|
|
276
|
+
};
|
|
277
|
+
mockSuccessfulResponse(mockResponse);
|
|
278
|
+
const result = await client.transferTransaction(request);
|
|
279
|
+
// Should handle empty message gracefully
|
|
280
|
+
expect(result.instructions).toEqual([]);
|
|
280
281
|
});
|
|
281
282
|
});
|
|
282
283
|
describe('getPaymentInstruction', () => {
|
|
283
|
-
const
|
|
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
|
-
},
|
|
284
|
+
const mockConfig = {
|
|
299
285
|
fee_payers: ['11111111111111111111111111111111'],
|
|
300
286
|
validation_config: {
|
|
287
|
+
max_allowed_lamports: 1000000,
|
|
288
|
+
max_signatures: 10,
|
|
289
|
+
price_source: 'Jupiter',
|
|
301
290
|
allowed_programs: ['program1'],
|
|
302
|
-
allowed_spl_paid_tokens: ['4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'],
|
|
303
291
|
allowed_tokens: ['token1'],
|
|
292
|
+
allowed_spl_paid_tokens: ['4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'],
|
|
304
293
|
disallowed_accounts: [],
|
|
305
294
|
fee_payer_policy: {
|
|
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,
|
|
318
|
-
allow_transfer: true,
|
|
319
|
-
},
|
|
320
295
|
system: {
|
|
321
|
-
|
|
296
|
+
allow_transfer: true,
|
|
322
297
|
allow_assign: true,
|
|
323
298
|
allow_create_account: true,
|
|
324
|
-
|
|
299
|
+
allow_allocate: true,
|
|
325
300
|
nonce: {
|
|
301
|
+
allow_initialize: true,
|
|
326
302
|
allow_advance: true,
|
|
327
303
|
allow_authorize: true,
|
|
328
|
-
allow_initialize: true,
|
|
329
304
|
allow_withdraw: true,
|
|
330
305
|
},
|
|
331
306
|
},
|
|
332
|
-
|
|
333
|
-
|
|
307
|
+
spl_token: {
|
|
308
|
+
allow_transfer: true,
|
|
334
309
|
allow_burn: true,
|
|
335
310
|
allow_close_account: true,
|
|
336
|
-
|
|
337
|
-
allow_initialize_account: true,
|
|
338
|
-
allow_initialize_mint: true,
|
|
339
|
-
allow_initialize_multisig: true,
|
|
340
|
-
allow_mint_to: true,
|
|
311
|
+
allow_approve: true,
|
|
341
312
|
allow_revoke: true,
|
|
342
313
|
allow_set_authority: true,
|
|
314
|
+
allow_mint_to: true,
|
|
315
|
+
allow_freeze_account: true,
|
|
343
316
|
allow_thaw_account: true,
|
|
317
|
+
},
|
|
318
|
+
token_2022: {
|
|
344
319
|
allow_transfer: true,
|
|
320
|
+
allow_burn: true,
|
|
321
|
+
allow_close_account: true,
|
|
322
|
+
allow_approve: true,
|
|
323
|
+
allow_revoke: true,
|
|
324
|
+
allow_set_authority: true,
|
|
325
|
+
allow_mint_to: true,
|
|
326
|
+
allow_freeze_account: true,
|
|
327
|
+
allow_thaw_account: true,
|
|
345
328
|
},
|
|
346
329
|
},
|
|
347
|
-
max_allowed_lamports: 1000000,
|
|
348
|
-
max_signatures: 10,
|
|
349
330
|
price: {
|
|
350
|
-
margin: 0.1,
|
|
351
331
|
type: 'margin',
|
|
332
|
+
margin: 0.1,
|
|
352
333
|
},
|
|
353
|
-
price_source: 'Jupiter',
|
|
354
334
|
token2022: {
|
|
355
|
-
blocked_account_extensions: [],
|
|
356
335
|
blocked_mint_extensions: [],
|
|
336
|
+
blocked_account_extensions: [],
|
|
357
337
|
},
|
|
358
338
|
},
|
|
339
|
+
enabled_methods: {
|
|
340
|
+
liveness: true,
|
|
341
|
+
estimate_transaction_fee: true,
|
|
342
|
+
get_supported_tokens: true,
|
|
343
|
+
sign_transaction: true,
|
|
344
|
+
sign_and_send_transaction: true,
|
|
345
|
+
transfer_transaction: true,
|
|
346
|
+
get_blockhash: true,
|
|
347
|
+
get_config: true,
|
|
348
|
+
},
|
|
359
349
|
};
|
|
360
350
|
const mockFeeEstimate = {
|
|
361
351
|
fee_in_lamports: 5000,
|
|
362
352
|
fee_in_token: 50000,
|
|
363
|
-
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
364
353
|
signer_pubkey: 'DemoKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
354
|
+
payment_address: 'PayKMZWkk483QoFPLRPQ2XVKB7bWnuXwSjvDE1JsWk7',
|
|
365
355
|
};
|
|
366
356
|
// Create a mock base64-encoded transaction
|
|
367
357
|
// This is a minimal valid transaction structure
|
|
368
358
|
const mockTransactionBase64 = 'Aoq7ymA5OGP+gmDXiY5m3cYXlY2Rz/a/gFjOgt9ZuoCS7UzuiGGaEnW2OOtvHvMQHkkD7Z4LRF5B63ftu+1oZwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgECB1urjQEjgFgzqYhJ8IXJeSg4cJP1j1g2CJstOQTDchOKUzqH3PxgGW3c4V3vZV05A5Y30/MggOBs0Kd00s1JEwg5TaEeaV4+KL2y7fXIAuf6cN0ZQitbhY+G9ExtBSChspOXPgNcy9pYpETe4bmB+fg4bfZx1tnicA/kIyyubczAmbcIKIuniNOOQYG2ggKCz8NjEsHVezrWMatndu1wk6J5miGP26J6Vwp31AljiAajAFuP0D9mWJwSeFuA7J5rPwbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpd/O36SW02zRtNtqk6GFeip2+yBQsVTeSbLL4rWJRkd4CBgQCBQQBCgxAQg8AAAAAAAYGBAIFAwEKDBAnAAAAAAAABg==';
|
|
369
359
|
const validRequest = {
|
|
360
|
+
transaction: mockTransactionBase64,
|
|
370
361
|
fee_token: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
|
|
371
362
|
source_wallet: '11111111111111111111111111111111',
|
|
372
363
|
token_program_id: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
|
|
373
|
-
transaction: mockTransactionBase64,
|
|
374
364
|
};
|
|
375
365
|
beforeEach(() => {
|
|
376
366
|
// Mock console.log to avoid noise in tests
|
|
@@ -383,17 +373,16 @@ describe('KoraClient Unit Tests', () => {
|
|
|
383
373
|
// Mock estimateTransactionFee call
|
|
384
374
|
mockFetch.mockResolvedValueOnce({
|
|
385
375
|
json: jest.fn().mockResolvedValueOnce({
|
|
386
|
-
id: 1,
|
|
387
376
|
jsonrpc: '2.0',
|
|
377
|
+
id: 1,
|
|
388
378
|
result: mockFeeEstimate,
|
|
389
379
|
}),
|
|
390
380
|
});
|
|
391
381
|
const result = await client.getPaymentInstruction(validRequest);
|
|
392
382
|
expect(result).toEqual({
|
|
393
383
|
original_transaction: validRequest.transaction,
|
|
394
|
-
payment_address: mockFeeEstimate.payment_address,
|
|
395
|
-
payment_amount: mockFeeEstimate.fee_in_token,
|
|
396
384
|
payment_instruction: expect.objectContaining({
|
|
385
|
+
programAddress: TOKEN_PROGRAM_ADDRESS,
|
|
397
386
|
accounts: [
|
|
398
387
|
expect.objectContaining({
|
|
399
388
|
role: 1, // writable
|
|
@@ -402,20 +391,25 @@ describe('KoraClient Unit Tests', () => {
|
|
|
402
391
|
role: 1, // writable
|
|
403
392
|
}), // Destination token account
|
|
404
393
|
expect.objectContaining({
|
|
405
|
-
// readonly-signer
|
|
394
|
+
role: 2, // readonly-signer
|
|
406
395
|
address: validRequest.source_wallet,
|
|
407
|
-
role: 2,
|
|
408
396
|
signer: expect.objectContaining({
|
|
409
397
|
address: validRequest.source_wallet,
|
|
410
398
|
}),
|
|
411
399
|
}), // Authority
|
|
412
400
|
],
|
|
413
401
|
data: expect.any(Uint8Array),
|
|
414
|
-
programAddress: TOKEN_PROGRAM_ADDRESS,
|
|
415
402
|
}),
|
|
403
|
+
payment_amount: mockFeeEstimate.fee_in_token,
|
|
416
404
|
payment_token: validRequest.fee_token,
|
|
405
|
+
payment_address: mockFeeEstimate.payment_address,
|
|
417
406
|
signer_address: mockFeeEstimate.signer_pubkey,
|
|
407
|
+
signer: expect.objectContaining({
|
|
408
|
+
address: validRequest.source_wallet,
|
|
409
|
+
}),
|
|
418
410
|
});
|
|
411
|
+
expect(result.signer).toBeDefined();
|
|
412
|
+
expect(result.signer.address).toBe(validRequest.source_wallet);
|
|
419
413
|
// Verify only estimateTransactionFee was called
|
|
420
414
|
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
421
415
|
expect(mockFetch).toHaveBeenCalledWith(mockRpcUrl, {
|
|
@@ -438,8 +432,8 @@ describe('KoraClient Unit Tests', () => {
|
|
|
438
432
|
// Mock estimateTransactionFee call
|
|
439
433
|
mockFetch.mockResolvedValueOnce({
|
|
440
434
|
json: jest.fn().mockResolvedValueOnce({
|
|
441
|
-
id: 1,
|
|
442
435
|
jsonrpc: '2.0',
|
|
436
|
+
id: 1,
|
|
443
437
|
result: mockFeeEstimate,
|
|
444
438
|
}),
|
|
445
439
|
});
|
|
@@ -462,9 +456,9 @@ describe('KoraClient Unit Tests', () => {
|
|
|
462
456
|
const mockError = { code: -32602, message: 'Invalid transaction' };
|
|
463
457
|
mockFetch.mockResolvedValueOnce({
|
|
464
458
|
json: jest.fn().mockResolvedValueOnce({
|
|
465
|
-
error: mockError,
|
|
466
|
-
id: 1,
|
|
467
459
|
jsonrpc: '2.0',
|
|
460
|
+
id: 1,
|
|
461
|
+
error: mockError,
|
|
468
462
|
}),
|
|
469
463
|
});
|
|
470
464
|
await expect(client.getPaymentInstruction(validRequest)).rejects.toThrow('RPC Error -32602: Invalid transaction');
|
|
@@ -476,18 +470,18 @@ describe('KoraClient Unit Tests', () => {
|
|
|
476
470
|
it('should return correct payment details in response', async () => {
|
|
477
471
|
mockFetch.mockResolvedValueOnce({
|
|
478
472
|
json: jest.fn().mockResolvedValueOnce({
|
|
479
|
-
id: 1,
|
|
480
473
|
jsonrpc: '2.0',
|
|
474
|
+
id: 1,
|
|
481
475
|
result: mockFeeEstimate,
|
|
482
476
|
}),
|
|
483
477
|
});
|
|
484
478
|
const result = await client.getPaymentInstruction(validRequest);
|
|
485
479
|
expect(result).toMatchObject({
|
|
486
480
|
original_transaction: validRequest.transaction,
|
|
487
|
-
payment_address: mockFeeEstimate.payment_address,
|
|
488
|
-
payment_amount: mockFeeEstimate.fee_in_token,
|
|
489
481
|
payment_instruction: expect.any(Object),
|
|
482
|
+
payment_amount: mockFeeEstimate.fee_in_token,
|
|
490
483
|
payment_token: validRequest.fee_token,
|
|
484
|
+
payment_address: mockFeeEstimate.payment_address,
|
|
491
485
|
signer_address: mockFeeEstimate.signer_pubkey,
|
|
492
486
|
});
|
|
493
487
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/kora",
|
|
3
|
-
"version": "0.2.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "TypeScript SDK for Kora RPC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -16,30 +16,47 @@
|
|
|
16
16
|
],
|
|
17
17
|
"author": "",
|
|
18
18
|
"license": "MIT",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/solana-foundation/kora",
|
|
22
|
+
"directory": "sdks/ts"
|
|
23
|
+
},
|
|
19
24
|
"peerDependencies": {
|
|
20
|
-
"@solana-program/
|
|
21
|
-
"@solana/
|
|
25
|
+
"@solana-program/compute-budget": "^0.13.0",
|
|
26
|
+
"@solana-program/token": "^0.12.0",
|
|
27
|
+
"@solana/kit": "^6.1.0",
|
|
28
|
+
"@solana/kit-plugin-instruction-plan": "^0.6.0",
|
|
29
|
+
"@solana/kit-plugin-payer": "^0.6.0",
|
|
30
|
+
"@solana/kit-plugin-rpc": "^0.6.0"
|
|
22
31
|
},
|
|
23
32
|
"devDependencies": {
|
|
24
|
-
"@
|
|
25
|
-
"@solana-program/
|
|
26
|
-
"@solana-program/
|
|
27
|
-
"@solana/
|
|
28
|
-
"@solana/
|
|
33
|
+
"@eslint/js": "^9.39.3",
|
|
34
|
+
"@solana-program/compute-budget": "^0.13.0",
|
|
35
|
+
"@solana-program/system": "^0.11.0",
|
|
36
|
+
"@solana-program/token": "^0.12.0",
|
|
37
|
+
"@solana/eslint-config-solana": "6.0.0",
|
|
38
|
+
"@solana/kit": "^6.1.0",
|
|
39
|
+
"@solana/kit-plugin-instruction-plan": "^0.6.0",
|
|
40
|
+
"@solana/kit-plugin-payer": "^0.6.0",
|
|
41
|
+
"@solana/kit-plugin-rpc": "^0.6.0",
|
|
29
42
|
"@solana/prettier-config-solana": "^0.0.6",
|
|
30
43
|
"@types/jest": "^29.5.12",
|
|
31
44
|
"@types/node": "^20.17.27",
|
|
32
|
-
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
33
|
-
"@typescript-eslint/parser": "^8.38.0",
|
|
34
45
|
"dotenv": "^16.4.5",
|
|
35
|
-
"eslint": "^9.
|
|
46
|
+
"eslint": "^9.39.3",
|
|
47
|
+
"eslint-plugin-jest": "^29.15.0",
|
|
48
|
+
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
49
|
+
"eslint-plugin-sort-keys-fix": "^1.1.2",
|
|
50
|
+
"eslint-plugin-typescript-sort-keys": "^3.3.0",
|
|
51
|
+
"globals": "^16.5.0",
|
|
36
52
|
"jest": "^29.7.0",
|
|
37
53
|
"prettier": "^3.2.5",
|
|
38
54
|
"ts-jest": "^29.1.2",
|
|
39
55
|
"ts-node": "^10.9.2",
|
|
40
56
|
"typedoc": "^0.28.9",
|
|
41
57
|
"typedoc-plugin-markdown": "^4.8.0",
|
|
42
|
-
"typescript": "^5.
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"typescript-eslint": "^8.56.1",
|
|
43
60
|
"ws": "^8.18.3"
|
|
44
61
|
},
|
|
45
62
|
"scripts": {
|
|
@@ -50,13 +67,14 @@
|
|
|
50
67
|
"test:coverage": "jest --coverage",
|
|
51
68
|
"test:integration": "pnpm test integration.test.ts",
|
|
52
69
|
"test:integration:auth": "ENABLE_AUTH=true pnpm test integration.test.ts",
|
|
70
|
+
"test:integration:free": "FREE_PRICING=true pnpm test integration.test.ts",
|
|
53
71
|
"test:integration:privy": "KORA_SIGNER_TYPE=privy pnpm test integration.test.ts",
|
|
54
72
|
"test:integration:turnkey": "KORA_SIGNER_TYPE=turnkey pnpm test integration.test.ts",
|
|
55
73
|
"test:unit": "pnpm test unit.test.ts",
|
|
56
74
|
"test:ci:integration": "node scripts/test-with-validator.js",
|
|
57
75
|
"test:ci:integration:auth": "ENABLE_AUTH=true node scripts/test-with-validator.js",
|
|
58
76
|
"test:ci:unit": "jest test/unit.test.ts",
|
|
59
|
-
"lint": "eslint src
|
|
77
|
+
"lint": "eslint src/",
|
|
60
78
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
61
79
|
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
62
80
|
"type-check": "tsc --noEmit",
|