@ic-pay/icpay-sdk 1.4.77 → 1.4.93

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/index.js CHANGED
@@ -118,6 +118,122 @@ function u8FromBase64(b64) {
118
118
  arr[i] = bin.charCodeAt(i);
119
119
  return arr;
120
120
  }
121
+ /**
122
+ * Normalize Solana signTransaction result to base64 signed transaction.
123
+ * Wallets may return: signedTransaction, transaction, signedMessage (string base64/base58),
124
+ * serializedTransaction (Uint8Array), or the raw value. Phantom may return base58.
125
+ */
126
+ function normalizeSolanaSignedTransaction(r) {
127
+ if (r == null)
128
+ return null;
129
+ const toB64 = (val) => {
130
+ if (val == null)
131
+ return null;
132
+ if (typeof val === 'string') {
133
+ const looksBase64 = /^[A-Za-z0-9+/=]+$/.test(val) && val.length >= 80 && val.length % 4 === 0;
134
+ if (looksBase64)
135
+ return val;
136
+ try {
137
+ const decoded = base58Decode(val);
138
+ if (decoded.length > 64)
139
+ return b64FromBytes(decoded);
140
+ }
141
+ catch { }
142
+ return null;
143
+ }
144
+ if (val.byteLength != null || ArrayBuffer.isView(val)) {
145
+ const b = val instanceof Uint8Array ? val : new Uint8Array(val);
146
+ if (b.length > 64)
147
+ return b64FromBytes(b);
148
+ }
149
+ if (typeof val === 'object' && typeof val.serialize === 'function') {
150
+ try {
151
+ const out = val.serialize({ requireAllSignatures: false, verifySignatures: false });
152
+ const b = out instanceof Uint8Array ? out : new Uint8Array(out);
153
+ if (b.length > 64)
154
+ return b64FromBytes(b);
155
+ }
156
+ catch { }
157
+ }
158
+ return null;
159
+ };
160
+ const direct = toB64(r);
161
+ if (direct)
162
+ return direct;
163
+ if (typeof r === 'object') {
164
+ for (const key of ['signedTransaction', 'transaction', 'signedMessage', 'serializedTransaction', 'encodedTransaction', 'message']) {
165
+ const v = r[key];
166
+ const b64 = toB64(v);
167
+ if (b64)
168
+ return b64;
169
+ }
170
+ }
171
+ return null;
172
+ }
173
+ /** Normalize Solana signMessage result to base64 64-byte signature. Phantom returns { signature, rawSignature }; some wallets return { signature: Uint8Array } or string. */
174
+ function normalizeSolanaMessageSignature(r) {
175
+ if (!r)
176
+ return null;
177
+ // Direct string (base58 or base64)
178
+ if (typeof r === 'string') {
179
+ if (r.length === 88 && /^[1-9A-HJ-NP-Za-km-z]+$/.test(r)) {
180
+ try {
181
+ const b = base58Decode(r);
182
+ return b.length === 64 ? b64FromBytes(b) : null;
183
+ }
184
+ catch {
185
+ return null;
186
+ }
187
+ }
188
+ try {
189
+ const b = u8FromBase64(r);
190
+ return b.length === 64 ? b64FromBytes(b) : null;
191
+ }
192
+ catch {
193
+ return null;
194
+ }
195
+ }
196
+ // Byte-like (Uint8Array / ArrayBufferView)
197
+ if (r.byteLength != null || ArrayBuffer.isView(r)) {
198
+ const b = r instanceof Uint8Array ? r : new Uint8Array(r);
199
+ return b.length === 64 ? b64FromBytes(b) : null;
200
+ }
201
+ // Object: signature (string or Uint8Array) or rawSignature (base64 string)
202
+ if (typeof r === 'object') {
203
+ const sig = r.signature;
204
+ if (sig != null) {
205
+ if (typeof sig === 'string') {
206
+ try {
207
+ const b = base58Decode(sig);
208
+ return b.length === 64 ? b64FromBytes(b) : null;
209
+ }
210
+ catch { }
211
+ try {
212
+ const b = u8FromBase64(sig);
213
+ return b.length === 64 ? b64FromBytes(b) : null;
214
+ }
215
+ catch { }
216
+ }
217
+ if (sig.byteLength != null || ArrayBuffer.isView(sig)) {
218
+ const b = sig instanceof Uint8Array ? sig : new Uint8Array(sig);
219
+ return b.length === 64 ? b64FromBytes(b) : null;
220
+ }
221
+ }
222
+ const raw = r.rawSignature;
223
+ if (typeof raw === 'string') {
224
+ try {
225
+ const b = u8FromBase64(raw);
226
+ return b.length === 64 ? b64FromBytes(b) : null;
227
+ }
228
+ catch { }
229
+ }
230
+ if (Array.isArray(r.data)) {
231
+ const b = Uint8Array.from(r.data);
232
+ return b.length === 64 ? b64FromBytes(b) : null;
233
+ }
234
+ }
235
+ return null;
236
+ }
121
237
  // Normalize metadata so internal icpay-managed fields are nested under metadata.icpay.
