diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0db9a1a..14a68f35 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,9 +23,10 @@ Feature release including multi-hook support, improved UX for off chain token ho
 
 - TS interface custom view
 
-### Performance Improvements
+### Performance / Quality Improvements 
 
 - Reduced the duplication of variable definitions (moved to a common constants file).
+- Increased unit test coverage
 
 **Full Change log**:
 
diff --git a/README.md b/README.md
index 1e82a5d0..0634e0c4 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 
 # `token-negotiator`
 
-Token Negotiator enables you build web experiences for users around the tokens they hold.
+Open source technology that enables you build web experiences for users around the tokens they hold.
 
 ## Usage
 
diff --git a/package.json b/package.json
index 7ac3aaff..dbc1c9e6 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@tokenscript/token-negotiator",
   "version": "3.2.0",
-  "description": "Token-negotiator a token attestation bridge between web 2.0 and 3.0.",
+  "description": "Open source technology that enables you build web experiences for users around the tokens they hold.",
   "module": "dist/index.js",
   "types": "dist/index.d.ts",
   "files": [
diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts
new file mode 100644
index 00000000..e332377a
--- /dev/null
+++ b/src/__tests__/index.spec.ts
@@ -0,0 +1,7 @@
+import { Client } from '../index'
+
+describe('src spec', () => {
+	test('ensure client is defined', async () => {
+		expect(Client).toBeDefined()
+	})
+})
diff --git a/src/client/__tests__/client.spec.ts b/src/client/__tests__/client.spec.ts
index 2d390ca6..1ecae022 100644
--- a/src/client/__tests__/client.spec.ts
+++ b/src/client/__tests__/client.spec.ts
@@ -1,17 +1,11 @@
 // @ts-nocheck
 import { AbstractAuthentication } from '../auth/abstractAuthentication'
-import { AttestedAddress } from '../auth/attestedAddress'
 import { Client } from '../index'
 import { TicketZKProof } from '../auth/ticketZKProof'
-import { URLNS } from '../../core/messaging'
-import { Outlet, defaultConfig } from '../../outlet/index'
-import { Client as client_2_0, Outlet as outlet_2_0 } from 'tn2_0'
-import { Client as client_2_2, Outlet as outlet_2_2 } from 'tn2_2'
 import { OffChainTokenConfig } from '../interface'
+import { TextEncoder, TextDecoder } from 'util';
 
-function delay(time) {
-	return new Promise((resolve) => setTimeout(resolve, time))
-}
+Object.assign(global, { TextDecoder, TextEncoder });
 
 let tokenIssuer: OffChainTokenConfig = {
 	collectionID: 'devcon',
@@ -27,37 +21,8 @@ let tokenIssuer: OffChainTokenConfig = {
 	base64attestorPubKey: '',
 }
 
-let tokenIssuer2: OffChainTokenConfig = {
-	collectionID: 'edcon',
-	title: 'Devcon',
-	onChain: false,
-	tokenOrigin: 'http://some.url/',
-	attestationOrigin: 'https://stage.attestation.id/',
-	unEndPoint: 'https://crypto-verify.herokuapp.com/use-devcon-ticket',
-	image: 'https://raw.githubusercontent.com/TokenScript/token-negotiator/main/mock-images/devcon.svg',
-	base64senderPublicKeys: {
-		10: 'MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAGJAHCiHbrCNAY9fAMdom4dGD6v/KkTIgRCkwLCjXFTkXWGrCEXHaZ8kWwdqlu0oYCrNQ2vdlqOl0s26/LzO8A==|MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAGJAHCiHbrCNAY9fAMdom4dGD6v/KkTIgRCkwLCjXFTkXWGrCEXHaZ8kWwdqlu0oYCrNQ2vdlqOl0s26/LzO8B==',
-	},
-	base64attestorPubKey: '',
-}
-
-let tokenIssuer3: OffChainTokenConfig = {
-	collectionID: 'devconnect',
-	title: 'Devcon',
-	onChain: false,
-	tokenOrigin: 'http://some.url/',
-	attestationOrigin: 'https://stage.attestation.id/',
-	unEndPoint: 'https://crypto-verify.herokuapp.com/use-devcon-ticket',
-	image: 'https://raw.githubusercontent.com/TokenScript/token-negotiator/main/mock-images/devcon.svg',
-	base64senderPublicKeys: {
-		55: 'MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAGJAHCiHbrCNAY9fAMdom4dGD6v/KkTIgRCkwLCjXFTkXWGrCEXHaZ8kWwdqlu0oYCrNQ2vdlqOl0s26/LzO8A==',
-	},
-	base64attestorPubKey: '',
-}
-
 const config = {
 	type: 'passive',
-	// requred to force redirect mode for Client 2.2
 	enableOffChainRedirectMode: true,
 	issuers: [tokenIssuer],
 }
@@ -126,6 +91,7 @@ class LocalStorageMock {
 }
 
 describe('client spec', () => {
+
 	test('tokenNegotiatorClient a failed new instance of client - missing issuers key', () => {
 		let client = new Client({
 			type: 'passive',
@@ -137,6 +103,54 @@ describe('client spec', () => {
 		})
 	})
 
+	test('client library interface method switch theme can be used', () => {
+		const tokenNegotiatorClient = getOffChainConfigClient()
+		let client = new Client({
+			type: 'active',
+			issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(),
+			options: {},
+		})
+		client.negotiate().then(() => {
+			client.switchTheme('dark');
+		});
+	})
+
+	test('client library can add token via magic link', () => {
+		const tokenNegotiatorClient = getOffChainConfigClient()
+		let client = new Client({
+			type: 'active',
+			issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(),
+			options: {},
+		})
+		client.negotiate().then(() => {
+			client.addTokenViaMagicLink('https://outlet-stage.brandconnector.io/#type=asn&ticket=MIGTME0MATYCAgTUAgECBEEEDoIoocY3CRCPqbHzou84M7C-cWAfzrTnPwz7qWGWv3UVn53jWeTG8CSykYVk-SUdNwlGTiD-h8Xsf2cGzniNPQNCAK6Q153BMkBc9E2AR3MjEWNU_f-15Cl2w0EIvaqGoqYrHKSMm3CIjKik_KBRTzRrbQqM5lGe_jUivjhmfwR5HOUc&secret=6191295225924896663249851881131284553005448461740837624904453538708620527945&id=bob%40alice.com')
+		});
+	})
+
+	test('client can trigger promise to manage', () => {
+		const tokenNegotiatorClient = getOffChainConfigClient()
+		let client = new Client({
+			type: 'active',
+			issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(),
+			options: {},
+		})
+		client.negotiate().then(() => {
+			client.handleWalletRequired([]);
+		});
+	})
+
+	test('client can handle proof error', () => {
+		const tokenNegotiatorClient = getOffChainConfigClient()
+		let client = new Client({
+			type: 'active',
+			issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(),
+			options: {},
+		})
+		client.negotiate().then(() => {
+			client.handleProofError({ error: 'something went wrong' }, 'devconVi');
+		});
+	})
+
 	test('tokenNegotiatorClient a failed new instance of client - missing issuers length', () => {
 		let client = new Client({
 			type: 'passive',
@@ -496,121 +510,3 @@ describe('client spec', () => {
 	})
 
 })
-
-// TODO: Reimplement cross-version test for version 3.1
-/* describe('client spec cross-version', () => {
-	let originalDocument = document
-	let originalLocation = window.location
-
-	const nonLocalUrl = 'https://non-local.url'
-
-	beforeAll(() => {
-		Object.defineProperty(global, 'document', {
-			value: {
-				location: {
-					href: '',
-					referrer: '',
-					hash: '',
-					search: '',
-					origin: '',
-				},
-				addEventListener: () => {
-					return true
-				},
-			},
-		})
-
-		Object.defineProperty(window, 'location', {
-			value: {
-				href: nonLocalUrl,
-				origin: nonLocalUrl,
-			},
-			writable: true, // possibility to override
-		})
-
-		// required to force redirect mode
-		window.navigator.brave = 1
-	})
-
-	afterAll(() => {
-		Object.defineProperty(global, 'document', {
-			value: originalDocument,
-		})
-
-		Object.defineProperty(window, 'location', {
-			value: originalLocation,
-		})
-	})
-
-	test('Outlet_2_0 save magicLink', async () => {
-		let magicLinkParams =
-			'?ticket=MIGTME0MATYCAgFNAgEBBEEEF6_tKK2dCfLQiwS4FuqmiQDVrafJ05vCOkYN4iT28JULCClrvI2_kGTxrL12sXlH9w9mohLQlMdmaWvFzaZVlgNCAKu7SESOLf7L5sjZPcTQVkAu9YTC88mNK8oyUjiP2gsnTUxr0BGr0eWSTYmbDqNlX3JXOEqvEH39LEQjWsXn44oc&secret=45845870684&mail=oleh.hryb.us@gmail.com'
-
-		window.location.search = magicLinkParams
-
-		// LocalStorage must be empty
-		expect(localStorage.getItem(defaultConfig.itemStorageKey)).toBe(null)
-		new outlet_2_0(tokenIssuer)
-
-		expect(localStorage.getItem(defaultConfig.itemStorageKey)).toContain(magicLinkParams)
-	})
-
-	test('Redirect Client_lastest -> Outlet 2.2', async () => {
-		let client = new Client(config)
-
-		// prepare Redirect URL
-		await client.negotiate()
-		let url = new URL(window.location.href)
-		expect(new URLSearchParams(url.hash.substring(1)).get('action')).toBe('get-issuer-tokens')
-
-		window.location.hash = url.hash
-		new outlet_2_2(tokenIssuer)
-
-		// need delay, because pageOnLoadEventHandler() is async
-		await delay(1000)
-
-		let hash = new URL(document.location.href).hash.substring(1)
-		expect(new URLSearchParams(hash).get('action')).toBe('get-issuer-tokens-response')
-	})
-
-	test('Redirect Client_2.2 -> Outlet_lastest', async () => {
-		let client = new client_2_2(config)
-
-		window.location.hash = ''
-		window.location.href = 'http://localhost'
-		document.location.hash = ''
-		document.location.href = 'http://localhost'
-		// prepare Redirect URL
-		await client.negotiate()
-		let url = new URL(document.location.href)
-		expect(new URLSearchParams(url.hash.substring(1)).get('action')).toBe('get-issuer-tokens')
-
-		// console.log(
-		// 	`window.location.hash = "${window.location.hash}",
-		// 	window.location.href = "${window.location.href}",
-		// 	document.location.hash = "${document.location.hash}",
-		// 	document.location.href = "${document.location.href}",`
-		// )
-
-		window.location.hash = url.hash
-		document.location.hash = url.hash
-		document.referrer = nonLocalUrl
-		localStorage.setItem('tn-whitelist', '{"https://non-local.url":{"type":"read"}}')
-
-		new Outlet(tokenIssuer)
-
-		// need delay, because pageOnLoadEventHandler() is async
-		await delay(1000)
-
-		let hash = new URL(window.location.href).hash.substring(1)
-		expect(new URLSearchParams(hash).get('action')).toBe('get-issuer-tokens-response')
-	})
-
-	test('tokenNegotiatorClient read prefixed param', async () => {
-		window.location.hash = `p1=1&${URLNS}p2=2`
-		let client = getOffChainConfigClient()
-
-		expect(client.getDataFromQuery('p2')).toBe('2')
-		expect(client.getDataFromQuery('p1')).toBe('1')
-	})
-})*/