Skip to content

Commit a0536c3

Browse files
authored
Merge pull request #27 from magiclabs/implement-reveal-pk-express-api
feat: implement reveal pk in express api
2 parents df09287 + 413a810 commit a0536c3

File tree

7 files changed

+109
-28
lines changed

7 files changed

+109
-28
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Add the following environment variables to your `.env.local` file:
77
```env
88
GOOGLE_CLIENT_ID=your-google-client-id
99
GOOGLE_CLIENT_SECRET=your-google-client-secret
10-
OIDC_PROVIDER_ID=your-magic-provider-id
10+
NEXT_PUBLIC_OIDC_PROVIDER_ID=your-magic-provider-id
1111
MAGIC_API_KEY=your-magic-secret-key
1212
NEXTAUTH_SECRET=your-next-auth-secret
1313
```

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@magic-ext/hedera": "^2.0.0",
1414
"@magic-ext/oauth2": "^13.0.0",
1515
"@magic-ext/solana": "^28.0.0",
16+
"@magic-sdk/api-wallets": "^0.1.0",
1617
"@metamask/eth-sig-util": "^8.2.0",
1718
"@next/third-parties": "^16.0.3",
1819
"@radix-ui/react-tabs": "^1.1.13",
@@ -22,7 +23,7 @@
2223
"clsx": "^2.1.1",
2324
"ethers": "^6.15.0",
2425
"magic-sdk": "^31.0.0",
25-
"next": "15.5.7",
26+
"next": "15.5.8",
2627
"next-auth": "^4.24.11",
2728
"prismjs": "^1.30.0",
2829
"react": "19.1.0",

pnpm-lock.yaml

Lines changed: 26 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/(demo)/api-wallet/wallet/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { UserInfo } from "@/components/api-wallet/UserInfo";
77
import { useApiWallet } from "@/contexts/ApiWalletContext";
88
import { LoadingScreen } from "@/components/LoadingScreen";
99
import { PageHeader } from "@/components/PageHeader";
10+
import UserMethods from "@/components/api-wallet/UserMethods";
1011

