Skip to content

Commit

Permalink
update packages and tsx; tweaks to wallet provider (#7)
Browse files Browse the repository at this point in the history
* update packages and tsx; tweaks to wallet provider

* use jsx:react; refactor components

* fix casing conflict
  • Loading branch information
coffeexcoin authored Sep 16, 2024
1 parent ffc4a52 commit 9e2eaff
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 77 deletions.
8 changes: 5 additions & 3 deletions packages/agw-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@
"@privy-io/react-auth": "^1.78.1"
},
"peerDependencies": {
"abitype": "^1.0.0",
"react": "^18.0.0",
"react": ">=18",
"typescript": ">=5.0.4",
"viem": "^2.19.0",
"@abstract-foundation/agw-sdk": "workspace:*"
},
"devDependencies": {
"@abstract-foundation/agw-sdk": "workspace:*",
"@types/react": "^18.3.6",
"react": ">=18.3.1",
"react-dom": ">=18.3.1",
"@types/react": ">=18.3.1",
"@types/react-dom": ">=18.3.0",
"viem": "^2.19.0"
},
"peerDependenciesMeta": {
Expand Down
39 changes: 39 additions & 0 deletions packages/agw-react/src/agwProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use client'
import {
PrivyProvider
} from "@privy-io/react-auth";
import React from "react";
import {
type Chain,
} from "viem";

import { SmartAccountProvider } from "./smartAccountContext.js";

interface AbstractWalletProviderProps {
appId: string;
defaultChain: Chain;
supportedChains: Chain[];
}

export const AbstractWalletProvider = ({
appId,
defaultChain,
supportedChains,
children,
}: React.PropsWithChildren<AbstractWalletProviderProps>) => {
return (
<PrivyProvider
appId={appId}
config={{
embeddedWallets: {
createOnLogin: "off",
noPromptOnSignature: true,
},
defaultChain: defaultChain,
supportedChains: supportedChains,
}}
>
<SmartAccountProvider appId={appId}>{children}</SmartAccountProvider>
</PrivyProvider>
);
};
6 changes: 2 additions & 4 deletions packages/agw-react/src/exports/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export {
AbstractWalletProvider,
useAbstractGlobalWallet,
} from '../AbstractWalletProvider.js';
export { AbstractWalletProvider } from '../agwProvider.js';
export { useAbstractGlobalWallet } from '../smartAccountContext.js';
export { useLoginWithAbstract } from '../useLoginWithAbstract.js';
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
'use client'
import {
type AbstractClient,
createAbstractClient,
} from "@abstract-foundation/agw-sdk";
import { toPrivyWalletProvider } from "@privy-io/cross-app-connect";
} from '@abstract-foundation/agw-sdk';
import { toPrivyWalletProvider } from '@privy-io/cross-app-connect';
import {
PrivyProvider,
type SignTypedDataParams,
useCrossAppAccounts,
usePrivy,
type User,
} from "@privy-io/react-auth";
import React, { useContext, useEffect, useMemo,useState } from "react";
} from '@privy-io/react-auth';
import React, {
createContext,
useContext,
useEffect,
useMemo,
useState,
} from 'react';
import {
type Account,
type Address,
type Chain,
custom,
type CustomSource,
type Hex,
hexToString,
toHex,
} from "viem";
import { toAccount } from "viem/accounts";
import { abstractTestnet, type ChainEIP712 } from "viem/chains";
} from 'viem';
import { toAccount } from 'viem/accounts';
import { abstractTestnet, type ChainEIP712 } from 'viem/chains';

