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

pass container element to iframe stamper #183

Merged
merged 5 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion examples/email-auth/src/components/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function Auth(props: AuthProps) {
if (!iframeStamper) {
const iframeStamper = new IframeStamper({
iframeUrl: props.iframeUrl,
iframeContainerId: TurnkeyIframeContainerId,
iframeContainer: document.getElementById(TurnkeyIframeContainerId),
iframeElementId: TurnkeyIframeElementId,
});
iframeStamper.init().then(() => {
Expand Down
2 changes: 1 addition & 1 deletion examples/email-recovery/src/components/Recovery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function Recovery(props: RecoveryProps) {
if (!iframeStamper) {
const iframeStamper = new IframeStamper({
iframeUrl: props.iframeUrl,
iframeContainerId: TurnkeyIframeContainerId,
iframeContainer: document.getElementById(TurnkeyIframeContainerId),
iframeElementId: TurnkeyIframeElementId,
});
iframeStamper.init().then(() => {
Expand Down
70 changes: 70 additions & 0 deletions examples/wallet-export/src/components/Export.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"use client";

import { IframeStamper } from "@turnkey/iframe-stamper";
import { Dispatch, SetStateAction, useEffect, useState } from "react";

interface ExportProps {
iframeUrl: string;
turnkeyBaseUrl: string;
iframeDisplay: string;
setIframeStamper: Dispatch<SetStateAction<IframeStamper | null>>;
}

const TurnkeyIframeContainerId = "turnkey-iframe-container-id";
const TurnkeyIframeElementId = "turnkey-iframe-element-id";

export function Export(props: ExportProps) {
const [iframeStamper, setIframeStamper] = useState<IframeStamper | null>(
null
);
const [iframeDisplay, setIframeDisplay] = useState<string>("none");

useEffect(() => {
setIframeDisplay(props.iframeDisplay);
return () => {
if (iframeDisplay === "block") {
setIframeDisplay("none");
}
};
}, [props.iframeDisplay]);

useEffect(() => {
if (!iframeStamper) {
const iframeStamper = new IframeStamper({
iframeUrl: props.iframeUrl,
iframeContainer: document.getElementById(TurnkeyIframeContainerId),
iframeElementId: TurnkeyIframeElementId,
});
iframeStamper.init().then(() => {
setIframeStamper(iframeStamper);
props.setIframeStamper(iframeStamper);
});
}

return () => {
if (iframeStamper) {
iframeStamper.clear();
setIframeStamper(null);
}
};
}, [props.setIframeStamper, iframeStamper, setIframeStamper]);

const iframeCss = `
iframe {
box-sizing: border-box;
width: 400px;
height: 120px;
border-radius: 8px;
border-width: 1px;
border-style: solid;
border-color: rgba(216, 219, 227, 1);
padding: 20px;
}
`;

return (
<div style={{ display: iframeDisplay }} id={TurnkeyIframeContainerId}>
<style>{iframeCss}</style>
</div>
);
}
16 changes: 6 additions & 10 deletions examples/wallet-export/src/pages/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -140,30 +140,26 @@
color: #fff;
}

.copyKey {
.reveal {
display: flex;
flex-direction: column;
align-items: center;
width: 600px;
}

.copyKey h2 {
.reveal h2 {
text-align: center;
font-family: "Inter";
padding-top: 40px;
}

.copyKey ul {
.reveal ul {
margin-top: 0;
text-align: justify;
}

.copyKey p {
.reveal p {
font-family: "Inter";
font-size: 14px;
color: #555b64;
}

.walletIframe iframe {
border: none;
width: 600px;
height: 600px;
}
80 changes: 40 additions & 40 deletions examples/wallet-export/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,19 @@ import { IframeStamper } from "@turnkey/iframe-stamper";
import * as React from "react";
import { useEffect, useState } from "react";
import axios from "axios";
import { Export } from "@/components/Export";
Copy link
Contributor

Choose a reason for hiding this comment

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

Clean!! ❤️

import { WalletsTable } from "@/components/WalletsTable";

type TWallet = TurnkeyApiTypes["v1Wallet"];

const TurnkeyIframeContainerId = "turnkey-iframe-container-id";
const TurnkeyIframeElementId = "turnkey-iframe-element-id";

export default function ExportPage() {
const [wallets, setWallets] = useState<TWallet[]>([]);
const [iframeStamper, setIframeStamper] = useState<IframeStamper | null>(
null
);
const [showWallet, setShowWallet] = useState<boolean>(false);
const [iframeDisplay, setIframeDisplay] = useState<string>("none");
const [selectedWallet, setSelectedWallet] = useState<string | null>(null);

// Initialize the iframeStamper
useEffect(() => {
if (!iframeStamper) {
const iframeStamper = new IframeStamper({
iframeUrl: process.env.NEXT_PUBLIC_EXPORT_IFRAME_URL!,
iframeContainerId: TurnkeyIframeContainerId,
iframeElementId: TurnkeyIframeElementId,
});
iframeStamper.init().then(() => {
setIframeStamper(iframeStamper);
});
}

return () => {
if (iframeStamper) {
iframeStamper.clear();
setIframeStamper(null);
}
};
}, [iframeStamper]);

// Get wallets
useEffect(() => {
getWallets();
Expand Down Expand Up @@ -72,7 +49,7 @@ export default function ExportPage() {
throw new Error("unexpected error while injecting export bundle");
}

setShowWallet(true);
setIframeDisplay("block");
};

return (
Expand All @@ -97,21 +74,42 @@ export default function ExportPage() {
<WalletsTable wallets={wallets} setSelectedWallet={setSelectedWallet} />
)}
{selectedWallet && (
<div className={styles.copyKey}>
<h2>Wallet seedphrase</h2>
<p>
You are about to reveal your wallet seedphrase. By revealing this
seedphrase you understand that:
</p>
<div className={styles.reveal}>
<h2>Before you continue</h2>
<p>By revealing the private key, you understand and agree that:</p>
<ul>
<li>
<p>Your seedphrase is the only way to recover your funds.</p>
<p>
You should never share your private key with anyone, including
the Turnkey team. Turnkey will never ask you for your private
key.
</p>
</li>
<li>
<p>
You are responsible for the security of this private key and any
assets associated with it, and Turnkey cannot help recover it on
your behalf. Failure to properly secure your private key may
result in total loss of the associated assets.
</p>
</li>
<li>
<p>Do not let anyone see your seedphrase.</p>
<p>
Turnkey is not responsible for any other wallet you may use with
this private key, and Turnkey does not represent that any other
software or hardware will be compatible with or protect your
private key.
</p>
</li>
<li>
<p>Never share your seedphrase with anyone, including Turnkey.</p>
<p>
You have read and agree to{" "}
<a href="https://www.turnkey.com/files/terms-of-service.pdf">
Turnkey{"'"}s Terms of Service
</a>
, including the risks related to exporting your private key
disclosed therein.
</p>
</li>
</ul>
<div className={styles.reveal}>
Expand All @@ -126,11 +124,13 @@ export default function ExportPage() {
</div>
</div>
)}
<div
style={{ display: showWallet ? "block" : "none" }}
id={TurnkeyIframeContainerId}
className={styles.walletIframe}
/>

<Export
setIframeStamper={setIframeStamper}
iframeUrl={process.env.NEXT_PUBLIC_EXPORT_IFRAME_URL!}
iframeDisplay={iframeDisplay}
turnkeyBaseUrl={process.env.NEXT_PUBLIC_BASE_URL!}
></Export>
</main>
);
}
6 changes: 6 additions & 0 deletions packages/iframe-stamper/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @turnkey/iframe-stamper

## 1.0.0

### Major Changes

- This breaking change uses an HTML element instead of an ID to reference the iframe's container.

## 0.4.1

### Patch Changes
Expand Down
10 changes: 5 additions & 5 deletions packages/iframe-stamper/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![npm](https://img.shields.io/npm/v/@turnkey/iframe-stamper?color=%234C48FF)](https://www.npmjs.com/package/@turnkey/iframe-stamper)

This package contains functions to stamp a Turnkey request through credentials contained in an iframe. It is meant to be used with [`@turnkey/http`](https://www.npmjs.com/package/@turnkey/http) to build flows.
This package contains functions to stamp a Turnkey request through credentials contained in an iframe. It is meant to be used with [`@turnkey/http`](https://www.npmjs.com/package/@turnkey/http) to build flows. To stamp the request, use the Recovery and Auth flows to request and inject a credential bundle.

Usage:

Expand All @@ -17,7 +17,7 @@ const TurnkeyIframeElementId = "turnkey-iframe";

const iframeStamper = new IframeStamper({
iframeUrl: process.env.IFRAME_URL!,
iframeContainerId: TurnkeyIframeContainerId,
iframeContainer: document.getElementById(TurnkeyIframeContainerId),
iframeElementId: TurnkeyIframeElementId,
});

Expand Down Expand Up @@ -45,13 +45,13 @@ const TurnkeyIframeElementId = "turnkey-iframe";

const iframeStamper = new IframeStamper({
iframeUrl: process.env.IFRAME_URL!,
iframeContainerId: TurnkeyIframeContainerId,
iframeContainer: document.getElementById(TurnkeyIframeContainerId),
iframeElementId: TurnkeyIframeElementId,
});

// This inserts the iframe in the DOM and returns the public key
const publicKey = await iframeStamper.init();

// Injects a new private key in the iframe
const injected = await iframeStamper.injectKeyExportBundle(exportBundle);
// Injects a new wallet in the iframe
const injected = await iframeStamper.injectWalletExportBundle(exportBundle);
```
2 changes: 1 addition & 1 deletion packages/iframe-stamper/src/__tests__/iframe-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ test("throws when instantiated outside of a browser environment", async function
expect(() => {
new IframeStamper({
iframeUrl: "https://recovery.tkhqlabs.xyz",
iframeContainerId: "my-container-id",
iframeContainer: null,
iframeElementId: "my-iframe-id",
});
}).toThrow("Cannot initialize iframe in non-browser environment");
Expand Down
15 changes: 6 additions & 9 deletions packages/iframe-stamper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type TStamp = {
export type TIframeStamperConfig = {
iframeUrl: string;
iframeElementId: string;
iframeContainerId: string;
iframeContainer: HTMLElement | null | undefined;
};

/**
Expand All @@ -61,19 +61,16 @@ export class IframeStamper {
throw new Error("Cannot initialize iframe in non-browser environment");
}

if (document.getElementById(config.iframeElementId)) {
throw new Error(
`Iframe element with ID ${config.iframeElementId} already exists`
);
if (!config.iframeContainer) {
throw new Error("Iframe container cannot be found");
}
this.container = config.iframeContainer;

const container = document.getElementById(config.iframeContainerId);
if (!container) {
if (this.container.querySelector(`#${config.iframeElementId}`)) {
throw new Error(
`Cannot create iframe stamper: no container with ID ${config.iframeContainerId} exists in the current document`
`Iframe element with ID ${config.iframeElementId} already exists`
);
}
this.container = container;

let iframe = window.document.createElement("iframe");
iframe.id = config.iframeElementId;
Expand Down
Loading