1112
export default function ApiWalletPage() {
1213
const { selectedNetwork, isAuthenticated, isLoading } = useApiWallet();
@@ -33,14 +34,16 @@ export default function ApiWalletPage() {
3334
</div>
3435

3536
{/* Right Side - Signing Methods */}
36-
<div className="w-full lg:w-2/3">
37+
<div className="w-full lg:w-2/3 flex flex-col gap-18">
3738
{/* Show Solana methods if Solana network is selected */}
3839
{selectedNetwork === "solana" ? (
3940
<SolanaSignMethods />
4041
) : (
4142
/* Default to EVM methods for Ethereum and other EVM networks */
4243
<EVMSignMethods />
4344
)}
45+
46+
<UserMethods />
4447
</div>
4548
</div>
4649
</div>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { useApiWallet } from "@/contexts/ApiWalletContext";
2+
import MagicApiWalletSDK, { WalletType } from "@magic-sdk/api-wallets";
3+
import { MethodsCard } from "../MethodsCard";
4+
5+
export default function UserMethods() {
6+
const { selectedNetwork, session } = useApiWallet();
7+
const oidcProviderId = process.env.NEXT_PUBLIC_OIDC_PROVIDER_ID ?? "";
8+
9+
const tabs = [
10+
{
11+
value: "reveal-private-key",
12+
label: "Reveal Private Key",
13+
functionName:
14+
"magic.wallet.exportPrivateKey({ walletType, bearerToken })",
15+
payload: null,
16+
handler: () =>
17+
revealPrivateKey(
18+
networkToWalletType(selectedNetwork ?? "ETH"),
19+
session?.idToken,
20+
oidcProviderId
21+
),
22+
},
23+
];
24+
25+
return (
26+
<MethodsCard
27+
title="User Methods"
28+
description="Test various user methods with Magic SDK"
29+
defaultTab={tabs[0].value}
30+
tabs={tabs}
31+
/>
32+
);
33+
}
34+
35+
async function revealPrivateKey(
36+
walletType: WalletType,
37+
bearerToken?: string,
38+
oidcProviderId?: string
39+
) {
40+
if (!bearerToken || !oidcProviderId) return;
41+
const magic = new MagicApiWalletSDK(process.env.NEXT_PUBLIC_MAGIC_API_WALLET_KEY);
42+
43+
await magic.wallet.exportPrivateKey({
44+
walletType,
45+
bearerToken,
46+
oidcProviderId,
47+
});
48+
}
49+
50+
const NETWORK_TO_TYPE: Record<string, WalletType> = {
51+
ethereum: "ETH",
52+
eth: "ETH",
53+
bitcoin: "BITCOIN",
54+
btc: "BITCOIN",
55+
solana: "SOLANA",
56+
sol: "SOLANA",
57+
};
58+
59+
export function networkToWalletType(network?: string): WalletType {
60+
if (!network) return "ETH";
61+
return NETWORK_TO_TYPE[network.toLowerCase()];
62+
}

src/lib/api-wallet/express.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { TeeEndpoint as ExpressEndpoint, TeeProxyEndpoint } from "../../types/tee-types";
1+
import {
2+
TeeEndpoint as ExpressEndpoint,
3+
TeeProxyEndpoint,
4+
} from "../../types/tee-types";
25

36
export const TEE_BASE = "https://tee.express.magiclabs.com";
47

@@ -10,18 +13,21 @@ export const TEE_BASE = "https://tee.express.magiclabs.com";
1013
* @returns Parsed JSON data from the response
1114
* @throws Error if response is not ok or contains error information
1215
*/
13-
export async function express<T = any>(path: ExpressEndpoint, jwt: string, init?: RequestInit): Promise<T> {
14-
const obj = JSON.parse(init?.body as string) as { chain: string }
16+
export async function express<T = any>(
17+
path: ExpressEndpoint,
18+
jwt: string,
19+
init?: RequestInit
20+
): Promise<T> {
21+
const obj = JSON.parse(init?.body as string) as { chain: string };
1522
const response = await fetch(TEE_BASE + path, {
1623
...init,
1724
headers: {
1825
"Content-Type": "application/json",
1926
Authorization: `Bearer ${jwt}`,
2027
"X-Magic-Secret-Key": process.env.MAGIC_API_KEY ?? "",
21-
"X-OIDC-Provider-ID": process.env.OIDC_PROVIDER_ID ?? "",
28+
"X-OIDC-Provider-ID": process.env.NEXT_PUBLIC_OIDC_PROVIDER_ID ?? "",
2229
"X-Magic-Chain": obj.chain,
23-
"X-Magic-Referrer":
24-
"https://demo.magic.link",
30+
"X-Magic-Referrer": "https://demo.magic.link",
2531
...(init?.headers || {}),
2632
},
2733
cache: "no-store",
@@ -30,7 +36,7 @@ export async function express<T = any>(path: ExpressEndpoint, jwt: string, init?
3036
// Handle response validation and JSON parsing
3137
if (!response.ok) {
3238
const data = await response.json().catch(() => ({}));
33-
39+
3440
// For other errors, throw a generic error
3541
throw new Error(data.error || `HTTP error! status: ${response.status}`);
3642
}

src/lib/embedded-wallet/get-magic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class MagicService {
2222

2323
public static get magic(): any {
2424
if (!this._magic) {
25-
this._magic = new Magic('pk_live_493172A4D3AFF148', {
25+
this._magic = new Magic(process.env.NEXT_PUBLIC_MAGIC_EMBEDDED_WALLET_KEY ?? "", {
2626
extensions: [
2727
new OAuthExtension(),
2828
new SolanaExtension({

0 commit comments

Comments
 (0)