Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Embedded SDK #623

Draft
wants to merge 33 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
eb66523
feat: init wander-embedded-sdk
kranthicodes Jan 22, 2025
e0c6738
feat: extend and modularize sdk
kranthicodes Jan 23, 2025
f679e6f
Add scaffolding for the Embedded SDK and API.
Danziger Jan 23, 2025
d9a794e
Improve logic to send resize and close messages to the parent window.
Danziger Jan 24, 2025
8164550
Fix useAuthRequestsLocation() location.
Danziger Jan 24, 2025
4cde537
Merge branch 'development' into feature/embedded-sdk-and-api-scaffolding
Danziger Jan 24, 2025
572c7bc
refactor: remove custom button ref option from sdk
kranthicodes Jan 24, 2025
216d590
feat: add new types to sdk made in scaffolding pr by dani
kranthicodes Jan 24, 2025
8d13dae
feat: use setupWalletSdk from core src
kranthicodes Jan 25, 2025
cf4260b
refactor: use proxy pattern with wallet api injection
kranthicodes Jan 26, 2025
87642c7
Fix message id validation.
Danziger Jan 26, 2025
299b3fc
refactor: update button styles and refactor mounting
kranthicodes Jan 26, 2025
d499ef5
refactor: conditionally render button when buttonStyles is not none
kranthicodes Jan 26, 2025
e6d6fd7
Merge branch 'development' into feature/embedded-sdk-and-api-scaffolding
Danziger Jan 27, 2025
fcb0d6f
refactor: dont check if mod exists in setupWalletSDK
kranthicodes Jan 27, 2025
15e20c6
Merge branch 'development' into feature/embedded-sdk-and-api-scaffolding
Danziger Jan 27, 2025
f89feb9
refactor: check if mod exists before executing
kranthicodes Jan 27, 2025
895f0f5
chore: lite docs for sdk
kranthicodes Jan 27, 2025
c450ff8
refactor: remove connect disconnect outgoing events
kranthicodes Jan 27, 2025
8bd069c
refactor: rename sdk
kranthicodes Jan 29, 2025
412d0b1
refactor: use new entry path with vite config
kranthicodes Jan 29, 2025
008a711
refactor: update setupWalletSDK to initialize proxy with walletAPI
kranthicodes Jan 29, 2025
6cadd88
Merge pull request #631 from kranthicodes/kranthi/embedded-sdk
Danziger Feb 7, 2025
abc989b
Merge develop.
Danziger Feb 7, 2025
be18a3e
Merge develop.
Danziger Feb 7, 2025
141870c
Rename ArConnect to Wander (for Embedded SDK).
Danziger Feb 7, 2025
ebf7f8a
WIP additional options / TS support for Embedded SDK.
Danziger Feb 7, 2025
8df12f5
Restructure message types, add missing options, expose CSS variables …
Danziger Feb 10, 2025
e25222f
Add some additional styling, transitions and make some progress towar…
Danziger Feb 11, 2025
79464d7
Keep working on the UI.
Danziger Feb 12, 2025
f703a8d
Clean up unused options and finish styling for all 4 iframe variants.
Danziger Feb 13, 2025
9078c78
Implement click outisde to close and fix some issues with default opt…
Danziger Feb 13, 2025
a651d2d
Add some comments regarding theming.
Danziger Feb 13, 2025
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
11 changes: 4 additions & 7 deletions shim.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,10 @@ declare module "@arconnect/webext-bridge" {

// EMBEDDED:

embedded_open: any;
embedded_close: any;
embedded_resize: any;
// TODO: Maybe yes, maybe not (we should not drift too far away from the BE wallet API)
// embedded_auth: any;
// embedded_balance: any;
// embedded_info: any;
embedded_auth: EmbeddedAuthMessageData;
embedded_balance: EmbeddedBalanceMessageData;
embedded_resize: EmbeddedResizeMessageData;
7i7o marked this conversation as resolved.
Show resolved Hide resolved
embedded_close: void;

// OTHER:

Expand Down
4 changes: 1 addition & 3 deletions src/components/dev/figma-screen/figma-screen.module.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
.root {
position: relative;
margin: 16px auto;
min-height: calc(100dvh - 32px);
margin: 0 auto;
border-radius: 4px;
border: 2px solid rgba(255, 255, 255, 0.25);
font-family: monospace;
}

Expand Down
88 changes: 85 additions & 3 deletions src/components/page/page.component.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,82 @@
import { type Variants, motion } from "framer-motion";
import type { PropsWithChildren } from "react";
import { useEffect, useRef, useState, type PropsWithChildren } from "react";
import styled from "styled-components";
import { postEmbeddedMessage } from "~utils/embedded/utils/messages/embedded-messages.utils";
import {
locationToRouteType,
routeTypeToPreferredLayout
} from "~utils/embedded/utils/routes/embedded-routes.utils";
import type { ArConnectRoutePath } from "~wallets/router/router.types";

export interface PageProps extends PropsWithChildren {}

export function Page({ children }: PageProps) {
const mainRef = useRef<HTMLDivElement>(null);

const opacityAnimation: Variants = {
initial: { opacity: 0 },
enter: { opacity: 1 },
exit: { opacity: 0, y: 0, transition: { duration: 0.2 } }
};

const [height, setHeight] = useState(0);

useEffect(() => {
const mainElement = mainRef.current;

if (!mainElement || import.meta.env?.VITE_IS_EMBEDDED_APP !== "1") return;

const resizeObserver = new ResizeObserver((entries) => {
const size = entries?.[0]?.contentBoxSize?.[0] || {
inlineSize: 0,
blockSize: 0
};
const width = Math.ceil(size.inlineSize);
const height = Math.ceil(size.blockSize);

if (width > 0 && height > 0) {
// We get the path manually to avoid causing duplicate re-renders of the `Page` component if using the
// `useLocation` hook:
const path = location.hash.replace("#", "") as ArConnectRoutePath;
const routeType = locationToRouteType(path);
const preferredLayout = routeTypeToPreferredLayout(routeType);

postEmbeddedMessage({
type: "embedded_resize",
data: {
routeType,
preferredLayout,
width,
height
}
});

// For debugging only:;
setHeight(height);
}
});

resizeObserver.observe(mainElement);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be notifying the parent about any change in size due to images loading, elements appearing/disappearing, etc.


return () => {
resizeObserver.disconnect();
};
}, []);

return (
<Main
ref={mainRef}
initial="initial"
animate="enter"
exit="exit"
variants={opacityAnimation}
data-test-id="Page"
>
{process.env.NODE_ENV === "development" &&
import.meta.env?.VITE_IS_EMBEDDED_APP === "1" ? (
<DivLine style={{ top: `${height}px` }} data-height={`${height}px`} />
) : null}

{children}
</Main>
);
Expand All @@ -28,6 +86,30 @@ const Main = styled(motion.main)`
position: relative;
top: 0;
width: 100%;
min-height: 100vh;
max-height: max-content;
min-height: ${import.meta.env?.VITE_IS_EMBEDDED_APP === "1"
? "none"
: "100vh"};
max-height: ${import.meta.env?.VITE_IS_EMBEDDED_APP === "1"
? "none"
: "max-content"};
`;

const DivLine = styled(motion.div)`
position: absolute;
top: 0;
left: 0;
width: 100%;
border-bottom: 2px dashed red;

&::before {
content: attr(data-height);
position: absolute;
top: 2px;
left: 16px;
transform: translate(0, -50%);
padding: 4px 8px;
background: red;
font: bold 11px monospace;
border-radius: 16px;
}
`;
1 change: 1 addition & 0 deletions src/iframe/iframe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
useEmbeddedLocation
} from "~wallets/router/iframe/iframe-router.hook";
import { EmbeddedProvider } from "~utils/embedded/embedded.provider";
import { BodyScroller } from "~wallets/router/router.utils";

export function ArConnectEmbeddedApp() {
useEffect(() => {
Expand Down
16 changes: 12 additions & 4 deletions src/utils/auth/auth.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ import type { IBridgeMessage } from "@arconnect/webext-bridge";
import { log, LOG_GROUP } from "~utils/log/log.utils";
import { isError } from "~utils/error/error.utils";
import type {
ArConnectRoutePath,
RouteOverride,
RouteRedirect
} from "~wallets/router/router.types";
import { postEmbeddedMessage } from "~utils/embedded/utils/messages/embedded-messages.utils";

interface AuthRequestsContextState {
authRequests: AuthRequest[];
Expand Down Expand Up @@ -88,13 +90,19 @@ export function AuthRequestsProvider({
);

const closeAuthPopup = useCallback((delay: number = 0) => {
// TODO: In the embedded wallet, maybe we need to store (but not show) unlock requests so that this doesn't
// clear automatically.

function closeOrClear() {
if (import.meta.env?.VITE_IS_EMBEDDED_APP === "1") {
// TODO: This might cause an infinite loop in the embedded wallet:
setAuthRequestContextState(AUTH_REQUESTS_CONTEXT_INITIAL_STATE);
// setAuthRequestContextState(AUTH_REQUESTS_CONTEXT_INITIAL_STATE);

// TODO: We could improve this to detect if we opened the wallet to show an AuthRequest, or if it was already
// open. In the former case, when all AuthRequests are handled, we close it. In the latter, we just clear the
// AuthRequests from the state but leave it open.

postEmbeddedMessage({
type: "embedded_close",
data: null
});
} else {
window.top.close();
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/embedded/embedded.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import type {
TempWalletPromise,
RecoveryJSON
} from "~utils/embedded/embedded.types";
import { isTempWalletPromiseExpired } from "~utils/embedded/embedded.utils";
import { log, LOG_GROUP } from "~utils/log/log.utils";
import { isTempWalletPromiseExpired } from "~utils/embedded/utils/wallets/embedded-wallets.utils";

const EMBEDDED_CONTEXT_INITIAL_STATE: EmbeddedContextState = {
authStatus: "unknown",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// TODO: Please, add TS Docs. Not all interfaces here are needed.

import { setAuthorization } from "~utils/embedded/sdk/utils/axios-client/sdk-axios-client.utils";
import { postEmbeddedMessage } from "~utils/embedded/utils/messages/embedded-messages.utils";

export interface AuthenticateParams {}

export interface AuthenticateReturn {}

export function authenticate() {
// TODO: Authenticate...

const authToken = "";
const userDetails = {};

setAuthorization(authToken);

postEmbeddedMessage({
type: "embedded_auth",
data: {
userDetails
}
});
}

export interface RefreshSessionParams {}

export interface RefreshSessionReturn {}

export function refreshSession() {
// TODO: Refresh session...

const authToken = "";
const userDetails = {};

setAuthorization(authToken);

postEmbeddedMessage({
type: "embedded_auth",
data: {
userDetails
}
});
}

export interface SignOutParams {}

export interface SignOutReturn {}

export function signOut() {
// TODO: Sign out...

setAuthorization(null);

postEmbeddedMessage({
type: "embedded_auth",
data: {
userDetails: null
}
});
}

export interface FakeAuthenticateParams {}

export interface FakeAuthenticateReturn {}

export function fakeAuthenticate() {
// TODO: Fake authenticate...

const authToken = "";
const userDetails = {};

setAuthorization(authToken);

postEmbeddedMessage({
type: "embedded_auth",
data: {
userDetails
}
});
}

export interface FakeRefreshSessionParams {}

export interface FakeRefreshSessionReturn {}

export function fakeRefreshSession() {
// TODO: Fake refresh session...

const authToken = "";
const userDetails = {};

setAuthorization(authToken);

postEmbeddedMessage({
type: "embedded_auth",
data: {
userDetails
}
});
}
13 changes: 13 additions & 0 deletions src/utils/embedded/sdk/domains/backup/sdk-backup.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// TODO: Please, add TS Docs. Not all interfaces here are needed.

export interface RegisterRecoveryShareParams {}

export interface RegisterRecoveryShareReturn {}

export function registerRecoveryShare() {}

export interface RegisterWalletExportParams {}

export interface RegisterWalletExportReturn {}

export function registerWalletExport() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// TODO: Please, add TS Docs. Not all interfaces here are needed.

export interface GenerateWalletRecoveryChallengeParams {}

export interface GenerateWalletRecoveryChallengeReturn {}

export function generateWalletRecoveryChallenge() {}

export interface FetchRecoverableAccountsParams {}

export interface FetchRecoverableAccountsReturn {}

export function fetchRecoverableAccounts() {}

export interface GenerateAccountRecoveryChallengeParams {}

export interface GenerateAccountRecoveryChallengeReturn {}

export function generateAccountRecoveryChallenge() {}

export interface RecoverAccountParams {}

export interface RecoverAccountReturn {}

export function recoverAccount() {}
19 changes: 19 additions & 0 deletions src/utils/embedded/sdk/domains/shares/sdk-shares.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// TODO: Please, add TS Docs. Not all interfaces here are needed.

export interface GenerateAuthShareChallengeParams {}

export interface GenerateAuthShareChallengeReturn {}

export function generateAuthShareChallenge() {}

export interface ActivateWalletParams {}

export interface ActivateWalletReturn {}

export function activateWallet() {}

export interface RotateAuthShareParams {}

export interface RotateAuthShareReturn {}

export function rotateAuthShare() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// TODO: Please, add TS Docs. Not all interfaces here are needed.

export interface GenerateShareRecoveryChallengeParams {}

export interface GenerateShareRecoveryChallengeReturn {}

export function generateShareRecoveryChallenge() {}

export interface RecoverWalletParams {}

export interface RecoverWalletReturn {}

export function recoverWallet() {}
Loading