diff --git a/examples/with-sdk-js/src/app/page.tsx b/examples/with-sdk-js/src/app/page.tsx index 7376e5e6c..302744d2b 100644 --- a/examples/with-sdk-js/src/app/page.tsx +++ b/examples/with-sdk-js/src/app/page.tsx @@ -1674,6 +1674,34 @@ export default function AuthPage() { )} + {authState === AuthState.Authenticated && ( +
+

On Ramp

+
+ +
+
+ )}

Otp Methods

diff --git a/packages/react-wallet-kit/src/providers/client/Provider.tsx b/packages/react-wallet-kit/src/providers/client/Provider.tsx index a58f98e64..2d6d0c988 100644 --- a/packages/react-wallet-kit/src/providers/client/Provider.tsx +++ b/packages/react-wallet-kit/src/providers/client/Provider.tsx @@ -151,6 +151,7 @@ import type { HandleAddPasskeyParams, HandleAddPhoneNumberParams, HandleAppleOauthParams, + HandleCoinbaseOnRampParams, HandleConnectExternalWalletParams, HandleDiscordOauthParams, HandleExportPrivateKeyParams, @@ -5129,6 +5130,47 @@ export const ClientProvider: React.FC = ({ [pushPage, masterConfig, client, session, user], ); + const handleCoinbaseOnRamp = useCallback( + async (params: HandleCoinbaseOnRampParams): Promise => { + const { successPageDuration = 2000 } = params || {}; + const organizationId = params?.organizationId || session?.organizationId; + if (!organizationId) { + throw new TurnkeyError( + "A session or passed in organization ID is required.", + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + + if (!client) + throw new TurnkeyError( + "Client is not initialized.", + TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED, + ); + + const res = await client.httpClient.initFiatOnRamp(params); + const { onRampUrl } = res; + + // Popup flow (can abstract this into a utility) + const width = popupWidth; + const height = popupHeight; + const left = window.screenX + (window.innerWidth - width) / 2; + const top = window.screenY + (window.innerHeight - height) / 2; + + const popupWindow = window.open( + "about:blank", + "_blank", + `width=${width},height=${height},top=${top},left=${left},scrollbars=yes,resizable=yes`, + ); + + if (!popupWindow) { + throw new Error("Failed to open Coinbase payment window."); + } + + popupWindow.location.href = onRampUrl.toString(); + }, + [masterConfig, client, session, user], + ); + useEffect(() => { if (proxyAuthConfigRef.current) return; @@ -5346,6 +5388,7 @@ export const ClientProvider: React.FC = ({ handleConnectExternalWallet, handleRemoveUserEmail, handleRemoveUserPhoneNumber, + handleCoinbaseOnRamp, }} > {children} diff --git a/packages/react-wallet-kit/src/providers/client/Types.tsx b/packages/react-wallet-kit/src/providers/client/Types.tsx index d09e89999..cc56321b2 100644 --- a/packages/react-wallet-kit/src/providers/client/Types.tsx +++ b/packages/react-wallet-kit/src/providers/client/Types.tsx @@ -24,6 +24,7 @@ import type { HandleAddPasskeyParams, HandleAddPhoneNumberParams, HandleAppleOauthParams, + HandleCoinbaseOnRampParams, HandleConnectExternalWalletParams, HandleDiscordOauthParams, HandleExportPrivateKeyParams, @@ -334,7 +335,7 @@ export type ClientContextType = Override< * @return A void promise. */ handleExportPrivateKey: ( - params: HandleExportPrivateKeyParams, + params: HandleExportPrivateKeyParams ) => Promise; /** @@ -361,7 +362,7 @@ export type ClientContextType = Override< */ handleExportWalletAccount: ( - params: HandleExportWalletAccountParams, + params: HandleExportWalletAccountParams ) => Promise; /** @@ -406,7 +407,7 @@ export type ClientContextType = Override< * @returns A promise that resolves to the new private key's ID. */ handleImportPrivateKey: ( - params?: HandleImportPrivateKeyParams, + params?: HandleImportPrivateKeyParams ) => Promise; /** @@ -431,7 +432,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, no active session is found, or if there is an error updating the user name. */ handleUpdateUserEmail: ( - params?: HandleUpdateUserEmailParams, + params?: HandleUpdateUserEmailParams ) => Promise; /** @@ -458,7 +459,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, no active session is found, SMS OTP is not enabled, or if there is an error updating the phone number. */ handleUpdateUserPhoneNumber: ( - params?: HandleUpdateUserPhoneNumberParams, + params?: HandleUpdateUserPhoneNumberParams ) => Promise; /** * Handles the update user email flow. @@ -483,7 +484,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, no active session is found, or if there is an error updating the email. */ handleUpdateUserName: ( - params?: HandleUpdateUserNameParams, + params?: HandleUpdateUserNameParams ) => Promise; /** * Handles the add user email flow. @@ -533,7 +534,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, no active session is found, or if there is an error adding the phone number. */ handleAddPhoneNumber: ( - params?: HandleAddPhoneNumberParams, + params?: HandleAddPhoneNumberParams ) => Promise; /** @@ -557,7 +558,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, no active session is found, or if there is an error adding the provider. */ handleAddOauthProvider: ( - params: HandleAddOauthProviderParams, + params: HandleAddOauthProviderParams ) => Promise; /** @@ -583,7 +584,7 @@ export type ClientContextType = Override< * if there is an error removing the provider, or if the user cancels the action. */ handleRemoveOauthProvider: ( - params: HandleRemoveOauthProviderParams, + params: HandleRemoveOauthProviderParams ) => Promise; /** @@ -631,7 +632,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, no active session is found, or if there is an error removing the passkey. */ handleRemovePasskey: ( - params: HandleRemovePasskeyParams, + params: HandleRemovePasskeyParams ) => Promise; /** @@ -656,7 +657,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized, if there is an error during the signing process, or if the user cancels the action. */ handleSignMessage: ( - params: HandleSignMessageParams, + params: HandleSignMessageParams ) => Promise; /** @@ -677,7 +678,7 @@ export type ClientContextType = Override< * @throws {TurnkeyError} If the client is not initialized or if the user cancels the action. */ handleConnectExternalWallet: ( - params?: HandleConnectExternalWalletParams, + params?: HandleConnectExternalWalletParams ) => Promise<{ type: "connect" | "disconnect"; account: WalletAccount; @@ -700,7 +701,7 @@ export type ClientContextType = Override< * if the user cancels the action, or if there is an error during the removal process. */ handleRemoveUserEmail: ( - params?: HandleRemoveUserEmailParams, + params?: HandleRemoveUserEmailParams ) => Promise; /** @@ -720,12 +721,15 @@ export type ClientContextType = Override< * if the user cancels the action, or if there is an error during the removal process. */ handleRemoveUserPhoneNumber: ( - params?: HandleRemoveUserPhoneNumberParams, + params?: HandleRemoveUserPhoneNumberParams ) => Promise; + + // TODO (Amir): Complete JSDoc + handleCoinbaseOnRamp: (params: HandleCoinbaseOnRampParams) => Promise; } >; /** @internal */ export const ClientContext = createContext( - undefined, + undefined ); diff --git a/packages/react-wallet-kit/src/types/method-types.ts b/packages/react-wallet-kit/src/types/method-types.ts index 4c8761c28..c856bcaf5 100644 --- a/packages/react-wallet-kit/src/types/method-types.ts +++ b/packages/react-wallet-kit/src/types/method-types.ts @@ -3,6 +3,11 @@ import type { StamperType, v1AddressFormat, v1Curve, + v1FiatOnRampBlockchainNetwork, + v1FiatOnRampCryptoCurrency, + v1FiatOnRampCurrency, + v1FiatOnRampPaymentMethod, + v1FiatOnRampProvider, v1HashFunction, v1PayloadEncoding, v1WalletAccountParams, @@ -227,3 +232,20 @@ export type HandleRemoveUserPhoneNumberParams = { stampWith?: StamperType | undefined; organizationId?: string; }; + +export type HandleCoinbaseOnRampParams = { + onrampProvider: v1FiatOnRampProvider; + walletAddress: string; + network: v1FiatOnRampBlockchainNetwork; + cryptoCurrencyCode: v1FiatOnRampCryptoCurrency; + fiatCurrencyCode?: v1FiatOnRampCurrency; + fiatCurrencyAmount?: string; + paymentMethod?: v1FiatOnRampPaymentMethod; + countryCode?: string; + countrySubdivisionCode?: string; + sandboxMode?: boolean; + urlForSignature?: string; + successPageDuration?: number | undefined; + stampWith?: StamperType | undefined; + organizationId?: string; +};