Skip to content
Draft
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
31 changes: 23 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,31 @@ By default, the list of connectors is:
## Connect with specific connectors

```js
const webwallet = await connect([new WebWalletConnector()])
const webwallet = await connect({
connectors: [new WebWalletConnector()]
})

const webwallet = await connect({
connectors: [new WebwalletGoogleAuthConnector({
clientId: "YOUR_GOOGLE_CLIENT_ID",
authorizedPartyId: "STRING_IDENTIFYING YOUR PROJECT"
})]
})

const argentMobileWallet = await connect([
new ArgentMobileConnector()
])
const google

const wallet = await connect([
new InjectedConnector({ options: { id: "argentX" } }),
new InjectedConnector({ options: { id: "braavos" } })
])
const argentMobileWallet = await connect({
connectors: [
new ArgentMobileConnector()
]
})

const wallet = await connect({
connectors: [
new InjectedConnector({ options: { id: "argentX" } }),
new InjectedConnector({ options: { id: "braavos" } })
]
})
```

## Reconnect to a previously connected wallet on load:
Expand Down
13 changes: 2 additions & 11 deletions src/connectors/webwallet/helpers/trpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ const appRouter = t.router({
.input(
z.object({
theme: z.enum(["light", "dark", "auto"]).optional(),
token: z.string().optional(),
authorizedPartyId: z.string().optional(),
}),
)
.output(
Expand All @@ -73,17 +75,6 @@ const appRouter = t.router({
}),
)
.mutation(async () => ({})),
connectWebwalletSSO: t.procedure
.input(
z.object({ token: z.string(), authorizedPartyId: z.string().optional() }),
)
.output(
z.object({
account: z.string().array().optional(),
chainId: z.string().optional(),
}),
)
.mutation(async () => ({})),
enable: t.procedure.output(z.string()).mutation(async () => ""),
execute: t.procedure
.input(StarknetMethodArgumentsSchemas.execute)
Expand Down
104 changes: 69 additions & 35 deletions src/connectors/webwallet/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {
Permission,
type AccountChangeEventHandler,
type RequestFnCall,
type RpcMessage,
type RpcTypeToMessageMap,
type AccountChangeEventHandler,
type StarknetWindowObject,
} from "@starknet-io/types-js"
import {
Account,
AccountInterface,
ProviderInterface,
type AccountInterface,
type ProviderInterface,
type ProviderOptions,
} from "starknet"
import {
Expand All @@ -28,25 +28,25 @@ import {
import { DEFAULT_WEBWALLET_ICON, DEFAULT_WEBWALLET_URL } from "./constants"
import { openWebwallet } from "./helpers/openWebwallet"
import { setPopupOptions } from "./helpers/trpc"
import type { WebWalletStarknetWindowObject } from "./starknetWindowObject/argentStarknetWindowObject"
import type {
Theme,
WebWalletStarknetWindowObject,
} from "./starknetWindowObject/argentStarknetWindowObject"
WebWalletConnectorOptions,
WebwalletGoogleAuthOptions,
} from "./types"

let _wallet: StarknetWindowObject | null = null
let _address: string | null = null

interface WebWalletConnectorOptions {
url?: string
theme?: Theme
ssoToken?: string
authorizedPartyId?: string
}

export class WebWalletConnector extends Connector {
private _wallet: StarknetWindowObject | null = null
private _options: WebWalletConnectorOptions

protected _wallet: StarknetWindowObject | null = null
protected _options: WebWalletConnectorOptions

/**
* @param options.url - Webwallet URL
* @param options.theme - Theme
* @param options.ssoToken - SSO token - response from Google Auth
* @param options.authorizedPartyId - String identifying your project
*/
constructor(options: WebWalletConnectorOptions = {}) {
super()
this._options = options
Expand Down Expand Up @@ -115,24 +115,15 @@ export class WebWalletConnector extends Connector {
}

try {
let account, chainId

if (this._options.ssoToken) {
const ssoReponse = await (
this._wallet as WebWalletStarknetWindowObject
).connectWebwalletSSO(
this._options.ssoToken,
this._options.authorizedPartyId,
)
account = ssoReponse.account
chainId = ssoReponse.chainId
} else {
const connectResponse = await (
this._wallet as WebWalletStarknetWindowObject
).connectWebwallet({ theme: this._options.theme })
account = connectResponse.account
chainId = connectResponse.chainId
}
const connectResponse = await (
this._wallet as WebWalletStarknetWindowObject
).connectWebwallet({
theme: this._options.theme,
token: this._options.ssoToken,
authorizedPartyId: this._options.authorizedPartyId,
})
const account = connectResponse.account
const chainId = connectResponse.chainId

if (!account || !chainId) {
return {}
Expand Down Expand Up @@ -227,7 +218,7 @@ export class WebWalletConnector extends Connector {
this._wallet = null
}

private async ensureWallet(): Promise<void> {
protected async ensureWallet(): Promise<void> {
const origin = this._options.url || DEFAULT_WEBWALLET_URL
setPopupOptions({
origin,
Expand All @@ -241,3 +232,46 @@ export class WebWalletConnector extends Connector {
}

export type { WebWalletStarknetWindowObject }

export class WebwalletGoogleAuthConnector extends WebWalletConnector {
private _clientId: string

/**
* @param options.clientId - Google client ID
* @param options.authorizedPartyId - String identifying your project
*/
constructor(
options: WebwalletGoogleAuthOptions = {
clientId: "",
},
) {
if (!options.clientId) {
throw new Error("clientId is required")
}

super(options)
this._clientId = options.clientId
}

get id(): string {
this._wallet = _wallet
return this._wallet?.id || "argentWebWalletGoogleAuth"
}

get title(): string {
return "Google"
}

get clientId(): string {
return this._clientId
}

public setSSOToken(response: { credential: string | null }) {
if (response.credential) {
// Send the token to your server for verification
this._options.ssoToken = response.credential
} else {
throw new Error("No credential received")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export type Theme = "light" | "dark"

type ConnectWebwalletProps = {
theme?: Theme
token?: string
authorizedPartyId?: string
}

export type WebWalletStarknetWindowObject = StarknetWindowObject & {
Expand All @@ -45,13 +47,6 @@ export type WebWalletStarknetWindowObject = StarknetWindowObject & {
account?: string[]
chainId?: string
}>
connectWebwalletSSO(
token: string,
authorizedPartyId?: string,
): Promise<{
account?: string[]
chainId?: string
}>
}

export const getArgentStarknetWindowObject = (
Expand All @@ -64,11 +59,12 @@ export const getArgentStarknetWindowObject = (
return proxyLink.getLoginStatus.mutate()
},
connectWebwallet: (props = {}) => {
const { theme } = props
return proxyLink.connectWebwallet.mutate({ theme })
},
connectWebwalletSSO: (token, authorizedPartyId) => {
return proxyLink.connectWebwalletSSO.mutate({ token, authorizedPartyId })
const { theme, token, authorizedPartyId } = props
return proxyLink.connectWebwallet.mutate({
theme,
token,
authorizedPartyId,
})
},
async request(call) {
switch (call.type) {
Expand Down
19 changes: 19 additions & 0 deletions src/connectors/webwallet/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Theme } from "../starknetWindowObject/argentStarknetWindowObject"

declare global {
interface Window {
google: any
}
}

export interface WebWalletConnectorOptions {
url?: string
theme?: Theme
ssoToken?: string
authorizedPartyId?: string
}

export interface WebwalletGoogleAuthOptions extends WebWalletConnectorOptions {
clientId: string
authorizedPartyId?: string
}
20 changes: 19 additions & 1 deletion src/helpers/defaultConnectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import {
} from "../connectors/argentMobile"
import { BraavosMobileBaseConnector } from "../connectors/braavosMobile"
import { InjectedConnector } from "../connectors/injected"
import { WebWalletConnector } from "../connectors/webwallet"
import {
WebWalletConnector,
WebwalletGoogleAuthConnector,
} from "../connectors/webwallet"

const isMobileDevice = () => {
// Primary method: User Agent + Touch support check
Expand All @@ -25,9 +28,14 @@ const isMobileDevice = () => {
export const defaultConnectors = ({
argentMobileOptions,
webWalletUrl,
googleAuthOptions,
}: {
argentMobileOptions: ArgentMobileConnectorOptions
webWalletUrl?: string
googleAuthOptions?: {
clientId: string
authorizedPartyId: string
}
}): StarknetkitConnector[] => {
const isSafari =
typeof window !== "undefined"
Expand All @@ -51,5 +59,15 @@ export const defaultConnectors = ({
}
defaultConnectors.push(new WebWalletConnector({ url: webWalletUrl }))

if (googleAuthOptions) {
defaultConnectors.push(
new WebwalletGoogleAuthConnector({
url: webWalletUrl,
clientId: googleAuthOptions.clientId,
authorizedPartyId: googleAuthOptions.authorizedPartyId,
}),
)
}

return defaultConnectors
}
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const connect = async ({
modalTheme,
dappName,
resultType = "wallet",
googleAuthOptions,
...restOptions
}: ConnectOptionsWithConnectors | ConnectOptions): Promise<ModalResult> => {
const { webWalletUrl = DEFAULT_WEBWALLET_URL, argentMobileOptions } =
Expand All @@ -72,6 +73,7 @@ export const connect = async ({
? defaultConnectors({
argentMobileOptions,
webWalletUrl,
googleAuthOptions,
})
: connectors

Expand Down
7 changes: 6 additions & 1 deletion src/modal/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { InjectedConnector } from "../connectors/injected"
import type { ModalWallet } from "../types/modal"
import ConnectorButton from "./ConnectorButton.svelte"
import WebwalletGoogleAuth from "./WebwalletGoogleAuth.svelte"

export let dappName: string = window?.document.title ?? ""
export let modalWallets: ModalWallet[]
Expand Down Expand Up @@ -144,7 +145,11 @@

<ul class="flex flex-col gap-3">
{#each modalWallets as wallet}
<ConnectorButton {wallet} {loadingItem} {cb} {theme} />
{#if wallet.connector.id === "argentWebWalletGoogleAuth"}
<WebwalletGoogleAuth {wallet} {cb} />
{:else}
<ConnectorButton {wallet} {loadingItem} {cb} {theme} />
{/if}
{/each}
</ul>
</main>
Expand Down
Loading