diff --git a/extension/background/db.js b/extension/background/db.js index 9be933d9c..b52ee457a 100644 --- a/extension/background/db.js +++ b/extension/background/db.js @@ -1,220 +1,5 @@ -"use strict"; - -var DB = function () { - let DB = {}; // returned object with exported functions - - let DB_NAME = "taler"; - let DB_VERSION = 1; - - let db = null; - let is_ready = null; - - DB.open = function (onsuccess, onerror) - { - is_ready = false; - - let req = indexedDB.open(DB_NAME, DB_VERSION); - req.onerror = onerror; - req.onsuccess = function (event) - { - db = event.target.result; - is_ready = true; - if (onsuccess) - onsuccess(); - }; - - req.onupgradeneeded = function (event) - { - console.log ("DB: upgrade needed: oldVersion = "+ event.oldVersion); - - db = event.target.result; - db.onerror = onerror; - - switch (event.oldVersion) - { - case 0: // DB does not exist yet - { - let example = {}; - - let mints = db.createObjectStore("mints", { keyPath: "mint_pub" }); - mints.createIndex("name", "name", { unique: true }); - - example.mint = { - mint_pub: "", // length: 32 - name: "Mint One", - url: "https://mint.one/", - }; - - let denoms = db.createObjectStore("denoms", { keyPath: "denom_pub" }); - - example.denom = { - denom_pub: "", // length: 32 - mint_pub: "", // length: 32 - mint_sig: "", // length: 64 - withdraw_expiry_time: 1234567890, - deposit_expiry_time: 1234567890, - start_time: 1234567890, - value: { - value: 1, - fraction: 230000, // 0..999999 - currency: "EUR", - }, - fee: { - withdraw: { - value: 0, - fraction: 100000, - currency: "EUR", - }, - deposit: { - value: 0, - fraction: 100000, - currency: "EUR", - }, - refresh: { - value: 0, - fraction: 100000, - currency: "EUR", - }, - }, - }; - - let reserves = db.createObjectStore("reserves", { keyPath: "reserve_pub"}); - example.reserve = { - reserve_pub: "", - reserve_priv: "", - mint_pub: "", - initial: { - value: 1, - fraction: 230000, - currency: "EUR", - }, - current: { - value: 1, - fraction: 230000, - currency: "EUR", - blind_session_pub: "", - status_sig: "", - }, - }; - - let withdrawals = db.createObjectStore("withdrawals", { keyPath: "id", autoIncrement: true }); - example.withdrawal = { - id: 1, // generated - reserve_pub: "", - reserve_sig: "", - denom_pub: "", - blind_priv: "", - coin_pub: "", - coin_priv: "", - coin_ev: "", - }; - - let coins = db.createObjectStore("coins", { keyPath: "coin_pub" }); - example.coin = { - // coin either has a withdraw_id or refresh_id - // or it is imported in which case both are null - withdraw_id: 1, // can be null - refresh_id: null, // can be null - is_refreshed: false, - denom_pub: "", - coin_pub: "", - coin_priv: "", - denom_sig: "", - spent: { - value: 1, - fraction: 230000, - }, - transactions: [ 123, 456 ], // list of transaction IDs where this coin was used - }; - - let transactions = db.createObjectStore("transactions", { keyPath: "id", autoIncrement: true }); - example.transaction = { - id: 1, // generated - wire_hash: "", - value: { - value: 1, - fraction: 230000, - currency: "EUR", - }, - contract: "", - is_checkout_done: true, - is_confirmed: true, - fulfillment_url: "https://some.shop/transaction/completed", - }; - - let refresh = db.createObjectStore("refresh"); - example.refresh = { - // TODO - }; - } - } - - is_ready = true; - if (onsuccess) - onsuccess(); - } - }; - - - DB.close = function () - { - db.close(); - }; - - - DB.wallet_get = function (onresult, onerror) - { - let wallet = { }; - - let tr = db.transaction([ "coins", "denoms" ], "readonly"); - let coins = tr.objectStore("coins"); - let denoms = tr.objectStore("denoms"); - - let coins_cur = coins.openCursor(); - coins_cur.onerror = onerror; - coins_cur.onsuccess = function () - { - let cur = event.target.result; - if (cur) { - let denom_get = denoms.get(cur.valcue.denom_pub); - denom_get.onerror = onerror; - denom_get.onsuccess = function (event) - { - let denom = event.target.result; - if (denom.currency in wallet) - { - let w = wallet[denom.currency]; - w.value += denom.value; - w.fraction = (w.fraction + denom.fraction) % 1000000; - if (1000000 <= w.fraction + denom.fraction) - w.value++; - } - else - { - wallet[denom.currency] = denom; - } - cur.continue(); - } - } - else // no more entries - { - onresult(wallet); - } - }; - }; - - - DB.transaction_list = function (onresult, onerror) - { - // TODO - }; - - - DB.reserve_list = function (onresult, onerror) - { - // TODO - }; - - return DB; -}(); +/** + * Declarations and helpers for + * things that are stored in the wallet's + * database. + */ diff --git a/extension/background/emscriptif.js b/extension/background/emscriptif.js index f94b58016..81580fbed 100644 --- a/extension/background/emscriptif.js +++ b/extension/background/emscriptif.js @@ -284,6 +284,13 @@ class RsaBlindingKey extends ArenaObject { o.nativePtr = emscAlloc.rsa_blinding_key_create(len); return o; } + static fromCrock(s, a) { + let obj = new this(a); + let buf = ByteArray.fromCrock(s); + obj.setNative(emscAlloc.rsa_blinding_key_decode(buf.getNative(), buf.size())); + buf.destroy(); + return obj; + } toCrock() { let ptr = emscAlloc.malloc(PTR_SIZE); let size = emscAlloc.rsa_blinding_key_encode(this.nativePtr, ptr); diff --git a/extension/background/emscriptif.ts b/extension/background/emscriptif.ts index 150b68741..f21e60db4 100644 --- a/extension/background/emscriptif.ts +++ b/extension/background/emscriptif.ts @@ -416,12 +416,20 @@ class EddsaPublicKey extends PackedArenaObject { } + class RsaBlindingKey extends ArenaObject { static create(len: number, a?: Arena) { let o = new RsaBlindingKey(a); o.nativePtr = emscAlloc.rsa_blinding_key_create(len); return o; } + static fromCrock(s: string, a?: Arena): RsaBlindingKey { + let obj = new this(a); + let buf = ByteArray.fromCrock(s); + obj.setNative(emscAlloc.rsa_blinding_key_decode(buf.getNative(), buf.size())); + buf.destroy(); + return obj; + } toCrock(): string { let ptr = emscAlloc.malloc(PTR_SIZE); diff --git a/extension/background/timerThread.js b/extension/background/timerThread.js index a42b0edf6..7ac66a711 100644 --- a/extension/background/timerThread.js +++ b/extension/background/timerThread.js @@ -1,3 +1,10 @@ +/** + * This file should be used as a WebWorker. + * Background pages in the WebExtensions model do + * not allow to schedule callbacks that should be called + * after a timeout. We can emulate this with WebWorkers. + */ + onmessage = function(e) { self.setInterval(() => postMessage(true), e.data.interval); } diff --git a/extension/background/wallet.js b/extension/background/wallet.js index 36d3e8a85..3bcbde91b 100644 --- a/extension/background/wallet.js +++ b/extension/background/wallet.js @@ -24,15 +24,18 @@ function openTalerDb() { db.createObjectStore("mints", { keyPath: "baseUrl" }); db.createObjectStore("reserves", { keyPath: "reserve_pub" }); db.createObjectStore("denoms", { keyPath: "denomPub" }); - db.createObjectStore("coins", { keyPath: "coinPub" }); - db.createObjectStore("withdrawals", { keyPath: "id", autoIncrement: true }); - db.createObjectStore("transactions", { keyPath: "id", autoIncrement: true }); + let coins = db.createObjectStore("coins", { keyPath: "coinPub" }); + coins.createIndex("mintBaseUrl", "mintBaseUrl"); + db.createObjectStore("transactions", { keyPath: "contractHash" }); db.createObjectStore("precoins", { keyPath: "coinPub", autoIncrement: true }); break; } }; }); } +/** + * See http://api.taler.net/wallet.html#general + */ function canonicalizeBaseUrl(url) { let x = new URI(url); if (!x.protocol()) { @@ -43,8 +46,24 @@ function canonicalizeBaseUrl(url) { x.query(); return x.href(); } +function grantCoins(db, feeThreshold, paymentAmount, mintBaseUrl) { + throw "not implemented"; +} +function confirmPay(db, detail, sendResponse) { + console.log("confirmPay", JSON.stringify(detail)); + let tx = db.transaction(['transactions'], 'readwrite'); + let trans = { + contractHash: detail.offer.H_contract, + contract: detail.offer.contract, + sig: detail.offer + }; + let contract = detail.offer.contract; + //let chosenCoinPromise = chooseCoins(db, contract.max_fee, contract.amount) + // .then(x => generateDepositPermissions(db, x)) + // .then(executePayment); + return true; +} function confirmReserve(db, detail, sendResponse) { - console.log('detail: ' + JSON.stringify(detail)); let reservePriv = EddsaPrivateKey.create(); let reservePub = reservePriv.getPublicKey(); let form = new FormData(); @@ -114,11 +133,8 @@ function rankDenom(denom1, denom2) { return (-1) * v1.cmp(v2); } function withdrawPrepare(db, denom, reserve) { - console.log("in withdraw prepare"); let reservePriv = new EddsaPrivateKey(); - console.log("loading reserve priv", reserve.reserve_priv); reservePriv.loadCrock(reserve.reserve_priv); - console.log("reserve priv is", reservePriv.toCrock()); let reservePub = new EddsaPublicKey(); reservePub.loadCrock(reserve.reserve_pub); let denomPub = RsaPublicKey.fromCrock(denom.denom_pub); @@ -126,9 +142,7 @@ function withdrawPrepare(db, denom, reserve) { let coinPub = coinPriv.getPublicKey(); let blindingFactor = RsaBlindingKey.create(1024); let pubHash = coinPub.hash(); - console.log("about to blind"); let ev = rsaBlind(pubHash, blindingFactor, denomPub); - console.log("blinded"); if (!denom.fee_withdraw) { throw Error("Field fee_withdraw missing"); } @@ -153,8 +167,10 @@ function withdrawPrepare(db, denom, reserve) { coinPub: coinPub.toCrock(), coinPriv: coinPriv.toCrock(), denomPub: denomPub.encode().toCrock(), + mintBaseUrl: reserve.mintBaseUrl, withdrawSig: sig.toCrock(), - coinEv: ev.toCrock() + coinEv: ev.toCrock(), + coinValue: denom.value }; console.log("storing precoin", JSON.stringify(preCoin)); let tx = db.transaction(['precoins'], 'readwrite'); @@ -197,15 +213,13 @@ function withdrawExecute(db, pc) { console.log("Withdrawal successful"); console.log(myRequest.responseText); let resp = JSON.parse(myRequest.responseText); - //let denomSig = rsaUnblind(RsaSignature.fromCrock(resp.coin_ev), - // RsaBlindingKey.fromCrock(pc.blindingKey), - // RsaPublicKey.fromCrock(pc.denomPub)); + let denomSig = rsaUnblind(RsaSignature.fromCrock(resp.coin_ev), RsaBlindingKey.fromCrock(pc.blindingKey), RsaPublicKey.fromCrock(pc.denomPub)); let coin = { coinPub: pc.coinPub, coinPriv: pc.coinPriv, denomPub: pc.denomPub, - reservePub: pc.reservePub, - denomSig: "foo" //denomSig.encode().toCrock() + denomSig: denomSig.encode().toCrock(), + currentAmount: pc.coinValue }; console.log("unblinded coin"); resolve(coin); @@ -442,6 +456,7 @@ openTalerDb().then((db) => { chrome.runtime.onMessage.addListener(function (req, sender, onresponse) { let dispatch = { "confirm-reserve": confirmReserve, + "confirm-pay": confirmPay, "dump-db": dumpDb, "balances": balances, "reset": reset @@ -449,7 +464,7 @@ openTalerDb().then((db) => { if (req.type in dispatch) { return dispatch[req.type](db, req.detail, onresponse); } - console.error(format("Request type unknown, req {0}", JSON.stringify(req))); + console.error(format("Request type {1} unknown, req {0}", JSON.stringify(req), req.type)); return false; }); }); diff --git a/extension/background/wallet.ts b/extension/background/wallet.ts index dd2ceca7d..07c8743e1 100644 --- a/extension/background/wallet.ts +++ b/extension/background/wallet.ts @@ -27,9 +27,9 @@ function openTalerDb(): Promise { db.createObjectStore("mints", { keyPath: "baseUrl" }); db.createObjectStore("reserves", { keyPath: "reserve_pub"}); db.createObjectStore("denoms", { keyPath: "denomPub" }); - db.createObjectStore("coins", { keyPath: "coinPub" }); - db.createObjectStore("withdrawals", { keyPath: "id", autoIncrement: true }); - db.createObjectStore("transactions", { keyPath: "id", autoIncrement: true }); + let coins = db.createObjectStore("coins", { keyPath: "coinPub" }); + coins.createIndex("mintBaseUrl", "mintBaseUrl"); + db.createObjectStore("transactions", { keyPath: "contractHash" }); db.createObjectStore("precoins", { keyPath: "coinPub", autoIncrement: true }); break; } @@ -38,6 +38,9 @@ function openTalerDb(): Promise { } +/** + * See http://api.taler.net/wallet.html#general + */ function canonicalizeBaseUrl(url) { let x = new URI(url); if (!x.protocol()) { @@ -49,9 +52,39 @@ function canonicalizeBaseUrl(url) { return x.href() } +interface ConfirmPayRequest { + offer: any; + selectedMint: any; +} + + +function grantCoins(db: IDBDatabase, + feeThreshold: AmountJson, + paymentAmount: AmountJson, + mintBaseUrl: string): Promise { + throw "not implemented"; +} + + +function confirmPay(db, detail: ConfirmPayRequest, sendResponse) { + console.log("confirmPay", JSON.stringify(detail)); + let tx = db.transaction(['transactions'], 'readwrite'); + let trans = { + contractHash: detail.offer.H_contract, + contract: detail.offer.contract, + sig: detail.offer + } + + let contract = detail.offer.contract; + + //let chosenCoinPromise = chooseCoins(db, contract.max_fee, contract.amount) + // .then(x => generateDepositPermissions(db, x)) + // .then(executePayment); + + return true; +} function confirmReserve(db, detail, sendResponse) { - console.log('detail: ' + JSON.stringify(detail)); let reservePriv = EddsaPrivateKey.create(); let reservePub = reservePriv.getPublicKey(); let form = new FormData(); @@ -126,45 +159,11 @@ function rankDenom(denom1: any, denom2: any) { } - -interface AmountJson { - value: number; - fraction: number; - currency: string; -} - - -interface Denomination { - value: AmountJson; - denomPub: string; -} - -interface PreCoin { - coinPub: string; - coinPriv: string; - reservePub: string; - denomPub: string; - blindingKey: string; - withdrawSig: string; - coinEv: string; -} - - -interface Coin { - coinPub: string; - coinPriv: string; - reservePub: string; - denomPub: string; - denomSig: string; -} - - -function withdrawPrepare(db: IDBDatabase, denom, reserve): Promise { - console.log("in withdraw prepare"); +function withdrawPrepare(db: IDBDatabase, + denom: Denomination, + reserve): Promise { let reservePriv = new EddsaPrivateKey(); - console.log("loading reserve priv", reserve.reserve_priv); reservePriv.loadCrock(reserve.reserve_priv); - console.log("reserve priv is", reservePriv.toCrock()); let reservePub = new EddsaPublicKey(); reservePub.loadCrock(reserve.reserve_pub); let denomPub = RsaPublicKey.fromCrock(denom.denom_pub); @@ -172,9 +171,7 @@ function withdrawPrepare(db: IDBDatabase, denom, reserve): Promise { let coinPub = coinPriv.getPublicKey(); let blindingFactor = RsaBlindingKey.create(1024); let pubHash: HashCode = coinPub.hash(); - console.log("about to blind"); let ev: ByteArray = rsaBlind(pubHash, blindingFactor, denomPub); - console.log("blinded"); if (!denom.fee_withdraw) { throw Error("Field fee_withdraw missing"); @@ -205,8 +202,10 @@ function withdrawPrepare(db: IDBDatabase, denom, reserve): Promise { coinPub: coinPub.toCrock(), coinPriv: coinPriv.toCrock(), denomPub: denomPub.encode().toCrock(), + mintBaseUrl: reserve.mintBaseUrl, withdrawSig: sig.toCrock(), - coinEv: ev.toCrock() + coinEv: ev.toCrock(), + coinValue: denom.value }; console.log("storing precoin", JSON.stringify(preCoin)); @@ -254,15 +253,15 @@ function withdrawExecute(db, pc: PreCoin): Promise { console.log("Withdrawal successful"); console.log(myRequest.responseText); let resp = JSON.parse(myRequest.responseText); - //let denomSig = rsaUnblind(RsaSignature.fromCrock(resp.coin_ev), - // RsaBlindingKey.fromCrock(pc.blindingKey), - // RsaPublicKey.fromCrock(pc.denomPub)); + let denomSig = rsaUnblind(RsaSignature.fromCrock(resp.coin_ev), + RsaBlindingKey.fromCrock(pc.blindingKey), + RsaPublicKey.fromCrock(pc.denomPub)); let coin: Coin = { coinPub: pc.coinPub, coinPriv: pc.coinPriv, denomPub: pc.denomPub, - reservePub: pc.reservePub, - denomSig: "foo" //denomSig.encode().toCrock() + denomSig: denomSig.encode().toCrock(), + currentAmount: pc.coinValue } console.log("unblinded coin"); resolve(coin); @@ -505,7 +504,7 @@ function balances(db, detail, sendResponse) { sendResponse(byCurrency); console.log("response", JSON.stringify(byCurrency)); } - } + }; return true; } @@ -517,15 +516,15 @@ openTalerDb().then((db) => { function (req, sender, onresponse) { let dispatch = { "confirm-reserve": confirmReserve, + "confirm-pay": confirmPay, "dump-db": dumpDb, "balances": balances, "reset": reset - } + }; if (req.type in dispatch) { return dispatch[req.type](db, req.detail, onresponse); } - console.error(format("Request type unknown, req {0}", JSON.stringify(req))); + console.error(format("Request type {1} unknown, req {0}", JSON.stringify(req), req.type)); return false; }); }); - diff --git a/extension/content_scripts/notify.js b/extension/content_scripts/notify.js index 640c5bdc6..e86c0f84f 100644 --- a/extension/content_scripts/notify.js +++ b/extension/content_scripts/notify.js @@ -44,10 +44,10 @@ document.addEventListener("DOMContentLoaded", function(e) { }); document.body.addEventListener('taler-contract', function(e) { // XXX: the merchant should just give us the parsed data ... - let contract = JSON.parse(e.detail); + let offer = JSON.parse(e.detail); let uri = URI(chrome.extension.getURL("pages/confirm-contract.html")); let params = { - contract: JSON.stringify(contract) + offer: JSON.stringify(offer) } document.location.href = uri.query(params).href(); }); diff --git a/extension/pages/confirm-contract.js b/extension/pages/confirm-contract.js index fe16bcbca..c59ac90a9 100644 --- a/extension/pages/confirm-contract.js +++ b/extension/pages/confirm-contract.js @@ -16,15 +16,15 @@ Handlebars.registerHelper('prettyAmount', function (amount) { return v.toFixed(2) + " " + amount.currency; }); document.addEventListener("DOMContentLoaded", (e) => { - let contract = JSON.parse(query.contract); - console.dir(contract); + let offer = JSON.parse(query.offer); + console.dir(offer); let source = $_("contract-template").innerHTML; let template = Handlebars.compile(source); - let html = template(contract.contract); + let html = template(offer.contract); $_("render-contract").innerHTML = html; - document.getElementById("confirm-purchase").addEventListener("click", (e) => { + document.getElementById("confirm-pay").addEventListener("click", (e) => { let d = clone(query); - chrome.runtime.sendMessage({ type: 'confirm-purchase', detail: d }, (resp) => { + chrome.runtime.sendMessage({ type: 'confirm-pay', detail: d }, (resp) => { if (resp.success === true) { document.location.href = resp.backlink; } diff --git a/extension/pages/confirm-contract.tsx b/extension/pages/confirm-contract.tsx index e12fdfd2d..811e2e001 100644 --- a/extension/pages/confirm-contract.tsx +++ b/extension/pages/confirm-contract.tsx @@ -24,19 +24,18 @@ Handlebars.registerHelper('prettyAmount', function(amount) { document.addEventListener("DOMContentLoaded", (e) => { - let contract = JSON.parse(query.contract); - console.dir(contract); + let offer = JSON.parse(query.offer); + console.dir(offer); let source = $_("contract-template").innerHTML; let template = Handlebars.compile(source); - let html = template(contract.contract); + let html = template(offer.contract); $_("render-contract").innerHTML = html; - - document.getElementById("confirm-purchase").addEventListener("click", (e) => { + document.getElementById("confirm-pay").addEventListener("click", (e) => { let d = clone(query); - chrome.runtime.sendMessage({type:'confirm-purchase', detail: d}, (resp) => { + chrome.runtime.sendMessage({type:'confirm-pay', detail: d}, (resp) => { if (resp.success === true) { document.location.href = resp.backlink; } else { @@ -46,7 +45,6 @@ document.addEventListener("DOMContentLoaded", (e) => {
${resp.text}
`; } }); - }); }); diff --git a/extension/popup/balance-overview.html b/extension/popup/balance-overview.html index 2f82becf8..a3aeae697 100644 --- a/extension/popup/balance-overview.html +++ b/extension/popup/balance-overview.html @@ -10,9 +10,14 @@ @@ -26,11 +31,6 @@
-
-

Looks like your wallet is empty. Want to get some - KUDOS? -

-
diff --git a/extension/popup/balance-overview.js b/extension/popup/balance-overview.js index f33be0637..4fd991b23 100644 --- a/extension/popup/balance-overview.js +++ b/extension/popup/balance-overview.js @@ -17,31 +17,9 @@ let React = { document.addEventListener('DOMContentLoaded', (e) => { console.log("content loaded"); chrome.runtime.sendMessage({ type: "balances" }, function (wallet) { - console.log("got balance"); - let n = 0; - let table = React.createElement("div", null); - let source = document.getElementById("balance-template").innerHTML; - console.log("size", Object.keys(wallet).length); - if (Object.keys(wallet).length > 0) { - let template = Handlebars.compile(source); - console.log("wallet ", JSON.stringify(wallet)); - let html = template(wallet); - console.log("Hb generated html", html); - table.innerHTML = html; - let p = document.getElementById("content"); - p.replaceChild(table, p.firstElementChild); - } - /* - for (let curr in wallet) { - n++; - let x = wallet[curr]; - let num = x.value + x.fraction / 10e6; - table.appendChild(

{num} {x.currency}

); - } - if (n != 0) { - let p = document.getElementById("content"); - p.replaceChild(table, p.firstElementChild); - } */ + let context = document.getElementById("balance-template").innerHTML; + let template = Handlebars.compile(context); + document.getElementById("content").innerHTML = template(wallet); }); document.getElementById("debug").addEventListener("click", (e) => { chrome.tabs.create({ diff --git a/extension/popup/balance-overview.tsx b/extension/popup/balance-overview.tsx index b1ee0fa27..88ff1bccb 100644 --- a/extension/popup/balance-overview.tsx +++ b/extension/popup/balance-overview.tsx @@ -19,33 +19,9 @@ let React = { document.addEventListener('DOMContentLoaded', (e) => { console.log("content loaded"); chrome.runtime.sendMessage({type: "balances"}, function(wallet) { - console.log("got balance"); - let n = 0; - let table =
; - - let source = document.getElementById("balance-template").innerHTML; - console.log("size", Object.keys(wallet).length); - if (Object.keys(wallet).length > 0){ - let template = Handlebars.compile(source); - console.log("wallet ", JSON.stringify(wallet)); - let html = template(wallet); - console.log("Hb generated html", html); - table.innerHTML = html; - let p = document.getElementById("content"); - p.replaceChild(table, p.firstElementChild); - } - - /* - for (let curr in wallet) { - n++; - let x = wallet[curr]; - let num = x.value + x.fraction / 10e6; - table.appendChild(

{num} {x.currency}

); - } - if (n != 0) { - let p = document.getElementById("content"); - p.replaceChild(table, p.firstElementChild); - } */ + let context = document.getElementById("balance-template").innerHTML; + let template = Handlebars.compile(context); + document.getElementById("content").innerHTML = template(wallet); }); document.getElementById("debug").addEventListener("click", (e) => { diff --git a/extension/tsconfig.json b/extension/tsconfig.json index 06a8424c6..94ea6f444 100644 --- a/extension/tsconfig.json +++ b/extension/tsconfig.json @@ -6,6 +6,7 @@ "files": [ "background/wallet.ts", "background/emscriptif.ts", + "background/db.ts", "lib/util.ts", "popup/balance-overview.tsx", "pages/confirm-contract.tsx"