accounts
Version:
Tempo Accounts SDK
83 lines (77 loc) • 3.21 kB
text/typescript
import { Discovery, Wata, mobileWebAuth as core_mobileWebAuth, type MobileWebAuth } from 'wata'
import type * as Adapter from '../../Adapter.js'
import * as Keystore from '../../Keystore.js'
import { fromRequest } from '../internal/fromRequest.js'
/**
* Creates a mobile web auth adapter that forwards wallet RPC through Wata.
*
* Authentication opens a browser session and completes via an encrypted app-link
* callback carrying the wallet RPC response.
*/
export function mobileWebAuth(options: mobileWebAuth.Options): Adapter.Adapter {
const { baseUrl, fetch, host, name, openAuthSession, rdns, redirectUri } = options
// The host discovery document is fetched once and reused for the
// adapter's lifetime; a wallet rotating its document requires a new
// adapter instance to pick up.
let hostDocument: Promise<Discovery.HostDocument> | undefined
function resolveHost() {
if (typeof host !== 'string') return host
hostDocument ??= Discovery.fetchHost(host, fetch !== undefined ? { fetch } : {}).catch(
(error) => {
hostDocument = undefined
throw error
},
)
return hostDocument
}
return fromRequest({
// React Native may lack WebCrypto and persists through string-based
// storage, so this opts into pure-JS P-256 (the access key lives app-side
// and signs without a wallet round-trip).
keystores: { p256: Keystore.p256() },
name,
rdns,
async request(request) {
// Mobile web auth is single-exchange: one authorization URL carries one
// RPC request envelope, and one callback URL carries one response.
// The wallet learns this app's identity from the consumer discovery
// document served at `baseUrl`, not from session metadata.
const host = await resolveHost()
if (host === undefined) throw new Error('`mobileWebAuth` requires a `host`.')
const wata = Wata.create({
baseUrl,
transports: [
core_mobileWebAuth({
callback: redirectUri,
host,
openAuthSession,
...(fetch !== undefined ? { fetch } : {}),
}),
],
})
const session = wata.start()
return (await session.send({ method: request.method, params: request.params ?? [] })).result
},
})
}
export declare namespace mobileWebAuth {
/** Base options for {@link mobileWebAuth}. */
export type BaseOptions = {
/** Public HTTPS origin that hosts this app's Wata consumer discovery document. */
baseUrl: string
/** Override the Wata discovery `fetch` implementation. */
fetch?: MobileWebAuth.Options['fetch'] | undefined
/** Host discovery origin or preloaded Wata host document. */
host: MobileWebAuth.Options['host']
/** Provider display name. */
name: string
/** Opens the browser auth session and returns the callback URL. */
openAuthSession: NonNullable<MobileWebAuth.Options['openAuthSession']>
/** Redirect URI for the auth callback (e.g. your app's deep link scheme). */
redirectUri: string
/** Reverse-DNS provider identifier. */
rdns: string
}
/** Options for {@link mobileWebAuth}. */
export type Options = BaseOptions
}