Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 162 additions & 2 deletions examples/testapp/src/pages/prolink-playground/index.page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { decodeProlink, encodeProlink } from '@base-org/account';
import { createProlinkUrl, decodeProlink, encodeProlink } from '@base-org/account';
import {
Accordion,
AccordionButton,
Expand Down Expand Up @@ -107,13 +107,17 @@ export default function ProlinkPlayground() {
const [encodedPayload, setEncodedPayload] = useState('');
const [error, setError] = useState<string | null>(null);
const [decodedResult, setDecodedResult] = useState<unknown>(null);
const [urlWithProlink, setUrlWithProlink] = useState('');

// Decode section
const [decodeInput, setDecodeInput] = useState('');
const [decodeLoading, setDecodeLoading] = useState(false);
const [decodeError, setDecodeError] = useState<string | null>(null);
const [decodeResult, setDecodeResult] = useState<unknown>(null);

// Link with Prolink section
const [urlForLinkWithProlink, setUrlForLinkWithProlink] = useState('https://base.app/base-pay');

const generateProlink = async () => {
setLoading(true);
setError(null);
Expand Down Expand Up @@ -213,6 +217,10 @@ export default function ProlinkPlayground() {
const payload = await encodeProlink(request);
setEncodedPayload(payload);

// Generate link with prolink
const urlWithProlink = createProlinkUrl(payload, urlForLinkWithProlink);
setUrlWithProlink(urlWithProlink);

// Decode to verify
const decoded = await decodeProlink(payload);
setDecodedResult(decoded);
Expand All @@ -237,6 +245,28 @@ export default function ProlinkPlayground() {
}
};

const generateLinkWithProlink = () => {
setLoading(true);
setError(null);
setUrlWithProlink('');

try {
const urlWithProlink = createProlinkUrl(encodedPayload, urlForLinkWithProlink);
setUrlWithProlink(urlWithProlink);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
setError(errorMessage);
toast({
title: 'Error generating link with prolink',
description: errorMessage,
status: 'error',
duration: 5000,
});
} finally {
setLoading(false);
}
};

const copyToClipboard = () => {
navigator.clipboard.writeText(encodedPayload);
toast({
Expand All @@ -247,6 +277,16 @@ export default function ProlinkPlayground() {
});
};

const copyLinkWithProlinkToClipboard = () => {
navigator.clipboard.writeText(urlWithProlink);
toast({
title: 'Copied!',
description: 'Link copied to clipboard',
status: 'success',
duration: 2000,
});
};

const decodePayload = async () => {
setDecodeLoading(true);
setDecodeError(null);
Expand Down Expand Up @@ -299,6 +339,7 @@ export default function ProlinkPlayground() {
<TabList>
<Tab>Encode</Tab>
<Tab>Decode</Tab>
<Tab>Link with Prolink</Tab>
</TabList>

<TabPanels>
Expand Down Expand Up @@ -616,6 +657,7 @@ export default function ProlinkPlayground() {
<TabList>
<Tab>Encoded Payload</Tab>
<Tab>Decoded Result</Tab>
<Tab>Link with Prolink</Tab>
</TabList>

<TabPanels>
Expand Down Expand Up @@ -645,6 +687,27 @@ export default function ProlinkPlayground() {
</Code>
</Box>
</TabPanel>

{/* Link with Prolink Tab */}
<TabPanel>
<VStack spacing={4} align="stretch">
<HStack>
<Box p={4} bg={codeBgColor} borderRadius="md" overflowX="auto">
<Code display="block" whiteSpace="pre-wrap" wordBreak="break-all">
{urlWithProlink}
</Code>
</Box>
<Button size="sm" onClick={copyLinkWithProlinkToClipboard}>
Copy Link
</Button>
</HStack>
<Text fontSize="sm" color="gray.600">
This link with prolink can be opened in the Base App to execute the
transaction. See the "Link with Prolink" tab for customization
options.
</Text>
</VStack>
</TabPanel>
</TabPanels>
</Tabs>
)}
Expand Down Expand Up @@ -720,7 +783,15 @@ export default function ProlinkPlayground() {
<>
<HStack>
<Text fontWeight="bold">Method:</Text>
<Text>{(decodeResult as { method: string }).method}</Text>
<Text>
{
(
decodeResult as {
method: string;
}
).method
}
</Text>
<Button size="sm" onClick={copyDecodedToClipboard}>
Copy JSON
</Button>
Expand All @@ -736,6 +807,95 @@ export default function ProlinkPlayground() {
</Box>
)}
</TabPanel>

{/* Link with Prolink Tab */}
<TabPanel px={0}>
<Box borderWidth="1px" borderRadius="lg" p={6} bg={bgColor} borderColor={borderColor}>
<VStack spacing={6} align="stretch">
<FormControl>
<FormLabel>Prolink Payload</FormLabel>
<Input
type="text"
value={encodedPayload}
onChange={(e) => setEncodedPayload(e.target.value)}
placeholder="Paste encoded prolink payload here..."
/>
<Text fontSize="sm" color="gray.600">
See the "Encode" tab to generate a prolink payload.
</Text>
</FormControl>

{/* URL for the link with the prolink */}
<FormControl>
<FormLabel>URL</FormLabel>
<Input
type="url"
value={urlForLinkWithProlink}
onChange={(e) => setUrlForLinkWithProlink(e.target.value)}
placeholder="https://base.app/base-pay"
/>
</FormControl>

<Divider />

<Button
colorScheme="blue"
size="lg"
onClick={generateLinkWithProlink}
isLoading={loading}
loadingText="Generating..."
>
Generate Link
</Button>
</VStack>
</Box>

{/* Results */}
{(urlWithProlink || error) && (
<Box
borderWidth="1px"
borderRadius="lg"
p={6}
mt={6}
bg={bgColor}
borderColor={borderColor}
>
<VStack spacing={6} align="stretch">
<Heading size="md">Results</Heading>

{error && (
<Box
p={4}
bg="red.50"
borderRadius="md"
borderColor="red.200"
borderWidth="1px"
>
<Text color="red.700" fontWeight="bold">
Error:
</Text>
<Text color="red.600" mt={2}>
{error}
</Text>
</Box>
)}

{urlWithProlink && (
<HStack>
<Box p={4} bg={codeBgColor} borderRadius="md" overflowX="auto">
<Code display="block" whiteSpace="pre-wrap" wordBreak="break-all">
{urlWithProlink}
</Code>
</Box>
<Button size="sm" onClick={copyLinkWithProlinkToClipboard}>
Copy Link
</Button>
</HStack>
)}
</VStack>
</Box>
)}
</TabPanel>
</TabPanels>
</Tabs>
</VStack>
Expand Down
26 changes: 20 additions & 6 deletions packages/account-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
// Copyright (c) 2018-2025 Coinbase, Inc. <https://www.coinbase.com/>
export type { AppMetadata, Preference, ProviderInterface } from ':core/provider/interface.js';
export type {
AppMetadata,
Preference,
ProviderInterface,
} from ':core/provider/interface.js';

export { createBaseAccountSDK } from './interface/builder/core/createBaseAccountSDK.js';

export { getCryptoKeyAccount, removeCryptoKey } from './kms/crypto-key/index.js';
export {
getCryptoKeyAccount,
removeCryptoKey,
} from './kms/crypto-key/index.js';

export { PACKAGE_VERSION as VERSION } from './core/constants.js';

export {
CHAIN_IDS,
TOKENS,
base,
CHAIN_IDS,
getPaymentStatus,
getSubscriptionStatus,
pay,
prepareCharge,
subscribe,
TOKENS,
} from './interface/payment/index.js';
export type {
ChargeOptions,
Expand All @@ -40,5 +47,12 @@ export type {
SubscriptionStatusOptions,
} from './interface/payment/index.js';

export { decodeProlink, encodeProlink } from './interface/public-utilities/prolink/index.js';
export type { ProlinkDecoded, ProlinkRequest } from './interface/public-utilities/prolink/index.js';
export {
createProlinkUrl,
decodeProlink,
encodeProlink,
} from './interface/public-utilities/prolink/index.js';
export type {
ProlinkDecoded,
ProlinkRequest,
} from './interface/public-utilities/prolink/index.js';
Loading