wallet-core: introduce easier syntax for transactions
This commit is contained in:
parent
13e7a67477
commit
48540f6264
@ -46,9 +46,13 @@ function upgradeFromStoreMap(
|
||||
): void {
|
||||
if (oldVersion === 0) {
|
||||
for (const n in storeMap) {
|
||||
const swi: StoreWithIndexes<StoreDescriptor<unknown>, any> = storeMap[n];
|
||||
const swi: StoreWithIndexes<
|
||||
any,
|
||||
StoreDescriptor<unknown>,
|
||||
any
|
||||
> = storeMap[n];
|
||||
const storeDesc: StoreDescriptor<unknown> = swi.store;
|
||||
const s = db.createObjectStore(storeDesc.name, {
|
||||
const s = db.createObjectStore(swi.storeName, {
|
||||
autoIncrement: storeDesc.autoIncrement,
|
||||
keyPath: storeDesc.keyPath,
|
||||
});
|
||||
@ -117,9 +121,7 @@ export async function openTalerDatabase(
|
||||
const metaDb = new DbAccess(metaDbHandle, walletMetadataStore);
|
||||
let currentMainVersion: string | undefined;
|
||||
await metaDb
|
||||
.mktx((x) => ({
|
||||
metaConfig: x.metaConfig,
|
||||
}))
|
||||
.mktx((stores) => [stores.metaConfig])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dbVersionRecord = await tx.metaConfig.get(CURRENT_DB_CONFIG_KEY);
|
||||
if (!dbVersionRecord) {
|
||||
@ -141,9 +143,7 @@ export async function openTalerDatabase(
|
||||
// We consider this a pre-release
|
||||
// development version, no migration is done.
|
||||
await metaDb
|
||||
.mktx((x) => ({
|
||||
metaConfig: x.metaConfig,
|
||||
}))
|
||||
.mktx((stores) => [stores.metaConfig])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.metaConfig.put({
|
||||
key: CURRENT_DB_CONFIG_KEY,
|
||||
|
@ -1733,7 +1733,8 @@ export interface OperationAttemptLongpollResult {
|
||||
|
||||
export const WalletStoresV1 = {
|
||||
coins: describeStore(
|
||||
describeContents<CoinRecord>("coins", {
|
||||
"coins",
|
||||
describeContents<CoinRecord>({
|
||||
keyPath: "coinPub",
|
||||
}),
|
||||
{
|
||||
@ -1743,17 +1744,20 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
reserves: describeStore(
|
||||
describeContents<ReserveRecord>("reserves", {
|
||||
"reserves",
|
||||
describeContents<ReserveRecord>({
|
||||
keyPath: "reservePub",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
config: describeStore(
|
||||
describeContents<ConfigRecord>("config", { keyPath: "key" }),
|
||||
"config",
|
||||
describeContents<ConfigRecord>({ keyPath: "key" }),
|
||||
{},
|
||||
),
|
||||
auditorTrust: describeStore(
|
||||
describeContents<AuditorTrustRecord>("auditorTrust", {
|
||||
"auditorTrust",
|
||||
describeContents<AuditorTrustRecord>({
|
||||
keyPath: ["currency", "auditorBaseUrl"],
|
||||
}),
|
||||
{
|
||||
@ -1764,7 +1768,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
exchangeTrust: describeStore(
|
||||
describeContents<ExchangeTrustRecord>("exchangeTrust", {
|
||||
"exchangeTrust",
|
||||
describeContents<ExchangeTrustRecord>({
|
||||
keyPath: ["currency", "exchangeBaseUrl"],
|
||||
}),
|
||||
{
|
||||
@ -1775,7 +1780,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
denominations: describeStore(
|
||||
describeContents<DenominationRecord>("denominations", {
|
||||
"denominations",
|
||||
describeContents<DenominationRecord>({
|
||||
keyPath: ["exchangeBaseUrl", "denomPubHash"],
|
||||
}),
|
||||
{
|
||||
@ -1783,19 +1789,22 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
exchanges: describeStore(
|
||||
describeContents<ExchangeRecord>("exchanges", {
|
||||
"exchanges",
|
||||
describeContents<ExchangeRecord>({
|
||||
keyPath: "baseUrl",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
exchangeDetails: describeStore(
|
||||
describeContents<ExchangeDetailsRecord>("exchangeDetails", {
|
||||
"exchangeDetails",
|
||||
describeContents<ExchangeDetailsRecord>({
|
||||
keyPath: ["exchangeBaseUrl", "currency", "masterPublicKey"],
|
||||
}),
|
||||
{},
|
||||
),
|
||||
proposals: describeStore(
|
||||
describeContents<ProposalRecord>("proposals", { keyPath: "proposalId" }),
|
||||
"proposals",
|
||||
describeContents<ProposalRecord>({ keyPath: "proposalId" }),
|
||||
{
|
||||
byUrlAndOrderId: describeIndex("byUrlAndOrderId", [
|
||||
"merchantBaseUrl",
|
||||
@ -1804,7 +1813,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
refreshGroups: describeStore(
|
||||
describeContents<RefreshGroupRecord>("refreshGroups", {
|
||||
"refreshGroups",
|
||||
describeContents<RefreshGroupRecord>({
|
||||
keyPath: "refreshGroupId",
|
||||
}),
|
||||
{
|
||||
@ -1812,13 +1822,15 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
recoupGroups: describeStore(
|
||||
describeContents<RecoupGroupRecord>("recoupGroups", {
|
||||
"recoupGroups",
|
||||
describeContents<RecoupGroupRecord>({
|
||||
keyPath: "recoupGroupId",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
purchases: describeStore(
|
||||
describeContents<PurchaseRecord>("purchases", { keyPath: "proposalId" }),
|
||||
"purchases",
|
||||
describeContents<PurchaseRecord>({ keyPath: "proposalId" }),
|
||||
{
|
||||
byFulfillmentUrl: describeIndex(
|
||||
"byFulfillmentUrl",
|
||||
@ -1831,7 +1843,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
tips: describeStore(
|
||||
describeContents<TipRecord>("tips", { keyPath: "walletTipId" }),
|
||||
"tips",
|
||||
describeContents<TipRecord>({ keyPath: "walletTipId" }),
|
||||
{
|
||||
byMerchantTipIdAndBaseUrl: describeIndex("byMerchantTipIdAndBaseUrl", [
|
||||
"merchantTipId",
|
||||
@ -1840,7 +1853,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
withdrawalGroups: describeStore(
|
||||
describeContents<WithdrawalGroupRecord>("withdrawalGroups", {
|
||||
"withdrawalGroups",
|
||||
describeContents<WithdrawalGroupRecord>({
|
||||
keyPath: "withdrawalGroupId",
|
||||
}),
|
||||
{
|
||||
@ -1853,7 +1867,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
planchets: describeStore(
|
||||
describeContents<PlanchetRecord>("planchets", { keyPath: "coinPub" }),
|
||||
"planchets",
|
||||
describeContents<PlanchetRecord>({ keyPath: "coinPub" }),
|
||||
{
|
||||
byGroupAndIndex: describeIndex("byGroupAndIndex", [
|
||||
"withdrawalGroupId",
|
||||
@ -1864,13 +1879,15 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
bankWithdrawUris: describeStore(
|
||||
describeContents<BankWithdrawUriRecord>("bankWithdrawUris", {
|
||||
"bankWithdrawUris",
|
||||
describeContents<BankWithdrawUriRecord>({
|
||||
keyPath: "talerWithdrawUri",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
backupProviders: describeStore(
|
||||
describeContents<BackupProviderRecord>("backupProviders", {
|
||||
"backupProviders",
|
||||
describeContents<BackupProviderRecord>({
|
||||
keyPath: "baseUrl",
|
||||
}),
|
||||
{
|
||||
@ -1884,7 +1901,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
depositGroups: describeStore(
|
||||
describeContents<DepositGroupRecord>("depositGroups", {
|
||||
"depositGroups",
|
||||
describeContents<DepositGroupRecord>({
|
||||
keyPath: "depositGroupId",
|
||||
}),
|
||||
{
|
||||
@ -1892,29 +1910,34 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
tombstones: describeStore(
|
||||
describeContents<TombstoneRecord>("tombstones", { keyPath: "id" }),
|
||||
"tombstones",
|
||||
describeContents<TombstoneRecord>({ keyPath: "id" }),
|
||||
{},
|
||||
),
|
||||
operationRetries: describeStore(
|
||||
describeContents<OperationRetryRecord>("operationRetries", {
|
||||
"operationRetries",
|
||||
describeContents<OperationRetryRecord>({
|
||||
keyPath: "id",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
ghostDepositGroups: describeStore(
|
||||
describeContents<GhostDepositGroupRecord>("ghostDepositGroups", {
|
||||
"ghostDepositGroups",
|
||||
describeContents<GhostDepositGroupRecord>({
|
||||
keyPath: "contractTermsHash",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
balancesPerCurrency: describeStore(
|
||||
describeContents<BalancePerCurrencyRecord>("balancesPerCurrency", {
|
||||
"balancesPerCurrency",
|
||||
describeContents<BalancePerCurrencyRecord>({
|
||||
keyPath: "currency",
|
||||
}),
|
||||
{},
|
||||
),
|
||||
peerPushPaymentIncoming: describeStore(
|
||||
describeContents<PeerPushPaymentIncomingRecord>("peerPushPaymentIncoming", {
|
||||
"peerPushPaymentIncoming",
|
||||
describeContents<PeerPushPaymentIncomingRecord>({
|
||||
keyPath: "peerPushPaymentIncomingId",
|
||||
}),
|
||||
{
|
||||
@ -1925,7 +1948,8 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
peerPullPaymentIncoming: describeStore(
|
||||
describeContents<PeerPullPaymentIncomingRecord>("peerPullPaymentIncoming", {
|
||||
"peerPullPaymentIncoming",
|
||||
describeContents<PeerPullPaymentIncomingRecord>({
|
||||
keyPath: "peerPullPaymentIncomingId",
|
||||
}),
|
||||
{
|
||||
@ -1936,21 +1960,17 @@ export const WalletStoresV1 = {
|
||||
},
|
||||
),
|
||||
peerPullPaymentInitiations: describeStore(
|
||||
describeContents<PeerPullPaymentInitiationRecord>(
|
||||
"peerPullPaymentInitiations",
|
||||
{
|
||||
describeContents<PeerPullPaymentInitiationRecord>({
|
||||
keyPath: "pursePub",
|
||||
},
|
||||
),
|
||||
}),
|
||||
{},
|
||||
),
|
||||
peerPushPaymentInitiations: describeStore(
|
||||
describeContents<PeerPushPaymentInitiationRecord>(
|
||||
"peerPushPaymentInitiations",
|
||||
{
|
||||
describeContents<PeerPushPaymentInitiationRecord>({
|
||||
keyPath: "pursePub",
|
||||
},
|
||||
),
|
||||
}),
|
||||
{},
|
||||
),
|
||||
};
|
||||
@ -1962,7 +1982,8 @@ export interface MetaConfigRecord {
|
||||
|
||||
export const walletMetadataStore = {
|
||||
metaConfig: describeStore(
|
||||
describeContents<MetaConfigRecord>("metaConfig", { keyPath: "key" }),
|
||||
"metaConfig",
|
||||
describeContents<MetaConfigRecord>({ keyPath: "key" }),
|
||||
{},
|
||||
),
|
||||
};
|
||||
|
@ -76,20 +76,20 @@ export async function exportBackup(
|
||||
): Promise<WalletBackupContentV1> {
|
||||
await provideBackupState(ws);
|
||||
return ws.db
|
||||
.mktx((x) => ({
|
||||
config: x.config,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
purchases: x.purchases,
|
||||
proposals: x.proposals,
|
||||
refreshGroups: x.refreshGroups,
|
||||
backupProviders: x.backupProviders,
|
||||
tips: x.tips,
|
||||
recoupGroups: x.recoupGroups,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.config,
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.coins,
|
||||
x.denominations,
|
||||
x.purchases,
|
||||
x.proposals,
|
||||
x.refreshGroups,
|
||||
x.backupProviders,
|
||||
x.tips,
|
||||
x.recoupGroups,
|
||||
x.withdrawalGroups,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const bs = await getWalletBackupState(ws, tx);
|
||||
|
||||
|
@ -224,22 +224,22 @@ export async function importBackup(
|
||||
logger.info(`importing backup ${j2s(backupBlobArg)}`);
|
||||
|
||||
return ws.db
|
||||
.mktx((x) => ({
|
||||
config: x.config,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
purchases: x.purchases,
|
||||
proposals: x.proposals,
|
||||
refreshGroups: x.refreshGroups,
|
||||
backupProviders: x.backupProviders,
|
||||
tips: x.tips,
|
||||
recoupGroups: x.recoupGroups,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
tombstones: x.tombstones,
|
||||
depositGroups: x.depositGroups,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.config,
|
||||
x.exchangeDetails,
|
||||
x.exchanges,
|
||||
x.coins,
|
||||
x.denominations,
|
||||
x.purchases,
|
||||
x.proposals,
|
||||
x.refreshGroups,
|
||||
x.backupProviders,
|
||||
x.tips,
|
||||
x.recoupGroups,
|
||||
x.withdrawalGroups,
|
||||
x.tombstones,
|
||||
x.depositGroups,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
// FIXME: validate schema!
|
||||
const backupBlob = backupBlobArg as WalletBackupContentV1;
|
||||
|
@ -264,7 +264,7 @@ async function runBackupCycleForProvider(
|
||||
args: BackupForProviderArgs,
|
||||
): Promise<OperationAttemptResult> {
|
||||
const provider = await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.backupProviders.get(args.backupProviderBaseUrl);
|
||||
});
|
||||
@ -322,9 +322,9 @@ async function runBackupCycleForProvider(
|
||||
|
||||
if (resp.status === HttpStatusCode.NotModified) {
|
||||
await ws.db
|
||||
.mktx((x) => ({ backupProvider: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
const prov = await tx.backupProvider.get(provider.baseUrl);
|
||||
const prov = await tx.backupProviders.get(provider.baseUrl);
|
||||
if (!prov) {
|
||||
return;
|
||||
}
|
||||
@ -333,7 +333,7 @@ async function runBackupCycleForProvider(
|
||||
tag: BackupProviderStateTag.Ready,
|
||||
nextBackupTimestamp: getNextBackupTimestamp(),
|
||||
};
|
||||
await tx.backupProvider.put(prov);
|
||||
await tx.backupProviders.put(prov);
|
||||
});
|
||||
return {
|
||||
type: OperationAttemptResultType.Finished,
|
||||
@ -367,10 +367,7 @@ async function runBackupCycleForProvider(
|
||||
// FIXME: check if the provider is overcharging us!
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
backupProviders: x.backupProviders,
|
||||
operationRetries: x.operationRetries,
|
||||
}))
|
||||
.mktx((x) => [x.backupProviders, x.operationRetries])
|
||||
.runReadWrite(async (tx) => {
|
||||
const provRec = await tx.backupProviders.get(provider.baseUrl);
|
||||
checkDbInvariant(!!provRec);
|
||||
@ -407,7 +404,7 @@ async function runBackupCycleForProvider(
|
||||
|
||||
if (resp.status === HttpStatusCode.NoContent) {
|
||||
await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
const prov = await tx.backupProviders.get(provider.baseUrl);
|
||||
if (!prov) {
|
||||
@ -435,12 +432,9 @@ async function runBackupCycleForProvider(
|
||||
const cryptoData = await computeBackupCryptoData(ws.cryptoApi, blob);
|
||||
await importBackup(ws, blob, cryptoData);
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
backupProvider: x.backupProviders,
|
||||
operationRetries: x.operationRetries,
|
||||
}))
|
||||
.mktx((x) => [x.backupProviders, x.operationRetries])
|
||||
.runReadWrite(async (tx) => {
|
||||
const prov = await tx.backupProvider.get(provider.baseUrl);
|
||||
const prov = await tx.backupProviders.get(provider.baseUrl);
|
||||
if (!prov) {
|
||||
logger.warn("backup provider not found anymore");
|
||||
return;
|
||||
@ -453,7 +447,7 @@ async function runBackupCycleForProvider(
|
||||
prov.state = {
|
||||
tag: BackupProviderStateTag.Retrying,
|
||||
};
|
||||
await tx.backupProvider.put(prov);
|
||||
await tx.backupProviders.put(prov);
|
||||
});
|
||||
logger.info("processed existing backup");
|
||||
// Now upload our own, merged backup.
|
||||
@ -480,7 +474,7 @@ export async function processBackupForProvider(
|
||||
backupProviderBaseUrl: string,
|
||||
): Promise<OperationAttemptResult> {
|
||||
const provider = await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.backupProviders.get(backupProviderBaseUrl);
|
||||
});
|
||||
@ -509,7 +503,7 @@ export async function removeBackupProvider(
|
||||
req: RemoveBackupProviderRequest,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx(({ backupProviders }) => ({ backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.backupProviders.delete(req.provider);
|
||||
});
|
||||
@ -539,7 +533,7 @@ export async function runBackupCycle(
|
||||
req: RunBackupCycleRequest,
|
||||
): Promise<void> {
|
||||
const providers = await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadOnly(async (tx) => {
|
||||
if (req.providers) {
|
||||
const rs = await Promise.all(
|
||||
@ -605,7 +599,7 @@ export async function addBackupProvider(
|
||||
await provideBackupState(ws);
|
||||
const canonUrl = canonicalizeBaseUrl(req.backupProviderBaseUrl);
|
||||
await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
const oldProv = await tx.backupProviders.get(canonUrl);
|
||||
if (oldProv) {
|
||||
@ -628,7 +622,7 @@ export async function addBackupProvider(
|
||||
codecForSyncTermsOfServiceResponse(),
|
||||
);
|
||||
await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
let state: BackupProviderState;
|
||||
if (req.activate) {
|
||||
@ -807,10 +801,7 @@ export async function getBackupInfo(
|
||||
): Promise<BackupInfo> {
|
||||
const backupConfig = await provideBackupState(ws);
|
||||
const providerRecords = await ws.db
|
||||
.mktx((x) => ({
|
||||
backupProviders: x.backupProviders,
|
||||
operationRetries: x.operationRetries,
|
||||
}))
|
||||
.mktx((x) => [x.backupProviders, x.operationRetries])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.backupProviders.iter().mapAsync(async (bp) => {
|
||||
const opId = RetryTags.forBackup(bp);
|
||||
@ -853,7 +844,7 @@ export async function getBackupRecovery(
|
||||
): Promise<BackupRecovery> {
|
||||
const bs = await provideBackupState(ws);
|
||||
const providers = await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.backupProviders.iter().toArray();
|
||||
});
|
||||
@ -874,7 +865,7 @@ async function backupRecoveryTheirs(
|
||||
br: BackupRecovery,
|
||||
) {
|
||||
await ws.db
|
||||
.mktx((x) => ({ config: x.config, backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.config, x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
let backupStateEntry: ConfigRecord | undefined = await tx.config.get(
|
||||
WALLET_BACKUP_STATE_KEY,
|
||||
@ -924,7 +915,7 @@ export async function loadBackupRecovery(
|
||||
): Promise<void> {
|
||||
const bs = await provideBackupState(ws);
|
||||
const providers = await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.backupProviders.iter().toArray();
|
||||
});
|
||||
@ -954,7 +945,7 @@ export async function exportBackupEncrypted(
|
||||
await provideBackupState(ws);
|
||||
const blob = await exportBackup(ws);
|
||||
const bs = await ws.db
|
||||
.mktx((x) => ({ config: x.config }))
|
||||
.mktx((x) => [x.config])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await getWalletBackupState(ws, tx);
|
||||
});
|
||||
|
@ -29,9 +29,7 @@ export async function provideBackupState(
|
||||
ws: InternalWalletState,
|
||||
): Promise<WalletBackupConfState> {
|
||||
const bs: ConfigRecord | undefined = await ws.db
|
||||
.mktx((x) => ({
|
||||
config: x.config,
|
||||
}))
|
||||
.mktx((stores) => [stores.config])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.config.get(WALLET_BACKUP_STATE_KEY);
|
||||
});
|
||||
@ -47,9 +45,7 @@ export async function provideBackupState(
|
||||
// and be based on hostname
|
||||
const deviceId = `wallet-core-${encodeCrock(d)}`;
|
||||
return await ws.db
|
||||
.mktx((x) => ({
|
||||
config: x.config,
|
||||
}))
|
||||
.mktx((x) => [x.config])
|
||||
.runReadWrite(async (tx) => {
|
||||
let backupStateEntry: ConfigRecord | undefined = await tx.config.get(
|
||||
WALLET_BACKUP_STATE_KEY,
|
||||
@ -87,9 +83,7 @@ export async function setWalletDeviceId(
|
||||
): Promise<void> {
|
||||
await provideBackupState(ws);
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
config: x.config,
|
||||
}))
|
||||
.mktx((x) => [x.config])
|
||||
.runReadWrite(async (tx) => {
|
||||
let backupStateEntry: ConfigRecord | undefined = await tx.config.get(
|
||||
WALLET_BACKUP_STATE_KEY,
|
||||
|
@ -139,12 +139,7 @@ export async function getBalances(
|
||||
logger.trace("starting to compute balance");
|
||||
|
||||
const wbal = await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
refreshGroups: x.refreshGroups,
|
||||
purchases: x.purchases,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.refreshGroups, x.purchases, x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return getBalancesInsideTransaction(ws, tx);
|
||||
});
|
||||
|
@ -83,9 +83,7 @@ export async function processDepositGroup(
|
||||
} = {},
|
||||
): Promise<OperationAttemptResult> {
|
||||
const depositGroup = await ws.db
|
||||
.mktx((x) => ({
|
||||
depositGroups: x.depositGroups,
|
||||
}))
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.depositGroups.get(depositGroupId);
|
||||
});
|
||||
@ -141,7 +139,7 @@ export async function processDepositGroup(
|
||||
});
|
||||
await readSuccessResponseJsonOrThrow(httpResp, codecForDepositSuccess());
|
||||
await ws.db
|
||||
.mktx((x) => ({ depositGroups: x.depositGroups }))
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dg = await tx.depositGroups.get(depositGroupId);
|
||||
if (!dg) {
|
||||
@ -153,9 +151,7 @@ export async function processDepositGroup(
|
||||
}
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
depositGroups: x.depositGroups,
|
||||
}))
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dg = await tx.depositGroups.get(depositGroupId);
|
||||
if (!dg) {
|
||||
@ -185,9 +181,7 @@ export async function trackDepositGroup(
|
||||
body: any;
|
||||
}[] = [];
|
||||
const depositGroup = await ws.db
|
||||
.mktx((x) => ({
|
||||
depositGroups: x.depositGroups,
|
||||
}))
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.depositGroups.get(req.depositGroupId);
|
||||
});
|
||||
@ -247,10 +241,7 @@ export async function getFeeForDeposit(
|
||||
const exchangeInfos: { url: string; master_pub: string }[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadOnly(async (tx) => {
|
||||
const allExchanges = await tx.exchanges.iter().toArray();
|
||||
for (const e of allExchanges) {
|
||||
@ -315,10 +306,7 @@ export async function prepareDepositGroup(
|
||||
const exchangeInfos: { url: string; master_pub: string }[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadOnly(async (tx) => {
|
||||
const allExchanges = await tx.exchanges.iter().toArray();
|
||||
for (const e of allExchanges) {
|
||||
@ -417,10 +405,7 @@ export async function createDepositGroup(
|
||||
const exchangeInfos: { url: string; master_pub: string }[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadOnly(async (tx) => {
|
||||
const allExchanges = await tx.exchanges.iter().toArray();
|
||||
for (const e of allExchanges) {
|
||||
@ -532,12 +517,13 @@ export async function createDepositGroup(
|
||||
};
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
depositGroups: x.depositGroups,
|
||||
coins: x.coins,
|
||||
refreshGroups: x.refreshGroups,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.depositGroups,
|
||||
x.coins,
|
||||
x.recoupGroups,
|
||||
x.denominations,
|
||||
x.refreshGroups,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
await applyCoinSpend(
|
||||
ws,
|
||||
@ -565,12 +551,7 @@ export async function getEffectiveDepositAmount(
|
||||
const exchangeSet: Set<string> = new Set();
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations, x.exchanges, x.exchangeDetails])
|
||||
.runReadOnly(async (tx) => {
|
||||
for (let i = 0; i < pcs.coinPubs.length; i++) {
|
||||
const coin = await tx.coins.get(pcs.coinPubs[i]);
|
||||
@ -637,12 +618,7 @@ export async function getTotalFeesForDepositAmount(
|
||||
const exchangeSet: Set<string> = new Set();
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations, x.exchanges, x.exchangeDetails])
|
||||
.runReadOnly(async (tx) => {
|
||||
for (let i = 0; i < pcs.coinPubs.length; i++) {
|
||||
const coin = await tx.coins.get(pcs.coinPubs[i]);
|
||||
|
@ -161,10 +161,7 @@ export async function getExchangeDetails(
|
||||
}
|
||||
|
||||
getExchangeDetails.makeContext = (db: DbAccess<typeof WalletStoresV1>) =>
|
||||
db.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}));
|
||||
db.mktx((x) => [x.exchanges, x.exchangeDetails]);
|
||||
|
||||
export async function updateExchangeTermsOfService(
|
||||
ws: InternalWalletState,
|
||||
@ -172,10 +169,7 @@ export async function updateExchangeTermsOfService(
|
||||
tos: ExchangeTosDownloadResult,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
const d = await getExchangeDetails(tx, exchangeBaseUrl);
|
||||
if (d) {
|
||||
@ -193,10 +187,7 @@ export async function acceptExchangeTermsOfService(
|
||||
etag: string | undefined,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
const d = await getExchangeDetails(tx, exchangeBaseUrl);
|
||||
if (d) {
|
||||
@ -326,10 +317,7 @@ async function provideExchangeRecord(
|
||||
exchangeDetails: ExchangeDetailsRecord | undefined;
|
||||
}> {
|
||||
return await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
let exchange = await tx.exchanges.get(baseUrl);
|
||||
if (!exchange) {
|
||||
@ -569,14 +557,14 @@ export async function updateExchangeFromUrlHandler(
|
||||
logger.trace("updating exchange info in database");
|
||||
|
||||
const updated = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
denominations: x.denominations,
|
||||
coins: x.coins,
|
||||
refreshGroups: x.refreshGroups,
|
||||
recoupGroups: x.recoupGroups,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.denominations,
|
||||
x.coins,
|
||||
x.refreshGroups,
|
||||
x.recoupGroups,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const r = await tx.exchanges.get(baseUrl);
|
||||
if (!r) {
|
||||
@ -770,12 +758,12 @@ export async function getExchangeTrust(
|
||||
let isAudited = false;
|
||||
|
||||
return await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
exchangesTrustStore: x.exchangeTrust,
|
||||
auditorTrust: x.auditorTrust,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.exchangeTrust,
|
||||
x.auditorTrust,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchangeDetails = await getExchangeDetails(
|
||||
tx,
|
||||
@ -786,7 +774,7 @@ export async function getExchangeTrust(
|
||||
throw Error(`exchange ${exchangeInfo.baseUrl} details not available`);
|
||||
}
|
||||
const exchangeTrustRecord =
|
||||
await tx.exchangesTrustStore.indexes.byExchangeMasterPub.get(
|
||||
await tx.exchangeTrust.indexes.byExchangeMasterPub.get(
|
||||
exchangeDetails.masterPublicKey,
|
||||
);
|
||||
if (
|
||||
|
@ -120,7 +120,7 @@ export async function getTotalPaymentCost(
|
||||
pcs: PayCoinSelection,
|
||||
): Promise<AmountJson> {
|
||||
return ws.db
|
||||
.mktx((x) => ({ coins: x.coins, denominations: x.denominations }))
|
||||
.mktx((x) => [x.coins, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const costs: AmountJson[] = [];
|
||||
for (let i = 0; i < pcs.coinPubs.length; i++) {
|
||||
@ -222,12 +222,7 @@ export async function getCandidatePayCoins(
|
||||
const wireFeesPerExchange: Record<string, AmountJson> = {};
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
denominations: x.denominations,
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations, x.coins])
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchanges = await tx.exchanges.iter().toArray();
|
||||
for (const exchange of exchanges) {
|
||||
@ -459,13 +454,13 @@ async function recordConfirmPay(
|
||||
};
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
proposals: x.proposals,
|
||||
purchases: x.purchases,
|
||||
coins: x.coins,
|
||||
refreshGroups: x.refreshGroups,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.proposals,
|
||||
x.purchases,
|
||||
x.coins,
|
||||
x.refreshGroups,
|
||||
x.denominations,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.proposals.get(proposal.proposalId);
|
||||
if (p) {
|
||||
@ -489,7 +484,7 @@ async function failProposalPermanently(
|
||||
err: TalerErrorDetail,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.proposals.get(proposalId);
|
||||
if (!p) {
|
||||
@ -567,13 +562,10 @@ export async function processDownloadProposal(
|
||||
proposalId: string,
|
||||
options: {} = {},
|
||||
): Promise<OperationAttemptResult> {
|
||||
|
||||
const res = ws.db.mktx2((x) => [x.auditorTrust, x.coins])
|
||||
|
||||
const proposal = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.proposals.get(proposalId);
|
||||
return await tx.proposals.get(proposalId);
|
||||
});
|
||||
|
||||
if (!proposal) {
|
||||
@ -608,7 +600,7 @@ export async function processDownloadProposal(
|
||||
|
||||
const opId = RetryTags.forProposalClaim(proposal);
|
||||
const retryRecord = await ws.db
|
||||
.mktx((x) => ({ operationRetries: x.operationRetries }))
|
||||
.mktx((x) => [x.operationRetries])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.operationRetries.get(opId);
|
||||
});
|
||||
@ -748,7 +740,7 @@ export async function processDownloadProposal(
|
||||
logger.trace(`extracted contract data: ${j2s(contractData)}`);
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals, purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases, x.proposals])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.proposals.get(proposalId);
|
||||
if (!p) {
|
||||
@ -807,7 +799,7 @@ async function startDownloadProposal(
|
||||
noncePriv: string | undefined,
|
||||
): Promise<string> {
|
||||
const oldProposal = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.proposals.indexes.byUrlAndOrderId.get([
|
||||
merchantBaseUrl,
|
||||
@ -855,7 +847,7 @@ async function startDownloadProposal(
|
||||
};
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadWrite(async (tx) => {
|
||||
const existingRecord = await tx.proposals.indexes.byUrlAndOrderId.get([
|
||||
merchantBaseUrl,
|
||||
@ -880,7 +872,7 @@ async function storeFirstPaySuccess(
|
||||
): Promise<void> {
|
||||
const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
|
||||
await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const purchase = await tx.purchases.get(proposalId);
|
||||
|
||||
@ -916,7 +908,7 @@ async function storePayReplaySuccess(
|
||||
sessionId: string | undefined,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const purchase = await tx.purchases.get(proposalId);
|
||||
|
||||
@ -950,9 +942,9 @@ async function handleInsufficientFunds(
|
||||
logger.trace("handling insufficient funds, trying to re-select coins");
|
||||
|
||||
const proposal = await ws.db
|
||||
.mktx((x) => ({ purchaes: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchaes.get(proposalId);
|
||||
return tx.purchases.get(proposalId);
|
||||
});
|
||||
if (!proposal) {
|
||||
return;
|
||||
@ -990,7 +982,7 @@ async function handleInsufficientFunds(
|
||||
const prevPayCoins: PreviousPayCoins = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({ coins: x.coins, denominations: x.denominations }))
|
||||
.mktx((x) => [x.coins, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
for (let i = 0; i < proposal.payCoinSelection.coinPubs.length; i++) {
|
||||
const coinPub = proposal.payCoinSelection.coinPubs[i];
|
||||
@ -1036,12 +1028,7 @@ async function handleInsufficientFunds(
|
||||
logger.trace("re-selected coins");
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.purchases, x.coins, x.denominations, x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.purchases.get(proposalId);
|
||||
if (!p) {
|
||||
@ -1060,7 +1047,7 @@ async function unblockBackup(
|
||||
proposalId: string,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ backupProviders: x.backupProviders }))
|
||||
.mktx((x) => [x.backupProviders])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.backupProviders.indexes.byPaymentProposalId
|
||||
.iter(proposalId)
|
||||
@ -1081,7 +1068,7 @@ export async function checkPaymentByProposalId(
|
||||
sessionId?: string,
|
||||
): Promise<PreparePayResult> {
|
||||
let proposal = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.proposals.get(proposalId);
|
||||
});
|
||||
@ -1095,7 +1082,7 @@ export async function checkPaymentByProposalId(
|
||||
}
|
||||
logger.trace("using existing purchase for same product");
|
||||
proposal = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.proposals.get(existingProposalId);
|
||||
});
|
||||
@ -1118,7 +1105,7 @@ export async function checkPaymentByProposalId(
|
||||
|
||||
// First check if we already paid for it.
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.get(proposalId);
|
||||
});
|
||||
@ -1176,7 +1163,7 @@ export async function checkPaymentByProposalId(
|
||||
"automatically re-submitting payment with different session ID",
|
||||
);
|
||||
await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.purchases.get(proposalId);
|
||||
if (!p) {
|
||||
@ -1230,7 +1217,7 @@ export async function getContractTermsDetails(
|
||||
proposalId: string,
|
||||
): Promise<WalletContractData> {
|
||||
const proposal = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.proposals.get(proposalId);
|
||||
});
|
||||
@ -1296,7 +1283,7 @@ export async function generateDepositPermissions(
|
||||
denom: DenominationRecord;
|
||||
}> = [];
|
||||
await ws.db
|
||||
.mktx((x) => ({ coins: x.coins, denominations: x.denominations }))
|
||||
.mktx((x) => [x.coins, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
for (let i = 0; i < payCoinSel.coinPubs.length; i++) {
|
||||
const coin = await tx.coins.get(payCoinSel.coinPubs[i]);
|
||||
@ -1359,7 +1346,7 @@ export async function runPayForConfirmPay(
|
||||
switch (res.type) {
|
||||
case OperationAttemptResultType.Finished: {
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.get(proposalId);
|
||||
});
|
||||
@ -1399,7 +1386,7 @@ export async function confirmPay(
|
||||
`executing confirmPay with proposalId ${proposalId} and sessionIdOverride ${sessionIdOverride}`,
|
||||
);
|
||||
const proposal = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.proposals.get(proposalId);
|
||||
});
|
||||
@ -1414,7 +1401,7 @@ export async function confirmPay(
|
||||
}
|
||||
|
||||
const existingPurchase = await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const purchase = await tx.purchases.get(proposalId);
|
||||
if (
|
||||
@ -1508,7 +1495,7 @@ export async function processPurchasePay(
|
||||
} = {},
|
||||
): Promise<OperationAttemptResult> {
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.get(proposalId);
|
||||
});
|
||||
@ -1568,20 +1555,12 @@ export async function processPurchasePay(
|
||||
);
|
||||
|
||||
logger.trace(`got resp ${JSON.stringify(resp)}`);
|
||||
|
||||
const payOpId = RetryTags.forPay(purchase);
|
||||
const payRetryRecord = await ws.db
|
||||
.mktx((x) => ({ operationRetries: x.operationRetries }))
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.operationRetries.get(payOpId);
|
||||
});
|
||||
|
||||
if (resp.status === HttpStatusCode.BadRequest) {
|
||||
const errDetails = await readUnexpectedResponseDetails(resp);
|
||||
logger.warn("unexpected 400 response for /pay");
|
||||
logger.warn(j2s(errDetails));
|
||||
await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const purch = await tx.purchases.get(proposalId);
|
||||
if (!purch) {
|
||||
@ -1683,7 +1662,7 @@ export async function refuseProposal(
|
||||
proposalId: string,
|
||||
): Promise<void> {
|
||||
const success = await ws.db
|
||||
.mktx((x) => ({ proposals: x.proposals }))
|
||||
.mktx((x) => [x.proposals])
|
||||
.runReadWrite(async (tx) => {
|
||||
const proposal = await tx.proposals.get(proposalId);
|
||||
if (!proposal) {
|
||||
|
@ -242,13 +242,14 @@ export async function initiatePeerToPeerPush(
|
||||
});
|
||||
|
||||
const coinSelRes: PeerCoinSelection | undefined = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
refreshGroups: x.refreshGroups,
|
||||
peerPushPaymentInitiations: x.peerPushPaymentInitiations,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.coins,
|
||||
x.denominations,
|
||||
x.refreshGroups,
|
||||
x.peerPullPaymentInitiations,
|
||||
x.peerPushPaymentInitiations,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const sel = await selectPeerCoins(ws, tx, instructedAmount);
|
||||
if (!sel) {
|
||||
@ -401,9 +402,7 @@ export async function checkPeerPushPayment(
|
||||
const peerPushPaymentIncomingId = encodeCrock(getRandomBytes(32));
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
peerPushPaymentIncoming: x.peerPushPaymentIncoming,
|
||||
}))
|
||||
.mktx((x) => [x.peerPushPaymentIncoming])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.peerPushPaymentIncoming.add({
|
||||
peerPushPaymentIncomingId,
|
||||
@ -456,10 +455,7 @@ async function getMergeReserveInfo(
|
||||
const newReservePair = await ws.cryptoApi.createEddsaKeypair({});
|
||||
|
||||
const mergeReserveInfo: MergeReserveInfo = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const ex = await tx.exchanges.get(req.exchangeBaseUrl);
|
||||
checkDbInvariant(!!ex);
|
||||
@ -482,7 +478,7 @@ export async function acceptPeerPushPayment(
|
||||
req: AcceptPeerPushPaymentRequest,
|
||||
): Promise<void> {
|
||||
const peerInc = await ws.db
|
||||
.mktx((x) => ({ peerPushPaymentIncoming: x.peerPushPaymentIncoming }))
|
||||
.mktx((x) => [x.peerPushPaymentIncoming])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.peerPushPaymentIncoming.get(req.peerPushPaymentIncomingId);
|
||||
});
|
||||
@ -564,7 +560,7 @@ export async function acceptPeerPullPayment(
|
||||
req: AcceptPeerPullPaymentRequest,
|
||||
): Promise<void> {
|
||||
const peerPullInc = await ws.db
|
||||
.mktx((x) => ({ peerPullPaymentIncoming: x.peerPullPaymentIncoming }))
|
||||
.mktx((x) => [x.peerPullPaymentIncoming])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.peerPullPaymentIncoming.get(req.peerPullPaymentIncomingId);
|
||||
});
|
||||
@ -579,13 +575,13 @@ export async function acceptPeerPullPayment(
|
||||
peerPullInc.contractTerms.amount,
|
||||
);
|
||||
const coinSelRes: PeerCoinSelection | undefined = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
refreshGroups: x.refreshGroups,
|
||||
peerPullPaymentIncoming: x.peerPullPaymentIncoming,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.coins,
|
||||
x.denominations,
|
||||
x.refreshGroups,
|
||||
x.peerPullPaymentIncoming,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const sel = await selectPeerCoins(ws, tx, instructedAmount);
|
||||
if (!sel) {
|
||||
@ -689,9 +685,7 @@ export async function checkPeerPullPayment(
|
||||
const peerPullPaymentIncomingId = encodeCrock(getRandomBytes(32));
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
peerPullPaymentIncoming: x.peerPullPaymentIncoming,
|
||||
}))
|
||||
.mktx((x) => [x.peerPullPaymentIncoming])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.peerPullPaymentIncoming.add({
|
||||
peerPullPaymentIncomingId,
|
||||
@ -775,11 +769,9 @@ export async function initiatePeerRequestForPay(
|
||||
});
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
peerPullPaymentInitiation: x.peerPullPaymentInitiations,
|
||||
}))
|
||||
.mktx((x) => [x.peerPullPaymentInitiations])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.peerPullPaymentInitiation.put({
|
||||
await tx.peerPullPaymentInitiations.put({
|
||||
amount: req.amount,
|
||||
contractTerms,
|
||||
exchangeBaseUrl: req.exchangeBaseUrl,
|
||||
|
@ -357,21 +357,21 @@ export async function getPendingOperations(
|
||||
): Promise<PendingOperationsResponse> {
|
||||
const now = AbsoluteTime.now();
|
||||
return await ws.db
|
||||
.mktx((x) => ({
|
||||
backupProviders: x.backupProviders,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
refreshGroups: x.refreshGroups,
|
||||
coins: x.coins,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
proposals: x.proposals,
|
||||
tips: x.tips,
|
||||
purchases: x.purchases,
|
||||
planchets: x.planchets,
|
||||
depositGroups: x.depositGroups,
|
||||
recoupGroups: x.recoupGroups,
|
||||
operationRetries: x.operationRetries,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.backupProviders,
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.refreshGroups,
|
||||
x.coins,
|
||||
x.withdrawalGroups,
|
||||
x.proposals,
|
||||
x.tips,
|
||||
x.purchases,
|
||||
x.planchets,
|
||||
x.depositGroups,
|
||||
x.recoupGroups,
|
||||
x.operationRetries,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const resp: PendingOperationsResponse = {
|
||||
pendingOperations: [],
|
||||
|
@ -96,12 +96,12 @@ async function recoupTipCoin(
|
||||
// Thus we just put the coin to sleep.
|
||||
// FIXME: somehow report this to the user
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
recoupGroups: x.recoupGroups,
|
||||
denominations: WalletStoresV1.denominations,
|
||||
refreshGroups: WalletStoresV1.refreshGroups,
|
||||
coins: WalletStoresV1.coins,
|
||||
}))
|
||||
.mktx((stores) => [
|
||||
stores.recoupGroups,
|
||||
stores.denominations,
|
||||
stores.refreshGroups,
|
||||
stores.coins,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
|
||||
if (!recoupGroup) {
|
||||
@ -123,9 +123,7 @@ async function recoupWithdrawCoin(
|
||||
): Promise<void> {
|
||||
const reservePub = cs.reservePub;
|
||||
const denomInfo = await ws.db
|
||||
.mktx((x) => ({
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const denomInfo = await ws.getDenomInfo(
|
||||
ws,
|
||||
@ -169,12 +167,7 @@ async function recoupWithdrawCoin(
|
||||
// FIXME: verify that our expectations about the amount match
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
recoupGroups: x.recoupGroups,
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations, x.recoupGroups, x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
|
||||
if (!recoupGroup) {
|
||||
@ -207,10 +200,7 @@ async function recoupRefreshCoin(
|
||||
cs: RefreshCoinSource,
|
||||
): Promise<void> {
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const denomInfo = await ws.getDenomInfo(
|
||||
ws,
|
||||
@ -257,12 +247,7 @@ async function recoupRefreshCoin(
|
||||
}
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
recoupGroups: x.recoupGroups,
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations, x.recoupGroups, x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
|
||||
if (!recoupGroup) {
|
||||
@ -319,9 +304,7 @@ export async function processRecoupGroupHandler(
|
||||
): Promise<OperationAttemptResult> {
|
||||
const forceNow = options.forceNow ?? false;
|
||||
let recoupGroup = await ws.db
|
||||
.mktx((x) => ({
|
||||
recoupGroups: x.recoupGroups,
|
||||
}))
|
||||
.mktx((x) => [x.recoupGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.recoupGroups.get(recoupGroupId);
|
||||
});
|
||||
@ -343,9 +326,7 @@ export async function processRecoupGroupHandler(
|
||||
await Promise.all(ps);
|
||||
|
||||
recoupGroup = await ws.db
|
||||
.mktx((x) => ({
|
||||
recoupGroups: x.recoupGroups,
|
||||
}))
|
||||
.mktx((x) => [x.recoupGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.recoupGroups.get(recoupGroupId);
|
||||
});
|
||||
@ -366,10 +347,7 @@ export async function processRecoupGroupHandler(
|
||||
for (let i = 0; i < recoupGroup.coinPubs.length; i++) {
|
||||
const coinPub = recoupGroup.coinPubs[i];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
reserves: x.reserves,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.reserves])
|
||||
.runReadOnly(async (tx) => {
|
||||
const coin = await tx.coins.get(coinPub);
|
||||
if (!coin) {
|
||||
@ -414,12 +392,7 @@ export async function processRecoupGroupHandler(
|
||||
}
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
recoupGroups: x.recoupGroups,
|
||||
denominations: WalletStoresV1.denominations,
|
||||
refreshGroups: WalletStoresV1.refreshGroups,
|
||||
coins: WalletStoresV1.coins,
|
||||
}))
|
||||
.mktx((x) => [x.recoupGroups, x.denominations, x.refreshGroups, x.coins])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg2 = await tx.recoupGroups.get(recoupGroupId);
|
||||
if (!rg2) {
|
||||
@ -497,10 +470,7 @@ async function processRecoup(
|
||||
coinIdx: number,
|
||||
): Promise<void> {
|
||||
const coin = await ws.db
|
||||
.mktx((x) => ({
|
||||
recoupGroups: x.recoupGroups,
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.recoupGroups, x.coins])
|
||||
.runReadOnly(async (tx) => {
|
||||
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
|
||||
if (!recoupGroup) {
|
||||
|
@ -155,10 +155,7 @@ async function refreshCreateSession(
|
||||
);
|
||||
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups, x.coins])
|
||||
.runReadWrite(async (tx) => {
|
||||
const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!refreshGroup) {
|
||||
@ -197,9 +194,7 @@ async function refreshCreateSession(
|
||||
// to update and filter withdrawable denoms.
|
||||
|
||||
const { availableAmount, availableDenoms } = await ws.db
|
||||
.mktx((x) => ({
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const oldDenom = await ws.getDenomInfo(
|
||||
ws,
|
||||
@ -237,10 +232,7 @@ async function refreshCreateSession(
|
||||
)} too small`,
|
||||
);
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!rg) {
|
||||
@ -259,10 +251,7 @@ async function refreshCreateSession(
|
||||
|
||||
// Store refresh session for this coin in the database.
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups, x.coins])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!rg) {
|
||||
@ -300,11 +289,7 @@ async function refreshMelt(
|
||||
coinIndex: number,
|
||||
): Promise<void> {
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups, x.coins, x.denominations])
|
||||
.runReadWrite(async (tx) => {
|
||||
const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!refreshGroup) {
|
||||
@ -414,9 +399,7 @@ async function refreshMelt(
|
||||
if (resp.status === HttpStatusCode.NotFound) {
|
||||
const errDetails = await readUnexpectedResponseDetails(resp);
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!rg) {
|
||||
@ -446,9 +429,7 @@ async function refreshMelt(
|
||||
refreshSession.norevealIndex = norevealIndex;
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!rg) {
|
||||
@ -538,11 +519,7 @@ async function refreshReveal(
|
||||
): Promise<void> {
|
||||
logger.info("doing refresh reveal");
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups, x.coins, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!refreshGroup) {
|
||||
@ -703,10 +680,7 @@ async function refreshReveal(
|
||||
}
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (!rg) {
|
||||
@ -740,12 +714,8 @@ export async function processRefreshGroup(
|
||||
logger.info(`processing refresh group ${refreshGroupId}`);
|
||||
|
||||
const refreshGroup = await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.refreshGroups.get(refreshGroupId);
|
||||
});
|
||||
.mktx((x) => [x.refreshGroups])
|
||||
.runReadOnly(async (tx) => tx.refreshGroups.get(refreshGroupId));
|
||||
if (!refreshGroup) {
|
||||
return {
|
||||
type: OperationAttemptResultType.Finished,
|
||||
@ -801,7 +771,7 @@ async function processRefreshSession(
|
||||
`processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`,
|
||||
);
|
||||
let refreshGroup = await ws.db
|
||||
.mktx((x) => ({ refreshGroups: x.refreshGroups }))
|
||||
.mktx((x) => [x.refreshGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.refreshGroups.get(refreshGroupId);
|
||||
});
|
||||
@ -814,7 +784,7 @@ async function processRefreshSession(
|
||||
if (!refreshGroup.refreshSessionPerCoin[coinIndex]) {
|
||||
await refreshCreateSession(ws, refreshGroupId, coinIndex);
|
||||
refreshGroup = await ws.db
|
||||
.mktx((x) => ({ refreshGroups: x.refreshGroups }))
|
||||
.mktx((x) => [x.refreshGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.refreshGroups.get(refreshGroupId);
|
||||
});
|
||||
@ -981,12 +951,7 @@ export async function autoRefresh(
|
||||
durationFromSpec({ days: 1 }),
|
||||
);
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
refreshGroups: x.refreshGroups,
|
||||
exchanges: x.exchanges,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations, x.refreshGroups, x.exchanges])
|
||||
.runReadWrite(async (tx) => {
|
||||
const exchange = await tx.exchanges.get(exchangeBaseUrl);
|
||||
if (!exchange) {
|
||||
|
@ -78,9 +78,7 @@ export async function prepareRefund(
|
||||
}
|
||||
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.indexes.byMerchantUrlAndOrderId.get([
|
||||
parseResult.merchantBaseUrl,
|
||||
@ -335,12 +333,7 @@ async function acceptRefunds(
|
||||
const now = TalerProtocolTimestamp.now();
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
refreshGroups: x.refreshGroups,
|
||||
}))
|
||||
.mktx((x) => [x.purchases, x.coins, x.denominations, x.refreshGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.purchases.get(proposalId);
|
||||
if (!p) {
|
||||
@ -517,9 +510,7 @@ export async function applyRefund(
|
||||
}
|
||||
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.indexes.byMerchantUrlAndOrderId.get([
|
||||
parseResult.merchantBaseUrl,
|
||||
@ -544,9 +535,7 @@ export async function applyRefundFromPurchaseId(
|
||||
|
||||
logger.info("processing purchase for refund");
|
||||
const success = await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.purchases.get(proposalId);
|
||||
if (!p) {
|
||||
@ -569,9 +558,7 @@ export async function applyRefundFromPurchaseId(
|
||||
}
|
||||
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.get(proposalId);
|
||||
});
|
||||
@ -642,7 +629,7 @@ async function queryAndSaveAwaitingRefund(
|
||||
Amounts.cmp(refundAwaiting, purchase.refundAwaiting) !== 0
|
||||
) {
|
||||
await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.purchases.get(purchase.proposalId);
|
||||
if (!p) {
|
||||
@ -667,9 +654,7 @@ export async function processPurchaseQueryRefund(
|
||||
): Promise<OperationAttemptResult> {
|
||||
const waitForAutoRefund = options.waitForAutoRefund ?? false;
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.get(proposalId);
|
||||
});
|
||||
@ -729,9 +714,7 @@ export async function processPurchaseQueryRefund(
|
||||
const abortingCoins: AbortingCoin[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.coins])
|
||||
.runReadOnly(async (tx) => {
|
||||
for (let i = 0; i < purchase.payCoinSelection.coinPubs.length; i++) {
|
||||
const coinPub = purchase.payCoinSelection.coinPubs[i];
|
||||
@ -796,9 +779,7 @@ export async function abortFailedPayWithRefund(
|
||||
proposalId: string,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadWrite(async (tx) => {
|
||||
const purchase = await tx.purchases.get(proposalId);
|
||||
if (!purchase) {
|
||||
|
@ -467,7 +467,7 @@ export async function testPay(
|
||||
throw Error("payment not done");
|
||||
}
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({ purchases: x.purchases }))
|
||||
.mktx((x) => [x.purchases])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.get(result.proposalId);
|
||||
});
|
||||
|
@ -71,9 +71,7 @@ export async function prepareTip(
|
||||
}
|
||||
|
||||
let tipRecord = await ws.db
|
||||
.mktx((x) => ({
|
||||
tips: x.tips,
|
||||
}))
|
||||
.mktx((x) => [x.tips])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.tips.indexes.byMerchantTipIdAndBaseUrl.get([
|
||||
res.merchantTipId,
|
||||
@ -106,7 +104,7 @@ export async function prepareTip(
|
||||
ws,
|
||||
tipPickupStatus.exchange_url,
|
||||
amount,
|
||||
undefined
|
||||
undefined,
|
||||
);
|
||||
|
||||
const walletTipId = encodeCrock(getRandomBytes(32));
|
||||
@ -136,9 +134,7 @@ export async function prepareTip(
|
||||
denomSelUid,
|
||||
};
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
tips: x.tips,
|
||||
}))
|
||||
.mktx((x) => [x.tips])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.tips.put(newTipRecord);
|
||||
});
|
||||
@ -166,9 +162,7 @@ export async function processTip(
|
||||
} = {},
|
||||
): Promise<OperationAttemptResult> {
|
||||
const tipRecord = await ws.db
|
||||
.mktx((x) => ({
|
||||
tips: x.tips,
|
||||
}))
|
||||
.mktx((x) => [x.tips])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.tips.get(walletTipId);
|
||||
});
|
||||
@ -196,9 +190,7 @@ export async function processTip(
|
||||
|
||||
for (const dh of denomsForWithdraw.selectedDenoms) {
|
||||
const denom = await ws.db
|
||||
.mktx((x) => ({
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.denominations.get([
|
||||
tipRecord.exchangeBaseUrl,
|
||||
@ -324,11 +316,7 @@ export async function processTip(
|
||||
}
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
tips: x.tips,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.tips, x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const tr = await tx.tips.get(walletTipId);
|
||||
if (!tr) {
|
||||
@ -355,9 +343,7 @@ export async function acceptTip(
|
||||
tipId: string,
|
||||
): Promise<void> {
|
||||
const found = await ws.db
|
||||
.mktx((x) => ({
|
||||
tips: x.tips,
|
||||
}))
|
||||
.mktx((x) => [x.tips])
|
||||
.runReadWrite(async (tx) => {
|
||||
const tipRecord = await tx.tips.get(tipId);
|
||||
if (!tipRecord) {
|
||||
|
@ -126,24 +126,24 @@ export async function getTransactions(
|
||||
const transactions: Transaction[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
proposals: x.proposals,
|
||||
purchases: x.purchases,
|
||||
refreshGroups: x.refreshGroups,
|
||||
tips: x.tips,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
planchets: x.planchets,
|
||||
recoupGroups: x.recoupGroups,
|
||||
depositGroups: x.depositGroups,
|
||||
tombstones: x.tombstones,
|
||||
peerPushPaymentInitiations: x.peerPushPaymentInitiations,
|
||||
peerPullPaymentIncoming: x.peerPullPaymentIncoming,
|
||||
operationRetries: x.operationRetries,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.coins,
|
||||
x.denominations,
|
||||
x.depositGroups,
|
||||
x.exchangeDetails,
|
||||
x.exchanges,
|
||||
x.operationRetries,
|
||||
x.peerPullPaymentIncoming,
|
||||
x.peerPushPaymentInitiations,
|
||||
x.planchets,
|
||||
x.proposals,
|
||||
x.purchases,
|
||||
x.recoupGroups,
|
||||
x.recoupGroups,
|
||||
x.tips,
|
||||
x.tombstones,
|
||||
x.withdrawalGroups,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
tx.peerPushPaymentInitiations.iter().forEachAsync(async (pi) => {
|
||||
const amount = Amounts.parseOrThrow(pi.amount);
|
||||
@ -609,10 +609,7 @@ export async function deleteTransaction(
|
||||
) {
|
||||
const withdrawalGroupId = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
|
||||
withdrawalGroupId,
|
||||
@ -628,11 +625,7 @@ export async function deleteTransaction(
|
||||
} else if (type === TransactionType.Payment) {
|
||||
const proposalId = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
proposals: x.proposals,
|
||||
purchases: x.purchases,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.proposals, x.purchases, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
let found = false;
|
||||
const proposal = await tx.proposals.get(proposalId);
|
||||
@ -654,10 +647,7 @@ export async function deleteTransaction(
|
||||
} else if (type === TransactionType.Refresh) {
|
||||
const refreshGroupId = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const rg = await tx.refreshGroups.get(refreshGroupId);
|
||||
if (rg) {
|
||||
@ -670,10 +660,7 @@ export async function deleteTransaction(
|
||||
} else if (type === TransactionType.Tip) {
|
||||
const tipId = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
tips: x.tips,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.tips, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const tipRecord = await tx.tips.get(tipId);
|
||||
if (tipRecord) {
|
||||
@ -686,10 +673,7 @@ export async function deleteTransaction(
|
||||
} else if (type === TransactionType.Deposit) {
|
||||
const depositGroupId = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
depositGroups: x.depositGroups,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.depositGroups, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const tipRecord = await tx.depositGroups.get(depositGroupId);
|
||||
if (tipRecord) {
|
||||
@ -704,11 +688,7 @@ export async function deleteTransaction(
|
||||
const executionTimeStr = rest[1];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
proposals: x.proposals,
|
||||
purchases: x.purchases,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.proposals, x.purchases, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const purchase = await tx.purchases.get(proposalId);
|
||||
if (purchase) {
|
||||
@ -726,10 +706,7 @@ export async function deleteTransaction(
|
||||
} else if (type === TransactionType.PeerPullDebit) {
|
||||
const peerPullPaymentIncomingId = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
peerPullPaymentIncoming: x.peerPullPaymentIncoming,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.peerPullPaymentIncoming, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const debit = await tx.peerPullPaymentIncoming.get(
|
||||
peerPullPaymentIncomingId,
|
||||
@ -747,10 +724,7 @@ export async function deleteTransaction(
|
||||
} else if (type === TransactionType.PeerPushDebit) {
|
||||
const pursePub = rest[0];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
peerPushPaymentInitiations: x.peerPushPaymentInitiations,
|
||||
tombstones: x.tombstones,
|
||||
}))
|
||||
.mktx((x) => [x.peerPushPaymentInitiations, x.tombstones])
|
||||
.runReadWrite(async (tx) => {
|
||||
const debit = await tx.peerPushPaymentInitiations.get(pursePub);
|
||||
if (debit) {
|
||||
|
@ -197,7 +197,7 @@ export interface ExchangeWithdrawDetails {
|
||||
* the array of ages.
|
||||
*
|
||||
*/
|
||||
ageRestrictionOptions?: number[],
|
||||
ageRestrictionOptions?: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -412,7 +412,7 @@ export async function getCandidateWithdrawalDenoms(
|
||||
exchangeBaseUrl: string,
|
||||
): Promise<DenominationRecord[]> {
|
||||
return await ws.db
|
||||
.mktx((x) => ({ denominations: x.denominations }))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
|
||||
exchangeBaseUrl,
|
||||
@ -434,9 +434,7 @@ async function processPlanchetGenerate(
|
||||
coinIdx: number,
|
||||
): Promise<void> {
|
||||
let planchet = await ws.db
|
||||
.mktx((x) => ({
|
||||
planchets: x.planchets,
|
||||
}))
|
||||
.mktx((x) => [x.planchets])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.planchets.indexes.byGroupAndIndex.get([
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
@ -462,9 +460,7 @@ async function processPlanchetGenerate(
|
||||
const denomPubHash = maybeDenomPubHash;
|
||||
|
||||
const denom = await ws.db
|
||||
.mktx((x) => ({
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
return ws.getDenomInfo(
|
||||
ws,
|
||||
@ -500,7 +496,7 @@ async function processPlanchetGenerate(
|
||||
lastError: undefined,
|
||||
};
|
||||
await ws.db
|
||||
.mktx((x) => ({ planchets: x.planchets }))
|
||||
.mktx((x) => [x.planchets])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.planchets.indexes.byGroupAndIndex.get([
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
@ -529,12 +525,12 @@ async function processPlanchetExchangeRequest(
|
||||
`processing planchet exchange request ${withdrawalGroup.withdrawalGroupId}/${coinIdx}`,
|
||||
);
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
planchets: x.planchets,
|
||||
exchanges: x.exchanges,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.withdrawalGroups,
|
||||
x.planchets,
|
||||
x.exchanges,
|
||||
x.denominations,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
@ -599,7 +595,7 @@ async function processPlanchetExchangeRequest(
|
||||
logger.trace("withdrawal request failed", e);
|
||||
logger.trace(e);
|
||||
await ws.db
|
||||
.mktx((x) => ({ planchets: x.planchets }))
|
||||
.mktx((x) => [x.planchets])
|
||||
.runReadWrite(async (tx) => {
|
||||
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
@ -631,12 +627,12 @@ async function processPlanchetExchangeBatchRequest(
|
||||
.map((x) => x.count)
|
||||
.reduce((a, b) => a + b);
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
planchets: x.planchets,
|
||||
exchanges: x.exchanges,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.withdrawalGroups,
|
||||
x.planchets,
|
||||
x.exchanges,
|
||||
x.denominations,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
const reqBody: { planchets: ExchangeWithdrawRequest[] } = {
|
||||
planchets: [],
|
||||
@ -705,11 +701,7 @@ async function processPlanchetVerifyAndStoreCoin(
|
||||
resp: WithdrawResponse,
|
||||
): Promise<void> {
|
||||
const d = await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
planchets: x.planchets,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups, x.planchets, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
@ -768,7 +760,7 @@ async function processPlanchetVerifyAndStoreCoin(
|
||||
|
||||
if (!isValid) {
|
||||
await ws.db
|
||||
.mktx((x) => ({ planchets: x.planchets }))
|
||||
.mktx((x) => [x.planchets])
|
||||
.runReadWrite(async (tx) => {
|
||||
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
@ -823,11 +815,7 @@ async function processPlanchetVerifyAndStoreCoin(
|
||||
// withdrawal succeeded. If so, mark the withdrawal
|
||||
// group as finished.
|
||||
const firstSuccess = await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
planchets: x.planchets,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.withdrawalGroups, x.planchets])
|
||||
.runReadWrite(async (tx) => {
|
||||
const p = await tx.planchets.get(planchetCoinPub);
|
||||
if (!p || p.withdrawalDone) {
|
||||
@ -858,10 +846,7 @@ export async function updateWithdrawalDenoms(
|
||||
`updating denominations used for withdrawal for ${exchangeBaseUrl}`,
|
||||
);
|
||||
const exchangeDetails = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadOnly(async (tx) => {
|
||||
return ws.exchangeOps.getExchangeDetails(tx, exchangeBaseUrl);
|
||||
});
|
||||
@ -890,7 +875,8 @@ export async function updateWithdrawalDenoms(
|
||||
denom.verificationStatus === DenominationVerificationStatus.Unverified
|
||||
) {
|
||||
logger.trace(
|
||||
`Validating denomination (${current + 1}/${denominations.length
|
||||
`Validating denomination (${current + 1}/${
|
||||
denominations.length
|
||||
}) signature of ${denom.denomPubHash}`,
|
||||
);
|
||||
let valid = false;
|
||||
@ -919,7 +905,7 @@ export async function updateWithdrawalDenoms(
|
||||
if (updatedDenominations.length > 0) {
|
||||
logger.trace("writing denomination batch to db");
|
||||
await ws.db
|
||||
.mktx((x) => ({ denominations: x.denominations }))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadWrite(async (tx) => {
|
||||
for (let i = 0; i < updatedDenominations.length; i++) {
|
||||
const denom = updatedDenominations[i];
|
||||
@ -988,9 +974,7 @@ async function queryReserve(
|
||||
logger.trace(`got reserve status ${j2s(result.response)}`);
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
if (!wg) {
|
||||
@ -1011,7 +995,7 @@ export async function processWithdrawalGroup(
|
||||
): Promise<OperationAttemptResult> {
|
||||
logger.trace("processing withdrawal group", withdrawalGroupId);
|
||||
const withdrawalGroup = await ws.db
|
||||
.mktx((x) => ({ withdrawalGroups: x.withdrawalGroups }))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
});
|
||||
@ -1080,7 +1064,7 @@ export async function processWithdrawalGroup(
|
||||
|
||||
if (withdrawalGroup.denomsSel.selectedDenoms.length === 0) {
|
||||
await ws.db
|
||||
.mktx((x) => ({ withdrawalGroups: x.withdrawalGroups }))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
if (!wg) {
|
||||
@ -1148,11 +1132,7 @@ export async function processWithdrawalGroup(
|
||||
let errorsPerCoin: Record<number, TalerErrorDetail> = {};
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
planchets: x.planchets,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.withdrawalGroups, x.planchets])
|
||||
.runReadWrite(async (tx) => {
|
||||
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
if (!wg) {
|
||||
@ -1202,7 +1182,9 @@ export async function processWithdrawalGroup(
|
||||
};
|
||||
}
|
||||
|
||||
const AGE_MASK_GROUPS = "8:10:12:14:16:18".split(":").map(n => parseInt(n, 10))
|
||||
const AGE_MASK_GROUPS = "8:10:12:14:16:18"
|
||||
.split(":")
|
||||
.map((n) => parseInt(n, 10));
|
||||
|
||||
export async function getExchangeWithdrawalInfo(
|
||||
ws: InternalWalletState,
|
||||
@ -1237,14 +1219,14 @@ export async function getExchangeWithdrawalInfo(
|
||||
exchange,
|
||||
);
|
||||
|
||||
let hasDenomWithAgeRestriction = false
|
||||
let hasDenomWithAgeRestriction = false;
|
||||
|
||||
let earliestDepositExpiration: TalerProtocolTimestamp | undefined;
|
||||
for (let i = 0; i < selectedDenoms.selectedDenoms.length; i++) {
|
||||
const ds = selectedDenoms.selectedDenoms[i];
|
||||
// FIXME: Do in one transaction!
|
||||
const denom = await ws.db
|
||||
.mktx((x) => ({ denominations: x.denominations }))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
return ws.getDenomInfo(ws, tx, exchangeBaseUrl, ds.denomPubHash);
|
||||
});
|
||||
@ -1262,13 +1244,14 @@ export async function getExchangeWithdrawalInfo(
|
||||
) {
|
||||
earliestDepositExpiration = expireDeposit;
|
||||
}
|
||||
hasDenomWithAgeRestriction = hasDenomWithAgeRestriction || denom.denomPub.age_mask > 0
|
||||
hasDenomWithAgeRestriction =
|
||||
hasDenomWithAgeRestriction || denom.denomPub.age_mask > 0;
|
||||
}
|
||||
|
||||
checkLogicInvariant(!!earliestDepositExpiration);
|
||||
|
||||
const possibleDenoms = await ws.db
|
||||
.mktx((x) => ({ denominations: x.denominations }))
|
||||
.mktx((x) => [x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const ds = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
|
||||
exchangeBaseUrl,
|
||||
@ -1325,7 +1308,9 @@ export async function getExchangeWithdrawalInfo(
|
||||
withdrawalAmountRaw: Amounts.stringify(instructedAmount),
|
||||
// TODO: remove hardcoding, this should be calculated from the denominations info
|
||||
// force enabled for testing
|
||||
ageRestrictionOptions: hasDenomWithAgeRestriction ? AGE_MASK_GROUPS : undefined
|
||||
ageRestrictionOptions: hasDenomWithAgeRestriction
|
||||
? AGE_MASK_GROUPS
|
||||
: undefined,
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
@ -1369,11 +1354,7 @@ export async function getWithdrawalDetailsForUri(
|
||||
const exchanges: ExchangeListItem[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchangeRecords = await tx.exchanges.iter().toArray();
|
||||
for (const r of exchangeRecords) {
|
||||
@ -1409,11 +1390,7 @@ export async function getFundingPaytoUrisTx(
|
||||
withdrawalGroupId: string,
|
||||
): Promise<string[]> {
|
||||
return await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.withdrawalGroups])
|
||||
.runReadWrite((tx) => getFundingPaytoUris(tx, withdrawalGroupId));
|
||||
}
|
||||
|
||||
@ -1461,9 +1438,7 @@ async function getWithdrawalGroupRecordTx(
|
||||
},
|
||||
): Promise<WithdrawalGroupRecord | undefined> {
|
||||
return await db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.withdrawalGroups.get(req.withdrawalGroupId);
|
||||
});
|
||||
@ -1490,9 +1465,7 @@ async function registerReserveWithBank(
|
||||
withdrawalGroupId: string,
|
||||
): Promise<void> {
|
||||
const withdrawalGroup = await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
});
|
||||
@ -1526,9 +1499,7 @@ async function registerReserveWithBank(
|
||||
codecForBankWithdrawalOperationPostResponse(),
|
||||
);
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const r = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
if (!r) {
|
||||
@ -1606,9 +1577,7 @@ async function processReserveBankStatus(
|
||||
if (status.aborted) {
|
||||
logger.info("bank aborted the withdrawal");
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const r = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
if (!r) {
|
||||
@ -1648,9 +1617,7 @@ async function processReserveBankStatus(
|
||||
}
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const r = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||
if (!r) {
|
||||
@ -1753,13 +1720,13 @@ export async function internalCreateWithdrawalGroup(
|
||||
);
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
reserves: x.reserves,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
exchangeTrust: x.exchangeTrust,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.withdrawalGroups,
|
||||
x.reserves,
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.exchangeTrust,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.withdrawalGroups.add(withdrawalGroup);
|
||||
await tx.reserves.put({
|
||||
@ -1790,7 +1757,7 @@ export async function acceptWithdrawalFromUri(
|
||||
},
|
||||
): Promise<AcceptWithdrawalResponse> {
|
||||
const existingWithdrawalGroup = await ws.db
|
||||
.mktx((x) => ({ withdrawalGroups: x.withdrawalGroups }))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await tx.withdrawalGroups.indexes.byTalerWithdrawUri.get(
|
||||
req.talerWithdrawUri,
|
||||
@ -1899,12 +1866,12 @@ export async function createManualWithdrawal(
|
||||
const withdrawalGroupId = withdrawalGroup.withdrawalGroupId;
|
||||
|
||||
const exchangePaytoUris = await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
exchangeTrust: x.exchangeTrust,
|
||||
}))
|
||||
.mktx((x) => [
|
||||
x.withdrawalGroups,
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.exchangeTrust,
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
return await getFundingPaytoUris(tx, withdrawalGroup.withdrawalGroupId);
|
||||
});
|
||||
|
@ -36,6 +36,7 @@ import {
|
||||
} from "@gnu-taler/idb-bridge";
|
||||
import { Logger } from "@gnu-taler/taler-util";
|
||||
import { performanceNow } from "./timer.js";
|
||||
import { access } from "fs";
|
||||
|
||||
const logger = new Logger("query.ts");
|
||||
|
||||
@ -280,7 +281,6 @@ export interface IndexDescriptor {
|
||||
|
||||
export interface StoreDescriptor<RecordType> {
|
||||
_dummy: undefined & RecordType;
|
||||
name: string;
|
||||
keyPath?: IDBKeyPath | IDBKeyPath[];
|
||||
autoIncrement?: boolean;
|
||||
}
|
||||
@ -291,10 +291,9 @@ export interface StoreOptions {
|
||||
}
|
||||
|
||||
export function describeContents<RecordType = never>(
|
||||
name: string,
|
||||
options: StoreOptions,
|
||||
): StoreDescriptor<RecordType> {
|
||||
return { name, keyPath: options.keyPath, _dummy: undefined as any };
|
||||
return { keyPath: options.keyPath, _dummy: undefined as any };
|
||||
}
|
||||
|
||||
export function describeIndex(
|
||||
@ -345,9 +344,11 @@ export interface StoreReadWriteAccessor<RecordType, IndexMap> {
|
||||
}
|
||||
|
||||
export interface StoreWithIndexes<
|
||||
StoreName extends string,
|
||||
SD extends StoreDescriptor<unknown>,
|
||||
IndexMap,
|
||||
> {
|
||||
storeName: StoreName;
|
||||
store: SD;
|
||||
indexMap: IndexMap;
|
||||
|
||||
@ -362,11 +363,17 @@ export type GetRecordType<T> = T extends StoreDescriptor<infer X> ? X : unknown;
|
||||
|
||||
const storeWithIndexesSymbol = Symbol("StoreWithIndexesMark");
|
||||
|
||||
export function describeStore<SD extends StoreDescriptor<unknown>, IndexMap>(
|
||||
export function describeStore<
|
||||
StoreName extends string,
|
||||
SD extends StoreDescriptor<unknown>,
|
||||
IndexMap,
|
||||
>(
|
||||
name: StoreName,
|
||||
s: SD,
|
||||
m: IndexMap,
|
||||
): StoreWithIndexes<SD, IndexMap> {
|
||||
): StoreWithIndexes<StoreName, SD, IndexMap> {
|
||||
return {
|
||||
storeName: name,
|
||||
store: s,
|
||||
indexMap: m,
|
||||
mark: storeWithIndexesSymbol,
|
||||
@ -375,6 +382,7 @@ export function describeStore<SD extends StoreDescriptor<unknown>, IndexMap>(
|
||||
|
||||
export type GetReadOnlyAccess<BoundStores> = {
|
||||
[P in keyof BoundStores]: BoundStores[P] extends StoreWithIndexes<
|
||||
infer SN,
|
||||
infer SD,
|
||||
infer IM
|
||||
>
|
||||
@ -384,6 +392,7 @@ export type GetReadOnlyAccess<BoundStores> = {
|
||||
|
||||
export type GetReadWriteAccess<BoundStores> = {
|
||||
[P in keyof BoundStores]: BoundStores[P] extends StoreWithIndexes<
|
||||
infer SN,
|
||||
infer SD,
|
||||
infer IM
|
||||
>
|
||||
@ -404,8 +413,12 @@ export interface TransactionContext<BoundStores> {
|
||||
runReadOnly<T>(f: ReadOnlyTransactionFunction<BoundStores, T>): Promise<T>;
|
||||
}
|
||||
|
||||
type CheckDescriptor<T> = T extends StoreWithIndexes<infer SD, infer IM>
|
||||
? StoreWithIndexes<SD, IM>
|
||||
type CheckDescriptor<T> = T extends StoreWithIndexes<
|
||||
infer SN,
|
||||
infer SD,
|
||||
infer IM
|
||||
>
|
||||
? StoreWithIndexes<SN, SD, IM>
|
||||
: unknown;
|
||||
|
||||
type GetPickerType<F, SM> = F extends (x: SM) => infer Out
|
||||
@ -477,13 +490,13 @@ function runTx<Arg, Res>(
|
||||
|
||||
function makeReadContext(
|
||||
tx: IDBTransaction,
|
||||
storePick: { [n: string]: StoreWithIndexes<any, any> },
|
||||
storePick: { [n: string]: StoreWithIndexes<any, any, any> },
|
||||
): any {
|
||||
const ctx: { [s: string]: StoreReadOnlyAccessor<any, any> } = {};
|
||||
for (const storeAlias in storePick) {
|
||||
const indexes: { [s: string]: IndexReadOnlyAccessor<any> } = {};
|
||||
const swi = storePick[storeAlias];
|
||||
const storeName = swi.store.name;
|
||||
const storeName = swi.storeName;
|
||||
for (const indexAlias in storePick[storeAlias].indexMap) {
|
||||
const indexDescriptor: IndexDescriptor =
|
||||
storePick[storeAlias].indexMap[indexAlias];
|
||||
@ -526,13 +539,13 @@ function makeReadContext(
|
||||
|
||||
function makeWriteContext(
|
||||
tx: IDBTransaction,
|
||||
storePick: { [n: string]: StoreWithIndexes<any, any> },
|
||||
storePick: { [n: string]: StoreWithIndexes<any, any, any> },
|
||||
): any {
|
||||
const ctx: { [s: string]: StoreReadWriteAccessor<any, any> } = {};
|
||||
for (const storeAlias in storePick) {
|
||||
const indexes: { [s: string]: IndexReadWriteAccessor<any> } = {};
|
||||
const swi = storePick[storeAlias];
|
||||
const storeName = swi.store.name;
|
||||
const storeName = swi.storeName;
|
||||
for (const indexAlias in storePick[storeAlias].indexMap) {
|
||||
const indexDescriptor: IndexDescriptor =
|
||||
storePick[storeAlias].indexMap[indexAlias];
|
||||
@ -585,25 +598,11 @@ function makeWriteContext(
|
||||
return ctx;
|
||||
}
|
||||
|
||||
const storeList = [
|
||||
{ name: "foo" as const, value: 1 as const },
|
||||
{ name: "bar" as const, value: 2 as const },
|
||||
];
|
||||
// => { foo: { value: 1}, bar: {value: 2} }
|
||||
|
||||
type StoreList = typeof storeList;
|
||||
|
||||
type StoreNames = StoreList[number] extends { name: infer I } ? I : never;
|
||||
|
||||
type H = StoreList[number] & { name: "foo"};
|
||||
|
||||
type Cleanup<V> = V extends { name: infer N, value: infer X} ? {name: N, value: X} : never;
|
||||
|
||||
type G = {
|
||||
[X in StoreNames]: {
|
||||
X: StoreList[number] & { name: X };
|
||||
};
|
||||
};
|
||||
type StoreNamesOf<X> = X extends { [x: number]: infer F }
|
||||
? F extends { storeName: infer I }
|
||||
? I
|
||||
: never
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Type-safe access to a database with a particular store map.
|
||||
@ -617,36 +616,41 @@ export class DbAccess<StoreMap> {
|
||||
return this.db;
|
||||
}
|
||||
|
||||
mktx2<
|
||||
/**
|
||||
* Run a transaction with selected object stores.
|
||||
*
|
||||
* The {@link namePicker} must be a function that selects a list of object
|
||||
* stores from all available object stores.
|
||||
*/
|
||||
mktx<
|
||||
StoreNames extends keyof StoreMap,
|
||||
Stores extends StoreMap[StoreNames],
|
||||
StoreList extends Stores[],
|
||||
>(namePicker: (x: StoreMap) => StoreList): StoreList {
|
||||
return namePicker(this.stores);
|
||||
}
|
||||
|
||||
mktx<
|
||||
PickerType extends (x: StoreMap) => unknown,
|
||||
BoundStores extends GetPickerType<PickerType, StoreMap>,
|
||||
>(f: PickerType): TransactionContext<BoundStores> {
|
||||
const storePick = f(this.stores) as any;
|
||||
BoundStores extends {
|
||||
[X in StoreNamesOf<StoreList>]: StoreList[number] & { storeName: X };
|
||||
},
|
||||
>(namePicker: (x: StoreMap) => StoreList): TransactionContext<BoundStores> {
|
||||
const storePick = namePicker(this.stores) as any;
|
||||
if (typeof storePick !== "object" || storePick === null) {
|
||||
throw Error();
|
||||
}
|
||||
const storeNames: string[] = [];
|
||||
for (const storeAlias of Object.keys(storePick)) {
|
||||
const swi = (storePick as any)[storeAlias] as StoreWithIndexes<any, any>;
|
||||
const accessibleStores: { [x: string]: StoreWithIndexes<any, any, any> } =
|
||||
{};
|
||||
for (const swiPicked of storePick) {
|
||||
const swi = swiPicked as StoreWithIndexes<any, any, any>;
|
||||
if (swi.mark !== storeWithIndexesSymbol) {
|
||||
throw Error("invalid store descriptor returned from selector function");
|
||||
}
|
||||
storeNames.push(swi.store.name);
|
||||
storeNames.push(swi.storeName);
|
||||
accessibleStores[swi.storeName] = swi;
|
||||
}
|
||||
|
||||
const runReadOnly = <T>(
|
||||
txf: ReadOnlyTransactionFunction<BoundStores, T>,
|
||||
): Promise<T> => {
|
||||
const tx = this.db.transaction(storeNames, "readonly");
|
||||
const readContext = makeReadContext(tx, storePick);
|
||||
const readContext = makeReadContext(tx, accessibleStores);
|
||||
return runTx(tx, readContext, txf);
|
||||
};
|
||||
|
||||
@ -654,7 +658,7 @@ export class DbAccess<StoreMap> {
|
||||
txf: ReadWriteTransactionFunction<BoundStores, T>,
|
||||
): Promise<T> => {
|
||||
const tx = this.db.transaction(storeNames, "readwrite");
|
||||
const writeContext = makeWriteContext(tx, storePick);
|
||||
const writeContext = makeWriteContext(tx, accessibleStores);
|
||||
return runTx(tx, writeContext, txf);
|
||||
};
|
||||
|
||||
|
@ -201,8 +201,9 @@ export async function scheduleRetry(
|
||||
errorDetail?: TalerErrorDetail,
|
||||
): Promise<void> {
|
||||
return await ws.db
|
||||
.mktx((x) => ({ operationRetries: x.operationRetries }))
|
||||
.mktx((x) => [x.operationRetries])
|
||||
.runReadWrite(async (tx) => {
|
||||
tx.operationRetries
|
||||
scheduleRetryInTx(ws, tx, opId, errorDetail);
|
||||
});
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ export async function storeOperationError(
|
||||
e: TalerErrorDetail,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ operationRetries: x.operationRetries }))
|
||||
.mktx((x) => [x.operationRetries])
|
||||
.runReadWrite(async (tx) => {
|
||||
const retryRecord = await tx.operationRetries.get(pendingTaskId);
|
||||
if (!retryRecord) {
|
||||
@ -345,7 +345,7 @@ export async function storeOperationFinished(
|
||||
pendingTaskId: string,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ operationRetries: x.operationRetries }))
|
||||
.mktx((x) => [x.operationRetries])
|
||||
.runReadWrite(async (tx) => {
|
||||
await tx.operationRetries.delete(pendingTaskId);
|
||||
});
|
||||
@ -356,7 +356,7 @@ export async function storeOperationPending(
|
||||
pendingTaskId: string,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ operationRetries: x.operationRetries }))
|
||||
.mktx((x) => [x.operationRetries])
|
||||
.runReadWrite(async (tx) => {
|
||||
const retryRecord = await tx.operationRetries.get(pendingTaskId);
|
||||
if (!retryRecord) {
|
||||
@ -542,7 +542,7 @@ async function runTaskLoop(
|
||||
*/
|
||||
async function fillDefaults(ws: InternalWalletState): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({ config: x.config, auditorTrustStore: x.auditorTrust }))
|
||||
.mktx((x) => [x.config, x.auditorTrust])
|
||||
.runReadWrite(async (tx) => {
|
||||
let applied = false;
|
||||
await tx.config.iter().forEach((x) => {
|
||||
@ -552,7 +552,7 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
|
||||
});
|
||||
if (!applied) {
|
||||
for (const c of builtinAuditors) {
|
||||
await tx.auditorTrustStore.put(c);
|
||||
await tx.auditorTrust.put(c);
|
||||
}
|
||||
}
|
||||
// FIXME: make sure exchanges are added transactionally to
|
||||
@ -634,9 +634,7 @@ async function listKnownBankAccounts(
|
||||
): Promise<KnownBankAccounts> {
|
||||
const accounts: { [account: string]: PaytoUri } = {};
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
const withdrawalGroups = await tx.withdrawalGroups.iter().toArray();
|
||||
for (const r of withdrawalGroups) {
|
||||
@ -660,11 +658,7 @@ async function getExchanges(
|
||||
): Promise<ExchangesListResponse> {
|
||||
const exchanges: ExchangeListItem[] = [];
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchangeRecords = await tx.exchanges.iter().toArray();
|
||||
for (const r of exchangeRecords) {
|
||||
@ -708,11 +702,7 @@ async function getExchangeDetailedInfo(
|
||||
): Promise<ExchangeFullDetails> {
|
||||
//TODO: should we use the forceUpdate parameter?
|
||||
const exchange = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
denominations: x.denominations,
|
||||
}))
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
|
||||
.runReadOnly(async (tx) => {
|
||||
const ex = await tx.exchanges.get(exchangeBaseurl);
|
||||
const dp = ex?.detailsPointer;
|
||||
@ -790,9 +780,7 @@ async function setCoinSuspended(
|
||||
suspended: boolean,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.coins])
|
||||
.runReadWrite(async (tx) => {
|
||||
const c = await tx.coins.get(coinPub);
|
||||
if (!c) {
|
||||
@ -811,11 +799,7 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
|
||||
const coinsJson: CoinDumpJson = { coins: [] };
|
||||
logger.info("dumping coins");
|
||||
await ws.db
|
||||
.mktx((x) => ({
|
||||
coins: x.coins,
|
||||
denominations: x.denominations,
|
||||
withdrawalGroups: x.withdrawalGroups,
|
||||
}))
|
||||
.mktx((x) => [x.coins, x.denominations, x.withdrawalGroups])
|
||||
.runReadOnly(async (tx) => {
|
||||
const coins = await tx.coins.iter().toArray();
|
||||
for (const c of coins) {
|
||||
@ -1065,11 +1049,7 @@ async function dispatchRequestInternal(
|
||||
const req = codecForForceRefreshRequest().decode(payload);
|
||||
const coinPubs = req.coinPubList.map((x) => ({ coinPub: x }));
|
||||
const refreshGroupId = await ws.db
|
||||
.mktx((x) => ({
|
||||
refreshGroups: x.refreshGroups,
|
||||
denominations: x.denominations,
|
||||
coins: x.coins,
|
||||
}))
|
||||
.mktx((x) => [x.refreshGroups, x.denominations, x.coins])
|
||||
.runReadWrite(async (tx) => {
|
||||
return await createRefreshGroup(
|
||||
ws,
|
||||
@ -1164,10 +1144,7 @@ async function dispatchRequestInternal(
|
||||
}
|
||||
case "listCurrencies": {
|
||||
return await ws.db
|
||||
.mktx((x) => ({
|
||||
auditorTrust: x.auditorTrust,
|
||||
exchangeTrust: x.exchangeTrust,
|
||||
}))
|
||||
.mktx((x) => [x.auditorTrust, x.exchangeTrust])
|
||||
.runReadOnly(async (tx) => {
|
||||
const trustedAuditors = await tx.auditorTrust.iter().toArray();
|
||||
const trustedExchanges = await tx.exchangeTrust.iter().toArray();
|
||||
|
Loading…
Reference in New Issue
Block a user