Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | 450x 1x 113x 1x 32x 20x 12x 4x 8x 1x 7x 1x 66x 3x 63x 1x 55x 55x 29x 26x 1x 25x 25x 15x 3x 12x 22x 10x 22x 1x 27x 27x 27x 1x 24x 24x 24x 24x 24x 24x 24x 7x 24x 5x 24x 1x 19x 19x 2x 5x 5x | import {Cancelable, LoginContext, PromptResponse} from '@wharfkit/session' import {Translator} from './transports/types' /** Anchor transport used for login and signing: browser authenticator or native app. */ export type AnchorMode = 'web' | 'app' function isValidMode(value: unknown): value is AnchorMode { return value === 'web' || value === 'app' } export function readMode(data: Record<string, any>): AnchorMode | undefined { if (isValidMode(data.mode)) { return data.mode } if (data.channelUrl || data.signerKey) { return 'app' } if (data.encryptionKey && data.messageKey) { return 'web' } return undefined } export function writeMode(data: Record<string, any>, mode: AnchorMode) { if (!isValidMode(mode)) { throw new Error(`Invalid Anchor mode: ${mode}`) } data.mode = mode } /** Per-call options from `login({arbitrary: {anchor: {...}}})`. */ export interface AnchorLoginOptions { mode?: AnchorMode /** Window the caller opened inside its own click, for the web transport to navigate. */ popup?: Window } /** Read one plugin's entry out of the shared arbitrary bag. Throws on a bad value. */ export function readLoginOptions(id: string, arbitrary?: Record<string, any>): AnchorLoginOptions { const options = arbitrary?.[id] if (options === undefined || options === null) { return {} } if (typeof options !== 'object') { throw new Error(`Invalid Anchor login options: ${options}`) } const result: AnchorLoginOptions = {} if (options.mode !== undefined) { if (!isValidMode(options.mode)) { throw new Error(`Invalid Anchor mode: ${options.mode}`) } result.mode = options.mode } if (options.popup) { result.popup = options.popup } return result } export function ledgerTransportAvailable(): boolean { Iif (typeof navigator === 'undefined') { return false } const nav = navigator as any return Boolean(nav.hid) || Boolean(nav.usb) } function modeElements(t: Translator, onChoice: (mode: AnchorMode) => void, includeWeb: boolean) { const webLabel = t('mode.web.label', { default: 'In this browser using anchorwallet.io', }) const webDetail = ledgerTransportAvailable() ? t('mode.web.detail', {default: 'with a passkey or Ledger'}) : t('mode.web.detail_no_ledger', {default: 'with a passkey'}) const appLabel = t('mode.app.label', {default: 'With the Anchor app'}) const appDetail = t('mode.app.detail', {default: 'on this or another device'}) const elements: any[] = [] if (includeWeb) { elements.push({ type: 'button', label: webLabel, data: { label: `${webLabel}\n${webDetail}`, variant: 'primary', onClick: () => onChoice('web'), }, }) } elements.push({ type: 'button', label: appLabel, data: { label: `${appLabel}\n${appDetail}`, variant: includeWeb ? 'secondary' : 'primary', onClick: () => onChoice('app'), }, }) return elements } /** Two buttons, no QR, no sub-product logos. `onChoice` fires synchronously inside the click. */ export function promptForMode( context: LoginContext, t: Translator, onChoice: (mode: AnchorMode) => void ): Cancelable<PromptResponse> { Iif (!context.ui) { throw new Error('No UI available') } return context.ui.prompt({ title: t('mode.title', {default: 'How do you use Anchor?'}), body: t('mode.body', { default: 'Choose where to approve requests. You can choose differently the next time you log in.', }), elements: modeElements(t, onChoice, true), }) } export function promptForRecovery( context: LoginContext, t: Translator, includeWeb: boolean, onChoice: (mode: AnchorMode) => void ): Cancelable<PromptResponse> { Iif (!context.ui) { throw new Error('No UI available') } return context.ui.prompt({ title: t('recovery.title', {default: 'Request cancelled'}), body: t('recovery.body', {default: 'Choose how you want to try again.'}), elements: modeElements(t, onChoice, includeWeb), }) } |