@0xsequence/waas
Advanced tools
Comparing version 0.0.0-20240429153138 to 0.0.0-20240429172204
@@ -7,4 +7,4 @@ 'use strict'; | ||
var jsonCanonicalize = require('json-canonicalize'); | ||
var idb = require('idb'); | ||
var network = require('@0xsequence/network'); | ||
var idb = require('idb'); | ||
var jwtDecode = require('jwt-decode'); | ||
@@ -355,2 +355,8 @@ var clientCognitoIdentityProvider = require('@aws-sdk/client-cognito-identity-provider'); | ||
} | ||
class TenantNotFoundError extends WebrpcError { | ||
constructor(name = 'TenantNotFound', code = 1001, message = 'Tenant not found', status = 0, cause) { | ||
super(name, code, message, status, cause); | ||
Object.setPrototypeOf(this, TenantNotFoundError.prototype); | ||
} | ||
} | ||
const webrpcErrorByCode = { | ||
@@ -368,3 +374,4 @@ [0]: WebrpcEndpointError, | ||
[-10]: WebrpcStreamFinishedError, | ||
[1000]: UnauthorizedError | ||
[1000]: UnauthorizedError, | ||
[1001]: TenantNotFoundError | ||
}; | ||
@@ -813,7 +820,7 @@ | ||
const idbStoreName$1 = 'seq-waas-session'; | ||
async function newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend) { | ||
const privateKey = await secureStoreBackend.get(idbName$1, idbStoreName$1, sessionId); | ||
if (!privateKey) { | ||
throw new Error('No private key found'); | ||
} | ||
async function newSECP256K1SessionFromSessionId(sessionId) { | ||
const db = await idb.openDB(idbName$1); | ||
const tx = db.transaction(idbStoreName$1, 'readonly'); | ||
const privateKey = await db.get(idbStoreName$1, sessionId); | ||
await tx.done; | ||
const wallet = new ethers.ethers.Wallet(privateKey); | ||
@@ -827,16 +834,24 @@ return { | ||
}, | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName$1, idbStoreName$1, sessionId); | ||
clear() { | ||
db.delete(idbStoreName$1, sessionId); | ||
} | ||
}; | ||
} | ||
async function newSECP256K1SessionFromPrivateKey(privateKey, secureStoreBackend) { | ||
async function newSECP256K1SessionFromPrivateKey(privateKey) { | ||
const wallet = new ethers.ethers.Wallet(privateKey); | ||
const db = await idb.openDB(idbName$1, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName$1); | ||
} | ||
}); | ||
const sessionId = await wallet.getAddress(); | ||
await secureStoreBackend.set(idbName$1, idbStoreName$1, sessionId, privateKey); | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend); | ||
const tx = db.transaction(idbStoreName$1, 'readwrite'); | ||
await db.put(idbStoreName$1, privateKey, sessionId); | ||
await tx.done; | ||
db.close(); | ||
return newSECP256K1SessionFromSessionId(sessionId); | ||
} | ||
async function newSECP256K1Session(secureStoreBackend) { | ||
async function newSECP256K1Session() { | ||
const wallet = ethers.ethers.Wallet.createRandom(); | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey, secureStoreBackend); | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey); | ||
} | ||
@@ -852,17 +867,11 @@ | ||
const idbStoreName = 'seq-waas-session'; | ||
// TODO: We need to update this to use the secure store backend | ||
// Currently it ignores the override and leverages idb | ||
// This is because the CryptoKeyPair is a bit more complicated | ||
// than a simple string that SecureStoreBackend can handle | ||
async function newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) { | ||
const keys = await secureStoreBackend.get(idbName, idbStoreName, sessionId); | ||
if (!keys || !keys.privateKey) { | ||
throw new Error('No private key found'); | ||
} | ||
async function newSECP256R1SessionFromSessionId(sessionId) { | ||
const db = await idb.openDB(idbName); | ||
const tx = db.transaction(idbStoreName, 'readonly'); | ||
const keys = await db.get(idbStoreName, sessionId); | ||
await tx.done; | ||
const encoder = new TextEncoder(); | ||
return { | ||
sessionId: async () => { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', keys.publicKey); | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', keys.publicKey); | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1); | ||
@@ -884,3 +893,3 @@ | ||
} | ||
const signatureBuff = await cryptoBackend.sign({ | ||
const signatureBuff = await window.crypto.subtle.sign({ | ||
name: 'ECDSA', | ||
@@ -894,20 +903,28 @@ hash: { | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName, idbStoreName, sessionId); | ||
await db.delete(idbStoreName, sessionId); | ||
} | ||
}; | ||
} | ||
async function newSECP256R1SessionFromKeyPair(keyPair, cryptoBackend, secureStoreBackend) { | ||
const sessionId = await pubKeyToSessionId(cryptoBackend, keyPair.publicKey); | ||
await secureStoreBackend.set(idbName, idbStoreName, sessionId, keyPair); | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend); | ||
async function newSECP256R1SessionFromKeyPair(keyPair) { | ||
const sessionId = await pubKeyToSessionId(keyPair.publicKey); | ||
const db = await idb.openDB(idbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName); | ||
} | ||
}); | ||
const tx = db.transaction(idbStoreName, 'readwrite'); | ||
await db.put(idbStoreName, keyPair, sessionId); | ||
await tx.done; | ||
db.close(); | ||
return newSECP256R1SessionFromSessionId(sessionId); | ||
} | ||
async function newSECP256R1Session(cryptoBackend, secureStoreBackend) { | ||
const generatedKeys = await cryptoBackend.generateKey({ | ||
async function newSECP256R1Session() { | ||
const generatedKeys = await window.crypto.subtle.generateKey({ | ||
name: 'ECDSA', | ||
namedCurve: 'P-256' | ||
}, false, ['sign', 'verify']); | ||
return newSECP256R1SessionFromKeyPair(generatedKeys, cryptoBackend, secureStoreBackend); | ||
return newSECP256R1SessionFromKeyPair(generatedKeys); | ||
} | ||
async function pubKeyToSessionId(cryptoBackend, pubKey) { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', pubKey); | ||
async function pubKeyToSessionId(pubKey) { | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', pubKey); | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1); | ||
@@ -921,22 +938,19 @@ | ||
async function newSessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend); | ||
async function newSessionFromSessionId(sessionId) { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1SessionFromSessionId(sessionId); | ||
} else { | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend); | ||
return newSECP256K1SessionFromSessionId(sessionId); | ||
} | ||
} | ||
async function newSession(cryptoBackend, secureStoreBackend) { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1Session(cryptoBackend, secureStoreBackend); | ||
async function newSession() { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1Session(); | ||
} else { | ||
return newSECP256K1Session(secureStoreBackend); | ||
return newSECP256K1Session(); | ||
} | ||
} | ||
function isSubtleCryptoAvailable() { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object'; | ||
} | ||
@@ -981,94 +995,2 @@ const RPC_BASE = 'https://nodes.sequence.app/'; | ||
const getDefaultSubtleCryptoBackend = () => { | ||
if (isWindowSubtleCryptoAvailable()) { | ||
return new WindowSubtleCryptoBackend(); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
function isWindowSubtleCryptoAvailable() { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object'; | ||
} | ||
class WindowSubtleCryptoBackend { | ||
constructor() { | ||
if (!isWindowSubtleCryptoAvailable()) { | ||
throw new Error('window.crypto.subtle is not available'); | ||
} | ||
} | ||
async generateKey(algorithm, extractable, keyUsages) { | ||
return window.crypto.subtle.generateKey(algorithm, extractable, keyUsages); | ||
} | ||
async exportKey(format, key) { | ||
const keyData = await window.crypto.subtle.exportKey(format, key); | ||
return new Uint8Array(keyData); | ||
} | ||
async digest(algorithm, data) { | ||
const digest = await window.crypto.subtle.digest(algorithm, data); | ||
return new Uint8Array(digest); | ||
} | ||
async sign(algorithm, key, data) { | ||
const signature = await window.crypto.subtle.sign(algorithm, key, data); | ||
return new Uint8Array(signature); | ||
} | ||
async verify(algorithm, key, signature, data) { | ||
return window.crypto.subtle.verify(algorithm, key, signature, data); | ||
} | ||
getRandomValues(len) { | ||
const randomValues = new Uint8Array(len); | ||
return window.crypto.getRandomValues(randomValues); | ||
} | ||
} | ||
const getDefaultSecureStoreBackend = () => { | ||
if (isIndexedDbAvailable()) { | ||
return new IndexedDbSecureStoreBackend(); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
function isIndexedDbAvailable() { | ||
return typeof indexedDB === 'object'; | ||
} | ||
class IndexedDbSecureStoreBackend { | ||
constructor() { | ||
this.db = void 0; | ||
if (!isIndexedDbAvailable()) { | ||
throw new Error('IndexedDB is not available'); | ||
} | ||
this.db = null; | ||
} | ||
async openDB(dbName, dbStoreName, version) { | ||
if (this.db) { | ||
return this.db; | ||
} | ||
this.db = await idb.openDB(dbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(dbStoreName); | ||
} | ||
}); | ||
return this.db; | ||
} | ||
async get(dbName, dbStoreName, key) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readonly'); | ||
const value = await db.get(dbStoreName, key); | ||
await tx.done; | ||
return value; | ||
} | ||
async set(dbName, dbStoreName, key, value) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readwrite'); | ||
await db.put(dbStoreName, value, key); | ||
await tx.done; | ||
return true; | ||
} | ||
async delete(dbName, dbStoreName, key) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readwrite'); | ||
await db.delete(dbStoreName, key); | ||
await tx.done; | ||
return true; | ||
} | ||
} | ||
const SEQUENCE_WAAS_WALLET_KEY = '@0xsequence.waas.wallet'; | ||
@@ -1083,7 +1005,5 @@ const SEQUENCE_WAAS_SESSION_ID_KEY = '@0xsequence.waas.session_id'; | ||
network: 1 | ||
}, store = new LocalStore(), cryptoBackend = getDefaultSubtleCryptoBackend(), secureStoreBackend = getDefaultSecureStoreBackend()) { | ||
}, store = new LocalStore()) { | ||
this.config = config; | ||
this.store = store; | ||
this.cryptoBackend = cryptoBackend; | ||
this.secureStoreBackend = secureStoreBackend; | ||
this.VERSION = '0.0.0-dev1'; | ||
@@ -1134,3 +1054,3 @@ this.status = void 0; | ||
} | ||
const session = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const session = await newSessionFromSessionId(sessionId); | ||
return signIntent(session, intent); | ||
@@ -1143,3 +1063,3 @@ } | ||
} | ||
const signer = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const signer = await newSessionFromSessionId(sessionId); | ||
return signer.sign(message); | ||
@@ -1160,3 +1080,3 @@ } | ||
if (!sessionId) { | ||
const session = await newSession(_this.cryptoBackend, _this.secureStoreBackend); | ||
const session = await newSession(); | ||
sessionId = await session.sessionId(); | ||
@@ -1528,8 +1448,7 @@ await _this.sessionId.set(sessionId); | ||
console.warn('window.crypto.getRandomValues is not available. Falling back to less secure Math.random().'); | ||
const _randomValues = new Uint8Array(len); | ||
for (let i = 0; i < len; i++) { | ||
const randomInteger = Math.floor(Math.random() * 256); | ||
_randomValues[i] = randomInteger; | ||
randomValues[i] = randomInteger; | ||
} | ||
return _randomValues; | ||
return randomValues; | ||
} | ||
@@ -1557,6 +1476,4 @@ } | ||
class SequenceWaaS { | ||
constructor(config, preset = LOCAL, store = new LocalStore(), cryptoBackend = getDefaultSubtleCryptoBackend(), secureStoreBackend = getDefaultSecureStoreBackend()) { | ||
constructor(config, preset = LOCAL, store = new LocalStore()) { | ||
this.store = store; | ||
this.cryptoBackend = cryptoBackend; | ||
this.secureStoreBackend = secureStoreBackend; | ||
this.waas = void 0; | ||
@@ -1574,3 +1491,3 @@ this.client = void 0; | ||
network: 1 | ||
}, config), this.store, this.cryptoBackend, this.secureStoreBackend); | ||
}, config), this.store); | ||
this.client = new WaasAuthenticator(this.config.rpcServer, this.fetch.bind(this)); | ||
@@ -1726,6 +1643,3 @@ this.deviceName = new StoreObj(this.store, '@0xsequence.waas.auth.deviceName', undefined); | ||
if (closeSessionId === thisSessionId) { | ||
if (!this.secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
const session = await newSessionFromSessionId(thisSessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const session = await newSessionFromSessionId(thisSessionId); | ||
session.clear(); | ||
@@ -1732,0 +1646,0 @@ await this.waas.completeSignOut(); |
@@ -7,4 +7,4 @@ 'use strict'; | ||
var jsonCanonicalize = require('json-canonicalize'); | ||
var idb = require('idb'); | ||
var network = require('@0xsequence/network'); | ||
var idb = require('idb'); | ||
var jwtDecode = require('jwt-decode'); | ||
@@ -355,2 +355,8 @@ var clientCognitoIdentityProvider = require('@aws-sdk/client-cognito-identity-provider'); | ||
} | ||
class TenantNotFoundError extends WebrpcError { | ||
constructor(name = 'TenantNotFound', code = 1001, message = 'Tenant not found', status = 0, cause) { | ||
super(name, code, message, status, cause); | ||
Object.setPrototypeOf(this, TenantNotFoundError.prototype); | ||
} | ||
} | ||
const webrpcErrorByCode = { | ||
@@ -368,3 +374,4 @@ [0]: WebrpcEndpointError, | ||
[-10]: WebrpcStreamFinishedError, | ||
[1000]: UnauthorizedError | ||
[1000]: UnauthorizedError, | ||
[1001]: TenantNotFoundError | ||
}; | ||
@@ -813,7 +820,7 @@ | ||
const idbStoreName$1 = 'seq-waas-session'; | ||
async function newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend) { | ||
const privateKey = await secureStoreBackend.get(idbName$1, idbStoreName$1, sessionId); | ||
if (!privateKey) { | ||
throw new Error('No private key found'); | ||
} | ||
async function newSECP256K1SessionFromSessionId(sessionId) { | ||
const db = await idb.openDB(idbName$1); | ||
const tx = db.transaction(idbStoreName$1, 'readonly'); | ||
const privateKey = await db.get(idbStoreName$1, sessionId); | ||
await tx.done; | ||
const wallet = new ethers.ethers.Wallet(privateKey); | ||
@@ -827,16 +834,24 @@ return { | ||
}, | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName$1, idbStoreName$1, sessionId); | ||
clear() { | ||
db.delete(idbStoreName$1, sessionId); | ||
} | ||
}; | ||
} | ||
async function newSECP256K1SessionFromPrivateKey(privateKey, secureStoreBackend) { | ||
async function newSECP256K1SessionFromPrivateKey(privateKey) { | ||
const wallet = new ethers.ethers.Wallet(privateKey); | ||
const db = await idb.openDB(idbName$1, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName$1); | ||
} | ||
}); | ||
const sessionId = await wallet.getAddress(); | ||
await secureStoreBackend.set(idbName$1, idbStoreName$1, sessionId, privateKey); | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend); | ||
const tx = db.transaction(idbStoreName$1, 'readwrite'); | ||
await db.put(idbStoreName$1, privateKey, sessionId); | ||
await tx.done; | ||
db.close(); | ||
return newSECP256K1SessionFromSessionId(sessionId); | ||
} | ||
async function newSECP256K1Session(secureStoreBackend) { | ||
async function newSECP256K1Session() { | ||
const wallet = ethers.ethers.Wallet.createRandom(); | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey, secureStoreBackend); | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey); | ||
} | ||
@@ -852,17 +867,11 @@ | ||
const idbStoreName = 'seq-waas-session'; | ||
// TODO: We need to update this to use the secure store backend | ||
// Currently it ignores the override and leverages idb | ||
// This is because the CryptoKeyPair is a bit more complicated | ||
// than a simple string that SecureStoreBackend can handle | ||
async function newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) { | ||
const keys = await secureStoreBackend.get(idbName, idbStoreName, sessionId); | ||
if (!keys || !keys.privateKey) { | ||
throw new Error('No private key found'); | ||
} | ||
async function newSECP256R1SessionFromSessionId(sessionId) { | ||
const db = await idb.openDB(idbName); | ||
const tx = db.transaction(idbStoreName, 'readonly'); | ||
const keys = await db.get(idbStoreName, sessionId); | ||
await tx.done; | ||
const encoder = new TextEncoder(); | ||
return { | ||
sessionId: async () => { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', keys.publicKey); | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', keys.publicKey); | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1); | ||
@@ -884,3 +893,3 @@ | ||
} | ||
const signatureBuff = await cryptoBackend.sign({ | ||
const signatureBuff = await window.crypto.subtle.sign({ | ||
name: 'ECDSA', | ||
@@ -894,20 +903,28 @@ hash: { | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName, idbStoreName, sessionId); | ||
await db.delete(idbStoreName, sessionId); | ||
} | ||
}; | ||
} | ||
async function newSECP256R1SessionFromKeyPair(keyPair, cryptoBackend, secureStoreBackend) { | ||
const sessionId = await pubKeyToSessionId(cryptoBackend, keyPair.publicKey); | ||
await secureStoreBackend.set(idbName, idbStoreName, sessionId, keyPair); | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend); | ||
async function newSECP256R1SessionFromKeyPair(keyPair) { | ||
const sessionId = await pubKeyToSessionId(keyPair.publicKey); | ||
const db = await idb.openDB(idbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName); | ||
} | ||
}); | ||
const tx = db.transaction(idbStoreName, 'readwrite'); | ||
await db.put(idbStoreName, keyPair, sessionId); | ||
await tx.done; | ||
db.close(); | ||
return newSECP256R1SessionFromSessionId(sessionId); | ||
} | ||
async function newSECP256R1Session(cryptoBackend, secureStoreBackend) { | ||
const generatedKeys = await cryptoBackend.generateKey({ | ||
async function newSECP256R1Session() { | ||
const generatedKeys = await window.crypto.subtle.generateKey({ | ||
name: 'ECDSA', | ||
namedCurve: 'P-256' | ||
}, false, ['sign', 'verify']); | ||
return newSECP256R1SessionFromKeyPair(generatedKeys, cryptoBackend, secureStoreBackend); | ||
return newSECP256R1SessionFromKeyPair(generatedKeys); | ||
} | ||
async function pubKeyToSessionId(cryptoBackend, pubKey) { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', pubKey); | ||
async function pubKeyToSessionId(pubKey) { | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', pubKey); | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1); | ||
@@ -921,22 +938,19 @@ | ||
async function newSessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend); | ||
async function newSessionFromSessionId(sessionId) { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1SessionFromSessionId(sessionId); | ||
} else { | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend); | ||
return newSECP256K1SessionFromSessionId(sessionId); | ||
} | ||
} | ||
async function newSession(cryptoBackend, secureStoreBackend) { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1Session(cryptoBackend, secureStoreBackend); | ||
async function newSession() { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1Session(); | ||
} else { | ||
return newSECP256K1Session(secureStoreBackend); | ||
return newSECP256K1Session(); | ||
} | ||
} | ||
function isSubtleCryptoAvailable() { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object'; | ||
} | ||
@@ -981,94 +995,2 @@ const RPC_BASE = 'https://nodes.sequence.app/'; | ||
const getDefaultSubtleCryptoBackend = () => { | ||
if (isWindowSubtleCryptoAvailable()) { | ||
return new WindowSubtleCryptoBackend(); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
function isWindowSubtleCryptoAvailable() { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object'; | ||
} | ||
class WindowSubtleCryptoBackend { | ||
constructor() { | ||
if (!isWindowSubtleCryptoAvailable()) { | ||
throw new Error('window.crypto.subtle is not available'); | ||
} | ||
} | ||
async generateKey(algorithm, extractable, keyUsages) { | ||
return window.crypto.subtle.generateKey(algorithm, extractable, keyUsages); | ||
} | ||
async exportKey(format, key) { | ||
const keyData = await window.crypto.subtle.exportKey(format, key); | ||
return new Uint8Array(keyData); | ||
} | ||
async digest(algorithm, data) { | ||
const digest = await window.crypto.subtle.digest(algorithm, data); | ||
return new Uint8Array(digest); | ||
} | ||
async sign(algorithm, key, data) { | ||
const signature = await window.crypto.subtle.sign(algorithm, key, data); | ||
return new Uint8Array(signature); | ||
} | ||
async verify(algorithm, key, signature, data) { | ||
return window.crypto.subtle.verify(algorithm, key, signature, data); | ||
} | ||
getRandomValues(len) { | ||
const randomValues = new Uint8Array(len); | ||
return window.crypto.getRandomValues(randomValues); | ||
} | ||
} | ||
const getDefaultSecureStoreBackend = () => { | ||
if (isIndexedDbAvailable()) { | ||
return new IndexedDbSecureStoreBackend(); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
function isIndexedDbAvailable() { | ||
return typeof indexedDB === 'object'; | ||
} | ||
class IndexedDbSecureStoreBackend { | ||
constructor() { | ||
this.db = void 0; | ||
if (!isIndexedDbAvailable()) { | ||
throw new Error('IndexedDB is not available'); | ||
} | ||
this.db = null; | ||
} | ||
async openDB(dbName, dbStoreName, version) { | ||
if (this.db) { | ||
return this.db; | ||
} | ||
this.db = await idb.openDB(dbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(dbStoreName); | ||
} | ||
}); | ||
return this.db; | ||
} | ||
async get(dbName, dbStoreName, key) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readonly'); | ||
const value = await db.get(dbStoreName, key); | ||
await tx.done; | ||
return value; | ||
} | ||
async set(dbName, dbStoreName, key, value) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readwrite'); | ||
await db.put(dbStoreName, value, key); | ||
await tx.done; | ||
return true; | ||
} | ||
async delete(dbName, dbStoreName, key) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readwrite'); | ||
await db.delete(dbStoreName, key); | ||
await tx.done; | ||
return true; | ||
} | ||
} | ||
const SEQUENCE_WAAS_WALLET_KEY = '@0xsequence.waas.wallet'; | ||
@@ -1083,7 +1005,5 @@ const SEQUENCE_WAAS_SESSION_ID_KEY = '@0xsequence.waas.session_id'; | ||
network: 1 | ||
}, store = new LocalStore(), cryptoBackend = getDefaultSubtleCryptoBackend(), secureStoreBackend = getDefaultSecureStoreBackend()) { | ||
}, store = new LocalStore()) { | ||
this.config = config; | ||
this.store = store; | ||
this.cryptoBackend = cryptoBackend; | ||
this.secureStoreBackend = secureStoreBackend; | ||
this.VERSION = '0.0.0-dev1'; | ||
@@ -1134,3 +1054,3 @@ this.status = void 0; | ||
} | ||
const session = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const session = await newSessionFromSessionId(sessionId); | ||
return signIntent(session, intent); | ||
@@ -1143,3 +1063,3 @@ } | ||
} | ||
const signer = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const signer = await newSessionFromSessionId(sessionId); | ||
return signer.sign(message); | ||
@@ -1160,3 +1080,3 @@ } | ||
if (!sessionId) { | ||
const session = await newSession(_this.cryptoBackend, _this.secureStoreBackend); | ||
const session = await newSession(); | ||
sessionId = await session.sessionId(); | ||
@@ -1528,8 +1448,7 @@ await _this.sessionId.set(sessionId); | ||
console.warn('window.crypto.getRandomValues is not available. Falling back to less secure Math.random().'); | ||
const _randomValues = new Uint8Array(len); | ||
for (let i = 0; i < len; i++) { | ||
const randomInteger = Math.floor(Math.random() * 256); | ||
_randomValues[i] = randomInteger; | ||
randomValues[i] = randomInteger; | ||
} | ||
return _randomValues; | ||
return randomValues; | ||
} | ||
@@ -1557,6 +1476,4 @@ } | ||
class SequenceWaaS { | ||
constructor(config, preset = LOCAL, store = new LocalStore(), cryptoBackend = getDefaultSubtleCryptoBackend(), secureStoreBackend = getDefaultSecureStoreBackend()) { | ||
constructor(config, preset = LOCAL, store = new LocalStore()) { | ||
this.store = store; | ||
this.cryptoBackend = cryptoBackend; | ||
this.secureStoreBackend = secureStoreBackend; | ||
this.waas = void 0; | ||
@@ -1574,3 +1491,3 @@ this.client = void 0; | ||
network: 1 | ||
}, config), this.store, this.cryptoBackend, this.secureStoreBackend); | ||
}, config), this.store); | ||
this.client = new WaasAuthenticator(this.config.rpcServer, this.fetch.bind(this)); | ||
@@ -1726,6 +1643,3 @@ this.deviceName = new StoreObj(this.store, '@0xsequence.waas.auth.deviceName', undefined); | ||
if (closeSessionId === thisSessionId) { | ||
if (!this.secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
const session = await newSessionFromSessionId(thisSessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const session = await newSessionFromSessionId(thisSessionId); | ||
session.clear(); | ||
@@ -1732,0 +1646,0 @@ await this.waas.completeSignOut(); |
import { ethers } from 'ethers'; | ||
import { canonicalize } from 'json-canonicalize'; | ||
import { openDB } from 'idb'; | ||
import { networks as networks$1 } from '@0xsequence/network'; | ||
import { openDB } from 'idb'; | ||
import { jwtDecode } from 'jwt-decode'; | ||
@@ -350,2 +350,8 @@ import { CognitoIdentityProviderClient, SignUpCommand, InitiateAuthCommand, UserLambdaValidationException, RespondToAuthChallengeCommand } from '@aws-sdk/client-cognito-identity-provider'; | ||
} | ||
class TenantNotFoundError extends WebrpcError { | ||
constructor(name = 'TenantNotFound', code = 1001, message = 'Tenant not found', status = 0, cause) { | ||
super(name, code, message, status, cause); | ||
Object.setPrototypeOf(this, TenantNotFoundError.prototype); | ||
} | ||
} | ||
const webrpcErrorByCode = { | ||
@@ -363,3 +369,4 @@ [0]: WebrpcEndpointError, | ||
[-10]: WebrpcStreamFinishedError, | ||
[1000]: UnauthorizedError | ||
[1000]: UnauthorizedError, | ||
[1001]: TenantNotFoundError | ||
}; | ||
@@ -808,7 +815,7 @@ | ||
const idbStoreName$1 = 'seq-waas-session'; | ||
async function newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend) { | ||
const privateKey = await secureStoreBackend.get(idbName$1, idbStoreName$1, sessionId); | ||
if (!privateKey) { | ||
throw new Error('No private key found'); | ||
} | ||
async function newSECP256K1SessionFromSessionId(sessionId) { | ||
const db = await openDB(idbName$1); | ||
const tx = db.transaction(idbStoreName$1, 'readonly'); | ||
const privateKey = await db.get(idbStoreName$1, sessionId); | ||
await tx.done; | ||
const wallet = new ethers.Wallet(privateKey); | ||
@@ -822,16 +829,24 @@ return { | ||
}, | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName$1, idbStoreName$1, sessionId); | ||
clear() { | ||
db.delete(idbStoreName$1, sessionId); | ||
} | ||
}; | ||
} | ||
async function newSECP256K1SessionFromPrivateKey(privateKey, secureStoreBackend) { | ||
async function newSECP256K1SessionFromPrivateKey(privateKey) { | ||
const wallet = new ethers.Wallet(privateKey); | ||
const db = await openDB(idbName$1, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName$1); | ||
} | ||
}); | ||
const sessionId = await wallet.getAddress(); | ||
await secureStoreBackend.set(idbName$1, idbStoreName$1, sessionId, privateKey); | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend); | ||
const tx = db.transaction(idbStoreName$1, 'readwrite'); | ||
await db.put(idbStoreName$1, privateKey, sessionId); | ||
await tx.done; | ||
db.close(); | ||
return newSECP256K1SessionFromSessionId(sessionId); | ||
} | ||
async function newSECP256K1Session(secureStoreBackend) { | ||
async function newSECP256K1Session() { | ||
const wallet = ethers.Wallet.createRandom(); | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey, secureStoreBackend); | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey); | ||
} | ||
@@ -847,17 +862,11 @@ | ||
const idbStoreName = 'seq-waas-session'; | ||
// TODO: We need to update this to use the secure store backend | ||
// Currently it ignores the override and leverages idb | ||
// This is because the CryptoKeyPair is a bit more complicated | ||
// than a simple string that SecureStoreBackend can handle | ||
async function newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) { | ||
const keys = await secureStoreBackend.get(idbName, idbStoreName, sessionId); | ||
if (!keys || !keys.privateKey) { | ||
throw new Error('No private key found'); | ||
} | ||
async function newSECP256R1SessionFromSessionId(sessionId) { | ||
const db = await openDB(idbName); | ||
const tx = db.transaction(idbStoreName, 'readonly'); | ||
const keys = await db.get(idbStoreName, sessionId); | ||
await tx.done; | ||
const encoder = new TextEncoder(); | ||
return { | ||
sessionId: async () => { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', keys.publicKey); | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', keys.publicKey); | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1); | ||
@@ -879,3 +888,3 @@ | ||
} | ||
const signatureBuff = await cryptoBackend.sign({ | ||
const signatureBuff = await window.crypto.subtle.sign({ | ||
name: 'ECDSA', | ||
@@ -889,20 +898,28 @@ hash: { | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName, idbStoreName, sessionId); | ||
await db.delete(idbStoreName, sessionId); | ||
} | ||
}; | ||
} | ||
async function newSECP256R1SessionFromKeyPair(keyPair, cryptoBackend, secureStoreBackend) { | ||
const sessionId = await pubKeyToSessionId(cryptoBackend, keyPair.publicKey); | ||
await secureStoreBackend.set(idbName, idbStoreName, sessionId, keyPair); | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend); | ||
async function newSECP256R1SessionFromKeyPair(keyPair) { | ||
const sessionId = await pubKeyToSessionId(keyPair.publicKey); | ||
const db = await openDB(idbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName); | ||
} | ||
}); | ||
const tx = db.transaction(idbStoreName, 'readwrite'); | ||
await db.put(idbStoreName, keyPair, sessionId); | ||
await tx.done; | ||
db.close(); | ||
return newSECP256R1SessionFromSessionId(sessionId); | ||
} | ||
async function newSECP256R1Session(cryptoBackend, secureStoreBackend) { | ||
const generatedKeys = await cryptoBackend.generateKey({ | ||
async function newSECP256R1Session() { | ||
const generatedKeys = await window.crypto.subtle.generateKey({ | ||
name: 'ECDSA', | ||
namedCurve: 'P-256' | ||
}, false, ['sign', 'verify']); | ||
return newSECP256R1SessionFromKeyPair(generatedKeys, cryptoBackend, secureStoreBackend); | ||
return newSECP256R1SessionFromKeyPair(generatedKeys); | ||
} | ||
async function pubKeyToSessionId(cryptoBackend, pubKey) { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', pubKey); | ||
async function pubKeyToSessionId(pubKey) { | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', pubKey); | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1); | ||
@@ -916,22 +933,19 @@ | ||
async function newSessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend); | ||
async function newSessionFromSessionId(sessionId) { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1SessionFromSessionId(sessionId); | ||
} else { | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend); | ||
return newSECP256K1SessionFromSessionId(sessionId); | ||
} | ||
} | ||
async function newSession(cryptoBackend, secureStoreBackend) { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1Session(cryptoBackend, secureStoreBackend); | ||
async function newSession() { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1Session(); | ||
} else { | ||
return newSECP256K1Session(secureStoreBackend); | ||
return newSECP256K1Session(); | ||
} | ||
} | ||
function isSubtleCryptoAvailable() { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object'; | ||
} | ||
@@ -976,94 +990,2 @@ const RPC_BASE = 'https://nodes.sequence.app/'; | ||
const getDefaultSubtleCryptoBackend = () => { | ||
if (isWindowSubtleCryptoAvailable()) { | ||
return new WindowSubtleCryptoBackend(); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
function isWindowSubtleCryptoAvailable() { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object'; | ||
} | ||
class WindowSubtleCryptoBackend { | ||
constructor() { | ||
if (!isWindowSubtleCryptoAvailable()) { | ||
throw new Error('window.crypto.subtle is not available'); | ||
} | ||
} | ||
async generateKey(algorithm, extractable, keyUsages) { | ||
return window.crypto.subtle.generateKey(algorithm, extractable, keyUsages); | ||
} | ||
async exportKey(format, key) { | ||
const keyData = await window.crypto.subtle.exportKey(format, key); | ||
return new Uint8Array(keyData); | ||
} | ||
async digest(algorithm, data) { | ||
const digest = await window.crypto.subtle.digest(algorithm, data); | ||
return new Uint8Array(digest); | ||
} | ||
async sign(algorithm, key, data) { | ||
const signature = await window.crypto.subtle.sign(algorithm, key, data); | ||
return new Uint8Array(signature); | ||
} | ||
async verify(algorithm, key, signature, data) { | ||
return window.crypto.subtle.verify(algorithm, key, signature, data); | ||
} | ||
getRandomValues(len) { | ||
const randomValues = new Uint8Array(len); | ||
return window.crypto.getRandomValues(randomValues); | ||
} | ||
} | ||
const getDefaultSecureStoreBackend = () => { | ||
if (isIndexedDbAvailable()) { | ||
return new IndexedDbSecureStoreBackend(); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
function isIndexedDbAvailable() { | ||
return typeof indexedDB === 'object'; | ||
} | ||
class IndexedDbSecureStoreBackend { | ||
constructor() { | ||
this.db = void 0; | ||
if (!isIndexedDbAvailable()) { | ||
throw new Error('IndexedDB is not available'); | ||
} | ||
this.db = null; | ||
} | ||
async openDB(dbName, dbStoreName, version) { | ||
if (this.db) { | ||
return this.db; | ||
} | ||
this.db = await openDB(dbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(dbStoreName); | ||
} | ||
}); | ||
return this.db; | ||
} | ||
async get(dbName, dbStoreName, key) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readonly'); | ||
const value = await db.get(dbStoreName, key); | ||
await tx.done; | ||
return value; | ||
} | ||
async set(dbName, dbStoreName, key, value) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readwrite'); | ||
await db.put(dbStoreName, value, key); | ||
await tx.done; | ||
return true; | ||
} | ||
async delete(dbName, dbStoreName, key) { | ||
const db = await this.openDB(dbName, dbStoreName, 1); | ||
const tx = db.transaction(dbStoreName, 'readwrite'); | ||
await db.delete(dbStoreName, key); | ||
await tx.done; | ||
return true; | ||
} | ||
} | ||
const SEQUENCE_WAAS_WALLET_KEY = '@0xsequence.waas.wallet'; | ||
@@ -1078,7 +1000,5 @@ const SEQUENCE_WAAS_SESSION_ID_KEY = '@0xsequence.waas.session_id'; | ||
network: 1 | ||
}, store = new LocalStore(), cryptoBackend = getDefaultSubtleCryptoBackend(), secureStoreBackend = getDefaultSecureStoreBackend()) { | ||
}, store = new LocalStore()) { | ||
this.config = config; | ||
this.store = store; | ||
this.cryptoBackend = cryptoBackend; | ||
this.secureStoreBackend = secureStoreBackend; | ||
this.VERSION = '0.0.0-dev1'; | ||
@@ -1129,3 +1049,3 @@ this.status = void 0; | ||
} | ||
const session = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const session = await newSessionFromSessionId(sessionId); | ||
return signIntent(session, intent); | ||
@@ -1138,3 +1058,3 @@ } | ||
} | ||
const signer = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const signer = await newSessionFromSessionId(sessionId); | ||
return signer.sign(message); | ||
@@ -1155,3 +1075,3 @@ } | ||
if (!sessionId) { | ||
const session = await newSession(_this.cryptoBackend, _this.secureStoreBackend); | ||
const session = await newSession(); | ||
sessionId = await session.sessionId(); | ||
@@ -1523,8 +1443,7 @@ await _this.sessionId.set(sessionId); | ||
console.warn('window.crypto.getRandomValues is not available. Falling back to less secure Math.random().'); | ||
const _randomValues = new Uint8Array(len); | ||
for (let i = 0; i < len; i++) { | ||
const randomInteger = Math.floor(Math.random() * 256); | ||
_randomValues[i] = randomInteger; | ||
randomValues[i] = randomInteger; | ||
} | ||
return _randomValues; | ||
return randomValues; | ||
} | ||
@@ -1552,6 +1471,4 @@ } | ||
class SequenceWaaS { | ||
constructor(config, preset = LOCAL, store = new LocalStore(), cryptoBackend = getDefaultSubtleCryptoBackend(), secureStoreBackend = getDefaultSecureStoreBackend()) { | ||
constructor(config, preset = LOCAL, store = new LocalStore()) { | ||
this.store = store; | ||
this.cryptoBackend = cryptoBackend; | ||
this.secureStoreBackend = secureStoreBackend; | ||
this.waas = void 0; | ||
@@ -1569,3 +1486,3 @@ this.client = void 0; | ||
network: 1 | ||
}, config), this.store, this.cryptoBackend, this.secureStoreBackend); | ||
}, config), this.store); | ||
this.client = new WaasAuthenticator(this.config.rpcServer, this.fetch.bind(this)); | ||
@@ -1721,6 +1638,3 @@ this.deviceName = new StoreObj(this.store, '@0xsequence.waas.auth.deviceName', undefined); | ||
if (closeSessionId === thisSessionId) { | ||
if (!this.secureStoreBackend) { | ||
throw new Error('No secure store available'); | ||
} | ||
const session = await newSessionFromSessionId(thisSessionId, this.cryptoBackend, this.secureStoreBackend); | ||
const session = await newSessionFromSessionId(thisSessionId); | ||
session.clear(); | ||
@@ -1727,0 +1641,0 @@ await this.waas.completeSignOut(); |
@@ -9,4 +9,2 @@ import { Observer } from "./base.js"; | ||
import { EmailAuth } from "./email.js"; | ||
import { SubtleCryptoBackend } from "./subtle-crypto.js"; | ||
import { SecureStoreBackend } from "./secure-store.js"; | ||
export type Sessions = (Session & { | ||
@@ -44,4 +42,2 @@ isThis: boolean; | ||
private readonly store; | ||
private readonly cryptoBackend; | ||
private readonly secureStoreBackend; | ||
private waas; | ||
@@ -55,3 +51,3 @@ private client; | ||
private lastDate; | ||
constructor(config: SequenceConfig & Partial<ExtendedSequenceConfig>, preset?: ExtendedSequenceConfig, store?: Store, cryptoBackend?: SubtleCryptoBackend | null, secureStoreBackend?: SecureStoreBackend | null); | ||
constructor(config: SequenceConfig & Partial<ExtendedSequenceConfig>, preset?: ExtendedSequenceConfig, store?: Store); | ||
get email(): EmailAuth; | ||
@@ -58,0 +54,0 @@ onValidationRequired(callback: () => void): Promise<() => void>; |
@@ -6,4 +6,2 @@ import { Intent, SignedIntent, SignMessageArgs, SendTransactionsArgs, SendERC20Args, SendERC721Args, SendERC1155Args, SendDelayedEncodeArgs, GetTransactionReceiptArgs } from "./intents/index.js"; | ||
import { IntentDataFeeOptions, IntentDataFinishValidateSession, IntentDataGetSession, IntentDataGetTransactionReceipt, IntentDataOpenSession, IntentDataSendTransaction, IntentDataSignMessage, IntentDataValidateSession } from "./clients/intent.gen.js"; | ||
import { SubtleCryptoBackend } from "./subtle-crypto.js"; | ||
import { SecureStoreBackend } from "./secure-store.js"; | ||
export type SessionAuthProofArgs = { | ||
@@ -25,4 +23,2 @@ nonce?: string; | ||
private readonly store; | ||
private readonly cryptoBackend; | ||
private readonly secureStoreBackend; | ||
readonly VERSION = "0.0.0-dev1"; | ||
@@ -33,3 +29,3 @@ private readonly status; | ||
private sessionObservers; | ||
constructor(config?: SequenceBaseConfig, store?: Store, cryptoBackend?: SubtleCryptoBackend | null, secureStoreBackend?: SecureStoreBackend | null); | ||
constructor(config?: SequenceBaseConfig, store?: Store); | ||
getAddress(): Promise<string>; | ||
@@ -36,0 +32,0 @@ private getWalletAddress; |
export declare const WebRPCVersion = "v1"; | ||
export declare const WebRPCSchemaVersion = "v0.1.0"; | ||
export declare const WebRPCSchemaHash = "57f5bd68170564b26d4854ab5a90faa3809bd20e"; | ||
export declare const WebRPCSchemaHash = "a175abb1a964c85ae743ed2577a103e44fd93f7c"; | ||
export interface Intent { | ||
@@ -36,4 +36,3 @@ version: string; | ||
ver: string; | ||
branch: string; | ||
commitHash: string; | ||
pcr0: string; | ||
} | ||
@@ -53,4 +52,3 @@ export interface Chain { | ||
iss: string; | ||
azp?: string; | ||
aud?: string; | ||
aud: Array<string>; | ||
} | ||
@@ -162,2 +160,3 @@ export interface Tenant { | ||
allowedOrigins: Array<string>; | ||
password?: string; | ||
} | ||
@@ -247,2 +246,5 @@ export interface CreateTenantReturn { | ||
} | ||
export declare class TenantNotFoundError extends WebrpcError { | ||
constructor(name?: string, code?: number, message?: string, status?: number, cause?: string); | ||
} | ||
export declare enum errors { | ||
@@ -260,4 +262,5 @@ WebrpcEndpoint = "WebrpcEndpoint", | ||
WebrpcStreamFinished = "WebrpcStreamFinished", | ||
Unauthorized = "Unauthorized" | ||
Unauthorized = "Unauthorized", | ||
TenantNotFound = "TenantNotFound" | ||
} | ||
export type Fetch = (input: RequestInfo, init?: RequestInit) => Promise<Response>; |
@@ -7,4 +7,3 @@ export * from "./base.js"; | ||
export { erc20, erc721, erc1155, delayedEncode } from "./intents/transactions.js"; | ||
export type { SecureStoreBackend } from "./secure-store.js"; | ||
export * from "./intents/responses.js"; | ||
export * as defaults from "./defaults.js"; |
@@ -1,3 +0,1 @@ | ||
import { SubtleCryptoBackend } from "../subtle-crypto.js"; | ||
import { SecureStoreBackend } from "../secure-store.js"; | ||
export type Session = { | ||
@@ -8,5 +6,6 @@ sessionId(): Promise<string>; | ||
}; | ||
export declare function newSessionFromSessionId(sessionId: string, cryptoBackend: SubtleCryptoBackend | null, secureStoreBackend: SecureStoreBackend | null): Promise<Session>; | ||
export declare function newSession(cryptoBackend: SubtleCryptoBackend | null, secureStoreBackend: SecureStoreBackend | null): Promise<Session>; | ||
export declare function newSessionFromSessionId(sessionId: string): Promise<Session>; | ||
export declare function newSession(): Promise<Session>; | ||
export declare function isSubtleCryptoAvailable(): boolean; | ||
export * from "./secp256r1.js"; | ||
export * from "./secp256k1.js"; |
@@ -1,5 +0,4 @@ | ||
import { SecureStoreBackend } from "../secure-store.js"; | ||
import { Session } from "./index.js"; | ||
export declare function newSECP256K1SessionFromSessionId(sessionId: string, secureStoreBackend: SecureStoreBackend): Promise<Session>; | ||
export declare function newSECP256K1SessionFromPrivateKey(privateKey: string, secureStoreBackend: SecureStoreBackend): Promise<Session>; | ||
export declare function newSECP256K1Session(secureStoreBackend: SecureStoreBackend): Promise<Session>; | ||
export declare function newSECP256K1SessionFromSessionId(sessionId: string): Promise<Session>; | ||
export declare function newSECP256K1SessionFromPrivateKey(privateKey: string): Promise<Session>; | ||
export declare function newSECP256K1Session(): Promise<Session>; |
import { Session } from "./index.js"; | ||
import { SubtleCryptoBackend } from "../subtle-crypto.js"; | ||
import { SecureStoreBackend } from "../secure-store.js"; | ||
export declare function newSECP256R1SessionFromSessionId(sessionId: string, cryptoBackend: SubtleCryptoBackend, secureStoreBackend: SecureStoreBackend): Promise<Session>; | ||
export declare function newSECP256R1SessionFromKeyPair(keyPair: CryptoKeyPair, cryptoBackend: SubtleCryptoBackend, secureStoreBackend: SecureStoreBackend): Promise<Session>; | ||
export declare function newSECP256R1Session(cryptoBackend: SubtleCryptoBackend, secureStoreBackend: SecureStoreBackend): Promise<Session>; | ||
export declare function newSECP256R1SessionFromSessionId(sessionId: string): Promise<Session>; | ||
export declare function newSECP256R1SessionFromKeyPair(keyPair: CryptoKeyPair): Promise<Session>; | ||
export declare function newSECP256R1Session(): Promise<Session>; |
{ | ||
"name": "@0xsequence/waas", | ||
"version": "0.0.0-20240429153138", | ||
"version": "0.0.0-20240429172204", | ||
"description": "waas session client", | ||
@@ -16,3 +16,3 @@ "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/waas", | ||
"jwt-decode": "^4.0.0", | ||
"@0xsequence/network": "0.0.0-20240429153138" | ||
"@0xsequence/network": "0.0.0-20240429172204" | ||
}, | ||
@@ -19,0 +19,0 @@ "files": [ |
@@ -36,4 +36,2 @@ import { Observer, SequenceWaaSBase } from './base' | ||
import { ethers } from 'ethers' | ||
import { SubtleCryptoBackend, getDefaultSubtleCryptoBackend } from './subtle-crypto' | ||
import { SecureStoreBackend, getDefaultSecureStoreBackend } from './secure-store' | ||
@@ -139,8 +137,6 @@ export type Sessions = (Session & { isThis: boolean })[] | ||
preset: ExtendedSequenceConfig = LOCAL, | ||
private readonly store: Store = new LocalStore(), | ||
private readonly cryptoBackend: SubtleCryptoBackend | null = getDefaultSubtleCryptoBackend(), | ||
private readonly secureStoreBackend: SecureStoreBackend | null = getDefaultSecureStoreBackend() | ||
private readonly store: Store = new LocalStore() | ||
) { | ||
this.config = defaultArgsOrFail(config, preset) | ||
this.waas = new SequenceWaaSBase({ network: 1, ...config }, this.store, this.cryptoBackend, this.secureStoreBackend) | ||
this.waas = new SequenceWaaSBase({ network: 1, ...config }, this.store) | ||
this.client = new WaasAuthenticator(this.config.rpcServer, this.fetch.bind(this)) | ||
@@ -310,7 +306,3 @@ this.deviceName = new StoreObj(this.store, '@0xsequence.waas.auth.deviceName', undefined) | ||
if (closeSessionId === thisSessionId) { | ||
if (!this.secureStoreBackend) { | ||
throw new Error('No secure store available') | ||
} | ||
const session = await newSessionFromSessionId(thisSessionId, this.cryptoBackend, this.secureStoreBackend) | ||
const session = await newSessionFromSessionId(thisSessionId) | ||
session.clear() | ||
@@ -317,0 +309,0 @@ await this.waas.completeSignOut() |
@@ -44,4 +44,2 @@ import { | ||
} from './clients/intent.gen' | ||
import { SubtleCryptoBackend, getDefaultSubtleCryptoBackend } from './subtle-crypto' | ||
import { SecureStoreBackend, getDefaultSecureStoreBackend } from './secure-store' | ||
@@ -86,5 +84,3 @@ type Status = 'pending' | 'signed-in' | 'signed-out' | ||
public readonly config = { network: 1 } as SequenceBaseConfig, | ||
private readonly store: Store = new LocalStore(), | ||
private readonly cryptoBackend: SubtleCryptoBackend | null = getDefaultSubtleCryptoBackend(), | ||
private readonly secureStoreBackend: SecureStoreBackend | null = getDefaultSecureStoreBackend() | ||
private readonly store: Store = new LocalStore() | ||
) { | ||
@@ -149,3 +145,3 @@ this.status = new StoreObj(this.store, SEQUENCE_WAAS_STATUS_KEY, 'signed-out') | ||
const session = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend) | ||
const session = await newSessionFromSessionId(sessionId) | ||
return signIntent(session, intent) | ||
@@ -160,3 +156,3 @@ } | ||
const signer = await newSessionFromSessionId(sessionId, this.cryptoBackend, this.secureStoreBackend) | ||
const signer = await newSessionFromSessionId(sessionId) | ||
return signer.sign(message) | ||
@@ -180,3 +176,3 @@ } | ||
if (!sessionId) { | ||
const session = await newSession(this.cryptoBackend, this.secureStoreBackend) | ||
const session = await newSession() | ||
sessionId = await session.sessionId() | ||
@@ -183,0 +179,0 @@ await this.sessionId.set(sessionId) |
/* eslint-disable */ | ||
// sequence-waas-authenticator v0.1.0 57f5bd68170564b26d4854ab5a90faa3809bd20e | ||
// sequence-waas-authenticator v0.1.0 a175abb1a964c85ae743ed2577a103e44fd93f7c | ||
// -- | ||
// Code generated by webrpc-gen@v0.14.0-dev with typescript generator. DO NOT EDIT. | ||
// Code generated by webrpc-gen@v0.15.2-dev with typescript generator. DO NOT EDIT. | ||
// | ||
@@ -15,3 +15,3 @@ // webrpc-gen -schema=authenticator.ridl -target=typescript -client -out=./clients/authenticator.gen.ts | ||
// Schema hash generated from your RIDL schema | ||
export const WebRPCSchemaHash = '57f5bd68170564b26d4854ab5a90faa3809bd20e' | ||
export const WebRPCSchemaHash = 'a175abb1a964c85ae743ed2577a103e44fd93f7c' | ||
@@ -59,4 +59,3 @@ // | ||
ver: string | ||
branch: string | ||
commitHash: string | ||
pcr0: string | ||
} | ||
@@ -79,4 +78,3 @@ | ||
iss: string | ||
azp?: string | ||
aud?: string | ||
aud: Array<string> | ||
} | ||
@@ -201,2 +199,3 @@ | ||
allowedOrigins: Array<string> | ||
password?: string | ||
} | ||
@@ -610,2 +609,15 @@ | ||
export class TenantNotFoundError extends WebrpcError { | ||
constructor( | ||
name: string = 'TenantNotFound', | ||
code: number = 1001, | ||
message: string = 'Tenant not found', | ||
status: number = 0, | ||
cause?: string | ||
) { | ||
super(name, code, message, status, cause) | ||
Object.setPrototypeOf(this, TenantNotFoundError.prototype) | ||
} | ||
} | ||
export enum errors { | ||
@@ -623,3 +635,4 @@ WebrpcEndpoint = 'WebrpcEndpoint', | ||
WebrpcStreamFinished = 'WebrpcStreamFinished', | ||
Unauthorized = 'Unauthorized' | ||
Unauthorized = 'Unauthorized', | ||
TenantNotFound = 'TenantNotFound' | ||
} | ||
@@ -639,5 +652,6 @@ | ||
[-10]: WebrpcStreamFinishedError, | ||
[1000]: UnauthorizedError | ||
[1000]: UnauthorizedError, | ||
[1001]: TenantNotFoundError | ||
} | ||
export type Fetch = (input: RequestInfo, init?: RequestInit) => Promise<Response> |
@@ -9,4 +9,4 @@ import { | ||
} from '@aws-sdk/client-cognito-identity-provider' | ||
import { Identity } from './auth' | ||
import { isSubtleCryptoAvailable } from './session' | ||
@@ -123,3 +123,2 @@ export class EmailAuth { | ||
console.warn('window.crypto.getRandomValues is not available. Falling back to less secure Math.random().') | ||
const randomValues = new Uint8Array(len) | ||
for (let i = 0; i < len; i++) { | ||
@@ -126,0 +125,0 @@ const randomInteger = Math.floor(Math.random() * 256) |
@@ -10,6 +10,4 @@ export * from './base' | ||
export type { SecureStoreBackend } from './secure-store' | ||
export * from './intents/responses' | ||
export * as defaults from './defaults' |
import { newSECP256K1SessionFromSessionId, newSECP256K1Session } from './secp256k1' | ||
import { newSECP256R1SessionFromSessionId, newSECP256R1Session } from './secp256r1' | ||
import { SubtleCryptoBackend } from '../subtle-crypto' | ||
import { SecureStoreBackend } from '../secure-store' | ||
@@ -12,25 +10,23 @@ export type Session = { | ||
export async function newSessionFromSessionId(sessionId: string, cryptoBackend: SubtleCryptoBackend | null, secureStoreBackend: SecureStoreBackend | null): Promise<Session> { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available') | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) | ||
export async function newSessionFromSessionId(sessionId: string): Promise<Session> { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1SessionFromSessionId(sessionId) | ||
} else { | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend) | ||
return newSECP256K1SessionFromSessionId(sessionId) | ||
} | ||
} | ||
export async function newSession(cryptoBackend: SubtleCryptoBackend | null, secureStoreBackend: SecureStoreBackend | null): Promise<Session> { | ||
if (!secureStoreBackend) { | ||
throw new Error('No secure store available') | ||
} | ||
if (cryptoBackend) { | ||
return newSECP256R1Session(cryptoBackend, secureStoreBackend) | ||
export async function newSession(): Promise<Session> { | ||
if (isSubtleCryptoAvailable()) { | ||
return newSECP256R1Session() | ||
} else { | ||
return newSECP256K1Session(secureStoreBackend) | ||
return newSECP256K1Session() | ||
} | ||
} | ||
export function isSubtleCryptoAvailable(): boolean { | ||
return typeof window === 'object' && typeof window.crypto === 'object' && typeof window.crypto.subtle === 'object' | ||
} | ||
export * from './secp256r1' | ||
export * from './secp256k1' |
import { ethers } from 'ethers' | ||
import { SecureStoreBackend } from '../secure-store' | ||
import { openDB } from 'idb' | ||
import { Session } from './index' | ||
@@ -8,8 +8,8 @@ | ||
export async function newSECP256K1SessionFromSessionId(sessionId: string, secureStoreBackend: SecureStoreBackend): Promise<Session> { | ||
const privateKey = await secureStoreBackend.get(idbName, idbStoreName, sessionId) | ||
export async function newSECP256K1SessionFromSessionId(sessionId: string): Promise<Session> { | ||
const db = await openDB(idbName) | ||
if (!privateKey) { | ||
throw new Error('No private key found') | ||
} | ||
const tx = db.transaction(idbStoreName, 'readonly') | ||
const privateKey = await db.get(idbStoreName, sessionId) | ||
await tx.done | ||
@@ -25,4 +25,4 @@ const wallet = new ethers.Wallet(privateKey) | ||
}, | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName, idbStoreName, sessionId) | ||
clear(): void { | ||
db.delete(idbStoreName, sessionId) | ||
} | ||
@@ -32,14 +32,25 @@ } as Session | ||
export async function newSECP256K1SessionFromPrivateKey(privateKey: string, secureStoreBackend: SecureStoreBackend): Promise<Session> { | ||
export async function newSECP256K1SessionFromPrivateKey(privateKey: string): Promise<Session> { | ||
const wallet = new ethers.Wallet(privateKey) | ||
const db = await openDB(idbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName) | ||
} | ||
}) | ||
const sessionId = await wallet.getAddress() | ||
await secureStoreBackend.set(idbName, idbStoreName, sessionId, privateKey) | ||
const tx = db.transaction(idbStoreName, 'readwrite') | ||
await db.put(idbStoreName, privateKey, sessionId) | ||
await tx.done | ||
return newSECP256K1SessionFromSessionId(sessionId, secureStoreBackend) | ||
db.close() | ||
return newSECP256K1SessionFromSessionId(sessionId) | ||
} | ||
export async function newSECP256K1Session(secureStoreBackend: SecureStoreBackend): Promise<Session> { | ||
export async function newSECP256K1Session(): Promise<Session> { | ||
const wallet = ethers.Wallet.createRandom() | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey, secureStoreBackend) | ||
return newSECP256K1SessionFromPrivateKey(wallet.privateKey) | ||
} |
import { ethers } from 'ethers' | ||
import { Session } from './index' | ||
import { KeyTypes } from './keyTypes' | ||
import { SubtleCryptoBackend } from '../subtle-crypto' | ||
import { SecureStoreBackend } from '../secure-store' | ||
import { openDB } from 'idb' | ||
const idbName = 'seq-waas-session-p256r1' | ||
const idbStoreName = 'seq-waas-session' | ||
// TODO: We need to update this to use the secure store backend | ||
// Currently it ignores the override and leverages idb | ||
// This is because the CryptoKeyPair is a bit more complicated | ||
// than a simple string that SecureStoreBackend can handle | ||
export async function newSECP256R1SessionFromSessionId(sessionId: string): Promise<Session> { | ||
const db = await openDB(idbName) | ||
export async function newSECP256R1SessionFromSessionId(sessionId: string, cryptoBackend: SubtleCryptoBackend, secureStoreBackend: SecureStoreBackend): Promise<Session> { | ||
const keys = await secureStoreBackend.get(idbName, idbStoreName, sessionId) | ||
const tx = db.transaction(idbStoreName, 'readonly') | ||
const keys = await db.get(idbStoreName, sessionId) | ||
await tx.done | ||
if (!keys || !keys.privateKey) { | ||
throw new Error('No private key found') | ||
} | ||
const encoder = new TextEncoder() | ||
return { | ||
sessionId: async () => { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', keys.publicKey) | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', keys.publicKey) | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1) | ||
@@ -43,3 +38,3 @@ | ||
} | ||
const signatureBuff = await cryptoBackend.sign( | ||
const signatureBuff = await window.crypto.subtle.sign( | ||
{ name: 'ECDSA', hash: { name: 'SHA-256' } }, | ||
@@ -52,3 +47,3 @@ keys.privateKey, | ||
clear: async () => { | ||
await secureStoreBackend.delete(idbName, idbStoreName, sessionId) | ||
await db.delete(idbStoreName, sessionId) | ||
} | ||
@@ -58,12 +53,22 @@ } | ||
export async function newSECP256R1SessionFromKeyPair(keyPair: CryptoKeyPair, cryptoBackend: SubtleCryptoBackend, secureStoreBackend: SecureStoreBackend): Promise<Session> { | ||
const sessionId = await pubKeyToSessionId(cryptoBackend, keyPair.publicKey) | ||
export async function newSECP256R1SessionFromKeyPair(keyPair: CryptoKeyPair): Promise<Session> { | ||
const sessionId = await pubKeyToSessionId(keyPair.publicKey) | ||
await secureStoreBackend.set(idbName, idbStoreName, sessionId, keyPair) | ||
const db = await openDB(idbName, 1, { | ||
upgrade(db) { | ||
db.createObjectStore(idbStoreName) | ||
} | ||
}) | ||
return newSECP256R1SessionFromSessionId(sessionId, cryptoBackend, secureStoreBackend) | ||
const tx = db.transaction(idbStoreName, 'readwrite') | ||
await db.put(idbStoreName, keyPair, sessionId) | ||
await tx.done | ||
db.close() | ||
return newSECP256R1SessionFromSessionId(sessionId) | ||
} | ||
export async function newSECP256R1Session(cryptoBackend: SubtleCryptoBackend, secureStoreBackend: SecureStoreBackend): Promise<Session> { | ||
const generatedKeys = await cryptoBackend.generateKey( | ||
export async function newSECP256R1Session(): Promise<Session> { | ||
const generatedKeys = await window.crypto.subtle.generateKey( | ||
{ | ||
@@ -76,7 +81,7 @@ name: 'ECDSA', | ||
) | ||
return newSECP256R1SessionFromKeyPair(generatedKeys, cryptoBackend, secureStoreBackend) | ||
return newSECP256R1SessionFromKeyPair(generatedKeys) | ||
} | ||
async function pubKeyToSessionId(cryptoBackend: SubtleCryptoBackend, pubKey: CryptoKey): Promise<string> { | ||
const pubKeyRaw = await cryptoBackend.exportKey('raw', pubKey) | ||
async function pubKeyToSessionId(pubKey: CryptoKey): Promise<string> { | ||
const pubKeyRaw = await window.crypto.subtle.exportKey('raw', pubKey) | ||
const pubKeyTypedRaw = new Uint8Array(pubKeyRaw.byteLength + 1) | ||
@@ -83,0 +88,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
321639
46
9305
+ Added@0xsequence/abi@0.0.0-20240429172204(transitive)
+ Added@0xsequence/core@0.0.0-20240429172204(transitive)
+ Added@0xsequence/indexer@0.0.0-20240429172204(transitive)
+ Added@0xsequence/network@0.0.0-20240429172204(transitive)
+ Added@0xsequence/relayer@0.0.0-20240429172204(transitive)
+ Added@0xsequence/utils@0.0.0-20240429172204(transitive)
- Removed@0xsequence/abi@0.0.0-20240429153138(transitive)
- Removed@0xsequence/core@0.0.0-20240429153138(transitive)
- Removed@0xsequence/indexer@0.0.0-20240429153138(transitive)
- Removed@0xsequence/network@0.0.0-20240429153138(transitive)
- Removed@0xsequence/relayer@0.0.0-20240429153138(transitive)
- Removed@0xsequence/utils@0.0.0-20240429153138(transitive)