@lombard.finance/sdk-solana 2.0.1 → 2.0.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.
Files changed (56) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.js +23 -22
  3. package/dist/index2.cjs +47 -47
  4. package/dist/index2.js +6103 -6029
  5. package/dist/sendBridgeTransaction.cjs +1 -1
  6. package/dist/sendBridgeTransaction.js +19 -19
  7. package/package.json +1 -1
  8. package/src/bridge/sendBridgeTransaction.ts +2 -2
  9. package/src/const/__tests__/rpcUrls.test.ts +73 -0
  10. package/src/const/errors.ts +0 -1
  11. package/src/const/getConfig.ts +30 -15
  12. package/src/const/rpcUrls.ts +53 -7
  13. package/src/idl/asset_router.json +182 -1532
  14. package/src/idl/bridge.json +139 -1185
  15. package/src/idl/consortium.json +62 -498
  16. package/src/idl/getAssetRouterIdl.ts +1 -3
  17. package/src/idl/getConsortiumIdl.ts +1 -3
  18. package/src/idl/getLbtcIdl.ts +4 -1
  19. package/src/idl/getMailboxIdl.ts +1 -3
  20. package/src/idl/lombard_token_pool.json +92 -932
  21. package/src/idl/mailbox.json +114 -1018
  22. package/src/idl/ratio_oracle.json +35 -332
  23. package/src/services/SolanaServiceImpl.test.ts +5 -4
  24. package/src/stories/components/ConnectButton/ConnectButton.tsx +2 -2
  25. package/src/stories/components/NetworkSelector/NetworkSelector.tsx +1 -1
  26. package/src/stories/components/OutputSelector/OutputSelector.tsx +4 -4
  27. package/src/stories/components/SelectField/SelectField.tsx +2 -3
  28. package/src/stories/hooks/useFetchOutputs.ts +1 -1
  29. package/src/stories/utils/fromCamelCase.ts +1 -1
  30. package/src/types/sdkTypes.ts +7 -0
  31. package/src/utils/createDebugLogger.ts +1 -1
  32. package/src/web3Sdk/claimToken/claimBtcb.ts +19 -5
  33. package/src/web3Sdk/claimToken/claimLbtcGmp.ts +55 -25
  34. package/src/web3Sdk/claimToken/claimToken.stories.tsx +4 -3
  35. package/src/web3Sdk/claimToken/claimToken.ts +16 -6
  36. package/src/web3Sdk/claimToken/shared.ts +18 -12
  37. package/src/web3Sdk/claimToken/utils/__tests__/signatureUtils.test.ts +10 -4
  38. package/src/web3Sdk/claimToken/utils/signatureUtils.ts +3 -1
  39. package/src/web3Sdk/deposit/deposit.stories.tsx +1 -4
  40. package/src/web3Sdk/deposit/deposit.test.ts +67 -37
  41. package/src/web3Sdk/deposit/deposit.ts +14 -14
  42. package/src/web3Sdk/detectWallet/detectWallet.test.ts +2 -2
  43. package/src/web3Sdk/getBalance/getBalance.test.ts +1 -1
  44. package/src/web3Sdk/getBalance/getBalance.ts +2 -1
  45. package/src/web3Sdk/getTokenFeeConfig/getTokenFeeConfig.stories.tsx +8 -18
  46. package/src/web3Sdk/getTokenFeeConfig/getTokenFeeConfig.ts +2 -4
  47. package/src/web3Sdk/redeem/redeem.stories.tsx +17 -8
  48. package/src/web3Sdk/redeem/redeem.test.ts +45 -13
  49. package/src/web3Sdk/redeem/redeem.ts +46 -20
  50. package/src/web3Sdk/redeemToken/redeemBtcb.ts +28 -12
  51. package/src/web3Sdk/redeemToken/redeemForBtc.stories.tsx +6 -6
  52. package/src/web3Sdk/redeemToken/redeemForBtc.test.ts +43 -13
  53. package/src/web3Sdk/redeemToken/redeemForBtc.ts +27 -14
  54. package/src/web3Sdk/redeemToken/redeemLbtc.ts +28 -12
  55. package/src/web3Sdk/redeemToken/shared.test.ts +6 -2
  56. package/src/web3Sdk/redeemToken/shared.ts +1 -3
@@ -15,10 +15,7 @@ import { ClaimContext, executeConsortiumSession } from './shared';
15
15
  * Payload: nonce u256 at [36:68], token at [232:264], recipient at [264:296], amount u256 at [296:328].
