@rozoai/intent-pay 0.1.37 → 0.1.38-beta.1
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/build/components/Common/TokenChainLogo/index.d.ts +7 -1
- package/build/components/Spinners/TokenLogoSpinner/index.d.ts +6 -1
- package/build/hooks/useDepositAddressOptions.d.ts +3 -2
- package/build/hooks/usePaymentState.d.ts +11 -5
- package/build/hooks/useRozoPay.d.ts +4 -4
- package/build/hooks/useSolanaPaymentOptions.d.ts +1 -1
- package/build/hooks/useStellarPaymentOptions.d.ts +1 -1
- package/build/hooks/useWalletPaymentOptions.d.ts +12 -7
- package/build/package.json.js +2 -2
- package/build/payment/createPaymentPayload.d.ts +3 -3
- package/build/payment/paymentFsm.d.ts +25 -2
- package/build/provider/PayContext.d.ts +3 -5
- package/build/src/components/Common/AmountInput/index.js +1 -1
- package/build/src/components/Common/AmountInput/index.js.map +1 -1
- package/build/src/components/Common/ConnectorList/index.js +2 -4
- package/build/src/components/Common/ConnectorList/index.js.map +1 -1
- package/build/src/components/Common/TokenChainLogo/index.js +26 -3
- package/build/src/components/Common/TokenChainLogo/index.js.map +1 -1
- package/build/src/components/Pages/MobileConnectors/index.js +4 -10
- package/build/src/components/Pages/MobileConnectors/index.js.map +1 -1
- package/build/src/components/Pages/PayWithToken/index.js +15 -4
- package/build/src/components/Pages/PayWithToken/index.js.map +1 -1
- package/build/src/components/Pages/SelectDepositAddressChain/index.js +6 -17
- package/build/src/components/Pages/SelectDepositAddressChain/index.js.map +1 -1
- package/build/src/components/Pages/SelectMethod/index.js +2 -6
- package/build/src/components/Pages/SelectMethod/index.js.map +1 -1
- package/build/src/components/Pages/Solana/PayWithSolanaToken/index.js +64 -26
- package/build/src/components/Pages/Solana/PayWithSolanaToken/index.js.map +1 -1
- package/build/src/components/Pages/Stellar/PayWithStellarToken/index.js +40 -38
- package/build/src/components/Pages/Stellar/PayWithStellarToken/index.js.map +1 -1
- package/build/src/components/Pages/WaitingDepositAddress/index.js +110 -33
- package/build/src/components/Pages/WaitingDepositAddress/index.js.map +1 -1
- package/build/src/components/RozoPayModal/index.js +9 -32
- package/build/src/components/RozoPayModal/index.js.map +1 -1
- package/build/src/components/Spinners/TokenLogoSpinner/index.js +5 -2
- package/build/src/components/Spinners/TokenLogoSpinner/index.js.map +1 -1
- package/build/src/hooks/useDepositAddressOptions.js +19 -9
- package/build/src/hooks/useDepositAddressOptions.js.map +1 -1
- package/build/src/hooks/usePaymentState.js +193 -72
- package/build/src/hooks/usePaymentState.js.map +1 -1
- package/build/src/hooks/useRozoPay.js +4 -2
- package/build/src/hooks/useRozoPay.js.map +1 -1
- package/build/src/hooks/useSolanaPaymentOptions.js +45 -12
- package/build/src/hooks/useSolanaPaymentOptions.js.map +1 -1
- package/build/src/hooks/useStellarPaymentOptions.js +40 -10
- package/build/src/hooks/useStellarPaymentOptions.js.map +1 -1
- package/build/src/hooks/useTokenOptions.js +4 -3
- package/build/src/hooks/useTokenOptions.js.map +1 -1
- package/build/src/hooks/useWalletPaymentOptions.js +54 -21
- package/build/src/hooks/useWalletPaymentOptions.js.map +1 -1
- package/build/src/payment/createPaymentPayload.js +38 -13
- package/build/src/payment/createPaymentPayload.js.map +1 -1
- package/build/src/payment/paymentEffects.js +4 -5
- package/build/src/payment/paymentEffects.js.map +1 -1
- package/build/src/payment/paymentFsm.js.map +1 -1
- package/build/src/provider/RozoPayProvider.js +0 -6
- package/build/src/provider/RozoPayProvider.js.map +1 -1
- package/build/src/utils/format.js +82 -13
- package/build/src/utils/format.js.map +1 -1
- package/build/src/utils/token.js +21 -5
- package/build/src/utils/token.js.map +1 -1
- package/build/src/wallets/walletConfigs.js +1 -1
- package/build/src/wallets/walletConfigs.js.map +1 -1
- package/build/utils/format.d.ts +44 -3
- package/build/utils/token.d.ts +6 -2
- package/package.json +2 -2
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { AnimatePresence } from 'framer-motion';
|
|
3
3
|
import { chainToLogo } from '../../../assets/chains.js';
|
|
4
|
+
import { isNativeToken } from '@rozoai/intent-common';
|
|
4
5
|
import CircleSpinner from '../CircleSpinner/index.js';
|
|
5
6
|
import { LoadingContainer, AnimationContainer } from '../styles.js';
|
|
6
7
|
import { ChainLogoContainer } from './styles.js';
|
|
7
8
|
|
|
8
|
-
const TokenLogoSpinner = ({ token, loading = false }) => {
|
|
9
|
-
|
|
9
|
+
const TokenLogoSpinner = ({ token, loading = false, nativeAsChainIcon = false, }) => {
|
|
10
|
+
const chainLogo = chainToLogo[token.chainId];
|
|
11
|
+
const showChainAsMain = nativeAsChainIcon && isNativeToken(token.token) && chainLogo != null;
|
|
12
|
+
return (jsx(LoadingContainer, { children: jsx(AnimationContainer, { "$circle": true, children: jsxs(AnimatePresence, { children: [chainLogo && !showChainAsMain && (jsx(ChainLogoContainer, { children: chainLogo }, "ChainLogoContainer")), jsx(CircleSpinner, { logo: showChainAsMain ? (chainLogo) : (jsx("img", { src: token.logoURI, alt: token.symbol })), loading: loading, unavailable: false }, "CircleSpinner")] }) }) }));
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
export { TokenLogoSpinner as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/components/Spinners/TokenLogoSpinner/index.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/components/Spinners/TokenLogoSpinner/index.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;AAQA,MAAM,gBAAgB,GAAG,CAAC,EACxB,KAAK,EACL,OAAO,GAAG,KAAK,EACf,iBAAiB,GAAG,KAAK,GAS1B,KAAI;IACH,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC7C,IAAA,MAAM,eAAe,GAAG,iBAAiB,IAAI,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,SAAS,IAAI,IAAI,CAAC;AAE7F,IAAA,QACEA,GAAA,CAAC,gBAAgB,EAAA,EAAA,QAAA,EACfA,IAAC,kBAAkB,EAAA,EAAA,SAAA,EAAU,IAAI,EAAA,QAAA,EAC/BC,KAAC,eAAe,EAAA,EAAA,QAAA,EAAA,CAEb,SAAS,IAAI,CAAC,eAAe,KAC5BD,GAAA,CAAC,kBAAkB,EAAA,EAAA,QAAA,EAChB,SAAS,EAAA,EADY,oBAAoB,CAEvB,CACtB,EACDA,GAAA,CAAC,aAAa,EAEZ,EAAA,IAAI,EACF,eAAe,IACb,SAAS,KAETA,GAAK,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,EAAI,CAAA,CAC/C,EAEH,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,KAAK,EAAA,EATd,eAAe,CAUnB,CAAA,EAAA,CACc,EACC,CAAA,EAAA,CACJ,EACnB;AACJ;;;;"}
|
|
@@ -62,14 +62,15 @@ const fallbackOptions = [
|
|
|
62
62
|
* - Ethereum (Chain ID: 1) - Ethereum mainnet
|
|
63
63
|
* - BSC (Chain ID: 56) - Conditional support for MP app IDs
|
|
64
64
|
*/
|
|
65
|
-
function useDepositAddressOptions({ trpc, usdRequired, payParams, }) {
|
|
65
|
+
function useDepositAddressOptions({ trpc, usdRequired, mode, payParams, }) {
|
|
66
66
|
const { data, isLoading, error } = useQuery({
|
|
67
|
-
enabled: usdRequired != null && usdRequired > 0,
|
|
68
|
-
queryKey: ["depositAddressOptions", usdRequired],
|
|
67
|
+
enabled: usdRequired != null && usdRequired > 0 && mode != null,
|
|
68
|
+
queryKey: ["depositAddressOptions", usdRequired, mode],
|
|
69
69
|
queryFn: async () => {
|
|
70
70
|
try {
|
|
71
71
|
return await trpc.getDepositAddressOptions.query({
|
|
72
|
-
usdRequired
|
|
72
|
+
usdRequired,
|
|
73
|
+
mode,
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
76
|
catch (err) {
|
|
@@ -85,17 +86,26 @@ function useDepositAddressOptions({ trpc, usdRequired, payParams, }) {
|
|
|
85
86
|
// Memoized configuration for deposit address options
|
|
86
87
|
const filteredOptions = useMemo(() => {
|
|
87
88
|
const options = data ?? [];
|
|
88
|
-
if (payParams?.preferredTokens && payParams
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
if (payParams?.preferredTokens && payParams?.preferredTokens.length > 0) {
|
|
90
|
+
// Address match: token addresses can differ in casing between the SDK
|
|
91
|
+
// token registry (EVM natives stored lowercase) and the API response
|
|
92
|
+
// (EIP-55 checksummed), so a strict `===` drops native ETH/POL/BNB
|
|
93
|
+
// deposit options. Normalize per-chain: EVM lowercase, Solana/Stellar
|
|
94
|
+
// case-sensitive.
|
|
95
|
+
const normalize = (chainId, addr) => normalizeTokenAddress(chainId, addr) ?? addr;
|
|
96
|
+
const preferred = new Set(payParams.preferredTokens.map((pt) => `${pt.chainId}:${normalize(pt.chainId, pt.token)}`));
|
|
97
|
+
return options.filter((option) => preferred.has(`${option.token.chainId}:${normalize(option.token.chainId, option.token.token)}`));
|
|
92
98
|
}
|
|
93
99
|
return options;
|
|
94
100
|
}, [data, payParams?.preferredTokens]);
|
|
95
101
|
return {
|
|
96
102
|
options: filteredOptions,
|
|
97
103
|
loading: isLoading,
|
|
98
|
-
error: error
|
|
104
|
+
error: error
|
|
105
|
+
? error instanceof Error
|
|
106
|
+
? error.message
|
|
107
|
+
: "Failed to load deposit address options"
|
|
108
|
+
: null,
|
|
99
109
|
};
|
|
100
110
|
}
|
|
101
111
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDepositAddressOptions.js","sources":["../../../src/hooks/useDepositAddressOptions.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"useDepositAddressOptions.js","sources":["../../../src/hooks/useDepositAddressOptions.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { ExternalPaymentOptions, rozoStellar, TokenSymbol, assert, getPayment, checkoutPayment, buildCheckoutPayload, createPayment, debugJson, formatPaymentResponseToHydratedOrder, bscUSDT, assertNotNull, isValidSolanaAddress,
|
|
1
|
+
import { ExternalPaymentOptions, rozoStellar, TokenSymbol, assert, isNativeToken, getPayment, checkoutPayment, buildCheckoutPayload, createPayment, debugJson, normalizeTokenAddress, formatPaymentResponseToHydratedOrder, bscUSDT, assertNotNull, isValidSolanaAddress, solanaSOL, stellarXLM, rozoStellarUSDC, rozoStellarEURC, solana, rozoSolana, stellar, FeeType, getChainById, getKnownToken, generateSolanaDeepLink, generateEVMDeepLink, writeRozoPayOrderID } from '@rozoai/intent-common';
|
|
2
2
|
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
|
|
3
|
-
import { VersionedTransaction, PublicKey, Transaction } from '@solana/web3.js';
|
|
3
|
+
import { VersionedTransaction, PublicKey, SystemProgram, Transaction } from '@solana/web3.js';
|
|
4
4
|
import { useRef, useState, useEffect, useCallback, useMemo } from 'react';
|
|
5
|
-
import {
|
|
5
|
+
import { getAddress, erc20Abi, hexToBytes, parseUnits } from 'viem';
|
|
6
6
|
import { useAccount, useSwitchChain, useSendTransaction, useWriteContract, useWalletClient, useCapabilities } from 'wagmi';
|
|
7
7
|
import { useWriteContracts } from 'wagmi/experimental';
|
|
8
|
+
import { tokenBaseAmountToDecimalString, tokenAmountToBaseUnits } from '../utils/format.js';
|
|
8
9
|
import { convertPreferredSymbolsToTokens } from '../utils/token.js';
|
|
9
10
|
import { createMemoInstruction } from '@solana/spl-memo';
|
|
10
11
|
import { getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, TOKEN_PROGRAM_ID, createTransferCheckedInstruction } from '@solana/spl-token';
|
|
@@ -52,7 +53,7 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
52
53
|
const { data: walletClient } = useWalletClient();
|
|
53
54
|
const { data: walletCapabilities, isPending: capabilitiesPending } = useCapabilities();
|
|
54
55
|
const { writeContractsAsync } = useWriteContracts();
|
|
55
|
-
//
|
|
56
|
+
// order.metadata.dataSuffix survives ROZO_INVOICE_URL redirects where the
|
|
56
57
|
// consumer's wagmi config (globalDataSuffix) is absent. Invoice checkout fetches the
|
|
57
58
|
// order first and passes metadata.dataSuffix into getDefaultConfig, but this fallback
|
|
58
59
|
// covers the in-SDK path where the order is already loaded.
|
|
@@ -161,12 +162,26 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
161
162
|
}
|
|
162
163
|
// payId mode: derive filtering params from the loaded order so that
|
|
163
164
|
// payment option hooks apply the same token filtering as appId mode.
|
|
164
|
-
// e.g. if destination is USDC,
|
|
165
|
+
// e.g. if destination is USDC, allow paying with USDC/USDT/native tokens
|
|
166
|
+
// (we don't support payout to native tokens yet, but paying *with* native
|
|
167
|
+
// source balances is fine). EURC destinations are payable only with EURC.
|
|
165
168
|
if (pay.order && pay.order.destFinalCallTokenAmount) {
|
|
166
169
|
const destSymbol = pay.order.destFinalCallTokenAmount.token.symbol;
|
|
167
|
-
// Derive preferredSymbol from destination: EURC destinations
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
+
// Derive preferredSymbol from destination: EURC destinations must be
|
|
171
|
+
// paid with EURC only. Everything else defaults to USDC + USDT plus
|
|
172
|
+
// native tokens as payable sources (payout is still fixed to
|
|
173
|
+
// toChain/toToken and never native).
|
|
174
|
+
const preferredSymbol = destSymbol === TokenSymbol.EURC
|
|
175
|
+
? [TokenSymbol.EURC]
|
|
176
|
+
: [
|
|
177
|
+
TokenSymbol.USDC,
|
|
178
|
+
TokenSymbol.USDT,
|
|
179
|
+
TokenSymbol.ETH,
|
|
180
|
+
TokenSymbol.BNB,
|
|
181
|
+
TokenSymbol.POL,
|
|
182
|
+
TokenSymbol.SOL,
|
|
183
|
+
TokenSymbol.XLM,
|
|
184
|
+
];
|
|
170
185
|
const preferredTokens = convertPreferredSymbolsToTokens(preferredSymbol, undefined);
|
|
171
186
|
return {
|
|
172
187
|
toChain: pay.order.destFinalCallTokenAmount.token.chainId,
|
|
@@ -214,6 +229,7 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
214
229
|
const depositAddressOptions = useDepositAddressOptions({
|
|
215
230
|
trpc,
|
|
216
231
|
usdRequired,
|
|
232
|
+
mode: pay.order?.mode,
|
|
217
233
|
payParams: stablePayParams,
|
|
218
234
|
});
|
|
219
235
|
const chainOrderUsdLimits = useOrderUsdLimits({ trpc });
|
|
@@ -253,15 +269,14 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
253
269
|
// Read from ref instead of closure to get latest value and avoid stale state
|
|
254
270
|
const payParams = currPayParamsRef.current;
|
|
255
271
|
const order = pay.order;
|
|
256
|
-
// Narrow order to the specific shapes supported by buildCreatePaymentPayload.
|
|
257
|
-
// In error/idle states `pay.order` can be a plain RozoPayOrder or null,
|
|
258
|
-
// which is not assignable to the expected OrderLike type.
|
|
259
|
-
const orderForPayload = order && "org" in order
|
|
260
|
-
? order
|
|
261
|
-
: undefined;
|
|
262
272
|
// If payment already exists (payId mode or rozoPaymentId set), checkout instead of create.
|
|
273
|
+
// backend forbids `checkout` when rotating to a native source token
|
|
274
|
+
// (SOL/ETH/XLM) — "create a new order instead" — so route native sources to the
|
|
275
|
+
// create branch below instead of calling checkout.
|
|
263
276
|
const existingPayId = order?.externalId ?? rozoPaymentId ?? undefined;
|
|
264
|
-
|
|
277
|
+
const rotateToNative = walletOption != null && isNativeToken(walletOption.required.token.token);
|
|
278
|
+
const shouldCheckout = !!existingPayId && !rotateToNative;
|
|
279
|
+
if (!payParams || shouldCheckout) {
|
|
265
280
|
if (!existingPayId) {
|
|
266
281
|
throw new Error("No pay params provided");
|
|
267
282
|
}
|
|
@@ -270,11 +285,20 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
270
285
|
if (!paymentRes?.data) {
|
|
271
286
|
throw new Error("Failed to fetch payment");
|
|
272
287
|
}
|
|
288
|
+
// Use required.amount (base units, already priced by the backend)
|
|
289
|
+
// converted to a human-readable token amount — NOT required.usd,
|
|
290
|
+
// which only equals the token amount for 1:1-USD-pegged tokens
|
|
291
|
+
// (USDC/USDT). For native ETH/BNB/POL/SOL/XLM this would send the
|
|
292
|
+
// wrong amount to the backend (e.g. "1.00" instead of "0.0005").
|
|
293
|
+
// Some endpoints return required.amount as an already-human-readable
|
|
294
|
+
// decimal string instead of integer base units, so detect the shape
|
|
295
|
+
// first — BigInt() throws on decimal strings.
|
|
296
|
+
const sourceAmount = tokenBaseAmountToDecimalString(walletOption.required.amount, walletOption.required.token.decimals);
|
|
273
297
|
const checkoutRes = await checkoutPayment(existingPayId, buildCheckoutPayload(paymentRes.data, {
|
|
274
298
|
chainId: walletOption.required.token.chainId,
|
|
275
299
|
tokenSymbol: walletOption.required.token.symbol,
|
|
276
300
|
tokenAddress: walletOption.required.token.token,
|
|
277
|
-
amount:
|
|
301
|
+
amount: sourceAmount,
|
|
278
302
|
}));
|
|
279
303
|
if (!checkoutRes?.data) {
|
|
280
304
|
throw new Error("Failed to checkout payment");
|
|
@@ -293,6 +317,14 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
293
317
|
}
|
|
294
318
|
}
|
|
295
319
|
try {
|
|
320
|
+
// Narrow order to the specific shapes supported by buildCreatePaymentPayload.
|
|
321
|
+
// In error/idle states `pay.order` can be a plain RozoPayOrder or null,
|
|
322
|
+
// which lacks `destFinalCallTokenAmount`; passing it through would throw
|
|
323
|
+
// when we derive the destination amount. Fall back to the payParams-only
|
|
324
|
+
// branch (order undefined) in that case.
|
|
325
|
+
const orderForPayload = order && "org" in order
|
|
326
|
+
? order
|
|
327
|
+
: undefined;
|
|
296
328
|
const payload = buildCreatePaymentPayload({
|
|
297
329
|
payParams,
|
|
298
330
|
order: orderForPayload,
|
|
@@ -333,22 +365,34 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
333
365
|
if (!validatePaymentRequirements(walletOption, pay.paymentState)) {
|
|
334
366
|
throw new Error(`[PAY TOKEN] required token ${debugJson(required)} does not match fees token ${debugJson(fees)}`);
|
|
335
367
|
}
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
|
|
368
|
+
// Use required.amount (base units, already priced by the backend) —
|
|
369
|
+
// NOT required.usd, which only equals the token amount for 1:1-USD-pegged
|
|
370
|
+
// tokens (USDC/USDT). For native ETH/BNB/POL this would send the wrong
|
|
371
|
+
// amount (e.g. 1.00 ETH instead of ~0.0006 ETH for a $1 payment).
|
|
372
|
+
const paymentAmount = tokenAmountToBaseUnits(required.amount, required.token.decimals);
|
|
339
373
|
// Check if we need to create a new Rozo payment (cache this check)
|
|
340
374
|
const previousChainId = pay.order.preferredChainId ? Number(pay.order.preferredChainId) : null;
|
|
375
|
+
const previousTokenAddress = pay.order.preferredTokenAddress;
|
|
341
376
|
// If we have an existing payment and chain differs, MUST create new payment
|
|
342
377
|
// Also check if order has externalId (existing payment) and we're on different chain
|
|
343
378
|
const hasExistingPayment = pay.order.externalId != null;
|
|
379
|
+
// Check both chain AND token change - if user switches token on same chain,
|
|
380
|
+
// we still need to checkout to update source token info
|
|
381
|
+
const tokenChanged = previousTokenAddress != null &&
|
|
382
|
+
normalizeTokenAddress(Number(previousChainId), previousTokenAddress) !==
|
|
383
|
+
normalizeTokenAddress(required.token.chainId, required.token.token);
|
|
344
384
|
const needRozoPayment = (previousChainId !== null && previousChainId !== required.token.chainId) ||
|
|
385
|
+
tokenChanged ||
|
|
345
386
|
(hasExistingPayment &&
|
|
346
387
|
previousChainId === null &&
|
|
347
388
|
pay.order.destFinalCallTokenAmount?.token?.chainId !== required.token.chainId);
|
|
348
|
-
log?.(`[PAY TOKEN] Chain check:
|
|
389
|
+
log?.(`[PAY TOKEN] Chain/token check: previousChain=${previousChainId}, currentChain=${required.token.chainId}, previousToken=${previousTokenAddress}, currentToken=${required.token.token}, tokenChanged=${tokenChanged}, hasExistingPayment=${hasExistingPayment}, needRozoPayment=${needRozoPayment}`);
|
|
349
390
|
// Prepare transaction parameters early (before async operations)
|
|
350
|
-
|
|
351
|
-
|
|
391
|
+
// Case-insensitive native detection: `required.token.token` is checksummed
|
|
392
|
+
// (from the API) while viem's `ethAddress` is lowercase, so a direct `===`
|
|
393
|
+
// would misclassify native ETH as an ERC20 and take the wrong transfer path.
|
|
394
|
+
const isNative = isNativeToken(required.token.token);
|
|
395
|
+
const tokenAddress = isNative ? null : getAddress(required.token.token);
|
|
352
396
|
// Get hydrated order efficiently with parallel preparation
|
|
353
397
|
let hydratedOrder;
|
|
354
398
|
let paymentId;
|
|
@@ -445,7 +489,14 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
445
489
|
// Execute transaction with optimized error handling
|
|
446
490
|
const paymentTxHash = await (async () => {
|
|
447
491
|
try {
|
|
448
|
-
if (
|
|
492
|
+
if (required.token.chainId !== bscUSDT.chainId) {
|
|
493
|
+
await switchChainAsync({ chainId: required.token.chainId });
|
|
494
|
+
}
|
|
495
|
+
log?.(`[PAY ERC20] dataSuffix: ${resolvedDataSuffix ?? "(none)"}`);
|
|
496
|
+
// EIP-5792 path: only when wallet advertises dataSuffix capability (Base App / Coinbase Wallet).
|
|
497
|
+
const chainCapabilities = walletCapabilities?.[required.token.chainId];
|
|
498
|
+
const supportsDataSuffix = !capabilitiesPending && resolvedDataSuffix != null && !!chainCapabilities?.dataSuffix;
|
|
499
|
+
if (isNative) {
|
|
449
500
|
// dataSuffix intentionally omitted — appending data to bare ETH transfers
|
|
450
501
|
// changes wallet UI display; builder-code attribution targets contract calls.
|
|
451
502
|
return await sendTransactionAsync({
|
|
@@ -454,13 +505,6 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
454
505
|
});
|
|
455
506
|
}
|
|
456
507
|
else {
|
|
457
|
-
if (required.token.chainId !== bscUSDT.chainId) {
|
|
458
|
-
await switchChainAsync({ chainId: required.token.chainId });
|
|
459
|
-
}
|
|
460
|
-
log?.(`[PAY ERC20] dataSuffix: ${resolvedDataSuffix ?? "(none)"}`);
|
|
461
|
-
// EIP-5792 path: only when wallet advertises dataSuffix capability (Base App / Coinbase Wallet).
|
|
462
|
-
const chainCapabilities = walletCapabilities?.[required.token.chainId];
|
|
463
|
-
const supportsDataSuffix = !capabilitiesPending && resolvedDataSuffix != null && !!chainCapabilities?.dataSuffix;
|
|
464
508
|
if (supportsDataSuffix) {
|
|
465
509
|
if (!walletClient)
|
|
466
510
|
throw new Error("No walletClient available");
|
|
@@ -593,11 +637,9 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
593
637
|
throw new Error(`Invalid Solana destination address format: ${rozoPayment.destAddress}`);
|
|
594
638
|
}
|
|
595
639
|
// Set up token addresses
|
|
596
|
-
let mintAddress;
|
|
597
640
|
let fromKey;
|
|
598
641
|
let toKey;
|
|
599
642
|
try {
|
|
600
|
-
mintAddress = new PublicKey(walletPaymentOption.required.token.token);
|
|
601
643
|
fromKey = new PublicKey(payerPublicKey);
|
|
602
644
|
toKey = new PublicKey(rozoPayment.destAddress);
|
|
603
645
|
}
|
|
@@ -605,32 +647,77 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
605
647
|
throw new Error(`Invalid Solana address format: ${error.message}. ` +
|
|
606
648
|
`Destination address: ${rozoPayment.destAddress}`);
|
|
607
649
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
650
|
+
const isNativeSol = walletPaymentOption.required.token.token === solanaSOL.token;
|
|
651
|
+
if (isNativeSol) {
|
|
652
|
+
if (!rozoPayment.sourceAmount) {
|
|
653
|
+
throw new Error("Source amount is required for native SOL payment");
|
|
654
|
+
}
|
|
655
|
+
// Native SOL: plain lamport transfer, no token account / mint involved.
|
|
656
|
+
// Use required.amount (already computed by the backend in lamports,
|
|
657
|
+
// correctly priced from USD via the live SOL/USD rate) instead of
|
|
658
|
+
// re-deriving from required.usd, which would incorrectly treat SOL
|
|
659
|
+
// as pegged 1:1 to USD.
|
|
660
|
+
log("[PAY SOLANA] Transaction details (native SOL):", {
|
|
661
|
+
fromKey: fromKey.toString(),
|
|
662
|
+
toKey: toKey.toString(),
|
|
663
|
+
amount: walletPaymentOption.required.amount,
|
|
664
|
+
usd: walletPaymentOption.required.usd,
|
|
665
|
+
memo: rozoPayment.memo,
|
|
666
|
+
});
|
|
667
|
+
// Keep as bigint — SystemProgram.transfer accepts number | bigint.
|
|
668
|
+
// Converting to Number would lose precision for amounts > 2^53 base units.
|
|
669
|
+
const lamports = tokenAmountToBaseUnits(walletPaymentOption.required.amount, solanaSOL.decimals);
|
|
670
|
+
log("[PAY SOLANA] Transfer amount (lamports):", lamports.toString());
|
|
671
|
+
instructions.push(SystemProgram.transfer({
|
|
672
|
+
fromPubkey: fromKey,
|
|
673
|
+
toPubkey: toKey,
|
|
674
|
+
lamports: parseUnits(rozoPayment.sourceAmount, solanaSOL.decimals),
|
|
675
|
+
}));
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
let mintAddress;
|
|
679
|
+
try {
|
|
680
|
+
mintAddress = new PublicKey(walletPaymentOption.required.token.token);
|
|
681
|
+
}
|
|
682
|
+
catch (error) {
|
|
683
|
+
throw new Error(`Invalid Solana address format: ${error.message}. ` +
|
|
684
|
+
`Destination address: ${rozoPayment.destAddress}`);
|
|
685
|
+
}
|
|
686
|
+
log("[PAY SOLANA] Transaction details:", {
|
|
687
|
+
tokenMint: mintAddress.toString(),
|
|
688
|
+
fromKey: fromKey.toString(),
|
|
689
|
+
toKey: toKey.toString(),
|
|
690
|
+
amount: walletPaymentOption.required.amount,
|
|
691
|
+
usd: walletPaymentOption.required.usd,
|
|
692
|
+
memo: rozoPayment.memo,
|
|
693
|
+
});
|
|
694
|
+
// Get token accounts for sender and recipient
|
|
695
|
+
log("[PAY SOLANA] Deriving associated token accounts...");
|
|
696
|
+
const senderTokenAccount = await getAssociatedTokenAddress(mintAddress, fromKey);
|
|
697
|
+
const recipientTokenAccount = await getAssociatedTokenAddress(mintAddress, toKey);
|
|
698
|
+
log("[PAY SOLANA] Sender token account:", senderTokenAccount.toString());
|
|
699
|
+
log("[PAY SOLANA] Recipient token account:", recipientTokenAccount.toString());
|
|
700
|
+
// Check if recipient token account exists
|
|
701
|
+
log("[PAY SOLANA] Checking if recipient token account exists...");
|
|
702
|
+
const recipientTokenInfo = await connection.getAccountInfo(recipientTokenAccount);
|
|
703
|
+
// Create recipient token account if it doesn't exist
|
|
704
|
+
if (!recipientTokenInfo) {
|
|
705
|
+
log("[PAY SOLANA] Creating recipient token account...");
|
|
706
|
+
instructions.push(createAssociatedTokenAccountInstruction(payerPublicKey, recipientTokenAccount, toKey, mintAddress, TOKEN_PROGRAM_ID));
|
|
707
|
+
}
|
|
708
|
+
// Add transfer instruction
|
|
709
|
+
// Use required.amount (already computed by the backend in the
|
|
710
|
+
// token's base units, correctly priced from USD) instead of
|
|
711
|
+
// re-deriving from required.usd with a hardcoded 6-decimal
|
|
712
|
+
// assumption, which silently breaks for non-1:1-USD or
|
|
713
|
+
// differently-decimaled SPL tokens.
|
|
714
|
+
log("[PAY SOLANA] Adding transfer instruction...");
|
|
715
|
+
// Keep as bigint — createTransferCheckedInstruction accepts number | bigint.
|
|
716
|
+
// Converting to Number would lose precision for amounts > 2^53 base units.
|
|
717
|
+
const transferAmount = tokenAmountToBaseUnits(walletPaymentOption.required.amount, walletPaymentOption.required.token.decimals);
|
|
718
|
+
log("[PAY SOLANA] Transfer amount (base units):", transferAmount.toString());
|
|
719
|
+
instructions.push(createTransferCheckedInstruction(senderTokenAccount, mintAddress, recipientTokenAccount, fromKey, transferAmount, walletPaymentOption.required.token.decimals));
|
|
628
720
|
}
|
|
629
|
-
// Add transfer instruction
|
|
630
|
-
log("[PAY SOLANA] Adding transfer instruction...");
|
|
631
|
-
const transferAmount = parseFloat(walletPaymentOption.required.usd.toString()) * 1_000_000;
|
|
632
|
-
log("[PAY SOLANA] Transfer amount (with decimals):", transferAmount);
|
|
633
|
-
instructions.push(createTransferCheckedInstruction(senderTokenAccount, mintAddress, recipientTokenAccount, fromKey, transferAmount, rozoSolanaUSDC.decimals));
|
|
634
721
|
// Add memo if provided
|
|
635
722
|
if (rozoPayment.memo) {
|
|
636
723
|
log("[PAY SOLANA] Adding memo instruction:", rozoPayment.memo);
|
|
@@ -693,18 +780,29 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
693
780
|
await setStellarWallet(stellarConnector);
|
|
694
781
|
}
|
|
695
782
|
const sourceAccount = await stellarServer.loadAccount(stellarPublicKey);
|
|
696
|
-
let
|
|
697
|
-
if (walletPaymentOption.required.token.token ===
|
|
698
|
-
|
|
783
|
+
let destAsset;
|
|
784
|
+
if (walletPaymentOption.required.token.token === stellarXLM.token) {
|
|
785
|
+
destAsset = Asset.native();
|
|
786
|
+
}
|
|
787
|
+
else if (walletPaymentOption.required.token.token === rozoStellarUSDC.token) {
|
|
788
|
+
destAsset = new Asset(walletPaymentOption.required.token.symbol, rozoStellarUSDC.token.split(":")[1]);
|
|
699
789
|
}
|
|
700
790
|
else if (walletPaymentOption.required.token.token === rozoStellarEURC.token) {
|
|
701
|
-
|
|
791
|
+
destAsset = new Asset(walletPaymentOption.required.token.symbol, rozoStellarEURC.token.split(":")[1]);
|
|
702
792
|
}
|
|
703
793
|
else {
|
|
704
794
|
throw new Error("Unsupported token");
|
|
705
795
|
}
|
|
706
|
-
const destAsset = new Asset(walletPaymentOption.required.token.symbol, issuer);
|
|
707
796
|
const fee = String(await stellarServer.fetchBaseFee());
|
|
797
|
+
// Use required.amount (base units, already priced by the backend)
|
|
798
|
+
// converted to a human-readable token amount — NOT required.usd,
|
|
799
|
+
// which only equals the token amount for 1:1-USD-pegged tokens
|
|
800
|
+
// (USDC/EURC). For native XLM this would send the wrong amount
|
|
801
|
+
// (e.g. "1.00" XLM instead of the correct ~2.7 XLM for a $1 payment).
|
|
802
|
+
// Some endpoints return required.amount as an already-human-readable
|
|
803
|
+
// decimal string instead of integer base units, so detect the shape
|
|
804
|
+
// first — BigInt() throws on decimal strings.
|
|
805
|
+
const paymentAmount = tokenBaseAmountToDecimalString(walletPaymentOption.required.amount, walletPaymentOption.required.token.decimals);
|
|
708
806
|
// Build transaction
|
|
709
807
|
const transaction = new TransactionBuilder(sourceAccount, {
|
|
710
808
|
fee,
|
|
@@ -713,7 +811,7 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
713
811
|
.addOperation(Operation.payment({
|
|
714
812
|
destination: destinationAddress,
|
|
715
813
|
asset: destAsset,
|
|
716
|
-
amount:
|
|
814
|
+
amount: paymentAmount,
|
|
717
815
|
}))
|
|
718
816
|
.setTimeout(180);
|
|
719
817
|
if (rozoPayment.memo) {
|
|
@@ -788,17 +886,29 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
788
886
|
}
|
|
789
887
|
else {
|
|
790
888
|
log?.("[PAY DEPOSIT ADDRESS] hydrating order");
|
|
889
|
+
// hydrateOrder needs required.amount so buildCreatePaymentPayload
|
|
890
|
+
// can set preferredAmountUnits. For BOTH native (SOL/ETH/XLM) and
|
|
891
|
+
// 1:1-USD-pegged sources, the amount must come from the fee response
|
|
892
|
+
// (BE-computed source amount in source units, fee-inclusive) — NOT the
|
|
893
|
+
// destination USD value. Otherwise tokenBaseAmountToDecimalString
|
|
894
|
+
// formats the toUnits through the source decimals and the BE rejects
|
|
895
|
+
// the underflowing pay-in (e.g. "10" with 6 decimals → "0.00001").
|
|
896
|
+
const isNativeSource = isNativeToken(option.token.token);
|
|
897
|
+
const sourceAmountUnits = String(fees?.source?.amount ??
|
|
898
|
+
(isNativeSource ? "" : (pay.order?.destFinalCallTokenAmount?.usd ?? "0")));
|
|
899
|
+
if (isNativeSource && sourceAmountUnits === "") {
|
|
900
|
+
throw new Error("Fee source amount required for native token deposit");
|
|
901
|
+
}
|
|
902
|
+
const actualFeeType = payParams?.feeType ?? FeeType.ExactIn;
|
|
791
903
|
const result = await pay.hydrateOrder(undefined, {
|
|
792
904
|
required: {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
chainId: option.token.chainId,
|
|
796
|
-
},
|
|
905
|
+
amount: sourceAmountUnits,
|
|
906
|
+
token: option.token,
|
|
797
907
|
},
|
|
798
908
|
fees: {
|
|
799
909
|
usd: fees?.source?.fee != null ? parseFloat(fees.source.fee) : 0,
|
|
800
910
|
},
|
|
801
|
-
});
|
|
911
|
+
}, actualFeeType);
|
|
802
912
|
order = result.order;
|
|
803
913
|
}
|
|
804
914
|
log?.(`[PAY DEPOSIT ADDRESS] hydrated order ${order.id} for ${order.usdValue} USD, checking out with deposit address: ${option}`);
|
|
@@ -815,12 +925,23 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
815
925
|
if (!preferredToken) {
|
|
816
926
|
throw new Error("Preferred token not found");
|
|
817
927
|
}
|
|
928
|
+
// Amount the user must send, in source-token units. Prefer the backend's
|
|
929
|
+
// source.amount (surfaced via metadata by formatPaymentResponseToHydratedOrder)
|
|
930
|
+
// over usdValue: for native sources (SOL/ETH/XLM) the source amount differs
|
|
931
|
+
// from the USD/destination value, so usdValue would show e.g. "1.3 SOL"
|
|
932
|
+
// instead of the correct ~0.0169 SOL. For 1:1-USD sources they coincide.
|
|
933
|
+
const isNativeDepositSource = isNativeToken(option.token.token);
|
|
934
|
+
const metaSourceAmount = order.metadata?.sourceAmountUnits;
|
|
935
|
+
if (isNativeDepositSource && metaSourceAmount == null) {
|
|
936
|
+
throw new Error("sourceAmountUnits missing on hydrated order for native deposit source");
|
|
937
|
+
}
|
|
938
|
+
const sourceAmountUnits = metaSourceAmount != null ? String(metaSourceAmount) : String(order.usdValue);
|
|
818
939
|
let uriDeeplink = null;
|
|
819
940
|
// Use Solana deep link if it's a Solana chain.
|
|
820
941
|
// Solana pay-in no longer requires a memo.
|
|
821
942
|
if ([solana.chainId, rozoSolana.chainId].includes(preferredToken.chainId)) {
|
|
822
943
|
uriDeeplink = generateSolanaDeepLink({
|
|
823
|
-
amountUnits:
|
|
944
|
+
amountUnits: sourceAmountUnits,
|
|
824
945
|
recipientAddress: order.intentAddr,
|
|
825
946
|
tokenAddress: preferredToken.token,
|
|
826
947
|
});
|
|
@@ -832,7 +953,7 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
832
953
|
// Otherwise use EVM deep link
|
|
833
954
|
else {
|
|
834
955
|
uriDeeplink = generateEVMDeepLink({
|
|
835
|
-
amountUnits: parseUnits(
|
|
956
|
+
amountUnits: parseUnits(sourceAmountUnits, preferredToken.decimals).toString(),
|
|
836
957
|
chainId: preferredToken.chainId,
|
|
837
958
|
recipientAddress: order.intentAddr,
|
|
838
959
|
tokenAddress: preferredToken.token,
|
|
@@ -840,7 +961,7 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
840
961
|
}
|
|
841
962
|
return {
|
|
842
963
|
address: order.intentAddr,
|
|
843
|
-
amount:
|
|
964
|
+
amount: sourceAmountUnits,
|
|
844
965
|
suffix: `${option.token.symbol} ${chain.name}`,
|
|
845
966
|
uri: uriDeeplink ?? "",
|
|
846
967
|
expirationS: Math.floor(Date.now() / 1000) + 300,
|
|
@@ -855,7 +976,7 @@ function usePaymentState({ trpc, lockPayParams, setRoute, log, redirectReturnUrl
|
|
|
855
976
|
order: pay.order,
|
|
856
977
|
message,
|
|
857
978
|
});
|
|
858
|
-
return
|
|
979
|
+
return undefined;
|
|
859
980
|
}
|
|
860
981
|
finally {
|
|
861
982
|
// Remove from processing set when done (allow retries after completion/failure)
|