diff --git a/package.json b/package.json index e0f48b7..90a6a86 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@wharfkit/wallet-plugin-web-authenticator", "description": "A Web Authenticator wallet plugin for use with @wharfkit/session.", - "version": "0.3.1", + "version": "0.5.0", "homepage": "https://github.com/wharfkit/wallet-plugin-web-authenticator", "license": "BSD-3-Clause", "main": "lib/wallet-plugin-web-authenticator.js", diff --git a/src/index.ts b/src/index.ts index 61d0998..e911878 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,8 +29,8 @@ import WebSocket from 'isomorphic-ws' import defaultTranslations from './translations' interface WebAuthenticatorOptions { - /** The URL of the web authenticator service */ - webAuthenticatorUrl?: string + /** The URLs for the web authenticator service, keyed by chain ID */ + urls: Record /** The buoy service URL for messaging */ buoyServiceUrl?: string /** The buoy WebSocket for messaging */ @@ -38,13 +38,13 @@ interface WebAuthenticatorOptions { } export class WalletPluginWebAuthenticator extends AbstractWalletPlugin implements WalletPlugin { - private webAuthenticatorUrl: string + private urls: Record private buoyServiceUrl: string private buoyWs?: WebSocket - constructor(options: WebAuthenticatorOptions = {}) { + constructor(options: WebAuthenticatorOptions) { super() - this.webAuthenticatorUrl = options.webAuthenticatorUrl || 'http://localhost:5174' + this.urls = options.urls this.buoyServiceUrl = options.buoyServiceUrl || 'https://cb.anchor.link' this.buoyWs = options?.buoyWs } @@ -85,6 +85,24 @@ export class WalletPluginWebAuthenticator extends AbstractWalletPlugin implement */ translations = defaultTranslations + getChainUrl(context: LoginContext | TransactContext): string { + // default to first + let url = this.urls[0] + + // override if chain specified + if (context.chain) { + url = this.urls[String(context.chain.id)] + } + + if (!url) { + throw new Error( + `No web authenticator URL configured for chain ID: ${context.chain?.id}` + ) + } + + return url + } + /** * Opens a popup window with the given URL and waits for it to complete */ @@ -218,7 +236,8 @@ export class WalletPluginWebAuthenticator extends AbstractWalletPlugin implement privateKey, } = await createIdentityRequest(context, this.buoyServiceUrl) - const loginUrl = `${this.webAuthenticatorUrl}/sign?esr=${request.encode()}&chain=${ + const url = this.getChainUrl(context) + const loginUrl = `${url}/sign?esr=${request.encode()}&chain=${ context.chain?.id }&requestKey=${requestKey}` @@ -228,8 +247,8 @@ export class WalletPluginWebAuthenticator extends AbstractWalletPlugin implement context.ui ) - this.data.privateKey = String(privateKey) - this.data.publicKey = payload.link_key + this.data.encryptionKey = String(privateKey) + this.data.messageKey = payload.link_key if (!payload.cid) { throw new Error('Login failed: No chain ID returned') @@ -274,7 +293,7 @@ export class WalletPluginWebAuthenticator extends AbstractWalletPlugin implement ): Promise { try { // Ensure we have a request key from login - if (!this.data.privateKey || !this.data.publicKey) { + if (!this.data.encryptionKey || !this.data.messageKey) { throw new Error('No request keys available - please login first') } @@ -299,18 +318,19 @@ export class WalletPluginWebAuthenticator extends AbstractWalletPlugin implement const sealedRequest = await sealMessage( modifiedRequest.encode(), - PrivateKey.from(this.data.privateKey), - PublicKey.from(this.data.publicKey), + PrivateKey.from(this.data.encryptionKey), + PublicKey.from(this.data.messageKey), nonce ) - const signUrl = `${this.webAuthenticatorUrl}/sign?sealed=${sealedRequest.toString( + const url = this.getChainUrl(context) + const signUrl = `${url}/sign?sealed=${sealedRequest.toString( 'hex' )}&nonce=${nonce.toString()}&chain=${context.chain?.id}&accountName=${ context.accountName }&permissionName=${context.permissionName}&appName=${ context.appName - }&requestKey=${String(PrivateKey.from(this.data.privateKey).toPublic())}` + }&requestKey=${String(PrivateKey.from(this.data.encryptionKey).toPublic())}` const response = await this.openPopup(signUrl, callback, context.ui) diff --git a/test/tests/common.ts b/test/tests/common.ts index ee896ee..23a30ca 100644 --- a/test/tests/common.ts +++ b/test/tests/common.ts @@ -1,5 +1,5 @@ import {Chains, SessionKit} from '@wharfkit/session' -import {PermissionLevel, Signature, APIClient, PrivateKey} from '@wharfkit/antelope' +import {APIClient, PermissionLevel, PrivateKey, Signature} from '@wharfkit/antelope' import { mockChainDefinition, mockPermissionLevel, @@ -9,21 +9,21 @@ import { } from '@wharfkit/mock-data' import {assert} from 'chai' import { - LoginContext, - ResolvedSigningRequest, - TransactContext, - ChainDefinition, ABICacheInterface, - WalletPluginSignResponse, - UserInterface, Cancelable, + ChainDefinition, + CreateAccountContext, + LoginContext, + LoginHooks, PromptArgs, PromptResponse, + ResolvedSigningRequest, + TransactContext, TransactHooks, - LoginHooks, - UserInterfaceLoginResponse, + UserInterface, UserInterfaceAccountCreationResponse, - CreateAccountContext, + UserInterfaceLoginResponse, + WalletPluginSignResponse, } from '@wharfkit/session' import {WalletPluginWebAuthenticator} from '$lib' @@ -184,7 +184,10 @@ suite('wallet plugin', function () { test('login functionality', async function () { const plugin = new WalletPluginWebAuthenticator({ - webAuthenticatorUrl: 'https://web-authenticator.greymass.com', + urls: { + '73e4385a2708e6d7048834fbc1079f2fabb17b3c125b146af438971e90716c4d': + 'https://web-authenticator.greymass.com', + }, }) // Mock login context @@ -229,14 +232,17 @@ suite('wallet plugin', function () { test('sign functionality', async function () { const plugin = new WalletPluginWebAuthenticator({ - webAuthenticatorUrl: 'https://web-authenticator.greymass.com', + urls: { + '73e4385a2708e6d7048834fbc1079f2fabb17b3c125b146af438971e90716c4d': + 'https://web-authenticator.greymass.com', + }, }) // Use different keys for the sign test to avoid channel ID conflicts const signPrivateKey = PrivateKey.generate('K1') const signPublicKey = signPrivateKey.toPublic() - plugin.data.privateKey = signPrivateKey - plugin.data.publicKey = signPublicKey + plugin.data.encryptionKey = signPrivateKey + plugin.data.messageKey = signPublicKey const mockResolvedSigningRequest = await makeMockResolvedSigningRequest() @@ -275,7 +281,10 @@ suite('wallet plugin', function () { test('popup success with UI feedback', async function () { const plugin = new WalletPluginWebAuthenticator({ - webAuthenticatorUrl: 'https://web-authenticator.greymass.com', + urls: { + '73e4385a2708e6d7048834fbc1079f2fabb17b3c125b146af438971e90716c4d': + 'https://web-authenticator.greymass.com', + }, }) // Mock login context with UI