16
16
  * Only the low 8 bytes of each u256 are used (placed in the last 8 bytes of the 32-byte slot).
17
17
  */
18
- function computeBasculeGmpMintId(
19
- payload: Buffer,
20
- chainId: Buffer,
21
- ): Uint8Array {
18
+ function computeBasculeGmpMintId(payload: Buffer, chainId: Buffer): Uint8Array {
22
19
  if (payload.length < 328) {
23
20
  throw new Error(
24
21
  `payload too short for bascule_gmp mint_id: ${payload.length} bytes`,
@@ -49,11 +46,22 @@ function computeBasculeGmpMintId(
49
46
  */
50
47
  export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
51
48
  const {
52
- provider, connection, params, config,
53
- payloadBytes, payloadHash, payloadHashArray,
54
- payer, assetRouterProgramId, consortiumProgramId,
55
- consortiumProgram, assetRouterConfigPDA, tokenAuthorityPDA,
56
- validatedPayloadPDA, arConfig, debugLog,
49
+ provider,
50
+ connection,
51
+ params,
52
+ config,
53
+ payloadBytes,
54
+ payloadHash,
55
+ payloadHashArray,
56
+ payer,
57
+ assetRouterProgramId,
58
+ consortiumProgramId,
59
+ consortiumProgram,
60
+ assetRouterConfigPDA,
61
+ tokenAuthorityPDA,
62
+ validatedPayloadPDA,
63
+ arConfig,
64
+ debugLog,
57
65
  } = ctx;
58
66
 
59
67
  if (payloadBytes.length < 328) {
@@ -67,7 +75,8 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
67
75
  [Buffer.from('message_handled'), payloadHash],
68
76
  assetRouterProgramId,
69
77
  );
70
- const messageHandledAccount = await connection.getAccountInfo(messageHandledPDA);
78
+ const messageHandledAccount =
79
+ await connection.getAccountInfo(messageHandledPDA);
71
80
  if (messageHandledAccount) {
72
81
  debugLog('Message already handled (LBTC already minted)');
73
82
  return ALREADY_MINTED_TX_HASH;
@@ -82,7 +91,8 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
82
91
  consortiumProgramId,
83
92
  );
84
93
 
85
- const sessionPayloadAccount = await connection.getAccountInfo(sessionPayloadPDA);
94
+ const sessionPayloadAccount =
95
+ await connection.getAccountInfo(sessionPayloadPDA);
86
96
  if (sessionPayloadAccount) {
87
97
  debugLog('Session payload already exists, skipping post_session_payload');
88
98
  } else {
@@ -112,7 +122,9 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
112
122
 
113
123
  // ── Step 5: deliver_message (mailbox) ──
114
124
  if (!config.mailbox) {
115
- throw new Error(`Mailbox program not configured for network: ${params.network}`);
125
+ throw new Error(
126
+ `Mailbox program not configured for network: ${params.network}`,
127
+ );
116
128
  }
117
129
  const mailboxProgramId = new PublicKey(config.mailbox);
118
130
  const mailboxProgram = new Program(
@@ -130,7 +142,9 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
130
142
  );
131
143
 
132
144
  if (!config.ledgerChainId) {
133
- throw new Error(`Ledger chain ID not configured for network: ${params.network}`);
145
+ throw new Error(
146
+ `Ledger chain ID not configured for network: ${params.network}`,
147
+ );
134
148
  }
135
149
  const ledgerChainId = Buffer.from(config.ledgerChainId, 'hex');
136
150
  debugLog('Ledger chain ID:', config.ledgerChainId);
@@ -188,7 +202,12 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
188
202
  }
189
203
  const tokenProgramId = mintAccountInfo.owner;
190
204
 
191
- const mintAccount = await getMint(connection, mint, undefined, tokenProgramId);
205
+ const mintAccount = await getMint(
206
+ connection,
207
+ mint,
208
+ undefined,
209
+ tokenProgramId,
210
+ );
192
211
  if (!mintAccount.mintAuthority) {
193
212
  throw new Error('Mint has no mint authority');
194
213
  }
@@ -206,7 +225,7 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
206
225
  // Build handle_message instruction
207
226
  const handleIx = await mailboxProgram.methods
208
227
  .handleMessage(payloadHashArray)
209
- .accounts({
228
+ .accounts({
210
229
  handler: provider.publicKey,
211
230
  config: mailboxConfigPDA,
212
231
  messageInfo: messageInfoPDA,
@@ -262,12 +281,22 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
262
281
  debugLog('Bascule GMP program:', effectiveBasculeGmpProgramId.toBase58());
263
282
  debugLog('Bascule validator PDA:', basculeValidatorPDA.toBase58());
264
283
  debugLog('Bascule GMP config PDA:', basculeGmpConfigPDA.toBase58());
265
- debugLog('Bascule GMP account roles PDA:', basculeGmpAccountRolesPDA.toBase58());
266
- debugLog('Bascule GMP mint payload PDA:', basculeGmpMintPayloadPDA.toBase58());
284
+ debugLog(
285
+ 'Bascule GMP account roles PDA:',
286
+ basculeGmpAccountRolesPDA.toBase58(),
287
+ );
288
+ debugLog(
289
+ 'Bascule GMP mint payload PDA:',
290
+ basculeGmpMintPayloadPDA.toBase58(),
291
+ );
267
292
 
268
293
  handleIx.keys.push(
269
294
  { pubkey: basculeValidatorPDA, isSigner: false, isWritable: true },
270
- { pubkey: effectiveBasculeGmpProgramId, isSigner: false, isWritable: false },
295
+ {
296
+ pubkey: effectiveBasculeGmpProgramId,
297
+ isSigner: false,
298
+ isWritable: false,
299
+ },
271
300
  { pubkey: basculeGmpConfigPDA, isSigner: false, isWritable: false },
272
301
  { pubkey: basculeGmpAccountRolesPDA, isSigner: false, isWritable: false },
273
302
  { pubkey: basculeGmpMintPayloadPDA, isSigner: false, isWritable: true },
@@ -275,18 +304,19 @@ export async function claimLbtcGmp(ctx: ClaimContext): Promise<string> {
275
304
  } else {
276
305
  debugLog('Bascule GMP not enabled, adding placeholder accounts');
277
306
  for (let i = 0; i < 5; i++) {
278
- handleIx.keys.push(
279
- { pubkey: assetRouterProgramId, isSigner: false, isWritable: false },
280
- );
307
+ handleIx.keys.push({
308
+ pubkey: assetRouterProgramId,
309
+ isSigner: false,
310
+ isWritable: false,
311
+ });
281
312
  }
282
313
  }
283
314
 
284
315
  debugLog('handle_message account count:', handleIx.keys.length);
316
+ debugLog('handle_message program:', handleIx.programId.toBase58());
285
317
  debugLog(
286
- 'handle_message program:', handleIx.programId.toBase58(),
287
- );
288
- debugLog(
289
- 'handle_message data (hex):', Buffer.from(handleIx.data).toString('hex'),
318
+ 'handle_message data (hex):',
319
+ Buffer.from(handleIx.data).toString('hex'),
290
320
  );
291
321
  handleIx.keys.forEach((k, i) => {
292
322
  debugLog(
@@ -60,10 +60,11 @@ export const StoryView = ({ environment, token }: ClaimTokenStoryArgs) => {
60
60
  if (!selectedOutput) throw new Error('Please select an output to claim.');
61
61
  if (!selectedOutput.raw_payload)
62
62
  throw new Error('Selected output has no raw_payload.');
63
- if (!selectedOutput.proof)
64
- throw new Error('Selected output has no proof.');
63
+ if (!selectedOutput.proof) throw new Error('Selected output has no proof.');
65
64
  if (!tokenMint)
66
- throw new Error(`Token mint not configured for ${token} on ${environment}.`);
65
+ throw new Error(
66
+ `Token mint not configured for ${token} on ${environment}.`,
67
+ );
67
68
 
68
69
  setTransactionLogs(null);
69
70
  try {
@@ -34,7 +34,13 @@ export async function claimToken(
34
34
  provider: ISolanaWalletProvider,
35
35
  params: ClaimTokenParams,
36
36
  ): Promise<string> {
37
- const { network, env = DEFAULT_ENV, rawPayload, rpcUrl, debug = false } = params;
37
+ const {
38
+ network,
39
+ env = DEFAULT_ENV,
40
+ rawPayload,
41
+ rpcUrl,
42
+ debug = false,
43
+ } = params;
38
44
  const { debugLog, printLogs } = createDebugLogger({ debug });
39
45
 
40
46
  try {
@@ -51,7 +57,7 @@ export async function claimToken(
51
57
  throw new Error(`Consortium not configured for network: ${network}`);
52
58
  }
53
59
 
54
- const connection = getConnection(network, rpcUrl);
60
+ const connection = getConnection(network, rpcUrl, env);
55
61
  const wallet = {
56
62
  publicKey: new PublicKey(provider.publicKey),
57
63
  signTransaction: provider.signTransaction,
@@ -127,10 +133,14 @@ export async function claimToken(
127
133
  assetRouterConfigPDA,
128
134
  );
129
135
  debugLog(
130
- 'Asset Router config — paused:', arConfig.paused,
131
- 'nativeMint:', arConfig.nativeMint.toBase58(),
132
- 'bascule:', arConfig.basculeProgramId?.toBase58() ?? 'null',
133
- 'basculeGmp:', arConfig.basculeGmpProgramId?.toBase58() ?? 'null',
136
+ 'Asset Router config — paused:',
137
+ arConfig.paused,
138
+ 'nativeMint:',
139
+ arConfig.nativeMint.toBase58(),
140
+ 'bascule:',
141
+ arConfig.basculeProgramId?.toBase58() ?? 'null',
142
+ 'basculeGmp:',
143
+ arConfig.basculeGmpProgramId?.toBase58() ?? 'null',
134
144
  );
135
145
 
136
146
  if (arConfig.paused) {
@@ -201,11 +201,19 @@ export async function fetchAssetRouterConfig(
201
201
  * Execute the consortium session flow: create_session, post_signatures, finalize_session.
202
202
  * Skips steps that are already completed on-chain.
203
203
  */
204
- export async function executeConsortiumSession(ctx: ClaimContext): Promise<void> {
204
+ export async function executeConsortiumSession(
205
+ ctx: ClaimContext,
206
+ ): Promise<void> {
205
207
  const {
206
- provider, connection, consortiumProgram,
207
- consortiumConfigPDA, sessionPDA, validatedPayloadPDA,
208
- payloadHashArray, params, debugLog,
208
+ provider,
209
+ connection,
210
+ consortiumProgram,
211
+ consortiumConfigPDA,
212
+ sessionPDA,
213
+ validatedPayloadPDA,
214
+ payloadHashArray,
215
+ params,
216
+ debugLog,
209
217
  } = ctx;
210
218
 
211
219
  const validatedPayloadAccount =
@@ -294,14 +302,15 @@ export async function executeConsortiumSession(ctx: ClaimContext): Promise<void>
294
302
 
295
303
  if (!sessionSigned) {
296
304
  debugLog('Step 2: post_session_signatures...');
297
- const { signatures: parsedSigs, indices } =
298
- parseSignaturesFromProof(params.proofSignature);
305
+ const { signatures: parsedSigs, indices } = parseSignaturesFromProof(
306
+ params.proofSignature,
307
+ );
299
308
 
300
309
  if (parsedSigs.length === 0 || indices.length === 0) {
301
310
  throw new Error('No valid signatures found in the proof');
302
311
  }
303
312
 
304
- const signatures = parsedSigs.map(sig => Array.from(sig));
313
+ const signatures = parsedSigs.map((sig) => Array.from(sig));
305
314
 
306
315
  const postSigsTx = await consortiumProgram.methods
307
316
  .postSessionSignatures(payloadHashArray, signatures, indices)
@@ -328,7 +337,7 @@ export async function executeConsortiumSession(ctx: ClaimContext): Promise<void>
328
337
  debugLog('Step 3: finalize_session...');
329
338
  const finalizeSessionTx = await consortiumProgram.methods
330
339
  .finalizeSession(payloadHashArray)
331
- .accounts({
340
+ .accounts({
332
341
  payer: provider.publicKey,
333
342
  config: consortiumConfigPDA,
334
343
  session: sessionPDA,
@@ -350,10 +359,7 @@ export async function executeConsortiumSession(ctx: ClaimContext): Promise<void>
350
359
  // ── Helpers ──
351
360
 
352
361
  export function computePayloadHash(payloadBytes: Buffer): Buffer {
353
- return Buffer.from(
354
- sha256(payloadBytes as unknown as Uint8Array),
355
- 'hex',
356
- );
362
+ return Buffer.from(sha256(payloadBytes as unknown as Uint8Array), 'hex');
357
363
  }
358
364
 
359
365
  /**
@@ -25,10 +25,12 @@ describe('signatureUtils', () => {
25
25
  expect(result.indices).toHaveLength(expectedSignatureCount);
26
26
 
27
27
  // Check indices
28
- expect(result.indices.map(bn => bn.toNumber())).toEqual(expectedIndices);
28
+ expect(result.indices.map((bn) => bn.toNumber())).toEqual(
29
+ expectedIndices,
30
+ );
29
31
 
30
32
  // Check each signature
31
- result.signatures.forEach(sig => {
33
+ result.signatures.forEach((sig) => {
32
34
  expect(sig).toBeInstanceOf(Uint8Array);
33
35
  expect(sig.length).toBe(64);
34
36
  });
@@ -54,7 +56,9 @@ describe('signatureUtils', () => {
54
56
  const result = parseSignaturesFromProof(proof);
55
57
 
56
58
  expect(result.signatures).toHaveLength(expectedSignatureCount);
57
- expect(result.indices.map(bn => bn.toNumber())).toEqual(expectedIndices);
59
+ expect(result.indices.map((bn) => bn.toNumber())).toEqual(
60
+ expectedIndices,
61
+ );
58
62
 
59
63
  for (const sig of result.signatures) {
60
64
  expect(sig).toBeInstanceOf(Uint8Array);
@@ -82,7 +86,9 @@ describe('signatureUtils', () => {
82
86
  const result = parseSignaturesFromProof(proof);
83
87
 
84
88
  expect(result.signatures).toHaveLength(expectedSignatureCount);
85
- expect(result.indices.map(bn => bn.toNumber())).toEqual(expectedIndices);
89
+ expect(result.indices.map((bn) => bn.toNumber())).toEqual(
90
+ expectedIndices,
91
+ );
86
92
 
87
93
  for (const sig of result.signatures) {
88
94
  expect(sig).toBeInstanceOf(Uint8Array);
@@ -150,7 +150,9 @@ export const parseSignaturesFromProof = (
150
150
  continue;
151
151
  }
152
152
 
153
- const isEmptyPlaceholder = signatureBytesCheck.every(byte => byte === 0);
153
+ const isEmptyPlaceholder = signatureBytesCheck.every(
154
+ (byte) => byte === 0,
155
+ );
154
156
 
155
157
  if (isEmptyPlaceholder) {
156
158
  // Skip placeholders
@@ -159,10 +159,7 @@ export const StoryView = ({
159
159
  />
160
160
  )}
161
161
  {(error || connectError) && (
162
- <ErrorDisplay
163
- error={error || connectError}
164
- title="Deposit Error"
165
- />
162
+ <ErrorDisplay error={error || connectError} title="Deposit Error" />
166
163
  )}
167
164
 
168
165
  {transactionLogs && transactionLogs.length > 0 && (
@@ -11,8 +11,10 @@ const MOCK_LBTC_MINT = 'LBTCojyVJ63rsEED2DLEGWMzSxWJyQynXE91LMLgV1J';
11
11
  const MOCK_BTCB_MINT = 'BTCB3ripBAut19jM8kDPVbJHb2ZdR2GcZvGZkCmFPtV8';
12
12
  const MOCK_ASSET_ROUTER = 'LomVyJDZ91jeVbNnTupJXKJTQFakJVMc87CmwDHYt95';
13
13
  const MOCK_MAILBOX = 'LomJw912MoUd7iiAesTQAgz1paLcTqi6ndG3w3pnKH9';
14
- const MOCK_SOLANA_CHAIN_ID = '0259db5080fc2c6d3bcf7ca90712d3c2e5e6c28f27f0dfbb9953bdb0894c03ab';
15
- const MOCK_LEDGER_CHAIN_ID = '031f51c4e4cc1dae1c752d2f8fe2ae045da668a13f2e47a465964d630f5ed22e';
14
+ const MOCK_SOLANA_CHAIN_ID =
15
+ '0259db5080fc2c6d3bcf7ca90712d3c2e5e6c28f27f0dfbb9953bdb0894c03ab';
16
+ const MOCK_LEDGER_CHAIN_ID =
17
+ '031f51c4e4cc1dae1c752d2f8fe2ae045da668a13f2e47a465964d630f5ed22e';
16
18
  const MOCK_PAYER = '8yarEiDaJVikHZbk3PQSoWiDn2T3oM1FHZN1Jv4VZFdr';
17
19
  const MOCK_RECIPIENT = 'DVMiNi7uxHEPABTBt1nLMoxnPniPKbLAFj4MPJq1RDjg';
18
20
  /** Distinct pubkey returned for ATA(mint=LBTC, owner=recipient) */
@@ -26,7 +28,8 @@ const fullConfig: IConfig = {
26
28
  assetRouter: MOCK_ASSET_ROUTER,
27
29
  mailbox: MOCK_MAILBOX,
28
30
  solanaRoutingChainId: MOCK_SOLANA_CHAIN_ID,
29
- bitcoinRoutingChainId: 'ff000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6',
31
+ bitcoinRoutingChainId:
32
+ 'ff000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6',
30
33
  ledgerChainId: MOCK_LEDGER_CHAIN_ID,
31
34
  lbtcProgramId: 'HEY7PCJe3GB27UWdopuYb1xDbB5SNtTcYPxRjntvfBSA',
32
35
  treasuryAddress: 'ByHNGi4zPJw5StyWZoLQJ9n2wT12oupJF2pTSNKMnnAZ',
@@ -92,7 +95,11 @@ vi.mock('../../const/rpcUrls', () => ({
92
95
  }));
93
96
 
94
97
  vi.mock('../../utils/tokenAccount', () => ({
95
- getTokenProgramForMint: vi.fn().mockResolvedValue(new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')),
98
+ getTokenProgramForMint: vi
99
+ .fn()
100
+ .mockResolvedValue(
101
+ new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
102
+ ),
96
103
  }));
97
104
 
98
105
  vi.mock('../../idl/getAssetRouterIdl', () => ({
@@ -112,7 +119,9 @@ vi.mock('@solana/spl-token', () => ({
112
119
  }
113
120
  return new PublicKey(MOCK_PAYER_ATA);
114
121
  }),
115
- ASSOCIATED_TOKEN_PROGRAM_ID: new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'),
122
+ ASSOCIATED_TOKEN_PROGRAM_ID: new PublicKey(
123
+ 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
124
+ ),
116
125
  }));
117
126
 
118
127
  const mockTx = { instructions: [{ keys: [] }] };
@@ -195,20 +204,23 @@ describe('deposit', () => {
195
204
 
196
205
  it('should throw when Asset Router is not configured', async () => {
197
206
  const { getConfig } = await import('../../const/getConfig');
198
- vi.mocked(getConfig).mockReturnValueOnce({ ...fullConfig, assetRouter: null });
207
+ vi.mocked(getConfig).mockReturnValueOnce({
208
+ ...fullConfig,
209
+ assetRouter: null,
210
+ });
199
211
 
200
- await expect(
201
- depositFn(testWallet(MOCK_PAYER), baseParams),
202
- ).rejects.toThrow('Asset Router not configured');
212
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
213
+ 'Asset Router not configured',
214
+ );
203
215
  });
204
216
 
205
217
  it('should throw when Mailbox is not configured', async () => {
206
218
  const { getConfig } = await import('../../const/getConfig');
207
219
  vi.mocked(getConfig).mockReturnValueOnce({ ...fullConfig, mailbox: null });
208
220
 
209
- await expect(
210
- depositFn(testWallet(MOCK_PAYER), baseParams),
211
- ).rejects.toThrow('Mailbox not configured');
221
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
222
+ 'Mailbox not configured',
223
+ );
212
224
  });
213
225
 
214
226
  it('should throw when Solana routing chain ID is not configured', async () => {
@@ -218,27 +230,33 @@ describe('deposit', () => {
218
230
  solanaRoutingChainId: null,
219
231
  });
220
232
 
221
- await expect(
222
- depositFn(testWallet(MOCK_PAYER), baseParams),
223
- ).rejects.toThrow('Solana routing chain ID not configured');
233
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
234
+ 'Solana routing chain ID not configured',
235
+ );
224
236
  });
225
237
 
226
238
  it('should throw when source token mint is not resolved', async () => {
227
239
  const { getConfig } = await import('../../const/getConfig');
228
- vi.mocked(getConfig).mockReturnValueOnce({ ...fullConfig, btcbTokenMint: '' });
240
+ vi.mocked(getConfig).mockReturnValueOnce({
241
+ ...fullConfig,
242
+ btcbTokenMint: '',
243
+ });
229
244
 
230
- await expect(
231
- depositFn(testWallet(MOCK_PAYER), baseParams),
232
- ).rejects.toThrow('Source token mint not configured');
245
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
246
+ 'Source token mint not configured',
247
+ );
233
248
  });
234
249
 
235
250
  it('should throw when destination token is not configured', async () => {
236
251
  const { getConfig } = await import('../../const/getConfig');
237
- vi.mocked(getConfig).mockReturnValueOnce({ ...fullConfig, lbtcTokenMint: '' });
252
+ vi.mocked(getConfig).mockReturnValueOnce({
253
+ ...fullConfig,
254
+ lbtcTokenMint: '',
255
+ });
238
256
 
239
- await expect(
240
- depositFn(testWallet(MOCK_PAYER), baseParams),
241
- ).rejects.toThrow('Destination token not configured');
257
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
258
+ 'Destination token not configured',
259
+ );
242
260
  });
243
261
 
244
262
  it('should throw when amount is zero', async () => {
@@ -255,9 +273,9 @@ describe('deposit', () => {
255
273
  return Promise.resolve({ data: buildMailboxConfigData() });
256
274
  });
257
275
 
258
- await expect(
259
- depositFn(testWallet(MOCK_PAYER), baseParams),
260
- ).rejects.toThrow('Asset Router is paused');
276
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
277
+ 'Asset Router is paused',
278
+ );
261
279
  });
262
280
 
263
281
  it('should throw on insufficient balance', async () => {
@@ -265,22 +283,27 @@ describe('deposit', () => {
265
283
  value: { amount: '10', uiAmountString: '0.0000001' },
266
284
  });
267
285
 
268
- await expect(
269
- depositFn(testWallet(MOCK_PAYER), baseParams),
270
- ).rejects.toThrow('Insufficient balance');
286
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
287
+ 'Insufficient balance',
288
+ );
271
289
  });
272
290
 
273
291
  it('should throw when Ledger chain ID is not configured', async () => {
274
292
  const { getConfig } = await import('../../const/getConfig');
275
- vi.mocked(getConfig).mockReturnValueOnce({ ...fullConfig, ledgerChainId: null });
293
+ vi.mocked(getConfig).mockReturnValueOnce({
294
+ ...fullConfig,
295
+ ledgerChainId: null,
296
+ });
276
297
 
277
- await expect(
278
- depositFn(testWallet(MOCK_PAYER), baseParams),
279
- ).rejects.toThrow('Ledger chain ID not configured');
298
+ await expect(depositFn(testWallet(MOCK_PAYER), baseParams)).rejects.toThrow(
299
+ 'Ledger chain ID not configured',
300
+ );
280
301
  });
281
302
 
282
303
  it('should return transaction signature on success', async () => {
283
- mockConnection.getAccountInfo.mockResolvedValue({ data: buildMailboxConfigData() });
304
+ mockConnection.getAccountInfo.mockResolvedValue({
305
+ data: buildMailboxConfigData(),
306
+ });
284
307
 
285
308
  const sig = await depositFn(testWallet(MOCK_PAYER), baseParams);
286
309
 
@@ -288,7 +311,9 @@ describe('deposit', () => {
288
311
  });
289
312
 
290
313
  it('should pass destination associated token account bytes to deposit()', async () => {
291
- mockConnection.getAccountInfo.mockResolvedValue({ data: buildMailboxConfigData() });
314
+ mockConnection.getAccountInfo.mockResolvedValue({
315
+ data: buildMailboxConfigData(),
316
+ });
292
317
 
293
318
  await depositFn(testWallet(MOCK_PAYER), baseParams);
294
319
 
@@ -301,7 +326,10 @@ describe('deposit', () => {
301
326
 
302
327
  it('should wrap errors with SolanaSdkError', async () => {
303
328
  const { getConfig } = await import('../../const/getConfig');
304
- vi.mocked(getConfig).mockReturnValueOnce({ ...fullConfig, assetRouter: null });
329
+ vi.mocked(getConfig).mockReturnValueOnce({
330
+ ...fullConfig,
331
+ assetRouter: null,
332
+ });
305
333
 
306
334
  try {
307
335
  await depositFn(testWallet(MOCK_PAYER), baseParams);
@@ -313,7 +341,9 @@ describe('deposit', () => {
313
341
  });
314
342
 
315
343
  it('should use env override when provided', async () => {
316
- mockConnection.getAccountInfo.mockResolvedValue({ data: buildMailboxConfigData() });
344
+ mockConnection.getAccountInfo.mockResolvedValue({
345
+ data: buildMailboxConfigData(),
346
+ });
317
347
 
318
348
  const { getConfig } = await import('../../const/getConfig');
319
349
 
@@ -107,7 +107,7 @@ export async function deposit(
107
107
 
108
108
  validateAmount(amount);
109
109
 
110
- const connection = getConnection(network, rpcUrl);
110
+ const connection = getConnection(network, rpcUrl, env);
111
111
  const payer = new PublicKey(provider.publicKey);
112
112
  const mint = new PublicKey(sourceMintAddress);
113
113
  const recipientPubkey = new PublicKey(recipient);
@@ -132,7 +132,10 @@ export async function deposit(
132
132
  getTokenProgramForMint(connection, destinationMint),
133
133
  ]);
134
134
  debugLog('Source token program:', tokenProgramId.toBase58());
135
- debugLog('Destination token program:', destinationTokenProgramId.toBase58());
135
+ debugLog(
136
+ 'Destination token program:',
137
+ destinationTokenProgramId.toBase58(),
138
+ );
136
139
 
137
140
  const [assetRouterConfigPDA] = PublicKey.findProgramAddressSync(
138
141
  [Buffer.from('asset_router_config')],
@@ -162,9 +165,7 @@ export async function deposit(
162
165
  mailboxProgramId,
163
166
  );
164
167
  if (!config.ledgerChainId) {
165
- throw new Error(
166
- `Ledger chain ID not configured for network: ${network}`,
167
- );
168
+ throw new Error(`Ledger chain ID not configured for network: ${network}`);
168
169
  }
169
170
  const ledgerChainId = Buffer.from(config.ledgerChainId, 'hex');
170
171
  const [outboundMessagePathPDA] = PublicKey.findProgramAddressSync(
@@ -177,10 +178,7 @@ export async function deposit(
177
178
  );
178
179
 
179
180
  debugLog('Mailbox config PDA:', mailboxConfigPDA.toBase58());
180
- debugLog(
181
- 'Outbound message path PDA:',
182
- outboundMessagePathPDA.toBase58(),
183
- );
181
+ debugLog('Outbound message path PDA:', outboundMessagePathPDA.toBase58());
184
182
  debugLog('Sender config PDA:', senderConfigPDA.toBase58());
185
183
 
186
184
  const [arConfigInfo, mailboxConfigInfo] = await Promise.all([
@@ -230,7 +228,10 @@ export async function deposit(
230
228
  ASSOCIATED_TOKEN_PROGRAM_ID,
231
229
  );
232
230
  debugLog('Payer token account:', payerTokenAccount.toBase58());
233
- debugLog('Recipient token account (payload):', recipientTokenAccount.toBase58());
231
+ debugLog(
232
+ 'Recipient token account (payload):',
233
+ recipientTokenAccount.toBase58(),
234
+ );
234
235
 
235
236
  const tokenBalance =
236
237
  await connection.getTokenAccountBalance(payerTokenAccount);
@@ -242,10 +243,9 @@ export async function deposit(
242
243
  );
243
244
  }
244
245
 
245
- const assetRouterProgram = new Program(
246
- getAssetRouterIdl(env),
247
- { connection },
248
- );
246
+ const assetRouterProgram = new Program(getAssetRouterIdl(env), {
247
+ connection,
248
+ });
249
249
 
250
250
  const toLchainIdArray = Array.from(toLchainId);
251
251
  const toTokenAddressArray = Array.from(toTokenAddress);
@@ -33,7 +33,7 @@ describe('detectWallet utilities', () => {
33
33
  describe('getSolanaWalletProvider', () => {
34
34
  it.each([InjectedWallet.PHANTOM])(
35
35
  'should return a solana wallet provider if available',
36
- wallet => {
36
+ (wallet) => {
37
37
  const provider = getSolanaWalletProvider(wallet);
38
38
  expect(provider).toBeDefined();
39
39
  },
@@ -41,7 +41,7 @@ describe('detectWallet utilities', () => {
41
41
 
42
42
  it.each([InjectedWallet.COINBASE, InjectedWallet.OKX])(
43
43
  'should throw if wallet is not available',
44
- wallet => {
44
+ (wallet) => {
45
45
  expect(() => getSolanaWalletProvider(wallet)).toThrow();
46
46
  },
47
47
  );
@@ -32,7 +32,7 @@ vi.mock('@solana/web3.js', async () => {
32
32
  },
33
33
  }),
34
34
  })),
35
- PublicKey: vi.fn().mockImplementation(key => {
35
+ PublicKey: vi.fn().mockImplementation((key) => {
36
36
  if (key === 'invalid-key') {
37
37
  throw new Error('Invalid public key');
38
38
  }
@@ -127,6 +127,7 @@ export async function getBalance({
127
127
  tokenAddress,
128
128
  network = DEFAULT_NETWORK,
129
129
  rpcUrl,
130
+ env,
130
131
  }: GetBalanceParams): Promise<GetBalanceResult> {
131
132
  try {
132
133
  // Validate the public key
@@ -151,7 +152,7 @@ export async function getBalance({
151
152
  }
152
153
 
153
154
  // Setup connection with appropriate RPC URL
154
- const connection = getConnection(network, rpcUrl);
155
+ const connection = getConnection(network, rpcUrl, env);
155
156
 
156
157
  try {
157
158
  return await fetchBalance(connection, pubKey, tokenAddress);