122
238
  // If icpay exists, merge; otherwise create. Move known internal keys and icpay_* keys under icpay.
123
239
  function normalizeSdkMetadata(base) {
@@ -800,6 +916,7 @@ class Icpay {
800
916
  const prebuiltBase64 = params.request?.__transactionBase64;
801
917
  if (typeof prebuiltBase64 === 'string' && prebuiltBase64.length > 0) {
802
918
  let signature = null;
919
+ let relay;
803
920
  try {
804
921
  if (sol?.request) {
805
922
  // Treat as Phantom only if the selected provider itself reports isPhantom,
@@ -835,76 +952,62 @@ class Icpay {
835
952
  }
836
953
  catch { }
837
954
  }
838
- let candidate = (r?.signedTransaction || r?.transaction || r?.signedMessage || r);
839
- if (typeof candidate === 'string') {
840
- const looksBase64 = /^[A-Za-z0-9+/=]+$/.test(candidate) && candidate.length % 4 === 0;
841
- if (looksBase64)
842
- signedTxB64 = candidate;
843
- else
844
- signerSigBase58 = candidate;
845
- }
846
- else if (candidate && (candidate.byteLength != null || ArrayBuffer.isView(candidate))) {
847
- const b = candidate instanceof Uint8Array ? candidate : new Uint8Array(candidate);
848
- if (b.length > 64)
849
- signedTxB64 = b64FromBytes(b);
850
- else if (b.length === 64)
851
- signerSigBase58 = base58Encode(b);
852
- }
853
- else if (r && typeof r === 'object') {
854
- const obj = r;
855
- if (typeof obj.signedTransaction === 'string')
856
- signedTxB64 = obj.signedTransaction;
857
- if (!signedTxB64 && typeof obj.signature === 'string')
858
- signerSigBase58 = obj.signature;
859
- if (!signedTxB64 && obj && typeof obj.serialize === 'function') {
860
- try {
861
- const out = obj.serialize({ requireAllSignatures: false, verifySignatures: false });
862
- if (out && (out.byteLength != null || ArrayBuffer.isView(out))) {
863
- const b = out instanceof Uint8Array ? out : new Uint8Array(out);
864
- if (b.length > 64)
865
- signedTxB64 = b64FromBytes(b);
955
+ signedTxB64 = normalizeSolanaSignedTransaction(r) ?? signedTxB64;
956
+ if (!signedTxB64 && !signerSigBase58) {
957
+ const candidate = (r?.signedTransaction || r?.transaction || r?.signedMessage || r);
958
+ if (typeof candidate === 'string') {
959
+ const looksBase64 = /^[A-Za-z0-9+/=]+$/.test(candidate) && candidate.length % 4 === 0;
960
+ if (looksBase64)
961
+ signedTxB64 = candidate;
962
+ else
963
+ signerSigBase58 = candidate;
964
+ }
965
+ else if (candidate && (candidate.byteLength != null || ArrayBuffer.isView(candidate))) {
966
+ const b = candidate instanceof Uint8Array ? candidate : new Uint8Array(candidate);
967
+ if (b.length > 64)
968
+ signedTxB64 = b64FromBytes(b);
969
+ else if (b.length === 64)
970
+ signerSigBase58 = base58Encode(b);
971
+ }
972
+ else if (r && typeof r === 'object') {
973
+ const obj = r;
974
+ if (typeof obj.signedTransaction === 'string')
975
+ signedTxB64 = obj.signedTransaction;
976
+ if (!signedTxB64 && typeof obj.signature === 'string')
977
+ signerSigBase58 = obj.signature;
978
+ if (!signedTxB64 && obj && typeof obj.serialize === 'function') {
979
+ try {
980
+ const out = obj.serialize({ requireAllSignatures: false, verifySignatures: false });
981
+ if (out && (out.byteLength != null || ArrayBuffer.isView(out))) {
982
+ const b = out instanceof Uint8Array ? out : new Uint8Array(out);
983
+ if (b.length > 64)
984
+ signedTxB64 = b64FromBytes(b);
985
+ }
866
986
  }
987
+ catch { }
867
988
  }
868
- catch { }
869
989
  }
870
990
  }
871
- // Direct provider API fallback (Phantom: signTransaction(Transaction))
872
991
  if (!signedTxB64 && typeof sol.signTransaction === 'function') {
873
992
  try {
874
993
  const txBytes = u8FromBase64(prebuiltBase64);
875
994
  const stx = await sol.signTransaction(txBytes);
876
- if (stx) {
877
- if (typeof stx === 'string') {
878
- const looksBase64 = /^[A-Za-z0-9+/=]+$/.test(stx) && stx.length % 4 === 0;
879
- if (looksBase64)
880
- signedTxB64 = stx;
881
- else
882
- signerSigBase58 = stx;
883
- }
884
- else if (stx && typeof stx.serialize === 'function') {
885
- try {
886
- const out = stx.serialize({ requireAllSignatures: false, verifySignatures: false });
887
- const b = out instanceof Uint8Array ? out : new Uint8Array(out);
888
- if (b.length > 64)
889
- signedTxB64 = b64FromBytes(b);
890
- }
891
- catch { }
892
- }
893
- else if (stx && (stx.byteLength != null || ArrayBuffer.isView(stx))) {
894
- const b = stx instanceof Uint8Array ? stx : new Uint8Array(stx);
895
- if (b.length > 64)
896
- signedTxB64 = b64FromBytes(b);
897
- else if (b.length === 64)
898
- signerSigBase58 = base58Encode(b);
899
- }
995
+ const parsed = normalizeSolanaSignedTransaction(stx);
996
+ if (parsed)
997
+ signedTxB64 = parsed;
998
+ else if (stx && typeof stx === 'string' && stx.length === 88)
999
+ signerSigBase58 = stx;
1000
+ else if (stx && (stx.byteLength != null || ArrayBuffer.isView(stx))) {
1001
+ const b = stx instanceof Uint8Array ? stx : new Uint8Array(stx);
1002
+ if (b.length === 64)
1003
+ signerSigBase58 = base58Encode(b);
900
1004
  }
901
1005
  }
902
1006
  catch { }
903
1007
  }
904
1008
  if (!signedTxB64 && !signerSigBase58)
905
1009
  throw new Error('Wallet did not return a signed transaction');
906
- // Relay via API
907
- let relay;
1010
+ // Relay via API. Standard flow prebuilt tx has payer as fee payer (no facilitatorPaysFee).
908
1011
  if (signedTxB64) {
909
1012
  relay = await this.publicApiClient.post('/sdk/public/payments/solana/relay', {
910
1013
  signedTransactionBase64: signedTxB64,
@@ -976,6 +1079,25 @@ class Icpay {
976
1079
  this.emitMethodSuccess('notifyLedgerTransaction', { paymentIntentId: params.paymentIntentId });
977
1080
  }
978
1081
  catch { }
1082
+ // If relay already returned completed payload (paymentIntent + payment), skip notify and polling
1083
+ const relayPayload = typeof relay?.paymentIntent !== 'undefined' || typeof relay?.payment !== 'undefined' ? relay : undefined;
1084
+ const relayStatus = relayPayload && (typeof relayPayload.status === 'string' ? relayPayload.status : relayPayload?.paymentIntent?.status || relayPayload?.payment?.status || '');
1085
+ const relayTerminal = typeof relayStatus === 'string' && ['completed', 'succeeded'].includes(String(relayStatus).toLowerCase());
1086
+ if (relayPayload && relayTerminal) {
1087
+ const norm = String(relayStatus).toLowerCase();
1088
+ const out = {
1089
+ transactionId: 0,
1090
+ status: norm === 'succeeded' ? 'completed' : norm,
1091
+ amount: params.amount.toString(),
1092
+ recipientCanister: params.ledgerCanisterId,
1093
+ timestamp: new Date(),
1094
+ description: 'Fund transfer',
1095
+ metadata: { ...(params.metadata || {}), icpay_solana_tx_sig: signature },
1096
+ payment: relayPayload,
1097
+ };
1098
+ this.emit('icpay-sdk-transaction-completed', out);
1099
+ return out;
1100
+ }
979
1101
  try {
980
1102
  await this.performNotifyPaymentIntent({ paymentIntentId: params.paymentIntentId, transactionId: signature, maxAttempts: 1 });
981
1103
  }
@@ -1405,6 +1527,7 @@ class Icpay {
1405
1527
  recipientAddress,
1406
1528
  recipientAddresses: request?.recipientAddresses || undefined,
1407
1529
  externalCostAmount: request?.externalCostAmount ?? request?.metadata?.externalCostAmount ?? undefined,
1530
+ fiat_currency: request?.fiat_currency,
1408
1531
  });
1409
1532
  }
1410
1533
  else {
@@ -1416,6 +1539,7 @@ class Icpay {
1416
1539
  metadata: normalizeSdkMetadata(request.metadata || {}),
1417
1540
  widgetParams: request.widgetParams || undefined,
1418
1541
  recipientAddresses: request?.recipientAddresses || undefined,
1542
+ fiat_currency: request?.fiat_currency,
1419
1543
  });
1420
1544
  }
1421
1545
  else {
@@ -1436,6 +1560,7 @@ class Icpay {
1436
1560
  recipientAddress,
1437
1561
  recipientAddresses: request?.recipientAddresses || undefined,
1438
1562
  externalCostAmount: request?.externalCostAmount ?? request?.metadata?.externalCostAmount ?? undefined,
1563
+ fiat_currency: request?.fiat_currency,
1439
1564
  });
1440
1565
  }
1441
1566
  }
@@ -1851,6 +1976,8 @@ class Icpay {
1851
1976
  search.set('amountUsd', String(params.amountUsd));
1852
1977
  if (typeof params.amount === 'string' && params.amount)
1853
1978
  search.set('amount', params.amount);
1979
+ if (typeof params.fiatCurrency === 'string' && params.fiatCurrency.trim())
1980
+ search.set('fiatCurrency', params.fiatCurrency.trim());
1854
1981
  if (Array.isArray(params.chainShortcodes) && params.chainShortcodes.length > 0)
1855
1982
  search.set('chainShortcodes', params.chainShortcodes.join(','));
1856
1983
  if (Array.isArray(params.tokenShortcodes) && params.tokenShortcodes.length > 0)
@@ -2092,6 +2219,7 @@ class Icpay {
2092
2219
  chainId: tokenShortcode ? undefined : request.chainId,
2093
2220
  recipientAddress: request?.recipientAddress || '0x0000000000000000000000000000000000000000',
2094
2221
  recipientAddresses: request?.recipientAddresses,
2222
+ fiat_currency: request?.fiat_currency ?? request?.fiatCurrency ?? this.config?.fiat_currency,
2095
2223
  };
2096
2224
  const res = await this.createPayment(createTransactionRequest);
2097
2225
  this.emitMethodSuccess('createPaymentUsd', res);
@@ -2136,11 +2264,15 @@ class Icpay {
2136
2264
  chainId: tokenShortcode ? undefined : request.chainId,
2137
2265
  x402: true,
2138
2266
  recipientAddress: request?.recipientAddress || '0x0000000000000000000000000000000000000000',
2267
+ fiat_currency: request?.fiat_currency ?? request?.fiatCurrency ?? this.config?.fiat_currency,
2139
2268
  };
2140
- // Include Solana payerPublicKey if available so server can build unsigned tx inline for Solana x402
2269
+ if (body.fiat_currency === undefined || body.fiat_currency === '') {
2270
+ delete body.fiat_currency;
2271
+ }
2272
+ // Include Solana payerPublicKey so server can build unsigned tx (standard x402 flow)
2141
2273
  try {
2142
2274
  const w = globalThis?.window || globalThis;
2143
- const sol = this.config?.solanaProvider || w?.solana || w?.phantom?.solana;
2275
+ const sol = this.config?.solanaProvider || this.config?.connectedWallet?.solana || this.config?.connectedWallet || w?.solana || w?.phantom?.solana;
2144
2276
  const pk = sol?.publicKey?.toBase58?.() || sol?.publicKey || null;
2145
2277
  if (pk && typeof pk === 'string') {
2146
2278
  body.payerPublicKey = pk;
@@ -2355,10 +2487,12 @@ class Icpay {
2355
2487
  });
2356
2488
  }
2357
2489
  if (isSol) {
2358
- // Solana x402: prefer message-sign flow if server provided a signable message
2490
+ // Solana x402: follow standard flow (https://solana.com/developers/guides/getstarted/intro-to-x402)
2491
+ // — client signs transaction with signTransaction, then relay. No signMessage.
2492
+ const solTxBase64 = requirement?.extra?.transactionBase64;
2493
+ const solMsgB58 = requirement?.extra?.messageBase58;
2359
2494
  const signableMsgB64 = requirement?.extra?.signableMessageBase64;
2360
2495
  const signableFields = requirement?.extra?.signableFields || {};
2361
- const wSolCtx = globalThis?.window || globalThis;
2362
2496
  const sol = providerForHeader;
2363
2497
  if (!sol)
2364
2498
  throw new errors_1.IcpayError({ code: errors_1.ICPAY_ERROR_CODES.WALLET_PROVIDER_NOT_AVAILABLE, message: 'Solana provider not available (window.solana)' });
@@ -2377,7 +2511,120 @@ class Icpay {
2377
2511
  }
2378
2512
  if (!fromBase58)
2379
2513
  throw new errors_1.IcpayError({ code: errors_1.ICPAY_ERROR_CODES.WALLET_NOT_CONNECTED, message: 'Solana wallet not connected' });
2380
- // No ICPay popups; only wallet UI should be shown for signing
2514
+ // Standard x402: when server provided unsigned tx, sign it and relay (no signMessage)
2515
+ if (solTxBase64 && solTxBase64.length > 0) {
2516
+ if (typeof sol?.connect === 'function') {
2517
+ try {
2518
+ await sol.connect({ onlyIfTrusted: false });
2519
+ }
2520
+ catch { }
2521
+ }
2522
+ const __txB64 = String(solTxBase64);
2523
+ const inlineMsgB58 = solMsgB58 && solMsgB58.length > 0 ? String(solMsgB58) : base58Encode(u8FromBase64(__txB64));
2524
+ let signedTxB64 = null;
2525
+ let r = null;
2526
+ if (sol?.request) {
2527
+ try {
2528
+ try {
2529
+ r = await sol.request({ method: 'signTransaction', params: { message: inlineMsgB58 } });
2530
+ }
2531
+ catch { }
2532
+ if (!r)
2533
+ try {
2534
+ r = await sol.request({ method: 'signTransaction', params: inlineMsgB58 });
2535
+ }
2536
+ catch { }
2537
+ if (!r)
2538
+ try {
2539
+ r = await sol.request({ method: 'solana:signTransaction', params: { transaction: __txB64 } });
2540
+ }
2541
+ catch { }
2542
+ if (!r)
2543
+ try {
2544
+ r = await sol.request({ method: 'signTransaction', params: { transaction: __txB64 } });
2545
+ }
2546
+ catch { }
2547
+ }
2548
+ catch { }
2549
+ }
2550
+ signedTxB64 = normalizeSolanaSignedTransaction(r) ?? signedTxB64;
2551
+ if (!signedTxB64 && r) {
2552
+ const candidate = (r?.signedTransaction || r?.transaction || r?.signedMessage || r);
2553
+ if (typeof candidate === 'string') {
2554
+ const looksBase64 = /^[A-Za-z0-9+/=]+$/.test(candidate) && candidate.length % 4 === 0;
2555
+ if (looksBase64)
2556
+ signedTxB64 = candidate;
2557
+ }
2558
+ else if (candidate && (candidate.byteLength != null || ArrayBuffer.isView(candidate))) {
2559
+ const b = candidate instanceof Uint8Array ? candidate : new Uint8Array(candidate);
2560
+ if (b.length > 64)
2561
+ signedTxB64 = b64FromBytes(b);
2562
+ }
2563
+ else if (typeof r === 'object') {
2564
+ const obj = r;
2565
+ if (typeof obj.signedTransaction === 'string')
2566
+ signedTxB64 = obj.signedTransaction;
2567
+ else if (typeof obj.transaction === 'string')
2568
+ signedTxB64 = obj.transaction;
2569
+ }
2570
+ }
2571
+ if (!signedTxB64 && typeof sol.signTransaction === 'function') {
2572
+ try {
2573
+ const txBytes = u8FromBase64(__txB64);
2574
+ const stx = await sol.signTransaction(txBytes);
2575
+ signedTxB64 = normalizeSolanaSignedTransaction(stx) ?? signedTxB64;
2576
+ }
2577
+ catch { }
2578
+ }
2579
+ if (signedTxB64) {
2580
+ const relay = await this.publicApiClient.post('/sdk/public/payments/solana/relay', {
2581
+ signedTransactionBase64: signedTxB64,
2582
+ paymentIntentId,
2583
+ facilitatorPaysFee: true,
2584
+ });
2585
+ const sig = (relay && relay.signature) || null;
2586
+ try {
2587
+ this.emitMethodSuccess('notifyLedgerTransaction', { paymentIntentId });
2588
+ }
2589
+ catch { }
2590
+ if (sig) {
2591
+ try {
2592
+ await this.performNotifyPaymentIntent({ paymentIntentId, transactionId: sig, maxAttempts: 1 });
2593
+ }
2594
+ catch { }
2595
+ }
2596
+ const relayStatus = relay?.status || relay?.paymentIntent?.status || relay?.payment?.status || '';
2597
+ const terminal = typeof relayStatus === 'string' && ['completed', 'succeeded'].includes(String(relayStatus).toLowerCase());
2598
+ if (terminal) {
2599
+ const out = {
2600
+ transactionId: 0,
2601
+ status: String(relayStatus).toLowerCase() === 'succeeded' ? 'completed' : relayStatus,
2602
+ amount: requirement?.maxAmountRequired?.toString?.() || '',
2603
+ recipientCanister: ledgerCanisterId,
2604
+ timestamp: new Date(),
2605
+ metadata: { ...(request.metadata || {}), icpay_x402: true, icpay_solana_tx_sig: sig },
2606
+ payment: relay,
2607
+ };
2608
+ this.emit('icpay-sdk-transaction-completed', out);
2609
+ this.emitMethodSuccess('createPaymentX402Usd', out);
2610
+ return out;
2611
+ }
2612
+ const waited = await this.awaitIntentTerminal({
2613
+ paymentIntentId,
2614
+ transactionId: sig,
2615
+ ledgerCanisterId: ledgerCanisterId,
2616
+ amount: requirement?.maxAmountRequired?.toString?.() || '',
2617
+ metadata: { ...(request.metadata || {}), icpay_x402: true, icpay_solana_tx_sig: sig },
2618
+ });
2619
+ this.emitMethodSuccess('createPaymentX402Usd', waited);
2620
+ return waited;
2621
+ }
2622
+ throw new errors_1.IcpayError({
2623
+ code: errors_1.ICPAY_ERROR_CODES.TRANSACTION_FAILED,
2624
+ message: 'Transaction was not signed. Please approve the transaction in your wallet.',
2625
+ });
2626
+ }
2627
+ // Fallback: message-sign flow only when no transactionBase64 (e.g. 402 built without payerPublicKey)
2381
2628
  if (signableMsgB64) {
2382
2629
  // Sign the provided message and settle via header (services will submit)
2383
2630
  // Ensure explicit connect prompt before signing
@@ -2391,7 +2638,7 @@ class Icpay {
2391
2638
  const msgBytes = u8FromBase64(signableMsgB64);
2392
2639
  const msgB58ForReq = base58Encode(msgBytes);
2393
2640
  // Attempts in order (strict):
2394
- // 1) Wallet Standard: request colon form with Uint8Array
2641
+ // 1) Wallet Standard: request colon form with Uint8Array (Phantom returns { signature, rawSignature } or { signature: Uint8Array })
2395
2642
  if (!sigB64 && sol?.request) {
2396
2643
  try {
2397
2644
  try {
@@ -2399,34 +2646,7 @@ class Icpay {
2399
2646
  }
2400
2647
  catch { }
2401
2648
  const r0 = await sol.request({ method: 'solana:signMessage', params: { message: msgBytes } });
2402
- if (typeof r0 === 'string') {
2403
- try {
2404
- const b = base58Decode(r0);
2405
- sigB64 = b64FromBytes(b);
2406
- }
2407
- catch {
2408
- sigB64 = r0;
2409
- }
2410
- }
2411
- else if (r0 && typeof r0.signature === 'string') {
2412
- try {
2413
- const b = base58Decode(r0.signature);
2414
- sigB64 = b64FromBytes(b);
2415
- }
2416
- catch {
2417
- sigB64 = r0.signature;
2418
- }
2419
- }
2420
- else if (r0 && (r0.byteLength != null || ArrayBuffer.isView(r0))) {
2421
- const b = r0 instanceof Uint8Array ? r0 : new Uint8Array(r0);
2422
- if (b && b.length === 64)
2423
- sigB64 = b64FromBytes(b);
2424
- }
2425
- else if (r0 && typeof r0 === 'object' && Array.isArray(r0.data)) {
2426
- const b = Uint8Array.from(r0.data);
2427
- if (b && b.length === 64)
2428
- sigB64 = b64FromBytes(b);
2429
- }
2649
+ sigB64 = normalizeSolanaMessageSignature(r0) ?? sigB64;
2430
2650
  }
2431
2651
  catch (e0) {
2432
2652
  try {
@@ -2443,30 +2663,7 @@ class Icpay {
2443
2663
  }
2444
2664
  catch { }
2445
2665
  const r2 = await sol.signMessage(msgBytes);
2446
- if (r2 && (r2.byteLength != null || ArrayBuffer.isView(r2))) {
2447
- const b = r2 instanceof Uint8Array ? r2 : new Uint8Array(r2);
2448
- if (b && b.length === 64)
2449
- sigB64 = b64FromBytes(b);
2450
- }
2451
- else if (typeof r2 === 'string') {
2452
- try {
2453
- const b = base58Decode(r2);
2454
- sigB64 = b64FromBytes(b);
2455
- }
2456
- catch {
2457
- sigB64 = r2;
2458
- }
2459
- }
2460
- else if (r2 && typeof r2 === 'object' && typeof r2.signature === 'string') {
2461
- const s = r2.signature;
2462
- try {
2463
- const b = base58Decode(s);
2464
- sigB64 = b64FromBytes(b);
2465
- }
2466
- catch {
2467
- sigB64 = s;
2468
- }
2469
- }
2666
+ sigB64 = normalizeSolanaMessageSignature(r2) ?? sigB64;
2470
2667
  }
2471
2668
  catch (e2) {
2472
2669
  try {
@@ -2483,34 +2680,7 @@ class Icpay {
2483
2680
  }
2484
2681
  catch { }
2485
2682
  const r3 = await sol.request({ method: 'signMessage', params: { message: msgBytes } });
2486
- if (typeof r3 === 'string') {
2487
- try {
2488
- const b = base58Decode(r3);
2489
- sigB64 = b64FromBytes(b);
2490
- }
2491
- catch {
2492
- sigB64 = r3;
2493
- }
2494
- }
2495
- else if (r3 && typeof r3.signature === 'string') {
2496
- try {
2497
- const b = base58Decode(r3.signature);
2498
- sigB64 = b64FromBytes(b);
2499
- }
2500
- catch {
2501
- sigB64 = r3.signature;
2502
- }
2503
- }
2504
- else if (r3 && (r3.byteLength != null || ArrayBuffer.isView(r3))) {
2505
- const b = r3 instanceof Uint8Array ? r3 : new Uint8Array(r3);
2506
- if (b && b.length === 64)
2507
- sigB64 = b64FromBytes(b);
2508
- }
2509
- else if (r3 && typeof r3 === 'object' && Array.isArray(r3.data)) {
2510
- const b = Uint8Array.from(r3.data);
2511
- if (b && b.length === 64)
2512
- sigB64 = b64FromBytes(b);
2513
- }
2683
+ sigB64 = normalizeSolanaMessageSignature(r3) ?? sigB64;
2514
2684
  }
2515
2685
  catch (e3) {
2516
2686
  try {
@@ -2527,34 +2697,7 @@ class Icpay {
2527
2697
  }
2528
2698
  catch { }
2529
2699
  const r4 = await sol.request({ method: 'signMessage', params: { message: msgB58ForReq } });
2530
- if (typeof r4 === 'string') {
2531
- try {
2532
- const b = base58Decode(r4);
2533
- sigB64 = b64FromBytes(b);
2534
- }
2535
- catch {
2536
- sigB64 = r4;
2537
- }
2538
- }
2539
- else if (r4 && typeof r4.signature === 'string') {
2540
- try {
2541
- const b = base58Decode(r4.signature);
2542
- sigB64 = b64FromBytes(b);
2543
- }
2544
- catch {
2545
- sigB64 = r4.signature;
2546
- }
2547
- }
2548
- else if (r4 && (r4.byteLength != null || ArrayBuffer.isView(r4))) {
2549
- const b = r4 instanceof Uint8Array ? r4 : new Uint8Array(r4);
2550
- if (b && b.length === 64)
2551
- sigB64 = b64FromBytes(b);
2552
- }
2553
- else if (r4 && typeof r4 === 'object' && Array.isArray(r4.data)) {
2554
- const b = Uint8Array.from(r4.data);
2555
- if (b && b.length === 64)
2556
- sigB64 = b64FromBytes(b);
2557
- }
2700
+ sigB64 = normalizeSolanaMessageSignature(r4) ?? sigB64;
2558
2701
  }
2559
2702
  catch (e4) {
2560
2703
  try {
@@ -2646,10 +2789,13 @@ class Icpay {
2646
2789
  return waitedSolHdr;
2647
2790
  }
2648
2791
  else {
2649
- // Fallback: if API provided an unsigned transaction, try transaction-signing path
2792
+ // Fallback: if API provided an unsigned transaction, try transaction-signing path (signTransaction like normal Solana flow)
2650
2793
  const fallbackTx = requirement?.extra?.transactionBase64;
2651
2794
  if (!fallbackTx) {
2652
- throw new errors_1.IcpayError({ code: errors_1.ICPAY_ERROR_CODES.TRANSACTION_FAILED, message: 'Wallet did not sign message' });
2795
+ throw new errors_1.IcpayError({
2796
+ code: errors_1.ICPAY_ERROR_CODES.TRANSACTION_FAILED,
2797
+ message: 'Wallet did not sign message. Connect your Solana wallet before starting the payment and try again.',
2798
+ });
2653
2799
  }
2654
2800
  // Inject for transaction-signing fallback below
2655
2801
  // eslint-disable-next-line @typescript-eslint/no-unused-vars