@futurekode/stablepay-react 0.4.0 → 0.5.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/dist/index.d.mts +51 -4
- package/dist/index.d.ts +51 -4
- package/dist/index.js +234 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +232 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
-
type StablePaySuccessPayload = {
|
|
4
|
+
type StablePaySuccessPayload$1 = {
|
|
5
5
|
signature: string;
|
|
6
6
|
amount: number;
|
|
7
7
|
to: string;
|
|
@@ -11,7 +11,7 @@ type StablePayPayArgs = {
|
|
|
11
11
|
amount: number;
|
|
12
12
|
to: string;
|
|
13
13
|
reference?: string;
|
|
14
|
-
onSuccess?: (payload: StablePaySuccessPayload) => void;
|
|
14
|
+
onSuccess?: (payload: StablePaySuccessPayload$1) => void;
|
|
15
15
|
onError?: (error: Error) => void;
|
|
16
16
|
};
|
|
17
17
|
type StablePayProviderProps = {
|
|
@@ -27,7 +27,7 @@ type StablePayProps = {
|
|
|
27
27
|
onClick?: (event: React.MouseEvent) => void;
|
|
28
28
|
disabled?: boolean;
|
|
29
29
|
}>;
|
|
30
|
-
onSuccess?: (payload: StablePaySuccessPayload) => void;
|
|
30
|
+
onSuccess?: (payload: StablePaySuccessPayload$1) => void;
|
|
31
31
|
onError?: (error: Error) => void;
|
|
32
32
|
};
|
|
33
33
|
type UseStablePayResult = {
|
|
@@ -36,6 +36,25 @@ type UseStablePayResult = {
|
|
|
36
36
|
error: Error | null;
|
|
37
37
|
signature: string | null;
|
|
38
38
|
};
|
|
39
|
+
type VerifyPaymentInput = {
|
|
40
|
+
to: string;
|
|
41
|
+
amount: string;
|
|
42
|
+
txHash: string;
|
|
43
|
+
reference?: string;
|
|
44
|
+
};
|
|
45
|
+
type VerifyPaymentResult = {
|
|
46
|
+
ok: true;
|
|
47
|
+
status: "confirmed" | "pending";
|
|
48
|
+
txHash: string;
|
|
49
|
+
to: string;
|
|
50
|
+
amount: string;
|
|
51
|
+
reference?: string;
|
|
52
|
+
confirmations: number;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
reason: "TX_FAILED" | "TO_MISMATCH" | "AMOUNT_TOO_LOW" | "REFERENCE_MISMATCH" | "INVALID_TRANSACTION";
|
|
56
|
+
txHash: string;
|
|
57
|
+
};
|
|
39
58
|
|
|
40
59
|
declare function StablePayProvider({ children, endpoint, to, }: StablePayProviderProps): react_jsx_runtime.JSX.Element;
|
|
41
60
|
|
|
@@ -51,4 +70,32 @@ declare function useStablePay(): {
|
|
|
51
70
|
signature: string | null;
|
|
52
71
|
};
|
|
53
72
|
|
|
54
|
-
|
|
73
|
+
type StablePaySuccessPayload = {
|
|
74
|
+
signature: string;
|
|
75
|
+
amount: number;
|
|
76
|
+
to: string;
|
|
77
|
+
reference?: string;
|
|
78
|
+
};
|
|
79
|
+
type PaymentVerificationStatus = "idle" | "verifying" | "pending" | "confirmed" | "failed";
|
|
80
|
+
type UsePaymentVerificationOptions = {
|
|
81
|
+
maxAttempts?: number;
|
|
82
|
+
intervalMs?: number;
|
|
83
|
+
};
|
|
84
|
+
type UsePaymentVerificationResult = {
|
|
85
|
+
status: PaymentVerificationStatus;
|
|
86
|
+
result: VerifyPaymentResult | null;
|
|
87
|
+
error: Error | null;
|
|
88
|
+
verify: (payload: StablePaySuccessPayload) => Promise<VerifyPaymentResult>;
|
|
89
|
+
reset: () => void;
|
|
90
|
+
};
|
|
91
|
+
declare function usePaymentVerification(options?: UsePaymentVerificationOptions): UsePaymentVerificationResult;
|
|
92
|
+
|
|
93
|
+
declare function verifyPayment(input: VerifyPaymentInput): Promise<VerifyPaymentResult>;
|
|
94
|
+
|
|
95
|
+
type WaitForPaymentConfirmationOptions = {
|
|
96
|
+
maxAttempts?: number;
|
|
97
|
+
intervalMs?: number;
|
|
98
|
+
};
|
|
99
|
+
declare function waitForPaymentConfirmation(input: VerifyPaymentInput, options?: WaitForPaymentConfirmationOptions): Promise<VerifyPaymentResult>;
|
|
100
|
+
|
|
101
|
+
export { StablePay, type StablePayPayArgs, type StablePayProps, StablePayProvider, type StablePayProviderProps, type StablePaySuccessPayload$1 as StablePaySuccessPayload, type UseStablePayResult, type VerifyPaymentInput, usePaymentVerification, useStablePay, verifyPayment, waitForPaymentConfirmation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
-
type StablePaySuccessPayload = {
|
|
4
|
+
type StablePaySuccessPayload$1 = {
|
|
5
5
|
signature: string;
|
|
6
6
|
amount: number;
|
|
7
7
|
to: string;
|
|
@@ -11,7 +11,7 @@ type StablePayPayArgs = {
|
|
|
11
11
|
amount: number;
|
|
12
12
|
to: string;
|
|
13
13
|
reference?: string;
|
|
14
|
-
onSuccess?: (payload: StablePaySuccessPayload) => void;
|
|
14
|
+
onSuccess?: (payload: StablePaySuccessPayload$1) => void;
|
|
15
15
|
onError?: (error: Error) => void;
|
|
16
16
|
};
|
|
17
17
|
type StablePayProviderProps = {
|
|
@@ -27,7 +27,7 @@ type StablePayProps = {
|
|
|
27
27
|
onClick?: (event: React.MouseEvent) => void;
|
|
28
28
|
disabled?: boolean;
|
|
29
29
|
}>;
|
|
30
|
-
onSuccess?: (payload: StablePaySuccessPayload) => void;
|
|
30
|
+
onSuccess?: (payload: StablePaySuccessPayload$1) => void;
|
|
31
31
|
onError?: (error: Error) => void;
|
|
32
32
|
};
|
|
33
33
|
type UseStablePayResult = {
|
|
@@ -36,6 +36,25 @@ type UseStablePayResult = {
|
|
|
36
36
|
error: Error | null;
|
|
37
37
|
signature: string | null;
|
|
38
38
|
};
|
|
39
|
+
type VerifyPaymentInput = {
|
|
40
|
+
to: string;
|
|
41
|
+
amount: string;
|
|
42
|
+
txHash: string;
|
|
43
|
+
reference?: string;
|
|
44
|
+
};
|
|
45
|
+
type VerifyPaymentResult = {
|
|
46
|
+
ok: true;
|
|
47
|
+
status: "confirmed" | "pending";
|
|
48
|
+
txHash: string;
|
|
49
|
+
to: string;
|
|
50
|
+
amount: string;
|
|
51
|
+
reference?: string;
|
|
52
|
+
confirmations: number;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
reason: "TX_FAILED" | "TO_MISMATCH" | "AMOUNT_TOO_LOW" | "REFERENCE_MISMATCH" | "INVALID_TRANSACTION";
|
|
56
|
+
txHash: string;
|
|
57
|
+
};
|
|
39
58
|
|
|
40
59
|
declare function StablePayProvider({ children, endpoint, to, }: StablePayProviderProps): react_jsx_runtime.JSX.Element;
|
|
41
60
|
|
|
@@ -51,4 +70,32 @@ declare function useStablePay(): {
|
|
|
51
70
|
signature: string | null;
|
|
52
71
|
};
|
|
53
72
|
|
|
54
|
-
|
|
73
|
+
type StablePaySuccessPayload = {
|
|
74
|
+
signature: string;
|
|
75
|
+
amount: number;
|
|
76
|
+
to: string;
|
|
77
|
+
reference?: string;
|
|
78
|
+
};
|
|
79
|
+
type PaymentVerificationStatus = "idle" | "verifying" | "pending" | "confirmed" | "failed";
|
|
80
|
+
type UsePaymentVerificationOptions = {
|
|
81
|
+
maxAttempts?: number;
|
|
82
|
+
intervalMs?: number;
|
|
83
|
+
};
|
|
84
|
+
type UsePaymentVerificationResult = {
|
|
85
|
+
status: PaymentVerificationStatus;
|
|
86
|
+
result: VerifyPaymentResult | null;
|
|
87
|
+
error: Error | null;
|
|
88
|
+
verify: (payload: StablePaySuccessPayload) => Promise<VerifyPaymentResult>;
|
|
89
|
+
reset: () => void;
|
|
90
|
+
};
|
|
91
|
+
declare function usePaymentVerification(options?: UsePaymentVerificationOptions): UsePaymentVerificationResult;
|
|
92
|
+
|
|
93
|
+
declare function verifyPayment(input: VerifyPaymentInput): Promise<VerifyPaymentResult>;
|
|
94
|
+
|
|
95
|
+
type WaitForPaymentConfirmationOptions = {
|
|
96
|
+
maxAttempts?: number;
|
|
97
|
+
intervalMs?: number;
|
|
98
|
+
};
|
|
99
|
+
declare function waitForPaymentConfirmation(input: VerifyPaymentInput, options?: WaitForPaymentConfirmationOptions): Promise<VerifyPaymentResult>;
|
|
100
|
+
|
|
101
|
+
export { StablePay, type StablePayPayArgs, type StablePayProps, StablePayProvider, type StablePayProviderProps, type StablePaySuccessPayload$1 as StablePaySuccessPayload, type UseStablePayResult, type VerifyPaymentInput, usePaymentVerification, useStablePay, verifyPayment, waitForPaymentConfirmation };
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,10 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
StablePay: () => StablePay,
|
|
34
34
|
StablePayProvider: () => StablePayProvider,
|
|
35
|
-
|
|
35
|
+
usePaymentVerification: () => usePaymentVerification,
|
|
36
|
+
useStablePay: () => useStablePay,
|
|
37
|
+
verifyPayment: () => verifyPayment,
|
|
38
|
+
waitForPaymentConfirmation: () => waitForPaymentConfirmation
|
|
36
39
|
});
|
|
37
40
|
module.exports = __toCommonJS(index_exports);
|
|
38
41
|
|
|
@@ -81,7 +84,7 @@ var import_web3 = require("@solana/web3.js");
|
|
|
81
84
|
var import_spl_token = require("@solana/spl-token");
|
|
82
85
|
|
|
83
86
|
// src/solana/constants.ts
|
|
84
|
-
var
|
|
87
|
+
var SOLANA_USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
85
88
|
var USDC_DECIMALS = 6;
|
|
86
89
|
|
|
87
90
|
// src/solana/amount.ts
|
|
@@ -104,7 +107,7 @@ async function buildUsdcTransfer({
|
|
|
104
107
|
amount,
|
|
105
108
|
reference
|
|
106
109
|
}) {
|
|
107
|
-
const mint = new import_web3.PublicKey(
|
|
110
|
+
const mint = new import_web3.PublicKey(SOLANA_USDC_MINT);
|
|
108
111
|
const fromAta = await (0, import_spl_token.getAssociatedTokenAddress)(mint, fromWallet);
|
|
109
112
|
const toAta = await (0, import_spl_token.getAssociatedTokenAddress)(mint, toWallet);
|
|
110
113
|
const tx = new import_web3.Transaction();
|
|
@@ -297,10 +300,237 @@ function StablePay({
|
|
|
297
300
|
disabled: Boolean(children.props.disabled) || loading
|
|
298
301
|
});
|
|
299
302
|
}
|
|
303
|
+
|
|
304
|
+
// src/hooks/usePaymentVerification.ts
|
|
305
|
+
var import_react5 = require("react");
|
|
306
|
+
|
|
307
|
+
// src/parseUsdcPaymentFromTransaction.ts
|
|
308
|
+
var import_web33 = require("@solana/web3.js");
|
|
309
|
+
function isParsedInstruction(ix) {
|
|
310
|
+
return "parsed" in ix;
|
|
311
|
+
}
|
|
312
|
+
async function parseUsdcPaymentFromTransaction(txHash) {
|
|
313
|
+
const connection = new import_web33.Connection(DEFAULT_RPC, "confirmed");
|
|
314
|
+
const tx = await connection.getParsedTransaction(txHash, {
|
|
315
|
+
maxSupportedTransactionVersion: 0,
|
|
316
|
+
commitment: "confirmed"
|
|
317
|
+
});
|
|
318
|
+
if (!tx || !tx.meta) return null;
|
|
319
|
+
if (tx.meta.err) {
|
|
320
|
+
return {
|
|
321
|
+
txHash,
|
|
322
|
+
status: "failed",
|
|
323
|
+
to: "",
|
|
324
|
+
amount: "0",
|
|
325
|
+
confirmations: 0
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
const allInstructions = [
|
|
329
|
+
...tx.transaction.message.instructions,
|
|
330
|
+
...tx.meta.innerInstructions?.flatMap((group) => group.instructions) ?? []
|
|
331
|
+
];
|
|
332
|
+
let amount = null;
|
|
333
|
+
let reference;
|
|
334
|
+
let destinationTokenAccount = null;
|
|
335
|
+
for (const ix of allInstructions) {
|
|
336
|
+
if (!isParsedInstruction(ix)) continue;
|
|
337
|
+
if (ix.program === "spl-token") {
|
|
338
|
+
const parsedType = ix.parsed?.type;
|
|
339
|
+
const info = ix.parsed?.info;
|
|
340
|
+
if ((parsedType === "transfer" || parsedType === "transferChecked") && info) {
|
|
341
|
+
const mint = info.mint;
|
|
342
|
+
const rawAmount = info.tokenAmount?.amount ?? info.amount;
|
|
343
|
+
if (mint === SOLANA_USDC_MINT && rawAmount) {
|
|
344
|
+
destinationTokenAccount = info.destination;
|
|
345
|
+
amount = (Number(rawAmount) / 1e6).toString();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (ix.program === "spl-memo") {
|
|
350
|
+
if (typeof ix.parsed === "string") {
|
|
351
|
+
reference = ix.parsed;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (!destinationTokenAccount || !amount) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
const currentSlot = await connection.getSlot("confirmed");
|
|
359
|
+
const confirmations = Math.max(0, currentSlot - tx.slot);
|
|
360
|
+
console.log("parsed tx", tx);
|
|
361
|
+
console.log("allInstructions", allInstructions);
|
|
362
|
+
console.log("destinationTokenAccount", destinationTokenAccount);
|
|
363
|
+
console.log("amount", amount);
|
|
364
|
+
console.log("reference", reference);
|
|
365
|
+
return {
|
|
366
|
+
txHash,
|
|
367
|
+
status: confirmations > 0 ? "confirmed" : "pending",
|
|
368
|
+
to: destinationTokenAccount,
|
|
369
|
+
amount,
|
|
370
|
+
reference,
|
|
371
|
+
confirmations
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/utils.ts
|
|
376
|
+
var import_web34 = require("@solana/web3.js");
|
|
377
|
+
var import_spl_token2 = require("@solana/spl-token");
|
|
378
|
+
function toAtomicUnits(amount) {
|
|
379
|
+
const [whole, fraction = ""] = amount.split(".");
|
|
380
|
+
const paddedFraction = (fraction + "000000").slice(0, 6);
|
|
381
|
+
return BigInt(whole) * 1000000n + BigInt(paddedFraction);
|
|
382
|
+
}
|
|
383
|
+
function amountGte(actual, expected) {
|
|
384
|
+
return toAtomicUnits(actual) >= toAtomicUnits(expected);
|
|
385
|
+
}
|
|
386
|
+
function sameAddress(a, b) {
|
|
387
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
388
|
+
}
|
|
389
|
+
function getUsdcTokenAccountForWallet(walletAddress) {
|
|
390
|
+
const wallet = new import_web34.PublicKey(walletAddress);
|
|
391
|
+
const mint = new import_web34.PublicKey(SOLANA_USDC_MINT);
|
|
392
|
+
return (0, import_spl_token2.getAssociatedTokenAddressSync)(mint, wallet, true).toBase58();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/verifyPayment.ts
|
|
396
|
+
async function verifyPayment(input) {
|
|
397
|
+
const parsed = await parseUsdcPaymentFromTransaction(input.txHash);
|
|
398
|
+
if (!parsed) {
|
|
399
|
+
return {
|
|
400
|
+
ok: false,
|
|
401
|
+
reason: "INVALID_TRANSACTION",
|
|
402
|
+
txHash: input.txHash
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (parsed.status === "failed") {
|
|
406
|
+
return {
|
|
407
|
+
ok: false,
|
|
408
|
+
reason: "TX_FAILED",
|
|
409
|
+
txHash: input.txHash
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
const expectedTokenAccount = getUsdcTokenAccountForWallet(input.to);
|
|
413
|
+
if (!sameAddress(parsed.to, expectedTokenAccount)) {
|
|
414
|
+
return {
|
|
415
|
+
ok: false,
|
|
416
|
+
reason: "TO_MISMATCH",
|
|
417
|
+
txHash: input.txHash
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (!amountGte(parsed.amount, input.amount)) {
|
|
421
|
+
return {
|
|
422
|
+
ok: false,
|
|
423
|
+
reason: "AMOUNT_TOO_LOW",
|
|
424
|
+
txHash: input.txHash
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (input.reference && parsed.reference !== input.reference) {
|
|
428
|
+
return {
|
|
429
|
+
ok: false,
|
|
430
|
+
reason: "REFERENCE_MISMATCH",
|
|
431
|
+
txHash: input.txHash
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
ok: true,
|
|
436
|
+
status: parsed.status === "pending" ? "pending" : "confirmed",
|
|
437
|
+
txHash: parsed.txHash,
|
|
438
|
+
to: input.to,
|
|
439
|
+
amount: parsed.amount,
|
|
440
|
+
reference: parsed.reference,
|
|
441
|
+
confirmations: parsed.confirmations
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// src/waitForPaymentConfirmation.ts
|
|
446
|
+
function sleep(ms) {
|
|
447
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
448
|
+
}
|
|
449
|
+
async function waitForPaymentConfirmation(input, options = {}) {
|
|
450
|
+
const maxAttempts = options.maxAttempts ?? 10;
|
|
451
|
+
const intervalMs = options.intervalMs ?? 1500;
|
|
452
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
453
|
+
const result = await verifyPayment(input);
|
|
454
|
+
if (result.ok && result.status === "confirmed") {
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
if (result.ok && result.status === "pending") {
|
|
458
|
+
await sleep(intervalMs);
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
if (!result.ok && result.reason === "INVALID_TRANSACTION") {
|
|
462
|
+
await sleep(intervalMs);
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
ok: false,
|
|
469
|
+
reason: "INVALID_TRANSACTION",
|
|
470
|
+
txHash: input.txHash
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/hooks/usePaymentVerification.ts
|
|
475
|
+
function usePaymentVerification(options = {}) {
|
|
476
|
+
const [status, setStatus] = (0, import_react5.useState)("idle");
|
|
477
|
+
const [result, setResult] = (0, import_react5.useState)(null);
|
|
478
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
479
|
+
const reset = (0, import_react5.useCallback)(() => {
|
|
480
|
+
setStatus("idle");
|
|
481
|
+
setResult(null);
|
|
482
|
+
setError(null);
|
|
483
|
+
}, []);
|
|
484
|
+
const verify = (0, import_react5.useCallback)(
|
|
485
|
+
async (payload) => {
|
|
486
|
+
setStatus("verifying");
|
|
487
|
+
setError(null);
|
|
488
|
+
try {
|
|
489
|
+
const verificationResult = await waitForPaymentConfirmation(
|
|
490
|
+
{
|
|
491
|
+
to: payload.to,
|
|
492
|
+
amount: String(payload.amount),
|
|
493
|
+
txHash: payload.signature,
|
|
494
|
+
reference: payload.reference
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
maxAttempts: options.maxAttempts,
|
|
498
|
+
intervalMs: options.intervalMs
|
|
499
|
+
}
|
|
500
|
+
);
|
|
501
|
+
setResult(verificationResult);
|
|
502
|
+
if (verificationResult.ok) {
|
|
503
|
+
setStatus(
|
|
504
|
+
verificationResult.status === "confirmed" ? "confirmed" : "pending"
|
|
505
|
+
);
|
|
506
|
+
} else {
|
|
507
|
+
setStatus("failed");
|
|
508
|
+
}
|
|
509
|
+
return verificationResult;
|
|
510
|
+
} catch (err) {
|
|
511
|
+
const nextError = err instanceof Error ? err : new Error("Payment verification failed");
|
|
512
|
+
setError(nextError);
|
|
513
|
+
setStatus("failed");
|
|
514
|
+
throw nextError;
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
[options.maxAttempts, options.intervalMs]
|
|
518
|
+
);
|
|
519
|
+
return {
|
|
520
|
+
status,
|
|
521
|
+
result,
|
|
522
|
+
error,
|
|
523
|
+
verify,
|
|
524
|
+
reset
|
|
525
|
+
};
|
|
526
|
+
}
|
|
300
527
|
// Annotate the CommonJS export names for ESM import in node:
|
|
301
528
|
0 && (module.exports = {
|
|
302
529
|
StablePay,
|
|
303
530
|
StablePayProvider,
|
|
304
|
-
|
|
531
|
+
usePaymentVerification,
|
|
532
|
+
useStablePay,
|
|
533
|
+
verifyPayment,
|
|
534
|
+
waitForPaymentConfirmation
|
|
305
535
|
});
|
|
306
536
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider/StablePayProvider.tsx","../src/context/StablePayContext.ts","../src/components/StablePay.tsx","../src/hooks/useStablePay.ts","../src/solana/buildUsdcTransfer.ts","../src/solana/constants.ts","../src/solana/amount.ts"],"sourcesContent":["export { StablePayProvider } from \"./provider/StablePayProvider\";\nexport { StablePay } from \"./components/StablePay\";\nexport { useStablePay } from \"./hooks/useStablePay\";\nexport type {\n StablePayProps,\n StablePayProviderProps,\n StablePaySuccessPayload,\n StablePayPayArgs,\n UseStablePayResult,\n} from \"./types\";\n","import React, { useMemo } from \"react\";\nimport {\n ConnectionProvider,\n WalletProvider,\n} from \"@solana/wallet-adapter-react\";\nimport { WalletModalProvider } from \"@solana/wallet-adapter-react-ui\";\nimport {\n PhantomWalletAdapter,\n SolflareWalletAdapter,\n} from \"@solana/wallet-adapter-wallets\";\nimport type { StablePayProviderProps } from \"../types\";\nimport StablePayContext from \"../context/StablePayContext\";\n\nimport \"@solana/wallet-adapter-react-ui/styles.css\";\n\nconst DEFAULT_RPC =\n \"https://mainnet.helius-rpc.com/?api-key=a90079ee-e2b5-438e-9b1a-2ae7ba8c1417\";\n\nexport function StablePayProvider({\n children,\n endpoint,\n to,\n}: StablePayProviderProps) {\n const resolvedEndpoint = endpoint ?? DEFAULT_RPC;\n\n const wallets = useMemo(\n () => [new PhantomWalletAdapter(), new SolflareWalletAdapter()],\n [],\n );\n\n return (\n <StablePayContext.Provider value={{ defaultTo: to }}>\n <ConnectionProvider endpoint={resolvedEndpoint}>\n <WalletProvider wallets={wallets} autoConnect>\n <WalletModalProvider>{children}</WalletModalProvider>\n </WalletProvider>\n </ConnectionProvider>\n </StablePayContext.Provider>\n );\n}\n","import { createContext, useContext } from \"react\";\n\ntype StablePayContextValue = {\n defaultTo?: string;\n};\n\nconst StablePayContext = createContext<StablePayContextValue>({});\n\nexport function useStablePayContext() {\n return useContext(StablePayContext);\n}\n\nexport default StablePayContext;\n","import React from \"react\";\nimport { useStablePay } from \"../hooks/useStablePay\";\nimport { useStablePayContext } from \"../context/StablePayContext\";\nimport type { StablePayProps } from \"../types\";\n\ntype ClickableChildProps = {\n onClick?: (event: React.MouseEvent) => void;\n disabled?: boolean;\n};\n\nfunction getResolvedTo(to?: string, defaultTo?: string): string {\n const resolved = to ?? defaultTo;\n\n if (!resolved) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n return resolved;\n}\n\nexport function StablePay({\n amount,\n to,\n reference,\n children,\n onSuccess,\n onError,\n}: StablePayProps) {\n const { pay, loading } = useStablePay();\n const { defaultTo } = useStablePayContext();\n\n const resolvedTo = getResolvedTo(to, defaultTo);\n\n if (!resolvedTo) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n if (!React.isValidElement<ClickableChildProps>(children)) {\n throw new Error(\"StablePay expects a single React element child.\");\n }\n\n async function handleClick(event: React.MouseEvent) {\n try {\n children.props.onClick?.(event);\n\n if (event.defaultPrevented) return;\n\n await pay({\n amount,\n to: resolvedTo,\n reference,\n onSuccess,\n onError,\n });\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Payment failed\"));\n }\n }\n\n return React.cloneElement(children, {\n onClick: handleClick,\n disabled: Boolean(children.props.disabled) || loading,\n });\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { useConnection, useWallet } from \"@solana/wallet-adapter-react\";\nimport { useWalletModal } from \"@solana/wallet-adapter-react-ui\";\nimport { buildUsdcTransfer } from \"../solana/buildUsdcTransfer\";\nimport { StablePayPayArgs } from \"../types\";\n\ntype PendingPayment = StablePayPayArgs;\n\nexport function useStablePay() {\n const { connection } = useConnection();\n const { connected, publicKey, sendTransaction } = useWallet();\n const { setVisible } = useWalletModal();\n\n const [loading, setLoading] = useState(false);\n const [signature, setSignature] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [pendingPayment, setPendingPayment] = useState<PendingPayment | null>(\n null,\n );\n\n const executePayment = useCallback(\n async ({ amount, to, reference }: StablePayPayArgs) => {\n if (!publicKey) {\n throw new Error(\"Wallet not connected\");\n }\n\n let recipient: PublicKey;\n\n try {\n recipient = new PublicKey(to);\n } catch {\n throw new Error(\"Invalid recipient wallet address\");\n }\n\n const transaction = await buildUsdcTransfer({\n connection,\n fromWallet: publicKey,\n toWallet: recipient,\n amount,\n reference,\n });\n\n const sig = await sendTransaction(transaction, connection);\n await connection.confirmTransaction(sig, \"confirmed\");\n\n setSignature(sig);\n return sig;\n },\n [publicKey, connection, sendTransaction],\n );\n\n const pay = useCallback(\n async ({ amount, to, reference, onSuccess, onError }: StablePayPayArgs) => {\n setLoading(true);\n setSignature(null);\n setError(null);\n\n // Not connected → store intent + callbacks\n if (!connected || !publicKey) {\n setPendingPayment({ amount, to, reference, onSuccess, onError });\n setVisible(true);\n return;\n }\n\n try {\n const sig = await executePayment({ amount, to, reference });\n onSuccess?.({\n signature: sig,\n amount,\n to,\n reference,\n });\n } catch (err) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n onError?.(normalized);\n } finally {\n setLoading(false);\n }\n },\n [connected, publicKey, executePayment, setVisible],\n );\n\n // Resume after wallet connects\n useEffect(() => {\n if (!connected || !publicKey || !pendingPayment) return;\n\n const payment = pendingPayment;\n\n let cancelled = false;\n\n async function resumePayment() {\n try {\n const sig = await executePayment(payment);\n\n if (!cancelled) {\n payment.onSuccess?.({\n signature: sig,\n amount: payment.amount,\n to: payment.to,\n reference: payment.reference,\n });\n setSignature(sig);\n setPendingPayment(null);\n }\n } catch (err) {\n if (!cancelled) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n payment.onError?.(normalized);\n setPendingPayment(null);\n }\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n resumePayment();\n\n return () => {\n cancelled = true;\n };\n }, [connected, publicKey, pendingPayment, executePayment]);\n\n return { pay, loading, error, signature };\n}\n","import {\n Connection,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_PROGRAM_ID,\n createAssociatedTokenAccountInstruction,\n createTransferCheckedInstruction,\n getAssociatedTokenAddress,\n} from \"@solana/spl-token\";\nimport { toTokenBaseUnits } from \"./amount\";\nimport { USDC_DECIMALS, USDC_MINT } from \"./constants\";\n\nconst MEMO_PROGRAM_ID = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\ntype BuildUsdcTransferParams = {\n connection: Connection;\n fromWallet: PublicKey;\n toWallet: PublicKey;\n amount: number;\n reference?: string;\n};\n\nexport async function buildUsdcTransfer({\n connection,\n fromWallet,\n toWallet,\n amount,\n reference,\n}: BuildUsdcTransferParams) {\n const mint = new PublicKey(USDC_MINT);\n const fromAta = await getAssociatedTokenAddress(mint, fromWallet);\n const toAta = await getAssociatedTokenAddress(mint, toWallet);\n\n const tx = new Transaction();\n\n console.log(\"REFERENCE IN BUILD:\", reference);\n\n if (reference) {\n const memoInstruction = new TransactionInstruction({\n keys: [],\n programId: MEMO_PROGRAM_ID,\n data: Buffer.from(reference),\n });\n\n tx.add(memoInstruction);\n }\n\n const toAtaInfo = await connection.getAccountInfo(toAta);\n\n if (!toAtaInfo) {\n tx.add(\n createAssociatedTokenAccountInstruction(\n fromWallet,\n toAta,\n toWallet,\n mint,\n ),\n );\n }\n\n tx.add(\n createTransferCheckedInstruction(\n fromAta,\n mint,\n toAta,\n fromWallet,\n Number(toTokenBaseUnits(amount)),\n USDC_DECIMALS,\n [],\n TOKEN_PROGRAM_ID,\n ),\n );\n\n const latestBlockhash = await connection.getLatestBlockhash();\n tx.feePayer = fromWallet;\n tx.recentBlockhash = latestBlockhash.blockhash;\n\n return tx;\n}\n","export const USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nexport const USDC_DECIMALS = 6;\n","import { USDC_DECIMALS } from \"./constants\";\n\nexport function toTokenBaseUnits(amount: number): bigint {\n if (!Number.isFinite(amount) || amount <= 0) {\n throw new Error(\"Amount must be a positive number\");\n }\n\n const multiplier = 10 ** USDC_DECIMALS;\n return BigInt(Math.round(amount * multiplier));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAA+B;AAC/B,kCAGO;AACP,qCAAoC;AACpC,oCAGO;;;ACTP,mBAA0C;AAM1C,IAAM,uBAAmB,4BAAqC,CAAC,CAAC;AAEzD,SAAS,sBAAsB;AACpC,aAAO,yBAAW,gBAAgB;AACpC;AAEA,IAAO,2BAAQ;;;ADCf,oBAAO;AAqBG;AAnBV,IAAM,cACJ;AAEK,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,mBAAmB,YAAY;AAErC,QAAM,cAAU;AAAA,IACd,MAAM,CAAC,IAAI,mDAAqB,GAAG,IAAI,oDAAsB,CAAC;AAAA,IAC9D,CAAC;AAAA,EACH;AAEA,SACE,4CAAC,yBAAiB,UAAjB,EAA0B,OAAO,EAAE,WAAW,GAAG,GAChD,sDAAC,kDAAmB,UAAU,kBAC5B,sDAAC,8CAAe,SAAkB,aAAW,MAC3C,sDAAC,sDAAqB,UAAS,GACjC,GACF,GACF;AAEJ;;;AEvCA,IAAAC,gBAAkB;;;ACAlB,IAAAC,gBAAiD;AACjD,IAAAC,eAA0B;AAC1B,IAAAC,+BAAyC;AACzC,IAAAC,kCAA+B;;;ACH/B,kBAKO;AACP,uBAKO;;;ACXA,IAAM,YAAY;AAClB,IAAM,gBAAgB;;;ACCtB,SAAS,iBAAiB,QAAwB;AACvD,MAAI,CAAC,OAAO,SAAS,MAAM,KAAK,UAAU,GAAG;AAC3C,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,QAAM,aAAa,MAAM;AACzB,SAAO,OAAO,KAAK,MAAM,SAAS,UAAU,CAAC;AAC/C;;;AFMA,IAAM,kBAAkB,IAAI;AAAA,EAC1B;AACF;AAUA,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,OAAO,IAAI,sBAAU,SAAS;AACpC,QAAM,UAAU,UAAM,4CAA0B,MAAM,UAAU;AAChE,QAAM,QAAQ,UAAM,4CAA0B,MAAM,QAAQ;AAE5D,QAAM,KAAK,IAAI,wBAAY;AAE3B,UAAQ,IAAI,uBAAuB,SAAS;AAE5C,MAAI,WAAW;AACb,UAAM,kBAAkB,IAAI,mCAAuB;AAAA,MACjD,MAAM,CAAC;AAAA,MACP,WAAW;AAAA,MACX,MAAM,OAAO,KAAK,SAAS;AAAA,IAC7B,CAAC;AAED,OAAG,IAAI,eAAe;AAAA,EACxB;AAEA,QAAM,YAAY,MAAM,WAAW,eAAe,KAAK;AAEvD,MAAI,CAAC,WAAW;AACd,OAAG;AAAA,UACD;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,KAAG;AAAA,QACD;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,iBAAiB,MAAM,CAAC;AAAA,MAC/B;AAAA,MACA,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,kBAAkB,MAAM,WAAW,mBAAmB;AAC5D,KAAG,WAAW;AACd,KAAG,kBAAkB,gBAAgB;AAErC,SAAO;AACT;;;AD1EO,SAAS,eAAe;AAC7B,QAAM,EAAE,WAAW,QAAI,4CAAc;AACrC,QAAM,EAAE,WAAW,WAAW,gBAAgB,QAAI,wCAAU;AAC5D,QAAM,EAAE,WAAW,QAAI,gDAAe;AAEtC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAwB,IAAI;AAC9D,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAuB,IAAI;AACrD,QAAM,CAAC,gBAAgB,iBAAiB,QAAI;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,qBAAiB;AAAA,IACrB,OAAO,EAAE,QAAQ,IAAI,UAAU,MAAwB;AACrD,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,sBAAsB;AAAA,MACxC;AAEA,UAAI;AAEJ,UAAI;AACF,oBAAY,IAAI,uBAAU,EAAE;AAAA,MAC9B,QAAQ;AACN,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,YAAM,cAAc,MAAM,kBAAkB;AAAA,QAC1C;AAAA,QACA,YAAY;AAAA,QACZ,UAAU;AAAA,QACV;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,MAAM,MAAM,gBAAgB,aAAa,UAAU;AACzD,YAAM,WAAW,mBAAmB,KAAK,WAAW;AAEpD,mBAAa,GAAG;AAChB,aAAO;AAAA,IACT;AAAA,IACA,CAAC,WAAW,YAAY,eAAe;AAAA,EACzC;AAEA,QAAM,UAAM;AAAA,IACV,OAAO,EAAE,QAAQ,IAAI,WAAW,WAAW,QAAQ,MAAwB;AACzE,iBAAW,IAAI;AACf,mBAAa,IAAI;AACjB,eAAS,IAAI;AAGb,UAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,0BAAkB,EAAE,QAAQ,IAAI,WAAW,WAAW,QAAQ,CAAC;AAC/D,mBAAW,IAAI;AACf;AAAA,MACF;AAEA,UAAI;AACF,cAAM,MAAM,MAAM,eAAe,EAAE,QAAQ,IAAI,UAAU,CAAC;AAC1D,oBAAY;AAAA,UACV,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,cAAM,aACJ,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB;AACzD,iBAAS,UAAU;AACnB,kBAAU,UAAU;AAAA,MACtB,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,WAAW,WAAW,gBAAgB,UAAU;AAAA,EACnD;AAGA,+BAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,aAAa,CAAC,eAAgB;AAEjD,UAAM,UAAU;AAEhB,QAAI,YAAY;AAEhB,mBAAe,gBAAgB;AAC7B,UAAI;AACF,cAAM,MAAM,MAAM,eAAe,OAAO;AAExC,YAAI,CAAC,WAAW;AACd,kBAAQ,YAAY;AAAA,YAClB,WAAW;AAAA,YACX,QAAQ,QAAQ;AAAA,YAChB,IAAI,QAAQ;AAAA,YACZ,WAAW,QAAQ;AAAA,UACrB,CAAC;AACD,uBAAa,GAAG;AAChB,4BAAkB,IAAI;AAAA,QACxB;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,CAAC,WAAW;AACd,gBAAM,aACJ,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB;AACzD,mBAAS,UAAU;AACnB,kBAAQ,UAAU,UAAU;AAC5B,4BAAkB,IAAI;AAAA,QACxB;AAAA,MACF,UAAE;AACA,YAAI,CAAC,WAAW;AACd,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAEA,kBAAc;AAEd,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,WAAW,WAAW,gBAAgB,cAAc,CAAC;AAEzD,SAAO,EAAE,KAAK,SAAS,OAAO,UAAU;AAC1C;;;ADxHA,SAAS,cAAc,IAAa,WAA4B;AAC9D,QAAM,WAAW,MAAM;AAEvB,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,EAAE,KAAK,QAAQ,IAAI,aAAa;AACtC,QAAM,EAAE,UAAU,IAAI,oBAAoB;AAE1C,QAAM,aAAa,cAAc,IAAI,SAAS;AAE9C,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,cAAAC,QAAM,eAAoC,QAAQ,GAAG;AACxD,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEA,iBAAe,YAAY,OAAyB;AAClD,QAAI;AACF,eAAS,MAAM,UAAU,KAAK;AAE9B,UAAI,MAAM,iBAAkB;AAE5B,YAAM,IAAI;AAAA,QACR;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,gBAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB,CAAC;AAAA,IACpE;AAAA,EACF;AAEA,SAAO,cAAAA,QAAM,aAAa,UAAU;AAAA,IAClC,SAAS;AAAA,IACT,UAAU,QAAQ,SAAS,MAAM,QAAQ,KAAK;AAAA,EAChD,CAAC;AACH;","names":["import_react","import_react","import_react","import_web3","import_wallet_adapter_react","import_wallet_adapter_react_ui","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider/StablePayProvider.tsx","../src/context/StablePayContext.ts","../src/components/StablePay.tsx","../src/hooks/useStablePay.ts","../src/solana/buildUsdcTransfer.ts","../src/solana/constants.ts","../src/solana/amount.ts","../src/hooks/usePaymentVerification.ts","../src/parseUsdcPaymentFromTransaction.ts","../src/utils.ts","../src/verifyPayment.ts","../src/waitForPaymentConfirmation.ts"],"sourcesContent":["export { StablePayProvider } from \"./provider/StablePayProvider\";\nexport { StablePay } from \"./components/StablePay\";\nexport { useStablePay } from \"./hooks/useStablePay\";\nexport { usePaymentVerification } from \"./hooks/usePaymentVerification\";\nexport { verifyPayment } from \"./verifyPayment\";\nexport { waitForPaymentConfirmation } from \"./waitForPaymentConfirmation\";\nexport type {\n StablePayProps,\n StablePayProviderProps,\n StablePaySuccessPayload,\n StablePayPayArgs,\n UseStablePayResult,\n VerifyPaymentInput,\n} from \"./types\";\n","import React, { useMemo } from \"react\";\nimport {\n ConnectionProvider,\n WalletProvider,\n} from \"@solana/wallet-adapter-react\";\nimport { WalletModalProvider } from \"@solana/wallet-adapter-react-ui\";\nimport {\n PhantomWalletAdapter,\n SolflareWalletAdapter,\n} from \"@solana/wallet-adapter-wallets\";\nimport type { StablePayProviderProps } from \"../types\";\nimport StablePayContext from \"../context/StablePayContext\";\n\nimport \"@solana/wallet-adapter-react-ui/styles.css\";\n\nexport const DEFAULT_RPC =\n \"https://mainnet.helius-rpc.com/?api-key=a90079ee-e2b5-438e-9b1a-2ae7ba8c1417\";\n\nexport function StablePayProvider({\n children,\n endpoint,\n to,\n}: StablePayProviderProps) {\n const resolvedEndpoint = endpoint ?? DEFAULT_RPC;\n\n const wallets = useMemo(\n () => [new PhantomWalletAdapter(), new SolflareWalletAdapter()],\n [],\n );\n\n return (\n <StablePayContext.Provider value={{ defaultTo: to }}>\n <ConnectionProvider endpoint={resolvedEndpoint}>\n <WalletProvider wallets={wallets} autoConnect>\n <WalletModalProvider>{children}</WalletModalProvider>\n </WalletProvider>\n </ConnectionProvider>\n </StablePayContext.Provider>\n );\n}\n","import { createContext, useContext } from \"react\";\n\ntype StablePayContextValue = {\n defaultTo?: string;\n};\n\nconst StablePayContext = createContext<StablePayContextValue>({});\n\nexport function useStablePayContext() {\n return useContext(StablePayContext);\n}\n\nexport default StablePayContext;\n","import React from \"react\";\nimport { useStablePay } from \"../hooks/useStablePay\";\nimport { useStablePayContext } from \"../context/StablePayContext\";\nimport type { StablePayProps } from \"../types\";\n\ntype ClickableChildProps = {\n onClick?: (event: React.MouseEvent) => void;\n disabled?: boolean;\n};\n\nfunction getResolvedTo(to?: string, defaultTo?: string): string {\n const resolved = to ?? defaultTo;\n\n if (!resolved) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n return resolved;\n}\n\nexport function StablePay({\n amount,\n to,\n reference,\n children,\n onSuccess,\n onError,\n}: StablePayProps) {\n const { pay, loading } = useStablePay();\n const { defaultTo } = useStablePayContext();\n\n const resolvedTo = getResolvedTo(to, defaultTo);\n\n if (!resolvedTo) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n if (!React.isValidElement<ClickableChildProps>(children)) {\n throw new Error(\"StablePay expects a single React element child.\");\n }\n\n async function handleClick(event: React.MouseEvent) {\n try {\n children.props.onClick?.(event);\n\n if (event.defaultPrevented) return;\n\n await pay({\n amount,\n to: resolvedTo,\n reference,\n onSuccess,\n onError,\n });\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Payment failed\"));\n }\n }\n\n return React.cloneElement(children, {\n onClick: handleClick,\n disabled: Boolean(children.props.disabled) || loading,\n });\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { useConnection, useWallet } from \"@solana/wallet-adapter-react\";\nimport { useWalletModal } from \"@solana/wallet-adapter-react-ui\";\nimport { buildUsdcTransfer } from \"../solana/buildUsdcTransfer\";\nimport { StablePayPayArgs } from \"../types\";\n\ntype PendingPayment = StablePayPayArgs;\n\nexport function useStablePay() {\n const { connection } = useConnection();\n const { connected, publicKey, sendTransaction } = useWallet();\n const { setVisible } = useWalletModal();\n\n const [loading, setLoading] = useState(false);\n const [signature, setSignature] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [pendingPayment, setPendingPayment] = useState<PendingPayment | null>(\n null,\n );\n\n const executePayment = useCallback(\n async ({ amount, to, reference }: StablePayPayArgs) => {\n if (!publicKey) {\n throw new Error(\"Wallet not connected\");\n }\n\n let recipient: PublicKey;\n\n try {\n recipient = new PublicKey(to);\n } catch {\n throw new Error(\"Invalid recipient wallet address\");\n }\n\n const transaction = await buildUsdcTransfer({\n connection,\n fromWallet: publicKey,\n toWallet: recipient,\n amount,\n reference,\n });\n\n const sig = await sendTransaction(transaction, connection);\n await connection.confirmTransaction(sig, \"confirmed\");\n\n setSignature(sig);\n return sig;\n },\n [publicKey, connection, sendTransaction],\n );\n\n const pay = useCallback(\n async ({ amount, to, reference, onSuccess, onError }: StablePayPayArgs) => {\n setLoading(true);\n setSignature(null);\n setError(null);\n\n // Not connected → store intent + callbacks\n if (!connected || !publicKey) {\n setPendingPayment({ amount, to, reference, onSuccess, onError });\n setVisible(true);\n return;\n }\n\n try {\n const sig = await executePayment({ amount, to, reference });\n onSuccess?.({\n signature: sig,\n amount,\n to,\n reference,\n });\n } catch (err) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n onError?.(normalized);\n } finally {\n setLoading(false);\n }\n },\n [connected, publicKey, executePayment, setVisible],\n );\n\n // Resume after wallet connects\n useEffect(() => {\n if (!connected || !publicKey || !pendingPayment) return;\n\n const payment = pendingPayment;\n\n let cancelled = false;\n\n async function resumePayment() {\n try {\n const sig = await executePayment(payment);\n\n if (!cancelled) {\n payment.onSuccess?.({\n signature: sig,\n amount: payment.amount,\n to: payment.to,\n reference: payment.reference,\n });\n setSignature(sig);\n setPendingPayment(null);\n }\n } catch (err) {\n if (!cancelled) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n payment.onError?.(normalized);\n setPendingPayment(null);\n }\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n resumePayment();\n\n return () => {\n cancelled = true;\n };\n }, [connected, publicKey, pendingPayment, executePayment]);\n\n return { pay, loading, error, signature };\n}\n","import {\n Connection,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_PROGRAM_ID,\n createAssociatedTokenAccountInstruction,\n createTransferCheckedInstruction,\n getAssociatedTokenAddress,\n} from \"@solana/spl-token\";\nimport { toTokenBaseUnits } from \"./amount\";\nimport { USDC_DECIMALS, SOLANA_USDC_MINT } from \"./constants\";\n\nconst MEMO_PROGRAM_ID = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\ntype BuildUsdcTransferParams = {\n connection: Connection;\n fromWallet: PublicKey;\n toWallet: PublicKey;\n amount: number;\n reference?: string;\n};\n\nexport async function buildUsdcTransfer({\n connection,\n fromWallet,\n toWallet,\n amount,\n reference,\n}: BuildUsdcTransferParams) {\n const mint = new PublicKey(SOLANA_USDC_MINT);\n const fromAta = await getAssociatedTokenAddress(mint, fromWallet);\n const toAta = await getAssociatedTokenAddress(mint, toWallet);\n\n const tx = new Transaction();\n\n console.log(\"REFERENCE IN BUILD:\", reference);\n\n if (reference) {\n const memoInstruction = new TransactionInstruction({\n keys: [],\n programId: MEMO_PROGRAM_ID,\n data: Buffer.from(reference),\n });\n\n tx.add(memoInstruction);\n }\n\n const toAtaInfo = await connection.getAccountInfo(toAta);\n\n if (!toAtaInfo) {\n tx.add(\n createAssociatedTokenAccountInstruction(\n fromWallet,\n toAta,\n toWallet,\n mint,\n ),\n );\n }\n\n tx.add(\n createTransferCheckedInstruction(\n fromAta,\n mint,\n toAta,\n fromWallet,\n Number(toTokenBaseUnits(amount)),\n USDC_DECIMALS,\n [],\n TOKEN_PROGRAM_ID,\n ),\n );\n\n const latestBlockhash = await connection.getLatestBlockhash();\n tx.feePayer = fromWallet;\n tx.recentBlockhash = latestBlockhash.blockhash;\n\n return tx;\n}\n","export const SOLANA_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nexport const USDC_DECIMALS = 6;\n","import { USDC_DECIMALS } from \"./constants\";\n\nexport function toTokenBaseUnits(amount: number): bigint {\n if (!Number.isFinite(amount) || amount <= 0) {\n throw new Error(\"Amount must be a positive number\");\n }\n\n const multiplier = 10 ** USDC_DECIMALS;\n return BigInt(Math.round(amount * multiplier));\n}\n","import { useCallback, useState } from \"react\";\nimport { VerifyPaymentResult } from \"../types\";\nimport { waitForPaymentConfirmation } from \"../waitForPaymentConfirmation\";\n\nexport type StablePaySuccessPayload = {\n signature: string;\n amount: number;\n to: string;\n reference?: string;\n};\n\nexport type PaymentVerificationStatus =\n | \"idle\"\n | \"verifying\"\n | \"pending\"\n | \"confirmed\"\n | \"failed\";\n\nexport type UsePaymentVerificationOptions = {\n maxAttempts?: number;\n intervalMs?: number;\n};\n\nexport type UsePaymentVerificationResult = {\n status: PaymentVerificationStatus;\n result: VerifyPaymentResult | null;\n error: Error | null;\n verify: (payload: StablePaySuccessPayload) => Promise<VerifyPaymentResult>;\n reset: () => void;\n};\n\nexport function usePaymentVerification(\n options: UsePaymentVerificationOptions = {},\n): UsePaymentVerificationResult {\n const [status, setStatus] = useState<PaymentVerificationStatus>(\"idle\");\n const [result, setResult] = useState<VerifyPaymentResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n const reset = useCallback(() => {\n setStatus(\"idle\");\n setResult(null);\n setError(null);\n }, []);\n\n const verify = useCallback(\n async (payload: StablePaySuccessPayload) => {\n setStatus(\"verifying\");\n setError(null);\n\n try {\n const verificationResult = await waitForPaymentConfirmation(\n {\n to: payload.to,\n amount: String(payload.amount),\n txHash: payload.signature,\n reference: payload.reference,\n },\n {\n maxAttempts: options.maxAttempts,\n intervalMs: options.intervalMs,\n },\n );\n\n setResult(verificationResult);\n\n if (verificationResult.ok) {\n setStatus(\n verificationResult.status === \"confirmed\" ? \"confirmed\" : \"pending\",\n );\n } else {\n setStatus(\"failed\");\n }\n\n return verificationResult;\n } catch (err) {\n const nextError =\n err instanceof Error ? err : new Error(\"Payment verification failed\");\n\n setError(nextError);\n setStatus(\"failed\");\n throw nextError;\n }\n },\n [options.maxAttempts, options.intervalMs],\n );\n\n return {\n status,\n result,\n error,\n verify,\n reset,\n };\n}\n","import {\n Connection,\n ParsedInstruction,\n PartiallyDecodedInstruction,\n PublicKey,\n} from \"@solana/web3.js\";\nimport { ParsedPayment } from \"./types\";\nimport { DEFAULT_RPC } from \"./provider/StablePayProvider\";\nimport { SOLANA_USDC_MINT } from \"./solana/constants\";\n\nfunction isParsedInstruction(\n ix: ParsedInstruction | PartiallyDecodedInstruction,\n): ix is ParsedInstruction {\n return \"parsed\" in ix;\n}\n\nexport async function parseUsdcPaymentFromTransaction(\n txHash: string,\n): Promise<ParsedPayment | null> {\n const connection = new Connection(DEFAULT_RPC, \"confirmed\");\n\n const tx = await connection.getParsedTransaction(txHash, {\n maxSupportedTransactionVersion: 0,\n commitment: \"confirmed\",\n });\n\n if (!tx || !tx.meta) return null;\n\n if (tx.meta.err) {\n return {\n txHash,\n status: \"failed\",\n to: \"\",\n amount: \"0\",\n confirmations: 0,\n };\n }\n\n const allInstructions = [\n ...tx.transaction.message.instructions,\n ...(tx.meta.innerInstructions?.flatMap((group) => group.instructions) ??\n []),\n ];\n\n let amount: string | null = null;\n let reference: string | undefined;\n let destinationTokenAccount: string | null = null;\n\n for (const ix of allInstructions) {\n if (!isParsedInstruction(ix)) continue;\n\n if (ix.program === \"spl-token\") {\n const parsedType = ix.parsed?.type;\n const info = ix.parsed?.info;\n\n if (\n (parsedType === \"transfer\" || parsedType === \"transferChecked\") &&\n info\n ) {\n const mint = info.mint;\n const rawAmount = info.tokenAmount?.amount ?? info.amount;\n\n if (mint === SOLANA_USDC_MINT && rawAmount) {\n destinationTokenAccount = info.destination;\n amount = (Number(rawAmount) / 1_000_000).toString();\n }\n }\n }\n\n if (ix.program === \"spl-memo\") {\n if (typeof ix.parsed === \"string\") {\n reference = ix.parsed;\n }\n }\n }\n\n if (!destinationTokenAccount || !amount) {\n return null;\n }\n\n const currentSlot = await connection.getSlot(\"confirmed\");\n const confirmations = Math.max(0, currentSlot - tx.slot);\n\n console.log(\"parsed tx\", tx);\n console.log(\"allInstructions\", allInstructions);\n console.log(\"destinationTokenAccount\", destinationTokenAccount);\n console.log(\"amount\", amount);\n console.log(\"reference\", reference);\n\n return {\n txHash,\n status: confirmations > 0 ? \"confirmed\" : \"pending\",\n to: destinationTokenAccount,\n amount,\n reference,\n confirmations,\n };\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport { SOLANA_USDC_MINT } from \"./solana/constants\";\nimport { getAssociatedTokenAddressSync } from \"@solana/spl-token\";\n\n/**\n * Convert human-readable USDC to atomic units (6 decimals)\n */\nexport function toAtomicUnits(amount: string): bigint {\n const [whole, fraction = \"\"] = amount.split(\".\");\n\n const paddedFraction = (fraction + \"000000\").slice(0, 6);\n\n return BigInt(whole) * 1_000_000n + BigInt(paddedFraction);\n}\n\nexport function amountGte(actual: string, expected: string): boolean {\n return toAtomicUnits(actual) >= toAtomicUnits(expected);\n}\n\nexport function sameAddress(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\nexport function getUsdcTokenAccountForWallet(walletAddress: string): string {\n const wallet = new PublicKey(walletAddress);\n const mint = new PublicKey(SOLANA_USDC_MINT);\n\n return getAssociatedTokenAddressSync(mint, wallet, true).toBase58();\n}\n","import { VerifyPaymentInput, VerifyPaymentResult } from \"./types\";\nimport { parseUsdcPaymentFromTransaction } from \"./parseUsdcPaymentFromTransaction\";\nimport { amountGte, getUsdcTokenAccountForWallet, sameAddress } from \"./utils\";\n\nexport async function verifyPayment(\n input: VerifyPaymentInput,\n): Promise<VerifyPaymentResult> {\n const parsed = await parseUsdcPaymentFromTransaction(input.txHash);\n\n if (!parsed) {\n return {\n ok: false,\n reason: \"INVALID_TRANSACTION\",\n txHash: input.txHash,\n };\n }\n\n if (parsed.status === \"failed\") {\n return {\n ok: false,\n reason: \"TX_FAILED\",\n txHash: input.txHash,\n };\n }\n\n const expectedTokenAccount = getUsdcTokenAccountForWallet(input.to);\n\n if (!sameAddress(parsed.to, expectedTokenAccount)) {\n return {\n ok: false,\n reason: \"TO_MISMATCH\",\n txHash: input.txHash,\n };\n }\n\n if (!amountGte(parsed.amount, input.amount)) {\n return {\n ok: false,\n reason: \"AMOUNT_TOO_LOW\",\n txHash: input.txHash,\n };\n }\n\n if (input.reference && parsed.reference !== input.reference) {\n return {\n ok: false,\n reason: \"REFERENCE_MISMATCH\",\n txHash: input.txHash,\n };\n }\n\n return {\n ok: true,\n status: parsed.status === \"pending\" ? \"pending\" : \"confirmed\",\n txHash: parsed.txHash,\n to: input.to,\n amount: parsed.amount,\n reference: parsed.reference,\n confirmations: parsed.confirmations,\n };\n}\n","import { verifyPayment } from \"./verifyPayment\";\nimport { VerifyPaymentInput, VerifyPaymentResult } from \"./types\";\n\ntype WaitForPaymentConfirmationOptions = {\n maxAttempts?: number;\n intervalMs?: number;\n};\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function waitForPaymentConfirmation(\n input: VerifyPaymentInput,\n options: WaitForPaymentConfirmationOptions = {},\n): Promise<VerifyPaymentResult> {\n const maxAttempts = options.maxAttempts ?? 10;\n const intervalMs = options.intervalMs ?? 1500;\n\n for (let i = 0; i < maxAttempts; i++) {\n const result = await verifyPayment(input);\n\n if (result.ok && result.status === \"confirmed\") {\n return result;\n }\n\n if (result.ok && result.status === \"pending\") {\n await sleep(intervalMs);\n continue;\n }\n\n if (!result.ok && result.reason === \"INVALID_TRANSACTION\") {\n await sleep(intervalMs);\n continue;\n }\n\n return result;\n }\n\n return {\n ok: false,\n reason: \"INVALID_TRANSACTION\",\n txHash: input.txHash,\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_web3","import_wallet_adapter_react","import_wallet_adapter_react_ui","React","import_react","import_web3","import_web3","import_spl_token"]}
|
package/dist/index.mjs
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
} from "@solana/spl-token";
|
|
59
59
|
|
|
60
60
|
// src/solana/constants.ts
|
|
61
|
-
var
|
|
61
|
+
var SOLANA_USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
62
62
|
var USDC_DECIMALS = 6;
|
|
63
63
|
|
|
64
64
|
// src/solana/amount.ts
|
|
@@ -81,7 +81,7 @@ async function buildUsdcTransfer({
|
|
|
81
81
|
amount,
|
|
82
82
|
reference
|
|
83
83
|
}) {
|
|
84
|
-
const mint = new PublicKey(
|
|
84
|
+
const mint = new PublicKey(SOLANA_USDC_MINT);
|
|
85
85
|
const fromAta = await getAssociatedTokenAddress(mint, fromWallet);
|
|
86
86
|
const toAta = await getAssociatedTokenAddress(mint, toWallet);
|
|
87
87
|
const tx = new Transaction();
|
|
@@ -274,9 +274,238 @@ function StablePay({
|
|
|
274
274
|
disabled: Boolean(children.props.disabled) || loading
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
|
+
|
|
278
|
+
// src/hooks/usePaymentVerification.ts
|
|
279
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
280
|
+
|
|
281
|
+
// src/parseUsdcPaymentFromTransaction.ts
|
|
282
|
+
import {
|
|
283
|
+
Connection as Connection2
|
|
284
|
+
} from "@solana/web3.js";
|
|
285
|
+
function isParsedInstruction(ix) {
|
|
286
|
+
return "parsed" in ix;
|
|
287
|
+
}
|
|
288
|
+
async function parseUsdcPaymentFromTransaction(txHash) {
|
|
289
|
+
const connection = new Connection2(DEFAULT_RPC, "confirmed");
|
|
290
|
+
const tx = await connection.getParsedTransaction(txHash, {
|
|
291
|
+
maxSupportedTransactionVersion: 0,
|
|
292
|
+
commitment: "confirmed"
|
|
293
|
+
});
|
|
294
|
+
if (!tx || !tx.meta) return null;
|
|
295
|
+
if (tx.meta.err) {
|
|
296
|
+
return {
|
|
297
|
+
txHash,
|
|
298
|
+
status: "failed",
|
|
299
|
+
to: "",
|
|
300
|
+
amount: "0",
|
|
301
|
+
confirmations: 0
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
const allInstructions = [
|
|
305
|
+
...tx.transaction.message.instructions,
|
|
306
|
+
...tx.meta.innerInstructions?.flatMap((group) => group.instructions) ?? []
|
|
307
|
+
];
|
|
308
|
+
let amount = null;
|
|
309
|
+
let reference;
|
|
310
|
+
let destinationTokenAccount = null;
|
|
311
|
+
for (const ix of allInstructions) {
|
|
312
|
+
if (!isParsedInstruction(ix)) continue;
|
|
313
|
+
if (ix.program === "spl-token") {
|
|
314
|
+
const parsedType = ix.parsed?.type;
|
|
315
|
+
const info = ix.parsed?.info;
|
|
316
|
+
if ((parsedType === "transfer" || parsedType === "transferChecked") && info) {
|
|
317
|
+
const mint = info.mint;
|
|
318
|
+
const rawAmount = info.tokenAmount?.amount ?? info.amount;
|
|
319
|
+
if (mint === SOLANA_USDC_MINT && rawAmount) {
|
|
320
|
+
destinationTokenAccount = info.destination;
|
|
321
|
+
amount = (Number(rawAmount) / 1e6).toString();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (ix.program === "spl-memo") {
|
|
326
|
+
if (typeof ix.parsed === "string") {
|
|
327
|
+
reference = ix.parsed;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (!destinationTokenAccount || !amount) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
const currentSlot = await connection.getSlot("confirmed");
|
|
335
|
+
const confirmations = Math.max(0, currentSlot - tx.slot);
|
|
336
|
+
console.log("parsed tx", tx);
|
|
337
|
+
console.log("allInstructions", allInstructions);
|
|
338
|
+
console.log("destinationTokenAccount", destinationTokenAccount);
|
|
339
|
+
console.log("amount", amount);
|
|
340
|
+
console.log("reference", reference);
|
|
341
|
+
return {
|
|
342
|
+
txHash,
|
|
343
|
+
status: confirmations > 0 ? "confirmed" : "pending",
|
|
344
|
+
to: destinationTokenAccount,
|
|
345
|
+
amount,
|
|
346
|
+
reference,
|
|
347
|
+
confirmations
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/utils.ts
|
|
352
|
+
import { PublicKey as PublicKey4 } from "@solana/web3.js";
|
|
353
|
+
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
|
|
354
|
+
function toAtomicUnits(amount) {
|
|
355
|
+
const [whole, fraction = ""] = amount.split(".");
|
|
356
|
+
const paddedFraction = (fraction + "000000").slice(0, 6);
|
|
357
|
+
return BigInt(whole) * 1000000n + BigInt(paddedFraction);
|
|
358
|
+
}
|
|
359
|
+
function amountGte(actual, expected) {
|
|
360
|
+
return toAtomicUnits(actual) >= toAtomicUnits(expected);
|
|
361
|
+
}
|
|
362
|
+
function sameAddress(a, b) {
|
|
363
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
364
|
+
}
|
|
365
|
+
function getUsdcTokenAccountForWallet(walletAddress) {
|
|
366
|
+
const wallet = new PublicKey4(walletAddress);
|
|
367
|
+
const mint = new PublicKey4(SOLANA_USDC_MINT);
|
|
368
|
+
return getAssociatedTokenAddressSync(mint, wallet, true).toBase58();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/verifyPayment.ts
|
|
372
|
+
async function verifyPayment(input) {
|
|
373
|
+
const parsed = await parseUsdcPaymentFromTransaction(input.txHash);
|
|
374
|
+
if (!parsed) {
|
|
375
|
+
return {
|
|
376
|
+
ok: false,
|
|
377
|
+
reason: "INVALID_TRANSACTION",
|
|
378
|
+
txHash: input.txHash
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (parsed.status === "failed") {
|
|
382
|
+
return {
|
|
383
|
+
ok: false,
|
|
384
|
+
reason: "TX_FAILED",
|
|
385
|
+
txHash: input.txHash
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const expectedTokenAccount = getUsdcTokenAccountForWallet(input.to);
|
|
389
|
+
if (!sameAddress(parsed.to, expectedTokenAccount)) {
|
|
390
|
+
return {
|
|
391
|
+
ok: false,
|
|
392
|
+
reason: "TO_MISMATCH",
|
|
393
|
+
txHash: input.txHash
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
if (!amountGte(parsed.amount, input.amount)) {
|
|
397
|
+
return {
|
|
398
|
+
ok: false,
|
|
399
|
+
reason: "AMOUNT_TOO_LOW",
|
|
400
|
+
txHash: input.txHash
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
if (input.reference && parsed.reference !== input.reference) {
|
|
404
|
+
return {
|
|
405
|
+
ok: false,
|
|
406
|
+
reason: "REFERENCE_MISMATCH",
|
|
407
|
+
txHash: input.txHash
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
ok: true,
|
|
412
|
+
status: parsed.status === "pending" ? "pending" : "confirmed",
|
|
413
|
+
txHash: parsed.txHash,
|
|
414
|
+
to: input.to,
|
|
415
|
+
amount: parsed.amount,
|
|
416
|
+
reference: parsed.reference,
|
|
417
|
+
confirmations: parsed.confirmations
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// src/waitForPaymentConfirmation.ts
|
|
422
|
+
function sleep(ms) {
|
|
423
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
424
|
+
}
|
|
425
|
+
async function waitForPaymentConfirmation(input, options = {}) {
|
|
426
|
+
const maxAttempts = options.maxAttempts ?? 10;
|
|
427
|
+
const intervalMs = options.intervalMs ?? 1500;
|
|
428
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
429
|
+
const result = await verifyPayment(input);
|
|
430
|
+
if (result.ok && result.status === "confirmed") {
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
if (result.ok && result.status === "pending") {
|
|
434
|
+
await sleep(intervalMs);
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (!result.ok && result.reason === "INVALID_TRANSACTION") {
|
|
438
|
+
await sleep(intervalMs);
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
return result;
|
|
442
|
+
}
|
|
443
|
+
return {
|
|
444
|
+
ok: false,
|
|
445
|
+
reason: "INVALID_TRANSACTION",
|
|
446
|
+
txHash: input.txHash
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/hooks/usePaymentVerification.ts
|
|
451
|
+
function usePaymentVerification(options = {}) {
|
|
452
|
+
const [status, setStatus] = useState2("idle");
|
|
453
|
+
const [result, setResult] = useState2(null);
|
|
454
|
+
const [error, setError] = useState2(null);
|
|
455
|
+
const reset = useCallback2(() => {
|
|
456
|
+
setStatus("idle");
|
|
457
|
+
setResult(null);
|
|
458
|
+
setError(null);
|
|
459
|
+
}, []);
|
|
460
|
+
const verify = useCallback2(
|
|
461
|
+
async (payload) => {
|
|
462
|
+
setStatus("verifying");
|
|
463
|
+
setError(null);
|
|
464
|
+
try {
|
|
465
|
+
const verificationResult = await waitForPaymentConfirmation(
|
|
466
|
+
{
|
|
467
|
+
to: payload.to,
|
|
468
|
+
amount: String(payload.amount),
|
|
469
|
+
txHash: payload.signature,
|
|
470
|
+
reference: payload.reference
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
maxAttempts: options.maxAttempts,
|
|
474
|
+
intervalMs: options.intervalMs
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
setResult(verificationResult);
|
|
478
|
+
if (verificationResult.ok) {
|
|
479
|
+
setStatus(
|
|
480
|
+
verificationResult.status === "confirmed" ? "confirmed" : "pending"
|
|
481
|
+
);
|
|
482
|
+
} else {
|
|
483
|
+
setStatus("failed");
|
|
484
|
+
}
|
|
485
|
+
return verificationResult;
|
|
486
|
+
} catch (err) {
|
|
487
|
+
const nextError = err instanceof Error ? err : new Error("Payment verification failed");
|
|
488
|
+
setError(nextError);
|
|
489
|
+
setStatus("failed");
|
|
490
|
+
throw nextError;
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
[options.maxAttempts, options.intervalMs]
|
|
494
|
+
);
|
|
495
|
+
return {
|
|
496
|
+
status,
|
|
497
|
+
result,
|
|
498
|
+
error,
|
|
499
|
+
verify,
|
|
500
|
+
reset
|
|
501
|
+
};
|
|
502
|
+
}
|
|
277
503
|
export {
|
|
278
504
|
StablePay,
|
|
279
505
|
StablePayProvider,
|
|
280
|
-
|
|
506
|
+
usePaymentVerification,
|
|
507
|
+
useStablePay,
|
|
508
|
+
verifyPayment,
|
|
509
|
+
waitForPaymentConfirmation
|
|
281
510
|
};
|
|
282
511
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider/StablePayProvider.tsx","../src/context/StablePayContext.ts","../src/components/StablePay.tsx","../src/hooks/useStablePay.ts","../src/solana/buildUsdcTransfer.ts","../src/solana/constants.ts","../src/solana/amount.ts"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport {\n ConnectionProvider,\n WalletProvider,\n} from \"@solana/wallet-adapter-react\";\nimport { WalletModalProvider } from \"@solana/wallet-adapter-react-ui\";\nimport {\n PhantomWalletAdapter,\n SolflareWalletAdapter,\n} from \"@solana/wallet-adapter-wallets\";\nimport type { StablePayProviderProps } from \"../types\";\nimport StablePayContext from \"../context/StablePayContext\";\n\nimport \"@solana/wallet-adapter-react-ui/styles.css\";\n\nconst DEFAULT_RPC =\n \"https://mainnet.helius-rpc.com/?api-key=a90079ee-e2b5-438e-9b1a-2ae7ba8c1417\";\n\nexport function StablePayProvider({\n children,\n endpoint,\n to,\n}: StablePayProviderProps) {\n const resolvedEndpoint = endpoint ?? DEFAULT_RPC;\n\n const wallets = useMemo(\n () => [new PhantomWalletAdapter(), new SolflareWalletAdapter()],\n [],\n );\n\n return (\n <StablePayContext.Provider value={{ defaultTo: to }}>\n <ConnectionProvider endpoint={resolvedEndpoint}>\n <WalletProvider wallets={wallets} autoConnect>\n <WalletModalProvider>{children}</WalletModalProvider>\n </WalletProvider>\n </ConnectionProvider>\n </StablePayContext.Provider>\n );\n}\n","import { createContext, useContext } from \"react\";\n\ntype StablePayContextValue = {\n defaultTo?: string;\n};\n\nconst StablePayContext = createContext<StablePayContextValue>({});\n\nexport function useStablePayContext() {\n return useContext(StablePayContext);\n}\n\nexport default StablePayContext;\n","import React from \"react\";\nimport { useStablePay } from \"../hooks/useStablePay\";\nimport { useStablePayContext } from \"../context/StablePayContext\";\nimport type { StablePayProps } from \"../types\";\n\ntype ClickableChildProps = {\n onClick?: (event: React.MouseEvent) => void;\n disabled?: boolean;\n};\n\nfunction getResolvedTo(to?: string, defaultTo?: string): string {\n const resolved = to ?? defaultTo;\n\n if (!resolved) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n return resolved;\n}\n\nexport function StablePay({\n amount,\n to,\n reference,\n children,\n onSuccess,\n onError,\n}: StablePayProps) {\n const { pay, loading } = useStablePay();\n const { defaultTo } = useStablePayContext();\n\n const resolvedTo = getResolvedTo(to, defaultTo);\n\n if (!resolvedTo) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n if (!React.isValidElement<ClickableChildProps>(children)) {\n throw new Error(\"StablePay expects a single React element child.\");\n }\n\n async function handleClick(event: React.MouseEvent) {\n try {\n children.props.onClick?.(event);\n\n if (event.defaultPrevented) return;\n\n await pay({\n amount,\n to: resolvedTo,\n reference,\n onSuccess,\n onError,\n });\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Payment failed\"));\n }\n }\n\n return React.cloneElement(children, {\n onClick: handleClick,\n disabled: Boolean(children.props.disabled) || loading,\n });\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { useConnection, useWallet } from \"@solana/wallet-adapter-react\";\nimport { useWalletModal } from \"@solana/wallet-adapter-react-ui\";\nimport { buildUsdcTransfer } from \"../solana/buildUsdcTransfer\";\nimport { StablePayPayArgs } from \"../types\";\n\ntype PendingPayment = StablePayPayArgs;\n\nexport function useStablePay() {\n const { connection } = useConnection();\n const { connected, publicKey, sendTransaction } = useWallet();\n const { setVisible } = useWalletModal();\n\n const [loading, setLoading] = useState(false);\n const [signature, setSignature] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [pendingPayment, setPendingPayment] = useState<PendingPayment | null>(\n null,\n );\n\n const executePayment = useCallback(\n async ({ amount, to, reference }: StablePayPayArgs) => {\n if (!publicKey) {\n throw new Error(\"Wallet not connected\");\n }\n\n let recipient: PublicKey;\n\n try {\n recipient = new PublicKey(to);\n } catch {\n throw new Error(\"Invalid recipient wallet address\");\n }\n\n const transaction = await buildUsdcTransfer({\n connection,\n fromWallet: publicKey,\n toWallet: recipient,\n amount,\n reference,\n });\n\n const sig = await sendTransaction(transaction, connection);\n await connection.confirmTransaction(sig, \"confirmed\");\n\n setSignature(sig);\n return sig;\n },\n [publicKey, connection, sendTransaction],\n );\n\n const pay = useCallback(\n async ({ amount, to, reference, onSuccess, onError }: StablePayPayArgs) => {\n setLoading(true);\n setSignature(null);\n setError(null);\n\n // Not connected → store intent + callbacks\n if (!connected || !publicKey) {\n setPendingPayment({ amount, to, reference, onSuccess, onError });\n setVisible(true);\n return;\n }\n\n try {\n const sig = await executePayment({ amount, to, reference });\n onSuccess?.({\n signature: sig,\n amount,\n to,\n reference,\n });\n } catch (err) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n onError?.(normalized);\n } finally {\n setLoading(false);\n }\n },\n [connected, publicKey, executePayment, setVisible],\n );\n\n // Resume after wallet connects\n useEffect(() => {\n if (!connected || !publicKey || !pendingPayment) return;\n\n const payment = pendingPayment;\n\n let cancelled = false;\n\n async function resumePayment() {\n try {\n const sig = await executePayment(payment);\n\n if (!cancelled) {\n payment.onSuccess?.({\n signature: sig,\n amount: payment.amount,\n to: payment.to,\n reference: payment.reference,\n });\n setSignature(sig);\n setPendingPayment(null);\n }\n } catch (err) {\n if (!cancelled) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n payment.onError?.(normalized);\n setPendingPayment(null);\n }\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n resumePayment();\n\n return () => {\n cancelled = true;\n };\n }, [connected, publicKey, pendingPayment, executePayment]);\n\n return { pay, loading, error, signature };\n}\n","import {\n Connection,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_PROGRAM_ID,\n createAssociatedTokenAccountInstruction,\n createTransferCheckedInstruction,\n getAssociatedTokenAddress,\n} from \"@solana/spl-token\";\nimport { toTokenBaseUnits } from \"./amount\";\nimport { USDC_DECIMALS, USDC_MINT } from \"./constants\";\n\nconst MEMO_PROGRAM_ID = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\ntype BuildUsdcTransferParams = {\n connection: Connection;\n fromWallet: PublicKey;\n toWallet: PublicKey;\n amount: number;\n reference?: string;\n};\n\nexport async function buildUsdcTransfer({\n connection,\n fromWallet,\n toWallet,\n amount,\n reference,\n}: BuildUsdcTransferParams) {\n const mint = new PublicKey(USDC_MINT);\n const fromAta = await getAssociatedTokenAddress(mint, fromWallet);\n const toAta = await getAssociatedTokenAddress(mint, toWallet);\n\n const tx = new Transaction();\n\n console.log(\"REFERENCE IN BUILD:\", reference);\n\n if (reference) {\n const memoInstruction = new TransactionInstruction({\n keys: [],\n programId: MEMO_PROGRAM_ID,\n data: Buffer.from(reference),\n });\n\n tx.add(memoInstruction);\n }\n\n const toAtaInfo = await connection.getAccountInfo(toAta);\n\n if (!toAtaInfo) {\n tx.add(\n createAssociatedTokenAccountInstruction(\n fromWallet,\n toAta,\n toWallet,\n mint,\n ),\n );\n }\n\n tx.add(\n createTransferCheckedInstruction(\n fromAta,\n mint,\n toAta,\n fromWallet,\n Number(toTokenBaseUnits(amount)),\n USDC_DECIMALS,\n [],\n TOKEN_PROGRAM_ID,\n ),\n );\n\n const latestBlockhash = await connection.getLatestBlockhash();\n tx.feePayer = fromWallet;\n tx.recentBlockhash = latestBlockhash.blockhash;\n\n return tx;\n}\n","export const USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nexport const USDC_DECIMALS = 6;\n","import { USDC_DECIMALS } from \"./constants\";\n\nexport function toTokenBaseUnits(amount: number): bigint {\n if (!Number.isFinite(amount) || amount <= 0) {\n throw new Error(\"Amount must be a positive number\");\n }\n\n const multiplier = 10 ** USDC_DECIMALS;\n return BigInt(Math.round(amount * multiplier));\n}\n"],"mappings":"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","names":["React","PublicKey","PublicKey","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider/StablePayProvider.tsx","../src/context/StablePayContext.ts","../src/components/StablePay.tsx","../src/hooks/useStablePay.ts","../src/solana/buildUsdcTransfer.ts","../src/solana/constants.ts","../src/solana/amount.ts","../src/hooks/usePaymentVerification.ts","../src/parseUsdcPaymentFromTransaction.ts","../src/utils.ts","../src/verifyPayment.ts","../src/waitForPaymentConfirmation.ts"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport {\n ConnectionProvider,\n WalletProvider,\n} from \"@solana/wallet-adapter-react\";\nimport { WalletModalProvider } from \"@solana/wallet-adapter-react-ui\";\nimport {\n PhantomWalletAdapter,\n SolflareWalletAdapter,\n} from \"@solana/wallet-adapter-wallets\";\nimport type { StablePayProviderProps } from \"../types\";\nimport StablePayContext from \"../context/StablePayContext\";\n\nimport \"@solana/wallet-adapter-react-ui/styles.css\";\n\nexport const DEFAULT_RPC =\n \"https://mainnet.helius-rpc.com/?api-key=a90079ee-e2b5-438e-9b1a-2ae7ba8c1417\";\n\nexport function StablePayProvider({\n children,\n endpoint,\n to,\n}: StablePayProviderProps) {\n const resolvedEndpoint = endpoint ?? DEFAULT_RPC;\n\n const wallets = useMemo(\n () => [new PhantomWalletAdapter(), new SolflareWalletAdapter()],\n [],\n );\n\n return (\n <StablePayContext.Provider value={{ defaultTo: to }}>\n <ConnectionProvider endpoint={resolvedEndpoint}>\n <WalletProvider wallets={wallets} autoConnect>\n <WalletModalProvider>{children}</WalletModalProvider>\n </WalletProvider>\n </ConnectionProvider>\n </StablePayContext.Provider>\n );\n}\n","import { createContext, useContext } from \"react\";\n\ntype StablePayContextValue = {\n defaultTo?: string;\n};\n\nconst StablePayContext = createContext<StablePayContextValue>({});\n\nexport function useStablePayContext() {\n return useContext(StablePayContext);\n}\n\nexport default StablePayContext;\n","import React from \"react\";\nimport { useStablePay } from \"../hooks/useStablePay\";\nimport { useStablePayContext } from \"../context/StablePayContext\";\nimport type { StablePayProps } from \"../types\";\n\ntype ClickableChildProps = {\n onClick?: (event: React.MouseEvent) => void;\n disabled?: boolean;\n};\n\nfunction getResolvedTo(to?: string, defaultTo?: string): string {\n const resolved = to ?? defaultTo;\n\n if (!resolved) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n return resolved;\n}\n\nexport function StablePay({\n amount,\n to,\n reference,\n children,\n onSuccess,\n onError,\n}: StablePayProps) {\n const { pay, loading } = useStablePay();\n const { defaultTo } = useStablePayContext();\n\n const resolvedTo = getResolvedTo(to, defaultTo);\n\n if (!resolvedTo) {\n throw new Error(\n \"StablePay: missing recipient address. Provide `to` on StablePay or StablePayProvider.\",\n );\n }\n\n if (!React.isValidElement<ClickableChildProps>(children)) {\n throw new Error(\"StablePay expects a single React element child.\");\n }\n\n async function handleClick(event: React.MouseEvent) {\n try {\n children.props.onClick?.(event);\n\n if (event.defaultPrevented) return;\n\n await pay({\n amount,\n to: resolvedTo,\n reference,\n onSuccess,\n onError,\n });\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(\"Payment failed\"));\n }\n }\n\n return React.cloneElement(children, {\n onClick: handleClick,\n disabled: Boolean(children.props.disabled) || loading,\n });\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { useConnection, useWallet } from \"@solana/wallet-adapter-react\";\nimport { useWalletModal } from \"@solana/wallet-adapter-react-ui\";\nimport { buildUsdcTransfer } from \"../solana/buildUsdcTransfer\";\nimport { StablePayPayArgs } from \"../types\";\n\ntype PendingPayment = StablePayPayArgs;\n\nexport function useStablePay() {\n const { connection } = useConnection();\n const { connected, publicKey, sendTransaction } = useWallet();\n const { setVisible } = useWalletModal();\n\n const [loading, setLoading] = useState(false);\n const [signature, setSignature] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [pendingPayment, setPendingPayment] = useState<PendingPayment | null>(\n null,\n );\n\n const executePayment = useCallback(\n async ({ amount, to, reference }: StablePayPayArgs) => {\n if (!publicKey) {\n throw new Error(\"Wallet not connected\");\n }\n\n let recipient: PublicKey;\n\n try {\n recipient = new PublicKey(to);\n } catch {\n throw new Error(\"Invalid recipient wallet address\");\n }\n\n const transaction = await buildUsdcTransfer({\n connection,\n fromWallet: publicKey,\n toWallet: recipient,\n amount,\n reference,\n });\n\n const sig = await sendTransaction(transaction, connection);\n await connection.confirmTransaction(sig, \"confirmed\");\n\n setSignature(sig);\n return sig;\n },\n [publicKey, connection, sendTransaction],\n );\n\n const pay = useCallback(\n async ({ amount, to, reference, onSuccess, onError }: StablePayPayArgs) => {\n setLoading(true);\n setSignature(null);\n setError(null);\n\n // Not connected → store intent + callbacks\n if (!connected || !publicKey) {\n setPendingPayment({ amount, to, reference, onSuccess, onError });\n setVisible(true);\n return;\n }\n\n try {\n const sig = await executePayment({ amount, to, reference });\n onSuccess?.({\n signature: sig,\n amount,\n to,\n reference,\n });\n } catch (err) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n onError?.(normalized);\n } finally {\n setLoading(false);\n }\n },\n [connected, publicKey, executePayment, setVisible],\n );\n\n // Resume after wallet connects\n useEffect(() => {\n if (!connected || !publicKey || !pendingPayment) return;\n\n const payment = pendingPayment;\n\n let cancelled = false;\n\n async function resumePayment() {\n try {\n const sig = await executePayment(payment);\n\n if (!cancelled) {\n payment.onSuccess?.({\n signature: sig,\n amount: payment.amount,\n to: payment.to,\n reference: payment.reference,\n });\n setSignature(sig);\n setPendingPayment(null);\n }\n } catch (err) {\n if (!cancelled) {\n const normalized =\n err instanceof Error ? err : new Error(\"Payment failed\");\n setError(normalized);\n payment.onError?.(normalized);\n setPendingPayment(null);\n }\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n resumePayment();\n\n return () => {\n cancelled = true;\n };\n }, [connected, publicKey, pendingPayment, executePayment]);\n\n return { pay, loading, error, signature };\n}\n","import {\n Connection,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_PROGRAM_ID,\n createAssociatedTokenAccountInstruction,\n createTransferCheckedInstruction,\n getAssociatedTokenAddress,\n} from \"@solana/spl-token\";\nimport { toTokenBaseUnits } from \"./amount\";\nimport { USDC_DECIMALS, SOLANA_USDC_MINT } from \"./constants\";\n\nconst MEMO_PROGRAM_ID = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\ntype BuildUsdcTransferParams = {\n connection: Connection;\n fromWallet: PublicKey;\n toWallet: PublicKey;\n amount: number;\n reference?: string;\n};\n\nexport async function buildUsdcTransfer({\n connection,\n fromWallet,\n toWallet,\n amount,\n reference,\n}: BuildUsdcTransferParams) {\n const mint = new PublicKey(SOLANA_USDC_MINT);\n const fromAta = await getAssociatedTokenAddress(mint, fromWallet);\n const toAta = await getAssociatedTokenAddress(mint, toWallet);\n\n const tx = new Transaction();\n\n console.log(\"REFERENCE IN BUILD:\", reference);\n\n if (reference) {\n const memoInstruction = new TransactionInstruction({\n keys: [],\n programId: MEMO_PROGRAM_ID,\n data: Buffer.from(reference),\n });\n\n tx.add(memoInstruction);\n }\n\n const toAtaInfo = await connection.getAccountInfo(toAta);\n\n if (!toAtaInfo) {\n tx.add(\n createAssociatedTokenAccountInstruction(\n fromWallet,\n toAta,\n toWallet,\n mint,\n ),\n );\n }\n\n tx.add(\n createTransferCheckedInstruction(\n fromAta,\n mint,\n toAta,\n fromWallet,\n Number(toTokenBaseUnits(amount)),\n USDC_DECIMALS,\n [],\n TOKEN_PROGRAM_ID,\n ),\n );\n\n const latestBlockhash = await connection.getLatestBlockhash();\n tx.feePayer = fromWallet;\n tx.recentBlockhash = latestBlockhash.blockhash;\n\n return tx;\n}\n","export const SOLANA_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nexport const USDC_DECIMALS = 6;\n","import { USDC_DECIMALS } from \"./constants\";\n\nexport function toTokenBaseUnits(amount: number): bigint {\n if (!Number.isFinite(amount) || amount <= 0) {\n throw new Error(\"Amount must be a positive number\");\n }\n\n const multiplier = 10 ** USDC_DECIMALS;\n return BigInt(Math.round(amount * multiplier));\n}\n","import { useCallback, useState } from \"react\";\nimport { VerifyPaymentResult } from \"../types\";\nimport { waitForPaymentConfirmation } from \"../waitForPaymentConfirmation\";\n\nexport type StablePaySuccessPayload = {\n signature: string;\n amount: number;\n to: string;\n reference?: string;\n};\n\nexport type PaymentVerificationStatus =\n | \"idle\"\n | \"verifying\"\n | \"pending\"\n | \"confirmed\"\n | \"failed\";\n\nexport type UsePaymentVerificationOptions = {\n maxAttempts?: number;\n intervalMs?: number;\n};\n\nexport type UsePaymentVerificationResult = {\n status: PaymentVerificationStatus;\n result: VerifyPaymentResult | null;\n error: Error | null;\n verify: (payload: StablePaySuccessPayload) => Promise<VerifyPaymentResult>;\n reset: () => void;\n};\n\nexport function usePaymentVerification(\n options: UsePaymentVerificationOptions = {},\n): UsePaymentVerificationResult {\n const [status, setStatus] = useState<PaymentVerificationStatus>(\"idle\");\n const [result, setResult] = useState<VerifyPaymentResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n const reset = useCallback(() => {\n setStatus(\"idle\");\n setResult(null);\n setError(null);\n }, []);\n\n const verify = useCallback(\n async (payload: StablePaySuccessPayload) => {\n setStatus(\"verifying\");\n setError(null);\n\n try {\n const verificationResult = await waitForPaymentConfirmation(\n {\n to: payload.to,\n amount: String(payload.amount),\n txHash: payload.signature,\n reference: payload.reference,\n },\n {\n maxAttempts: options.maxAttempts,\n intervalMs: options.intervalMs,\n },\n );\n\n setResult(verificationResult);\n\n if (verificationResult.ok) {\n setStatus(\n verificationResult.status === \"confirmed\" ? \"confirmed\" : \"pending\",\n );\n } else {\n setStatus(\"failed\");\n }\n\n return verificationResult;\n } catch (err) {\n const nextError =\n err instanceof Error ? err : new Error(\"Payment verification failed\");\n\n setError(nextError);\n setStatus(\"failed\");\n throw nextError;\n }\n },\n [options.maxAttempts, options.intervalMs],\n );\n\n return {\n status,\n result,\n error,\n verify,\n reset,\n };\n}\n","import {\n Connection,\n ParsedInstruction,\n PartiallyDecodedInstruction,\n PublicKey,\n} from \"@solana/web3.js\";\nimport { ParsedPayment } from \"./types\";\nimport { DEFAULT_RPC } from \"./provider/StablePayProvider\";\nimport { SOLANA_USDC_MINT } from \"./solana/constants\";\n\nfunction isParsedInstruction(\n ix: ParsedInstruction | PartiallyDecodedInstruction,\n): ix is ParsedInstruction {\n return \"parsed\" in ix;\n}\n\nexport async function parseUsdcPaymentFromTransaction(\n txHash: string,\n): Promise<ParsedPayment | null> {\n const connection = new Connection(DEFAULT_RPC, \"confirmed\");\n\n const tx = await connection.getParsedTransaction(txHash, {\n maxSupportedTransactionVersion: 0,\n commitment: \"confirmed\",\n });\n\n if (!tx || !tx.meta) return null;\n\n if (tx.meta.err) {\n return {\n txHash,\n status: \"failed\",\n to: \"\",\n amount: \"0\",\n confirmations: 0,\n };\n }\n\n const allInstructions = [\n ...tx.transaction.message.instructions,\n ...(tx.meta.innerInstructions?.flatMap((group) => group.instructions) ??\n []),\n ];\n\n let amount: string | null = null;\n let reference: string | undefined;\n let destinationTokenAccount: string | null = null;\n\n for (const ix of allInstructions) {\n if (!isParsedInstruction(ix)) continue;\n\n if (ix.program === \"spl-token\") {\n const parsedType = ix.parsed?.type;\n const info = ix.parsed?.info;\n\n if (\n (parsedType === \"transfer\" || parsedType === \"transferChecked\") &&\n info\n ) {\n const mint = info.mint;\n const rawAmount = info.tokenAmount?.amount ?? info.amount;\n\n if (mint === SOLANA_USDC_MINT && rawAmount) {\n destinationTokenAccount = info.destination;\n amount = (Number(rawAmount) / 1_000_000).toString();\n }\n }\n }\n\n if (ix.program === \"spl-memo\") {\n if (typeof ix.parsed === \"string\") {\n reference = ix.parsed;\n }\n }\n }\n\n if (!destinationTokenAccount || !amount) {\n return null;\n }\n\n const currentSlot = await connection.getSlot(\"confirmed\");\n const confirmations = Math.max(0, currentSlot - tx.slot);\n\n console.log(\"parsed tx\", tx);\n console.log(\"allInstructions\", allInstructions);\n console.log(\"destinationTokenAccount\", destinationTokenAccount);\n console.log(\"amount\", amount);\n console.log(\"reference\", reference);\n\n return {\n txHash,\n status: confirmations > 0 ? \"confirmed\" : \"pending\",\n to: destinationTokenAccount,\n amount,\n reference,\n confirmations,\n };\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport { SOLANA_USDC_MINT } from \"./solana/constants\";\nimport { getAssociatedTokenAddressSync } from \"@solana/spl-token\";\n\n/**\n * Convert human-readable USDC to atomic units (6 decimals)\n */\nexport function toAtomicUnits(amount: string): bigint {\n const [whole, fraction = \"\"] = amount.split(\".\");\n\n const paddedFraction = (fraction + \"000000\").slice(0, 6);\n\n return BigInt(whole) * 1_000_000n + BigInt(paddedFraction);\n}\n\nexport function amountGte(actual: string, expected: string): boolean {\n return toAtomicUnits(actual) >= toAtomicUnits(expected);\n}\n\nexport function sameAddress(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\nexport function getUsdcTokenAccountForWallet(walletAddress: string): string {\n const wallet = new PublicKey(walletAddress);\n const mint = new PublicKey(SOLANA_USDC_MINT);\n\n return getAssociatedTokenAddressSync(mint, wallet, true).toBase58();\n}\n","import { VerifyPaymentInput, VerifyPaymentResult } from \"./types\";\nimport { parseUsdcPaymentFromTransaction } from \"./parseUsdcPaymentFromTransaction\";\nimport { amountGte, getUsdcTokenAccountForWallet, sameAddress } from \"./utils\";\n\nexport async function verifyPayment(\n input: VerifyPaymentInput,\n): Promise<VerifyPaymentResult> {\n const parsed = await parseUsdcPaymentFromTransaction(input.txHash);\n\n if (!parsed) {\n return {\n ok: false,\n reason: \"INVALID_TRANSACTION\",\n txHash: input.txHash,\n };\n }\n\n if (parsed.status === \"failed\") {\n return {\n ok: false,\n reason: \"TX_FAILED\",\n txHash: input.txHash,\n };\n }\n\n const expectedTokenAccount = getUsdcTokenAccountForWallet(input.to);\n\n if (!sameAddress(parsed.to, expectedTokenAccount)) {\n return {\n ok: false,\n reason: \"TO_MISMATCH\",\n txHash: input.txHash,\n };\n }\n\n if (!amountGte(parsed.amount, input.amount)) {\n return {\n ok: false,\n reason: \"AMOUNT_TOO_LOW\",\n txHash: input.txHash,\n };\n }\n\n if (input.reference && parsed.reference !== input.reference) {\n return {\n ok: false,\n reason: \"REFERENCE_MISMATCH\",\n txHash: input.txHash,\n };\n }\n\n return {\n ok: true,\n status: parsed.status === \"pending\" ? \"pending\" : \"confirmed\",\n txHash: parsed.txHash,\n to: input.to,\n amount: parsed.amount,\n reference: parsed.reference,\n confirmations: parsed.confirmations,\n };\n}\n","import { verifyPayment } from \"./verifyPayment\";\nimport { VerifyPaymentInput, VerifyPaymentResult } from \"./types\";\n\ntype WaitForPaymentConfirmationOptions = {\n maxAttempts?: number;\n intervalMs?: number;\n};\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function waitForPaymentConfirmation(\n input: VerifyPaymentInput,\n options: WaitForPaymentConfirmationOptions = {},\n): Promise<VerifyPaymentResult> {\n const maxAttempts = options.maxAttempts ?? 10;\n const intervalMs = options.intervalMs ?? 1500;\n\n for (let i = 0; i < maxAttempts; i++) {\n const result = await verifyPayment(input);\n\n if (result.ok && result.status === \"confirmed\") {\n return result;\n }\n\n if (result.ok && result.status === \"pending\") {\n await sleep(intervalMs);\n continue;\n }\n\n if (!result.ok && result.reason === \"INVALID_TRANSACTION\") {\n await sleep(intervalMs);\n continue;\n }\n\n return result;\n }\n\n return {\n ok: false,\n reason: \"INVALID_TRANSACTION\",\n txHash: input.txHash,\n };\n}\n"],"mappings":"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","names":["React","PublicKey","PublicKey","React","useCallback","useState","Connection","Connection","PublicKey","PublicKey","useState","useCallback"]}
|