@futurekode/stablepay-react 0.3.0 → 0.4.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.js CHANGED
@@ -94,20 +94,38 @@ function toTokenBaseUnits(amount) {
94
94
  }
95
95
 
96
96
  // src/solana/buildUsdcTransfer.ts
97
+ var MEMO_PROGRAM_ID = new import_web3.PublicKey(
98
+ "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
99
+ );
97
100
  async function buildUsdcTransfer({
98
101
  connection,
99
102
  fromWallet,
100
103
  toWallet,
101
- amount
104
+ amount,
105
+ reference
102
106
  }) {
103
107
  const mint = new import_web3.PublicKey(USDC_MINT);
104
108
  const fromAta = await (0, import_spl_token.getAssociatedTokenAddress)(mint, fromWallet);
105
109
  const toAta = await (0, import_spl_token.getAssociatedTokenAddress)(mint, toWallet);
106
110
  const tx = new import_web3.Transaction();
111
+ console.log("REFERENCE IN BUILD:", reference);
112
+ if (reference) {
113
+ const memoInstruction = new import_web3.TransactionInstruction({
114
+ keys: [],
115
+ programId: MEMO_PROGRAM_ID,
116
+ data: Buffer.from(reference)
117
+ });
118
+ tx.add(memoInstruction);
119
+ }
107
120
  const toAtaInfo = await connection.getAccountInfo(toAta);
108
121
  if (!toAtaInfo) {
109
122
  tx.add(
110
- (0, import_spl_token.createAssociatedTokenAccountInstruction)(fromWallet, toAta, toWallet, mint)
123
+ (0, import_spl_token.createAssociatedTokenAccountInstruction)(
124
+ fromWallet,
125
+ toAta,
126
+ toWallet,
127
+ mint
128
+ )
111
129
  );
112
130
  }
113
131
  tx.add(
@@ -140,7 +158,7 @@ function useStablePay() {
140
158
  null
141
159
  );
142
160
  const executePayment = (0, import_react3.useCallback)(
143
- async ({ amount, to }) => {
161
+ async ({ amount, to, reference }) => {
144
162
  if (!publicKey) {
145
163
  throw new Error("Wallet not connected");
146
164
  }
@@ -154,7 +172,8 @@ function useStablePay() {
154
172
  connection,
155
173
  fromWallet: publicKey,
156
174
  toWallet: recipient,
157
- amount
175
+ amount,
176
+ reference
158
177
  });
159
178
  const sig = await sendTransaction(transaction, connection);
160
179
  await connection.confirmTransaction(sig, "confirmed");
@@ -174,7 +193,7 @@ function useStablePay() {
174
193
  return;
175
194
  }
176
195
  try {
177
- const sig = await executePayment({ amount, to });
196
+ const sig = await executePayment({ amount, to, reference });
178
197
  onSuccess?.({
179
198
  signature: sig,
180
199
  amount,
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 }: 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 });\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 });\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 { Connection, PublicKey, Transaction } 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\ntype BuildUsdcTransferParams = {\n connection: Connection;\n fromWallet: PublicKey;\n toWallet: PublicKey;\n amount: number;\n};\n\nexport async function buildUsdcTransfer({\n connection,\n fromWallet,\n toWallet,\n amount,\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 const toAtaInfo = await connection.getAccountInfo(toAta);\n\n if (!toAtaInfo) {\n tx.add(\n createAssociatedTokenAccountInstruction(fromWallet, toAta, toWallet, mint)\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":["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"],"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":"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","names":["import_react","import_react","import_react","import_web3","import_wallet_adapter_react","import_wallet_adapter_react_ui","React"]}
package/dist/index.mjs CHANGED
@@ -45,7 +45,11 @@ import { useConnection, useWallet } from "@solana/wallet-adapter-react";
45
45
  import { useWalletModal } from "@solana/wallet-adapter-react-ui";
46
46
 
47
47
  // src/solana/buildUsdcTransfer.ts
48
- import { PublicKey, Transaction } from "@solana/web3.js";
48
+ import {
49
+ PublicKey,
50
+ Transaction,
51
+ TransactionInstruction
52
+ } from "@solana/web3.js";
49
53
  import {
50
54
  TOKEN_PROGRAM_ID,
51
55
  createAssociatedTokenAccountInstruction,
@@ -67,20 +71,38 @@ function toTokenBaseUnits(amount) {
67
71
  }
68
72
 
69
73
  // src/solana/buildUsdcTransfer.ts
74
+ var MEMO_PROGRAM_ID = new PublicKey(
75
+ "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
76
+ );
70
77
  async function buildUsdcTransfer({
71
78
  connection,
72
79
  fromWallet,
73
80
  toWallet,
74
- amount
81
+ amount,
82
+ reference
75
83
  }) {
76
84
  const mint = new PublicKey(USDC_MINT);
77
85
  const fromAta = await getAssociatedTokenAddress(mint, fromWallet);
78
86
  const toAta = await getAssociatedTokenAddress(mint, toWallet);
79
87
  const tx = new Transaction();
88
+ console.log("REFERENCE IN BUILD:", reference);
89
+ if (reference) {
90
+ const memoInstruction = new TransactionInstruction({
91
+ keys: [],
92
+ programId: MEMO_PROGRAM_ID,
93
+ data: Buffer.from(reference)
94
+ });
95
+ tx.add(memoInstruction);
96
+ }
80
97
  const toAtaInfo = await connection.getAccountInfo(toAta);
81
98
  if (!toAtaInfo) {
82
99
  tx.add(
83
- createAssociatedTokenAccountInstruction(fromWallet, toAta, toWallet, mint)
100
+ createAssociatedTokenAccountInstruction(
101
+ fromWallet,
102
+ toAta,
103
+ toWallet,
104
+ mint
105
+ )
84
106
  );
85
107
  }
86
108
  tx.add(
@@ -113,7 +135,7 @@ function useStablePay() {
113
135
  null
114
136
  );
115
137
  const executePayment = useCallback(
116
- async ({ amount, to }) => {
138
+ async ({ amount, to, reference }) => {
117
139
  if (!publicKey) {
118
140
  throw new Error("Wallet not connected");
119
141
  }
@@ -127,7 +149,8 @@ function useStablePay() {
127
149
  connection,
128
150
  fromWallet: publicKey,
129
151
  toWallet: recipient,
130
- amount
152
+ amount,
153
+ reference
131
154
  });
132
155
  const sig = await sendTransaction(transaction, connection);
133
156
  await connection.confirmTransaction(sig, "confirmed");
@@ -147,7 +170,7 @@ function useStablePay() {
147
170
  return;
148
171
  }
149
172
  try {
150
- const sig = await executePayment({ amount, to });
173
+ const sig = await executePayment({ amount, to, reference });
151
174
  onSuccess?.({
152
175
  signature: sig,
153
176
  amount,
@@ -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 }: 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 });\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 });\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 { Connection, PublicKey, Transaction } 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\ntype BuildUsdcTransferParams = {\n connection: Connection;\n fromWallet: PublicKey;\n toWallet: PublicKey;\n amount: number;\n};\n\nexport async function buildUsdcTransfer({\n connection,\n fromWallet,\n toWallet,\n amount,\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 const toAtaInfo = await connection.getAccountInfo(toAta);\n\n if (!toAtaInfo) {\n tx.add(\n createAssociatedTokenAccountInstruction(fromWallet, toAta, toWallet, mint)\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"],"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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futurekode/stablepay-react",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Headless React wrapper for USDC payments on Solana",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",