/** Interface returned by custom `useSmartAccount` hook */
interface SmartAccountInterface {
Expand All @@ -36,47 +41,36 @@ interface SmartAccountInterface {
ready: boolean;
}

export const SmartAccountContext = React.createContext<SmartAccountInterface>({
export const SmartAccountContext = createContext<SmartAccountInterface>({
signer: undefined,
smartAccountClient: undefined,
smartAccountAddress: undefined,
ready: false,
});

export const useAbstractGlobalWallet = () => {
return useContext(SmartAccountContext);
};

interface AbstractWalletProviderProps {
appId: string;
defaultChain: Chain;
supportedChains: Chain[];
children: React.ReactNode;
}

const SmartAccountProvider = ({ appId, children }: { appId: string, children: React.ReactNode }) => {
export const SmartAccountProvider = ({
appId,
children,
}: React.PropsWithChildren<{ appId: string }>) => {
const { signMessage, signTypedData } = useCrossAppAccounts();
const { user, ready, authenticated } = usePrivy();

const account = useMemo(() => {
const getAccountFromCrossAppUser = (user: User) => {
const crossAppAccount = user.linkedAccounts.find(
(account) => account.type === "cross_app"
(account) => account.type === 'cross_app',
);
if (
crossAppAccount?.embeddedWallets === undefined ||
crossAppAccount.embeddedWallets.length === 0
) {
throw new Error("No embedded wallet found");
if (crossAppAccount?.embeddedWallets?.[0] === undefined) {
throw new Error('No embedded wallet found');
}
const address = crossAppAccount.embeddedWallets[0]?.address;
const address = crossAppAccount.embeddedWallets[0].address;

const signMessageWithPrivy: CustomSource["signMessage"] = async ({
const signMessageWithPrivy: CustomSource['signMessage'] = async ({
message,
}) => {
let messageString: string;
if (typeof message !== "string") {
if (typeof message.raw === "string") {
if (typeof message !== 'string') {
if (typeof message.raw === 'string') {
messageString = hexToString(message.raw);
} else {
messageString = hexToString(toHex(message.raw));
Expand All @@ -89,31 +83,31 @@ const SmartAccountProvider = ({ appId, children }: { appId: string, children: Re
}) as Promise<`0x${string}`>;
};

const signTransactionWithPrivy: CustomSource["signTransaction"] =
const signTransactionWithPrivy: CustomSource['signTransaction'] =
async () => {
throw new Error("Raw transaction signing not currently implemented");
throw new Error('Raw transaction signing not currently implemented');
};

// Sanitize the message to ensure it's a valid JSON object
// This is necessary because the message object can contain BigInt values, which
// can't be serialized by JSON.stringify
// TODO: Update this to not modify the underlying message but return a new copy
// with the proper type for the privy side. They are technically the same data but
// the viem typing doesn't play nice with the privy definition.
// the viem typing doesn't play nice with the privy definition.
function sanitizeMessage(message: any) {

Check warning on line 97 in packages/agw-react/src/smartAccountContext.tsx

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
for (const key in message) {
if (typeof message[key] === "object" && message[key] !== null) {
if (typeof message[key] === 'object' && message[key] !== null) {
sanitizeMessage(message[key]);
} else {
if (typeof message[key] === "bigint") {
if (typeof message[key] === 'bigint') {
message[key] = message[key].toString();
}
}
}
}

const signTypedDataWithPrivy: CustomSource["signTypedData"] = async (
data
const signTypedDataWithPrivy: CustomSource['signTypedData'] = async (
data,
) => {
sanitizeMessage(data.message);
return signTypedData(data as SignTypedDataParams, {
Expand Down Expand Up @@ -158,7 +152,7 @@ const SmartAccountProvider = ({ appId, children }: { appId: string, children: Re
const smartAccountClient = await createAbstractClient({
signer: eoa,
chain: abstractTestnet as ChainEIP712,
transport: custom(privyWalletProvider)
transport: custom(privyWalletProvider),
});

setSmartAccountClient(smartAccountClient);
Expand All @@ -183,25 +177,6 @@ const SmartAccountProvider = ({ appId, children }: { appId: string, children: Re
);
};

export const AbstractWalletProvider = ({
appId,
defaultChain,
supportedChains,
children,
}: AbstractWalletProviderProps) => {
return (
<PrivyProvider
appId={appId}
config={{
embeddedWallets: {
createOnLogin: "off",
noPromptOnSignature: true,
},
defaultChain: defaultChain,
supportedChains: supportedChains,
}}
>
<SmartAccountProvider appId={appId}>{children}</SmartAccountProvider>
</PrivyProvider>
);
export const useAbstractGlobalWallet = () => {
return useContext(SmartAccountContext);
};
4 changes: 2 additions & 2 deletions packages/agw-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["src/**/*.test.ts"],
"compilerOptions": {
"sourceMap": true,
"resolveJsonModule": true,
"jsx": "react-jsx"
"jsx": "react"
}
}
24 changes: 17 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 9e2eaff

Please sign in to comment.