wallet-core: pull out ToS into separate object store
This commit is contained in:
parent
f1cba79c65
commit
a57fcb144d
@ -1165,8 +1165,6 @@ export interface BackupExchange {
|
||||
|
||||
currency: string;
|
||||
|
||||
protocol_version_range: string;
|
||||
|
||||
/**
|
||||
* Time when the pointer to the exchange details
|
||||
* was last updated.
|
||||
|
@ -620,7 +620,7 @@ export interface KnownBankAccounts {
|
||||
accounts: KnownBankAccountsInfo[];
|
||||
}
|
||||
|
||||
export interface ExchangeTos {
|
||||
export interface ExchangeTosStatusDetails {
|
||||
acceptedVersion?: string;
|
||||
currentVersion?: string;
|
||||
contentType?: string;
|
||||
@ -805,7 +805,7 @@ export interface ExchangeFullDetails {
|
||||
exchangeBaseUrl: string;
|
||||
currency: string;
|
||||
paytoUris: string[];
|
||||
tos: ExchangeTos;
|
||||
tos: ExchangeTosStatusDetails;
|
||||
auditors: ExchangeAuditor[];
|
||||
wireInfo: WireInfo;
|
||||
denomFees: DenomOperationMap<FeeDescription[]>;
|
||||
@ -817,7 +817,7 @@ export interface ExchangeListItem {
|
||||
exchangeBaseUrl: string;
|
||||
currency: string;
|
||||
paytoUris: string[];
|
||||
tos: ExchangeTos;
|
||||
tos: ExchangeTosStatusDetails;
|
||||
}
|
||||
|
||||
const codecForAuditorDenomSig = (): Codec<AuditorDenomSig> =>
|
||||
@ -833,8 +833,8 @@ const codecForExchangeAuditor = (): Codec<ExchangeAuditor> =>
|
||||
.property("denomination_keys", codecForList(codecForAuditorDenomSig()))
|
||||
.build("codecForExchangeAuditor");
|
||||
|
||||
const codecForExchangeTos = (): Codec<ExchangeTos> =>
|
||||
buildCodecForObject<ExchangeTos>()
|
||||
const codecForExchangeTos = (): Codec<ExchangeTosStatusDetails> =>
|
||||
buildCodecForObject<ExchangeTosStatusDetails>()
|
||||
.property("acceptedVersion", codecOptional(codecForString()))
|
||||
.property("currentVersion", codecOptional(codecForString()))
|
||||
.property("contentType", codecOptional(codecForString()))
|
||||
|
@ -80,7 +80,7 @@ import { Event, IDBDatabase } from "@gnu-taler/idb-bridge";
|
||||
* for all previous versions must be written, which should be
|
||||
* avoided.
|
||||
*/
|
||||
export const TALER_DB_NAME = "taler-wallet-main-v6";
|
||||
export const TALER_DB_NAME = "taler-wallet-main-v7";
|
||||
|
||||
/**
|
||||
* Name of the metadata database. This database is used
|
||||
@ -99,7 +99,7 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
|
||||
* backwards-compatible way or object stores and indices
|
||||
* are added.
|
||||
*/
|
||||
export const WALLET_DB_MINOR_VERSION = 2;
|
||||
export const WALLET_DB_MINOR_VERSION = 1;
|
||||
|
||||
/**
|
||||
* Ranges for operation status fields.
|
||||
@ -450,40 +450,41 @@ export interface ExchangeDetailsRecord {
|
||||
*/
|
||||
signingKeys: ExchangeSignKeyJson[];
|
||||
|
||||
/**
|
||||
* Etag of the current ToS of the exchange.
|
||||
*/
|
||||
tosCurrentEtag: string;
|
||||
|
||||
/**
|
||||
* Information about ToS acceptance from the user.
|
||||
*/
|
||||
tosAccepted:
|
||||
| {
|
||||
etag: string;
|
||||
timestamp: TalerProtocolTimestamp;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
wireInfo: WireInfo;
|
||||
}
|
||||
|
||||
export interface ExchangeTosRecord {
|
||||
exchangeBaseUrl: string;
|
||||
|
||||
etag: string;
|
||||
|
||||
/**
|
||||
* Terms of service text or undefined if not downloaded yet.
|
||||
*
|
||||
* This is just used as a cache of the last downloaded ToS.
|
||||
*
|
||||
* FIXME: Put in separate object store!
|
||||
*/
|
||||
termsOfServiceText: string | undefined;
|
||||
|
||||
/**
|
||||
* content-type of the last downloaded termsOfServiceText.
|
||||
*
|
||||
* * FIXME: Put in separate object store!
|
||||
* Content-type of the last downloaded termsOfServiceText.
|
||||
*/
|
||||
termsOfServiceContentType: string | undefined;
|
||||
|
||||
/**
|
||||
* ETag for last terms of service download.
|
||||
*/
|
||||
termsOfServiceLastEtag: string | undefined;
|
||||
|
||||
/**
|
||||
* ETag for last terms of service accepted.
|
||||
*/
|
||||
termsOfServiceAcceptedEtag: string | undefined;
|
||||
|
||||
/**
|
||||
* Timestamp when the ToS was accepted.
|
||||
*
|
||||
* Used during backup merging.
|
||||
*/
|
||||
termsOfServiceAcceptedTimestamp: TalerProtocolTimestamp | undefined;
|
||||
|
||||
wireInfo: WireInfo;
|
||||
}
|
||||
|
||||
export interface ExchangeDetailsPointer {
|
||||
@ -491,11 +492,6 @@ export interface ExchangeDetailsPointer {
|
||||
|
||||
currency: string;
|
||||
|
||||
/**
|
||||
* Last observed protocol version range offered by the exchange.
|
||||
*/
|
||||
protocolVersionRange: string;
|
||||
|
||||
/**
|
||||
* Timestamp when the (masterPublicKey, currency) pointer
|
||||
* has been updated.
|
||||
@ -1899,6 +1895,14 @@ export const WalletStoresV1 = {
|
||||
byReservePub: describeIndex("byReservePub", "reservePub", {}),
|
||||
},
|
||||
),
|
||||
exchangeTos: describeStore(
|
||||
"exchangeTos",
|
||||
describeContents<ExchangeTosRecord>({
|
||||
keyPath: ["exchangeBaseUrl", "etag"],
|
||||
autoIncrement: true,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
config: describeStore(
|
||||
"config",
|
||||
describeContents<ConfigRecord>({ keyPath: "key" }),
|
||||
@ -2116,7 +2120,6 @@ export const WalletStoresV1 = {
|
||||
"bankAccounts",
|
||||
describeContents<BankAccountsRecord>({
|
||||
keyPath: "uri",
|
||||
versionAdded: 2,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
|
@ -298,7 +298,6 @@ export async function exportBackup(
|
||||
currency: dp.currency,
|
||||
master_public_key: dp.masterPublicKey,
|
||||
update_clock: dp.updateClock,
|
||||
protocol_version_range: dp.protocolVersionRange,
|
||||
});
|
||||
});
|
||||
|
||||
@ -358,8 +357,8 @@ export async function exportBackup(
|
||||
purseTimeout: x.purseTimeout,
|
||||
startDate: x.startDate,
|
||||
})),
|
||||
tos_accepted_etag: ex.termsOfServiceAcceptedEtag,
|
||||
tos_accepted_timestamp: ex.termsOfServiceAcceptedTimestamp,
|
||||
tos_accepted_etag: ex.tosAccepted?.etag,
|
||||
tos_accepted_timestamp: ex.tosAccepted?.timestamp,
|
||||
denominations:
|
||||
backupDenominationsByExchange[ex.exchangeBaseUrl] ?? [],
|
||||
});
|
||||
|
@ -351,7 +351,6 @@ export async function importBackup(
|
||||
currency: backupExchange.currency,
|
||||
masterPublicKey: backupExchange.master_public_key,
|
||||
updateClock: backupExchange.update_clock,
|
||||
protocolVersionRange: backupExchange.protocol_version_range,
|
||||
},
|
||||
permanent: true,
|
||||
lastUpdate: undefined,
|
||||
@ -388,14 +387,18 @@ export async function importBackup(
|
||||
wadFee: Amounts.parseOrThrow(fee.wad_fee),
|
||||
});
|
||||
}
|
||||
let tosAccepted = undefined;
|
||||
if (
|
||||
backupExchangeDetails.tos_accepted_etag &&
|
||||
backupExchangeDetails.tos_accepted_timestamp
|
||||
) {
|
||||
tosAccepted = {
|
||||
etag: backupExchangeDetails.tos_accepted_etag,
|
||||
timestamp: backupExchangeDetails.tos_accepted_timestamp,
|
||||
};
|
||||
}
|
||||
await tx.exchangeDetails.put({
|
||||
exchangeBaseUrl: backupExchangeDetails.base_url,
|
||||
termsOfServiceAcceptedEtag: backupExchangeDetails.tos_accepted_etag,
|
||||
termsOfServiceText: undefined,
|
||||
termsOfServiceLastEtag: undefined,
|
||||
termsOfServiceContentType: undefined,
|
||||
termsOfServiceAcceptedTimestamp:
|
||||
backupExchangeDetails.tos_accepted_timestamp,
|
||||
wireInfo,
|
||||
currency: backupExchangeDetails.currency,
|
||||
auditors: backupExchangeDetails.auditors.map((x) => ({
|
||||
@ -406,6 +409,8 @@ export async function importBackup(
|
||||
masterPublicKey: backupExchangeDetails.master_public_key,
|
||||
protocolVersionRange: backupExchangeDetails.protocol_version,
|
||||
reserveClosingDelay: backupExchangeDetails.reserve_closing_delay,
|
||||
tosCurrentEtag: backupExchangeDetails.tos_accepted_etag || "",
|
||||
tosAccepted,
|
||||
globalFees: backupExchangeDetails.global_fees.map((x) => ({
|
||||
accountFee: Amounts.parseOrThrow(x.accountFee),
|
||||
historyFee: Amounts.parseOrThrow(x.historyFee),
|
||||
@ -419,7 +424,6 @@ export async function importBackup(
|
||||
purseTimeout: x.purseTimeout,
|
||||
startDate: x.startDate,
|
||||
})),
|
||||
|
||||
signingKeys: backupExchangeDetails.signing_keys.map((x) => ({
|
||||
key: x.key,
|
||||
master_sig: x.master_sig,
|
||||
|
@ -174,24 +174,40 @@ export async function getExchangeDetails(
|
||||
getExchangeDetails.makeContext = (db: DbAccess<typeof WalletStoresV1>) =>
|
||||
db.mktx((x) => [x.exchanges, x.exchangeDetails]);
|
||||
|
||||
/**
|
||||
* Update the database based on the download of the terms of service.
|
||||
*/
|
||||
export async function updateExchangeTermsOfService(
|
||||
ws: InternalWalletState,
|
||||
exchangeBaseUrl: string,
|
||||
tos: ExchangeTosDownloadResult,
|
||||
): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.mktx((x) => [x.exchanges, x.exchangeTos, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
const d = await getExchangeDetails(tx, exchangeBaseUrl);
|
||||
let tosRecord = await tx.exchangeTos.get([exchangeBaseUrl, tos.tosEtag]);
|
||||
if (!tosRecord) {
|
||||
tosRecord = {
|
||||
etag: tos.tosEtag,
|
||||
exchangeBaseUrl,
|
||||
termsOfServiceContentType: tos.tosContentType,
|
||||
termsOfServiceText: tos.tosText,
|
||||
};
|
||||
await tx.exchangeTos.put(tosRecord);
|
||||
}
|
||||
if (d) {
|
||||
d.termsOfServiceText = tos.tosText;
|
||||
d.termsOfServiceContentType = tos.tosContentType;
|
||||
d.termsOfServiceLastEtag = tos.tosEtag;
|
||||
d.tosCurrentEtag = tos.tosEtag;
|
||||
await tx.exchangeDetails.put(d);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a ToS version as accepted by the user.
|
||||
*
|
||||
* @param etag version of the ToS to accept, or current ToS version of not given
|
||||
*/
|
||||
export async function acceptExchangeTermsOfService(
|
||||
ws: InternalWalletState,
|
||||
exchangeBaseUrl: string,
|
||||
@ -202,7 +218,10 @@ export async function acceptExchangeTermsOfService(
|
||||
.runReadWrite(async (tx) => {
|
||||
const d = await getExchangeDetails(tx, exchangeBaseUrl);
|
||||
if (d) {
|
||||
d.termsOfServiceAcceptedEtag = etag;
|
||||
d.tosAccepted = {
|
||||
etag: etag || d.tosCurrentEtag,
|
||||
timestamp: TalerProtocolTimestamp.now(),
|
||||
};
|
||||
await tx.exchangeDetails.put(d);
|
||||
}
|
||||
});
|
||||
@ -611,7 +630,8 @@ export async function updateExchangeFromUrlHandler(
|
||||
["text/plain"],
|
||||
);
|
||||
const tosHasBeenAccepted =
|
||||
exchangeDetails?.termsOfServiceAcceptedEtag === tosDownload.tosEtag;
|
||||
exchangeDetails?.tosAccepted &&
|
||||
exchangeDetails.tosAccepted.etag === tosDownload.tosEtag;
|
||||
|
||||
let recoupGroupId: string | undefined;
|
||||
|
||||
@ -647,13 +667,13 @@ export async function updateExchangeFromUrlHandler(
|
||||
globalFees,
|
||||
exchangeBaseUrl: r.baseUrl,
|
||||
wireInfo,
|
||||
termsOfServiceText: tosDownload.tosText,
|
||||
termsOfServiceAcceptedEtag: tosHasBeenAccepted
|
||||
? tosDownload.tosEtag
|
||||
tosCurrentEtag: tosDownload.tosContentType,
|
||||
tosAccepted: tosHasBeenAccepted
|
||||
? {
|
||||
etag: tosDownload.tosEtag,
|
||||
timestamp: TalerProtocolTimestamp.now(),
|
||||
}
|
||||
: undefined,
|
||||
termsOfServiceContentType: tosDownload.tosContentType,
|
||||
termsOfServiceLastEtag: tosDownload.tosEtag,
|
||||
termsOfServiceAcceptedTimestamp: TalerProtocolTimestamp.now(),
|
||||
};
|
||||
// FIXME: only update if pointer got updated
|
||||
r.lastUpdate = TalerProtocolTimestamp.now();
|
||||
@ -665,7 +685,6 @@ export async function updateExchangeFromUrlHandler(
|
||||
masterPublicKey: details.masterPublicKey,
|
||||
// FIXME: only change if pointer really changed
|
||||
updateClock: TalerProtocolTimestamp.now(),
|
||||
protocolVersionRange: keysInfo.protocolVersion,
|
||||
};
|
||||
await tx.exchanges.put(r);
|
||||
await tx.exchangeDetails.put(details);
|
||||
|
@ -69,6 +69,7 @@ import {
|
||||
CoinStatus,
|
||||
DenominationRecord,
|
||||
DenominationVerificationStatus,
|
||||
ExchangeTosRecord,
|
||||
PlanchetRecord,
|
||||
PlanchetStatus,
|
||||
WalletStoresV1,
|
||||
@ -1278,12 +1279,8 @@ export async function getExchangeWithdrawalInfo(
|
||||
}
|
||||
|
||||
let tosAccepted = false;
|
||||
|
||||
if (exchangeDetails.termsOfServiceLastEtag) {
|
||||
if (
|
||||
exchangeDetails.termsOfServiceAcceptedEtag ===
|
||||
exchangeDetails.termsOfServiceLastEtag
|
||||
) {
|
||||
if (exchangeDetails.tosAccepted?.timestamp) {
|
||||
if (exchangeDetails.tosAccepted.etag === exchangeDetails.tosCurrentEtag) {
|
||||
tosAccepted = true;
|
||||
}
|
||||
}
|
||||
@ -1357,7 +1354,12 @@ export async function getWithdrawalDetailsForUri(
|
||||
const exchanges: ExchangeListItem[] = [];
|
||||
|
||||
await ws.db
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.exchangeTos,
|
||||
x.denominations,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchangeRecords = await tx.exchanges.iter().toArray();
|
||||
for (const r of exchangeRecords) {
|
||||
@ -1366,14 +1368,19 @@ export async function getWithdrawalDetailsForUri(
|
||||
.iter(r.baseUrl)
|
||||
.toArray();
|
||||
if (details && denominations) {
|
||||
const tosRecord = await tx.exchangeTos.get([
|
||||
details.exchangeBaseUrl,
|
||||
details.tosCurrentEtag,
|
||||
]);
|
||||
exchanges.push({
|
||||
exchangeBaseUrl: details.exchangeBaseUrl,
|
||||
currency: details.currency,
|
||||
// FIXME: We probably don't want to include the full ToS here!
|
||||
tos: {
|
||||
acceptedVersion: details.termsOfServiceAcceptedEtag,
|
||||
currentVersion: details.termsOfServiceLastEtag,
|
||||
contentType: details.termsOfServiceContentType,
|
||||
content: details.termsOfServiceText,
|
||||
acceptedVersion: details.tosAccepted?.etag,
|
||||
currentVersion: details.tosCurrentEtag,
|
||||
contentType: tosRecord?.termsOfServiceContentType ?? "",
|
||||
content: tosRecord?.termsOfServiceText ?? "",
|
||||
},
|
||||
paytoUris: details.wireInfo.accounts.map((x) => x.payto_uri),
|
||||
});
|
||||
|
@ -94,6 +94,7 @@ import {
|
||||
WalletCoreVersion,
|
||||
WalletNotification,
|
||||
codecForSetDevModeRequest,
|
||||
ExchangeTosStatusDetails,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
|
||||
import {
|
||||
@ -107,6 +108,8 @@ import {
|
||||
CoinStatus,
|
||||
ConfigRecordKey,
|
||||
DenominationRecord,
|
||||
ExchangeDetailsRecord,
|
||||
ExchangeTosRecord,
|
||||
exportDb,
|
||||
importDb,
|
||||
WalletStoresV1,
|
||||
@ -228,7 +231,11 @@ import {
|
||||
OpenedPromise,
|
||||
openPromise,
|
||||
} from "./util/promiseUtils.js";
|
||||
import { DbAccess, GetReadWriteAccess } from "./util/query.js";
|
||||
import {
|
||||
DbAccess,
|
||||
GetReadOnlyAccess,
|
||||
GetReadWriteAccess,
|
||||
} from "./util/query.js";
|
||||
import { OperationAttemptResult } from "./util/retries.js";
|
||||
import { TimerAPI, TimerGroup } from "./util/timer.js";
|
||||
import {
|
||||
@ -461,6 +468,10 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exchange ToS in the requested format.
|
||||
* Try to download in the accepted format not cached.
|
||||
*/
|
||||
async function getExchangeTos(
|
||||
ws: InternalWalletState,
|
||||
exchangeBaseUrl: string,
|
||||
@ -468,9 +479,14 @@ async function getExchangeTos(
|
||||
): Promise<GetExchangeTosResult> {
|
||||
// FIXME: download ToS in acceptable format if passed!
|
||||
const { exchangeDetails } = await updateExchangeFromUrl(ws, exchangeBaseUrl);
|
||||
const content = exchangeDetails.termsOfServiceText;
|
||||
const currentEtag = exchangeDetails.termsOfServiceLastEtag;
|
||||
const contentType = exchangeDetails.termsOfServiceContentType;
|
||||
const tosDetails = await ws.db
|
||||
.mktx((x) => [x.exchangeTos])
|
||||
.runReadOnly(async (tx) => {
|
||||
return await getExchangeTosStatusDetails(tx, exchangeDetails);
|
||||
});
|
||||
const content = tosDetails.content;
|
||||
const currentEtag = tosDetails.currentVersion;
|
||||
const contentType = tosDetails.contentType;
|
||||
if (
|
||||
content === undefined ||
|
||||
currentEtag === undefined ||
|
||||
@ -483,7 +499,7 @@ async function getExchangeTos(
|
||||
acceptedFormat.findIndex((f) => f === contentType) !== -1
|
||||
) {
|
||||
return {
|
||||
acceptedEtag: exchangeDetails.termsOfServiceAcceptedEtag,
|
||||
acceptedEtag: exchangeDetails.tosAccepted?.etag,
|
||||
currentEtag,
|
||||
content,
|
||||
contentType,
|
||||
@ -499,16 +515,17 @@ async function getExchangeTos(
|
||||
|
||||
if (tosDownload.tosContentType === contentType) {
|
||||
return {
|
||||
acceptedEtag: exchangeDetails.termsOfServiceAcceptedEtag,
|
||||
acceptedEtag: exchangeDetails.tosAccepted?.etag,
|
||||
currentEtag,
|
||||
content,
|
||||
contentType,
|
||||
};
|
||||
}
|
||||
|
||||
await updateExchangeTermsOfService(ws, exchangeBaseUrl, tosDownload);
|
||||
|
||||
return {
|
||||
acceptedEtag: exchangeDetails.termsOfServiceAcceptedEtag,
|
||||
acceptedEtag: exchangeDetails.tosAccepted?.etag,
|
||||
currentEtag: tosDownload.tosEtag,
|
||||
content: tosDownload.tosText,
|
||||
contentType: tosDownload.tosContentType,
|
||||
@ -585,12 +602,43 @@ async function forgetKnownBankAccounts(
|
||||
return;
|
||||
}
|
||||
|
||||
async function getExchangeTosStatusDetails(
|
||||
tx: GetReadOnlyAccess<{ exchangeTos: typeof WalletStoresV1.exchangeTos }>,
|
||||
exchangeDetails: ExchangeDetailsRecord,
|
||||
): Promise<ExchangeTosStatusDetails> {
|
||||
let exchangeTos = await tx.exchangeTos.get([
|
||||
exchangeDetails.exchangeBaseUrl,
|
||||
exchangeDetails.tosCurrentEtag,
|
||||
]);
|
||||
|
||||
if (!exchangeTos) {
|
||||
exchangeTos = {
|
||||
etag: "not-available",
|
||||
termsOfServiceContentType: "text/plain",
|
||||
termsOfServiceText: "terms of service unavailable",
|
||||
exchangeBaseUrl: exchangeDetails.exchangeBaseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
acceptedVersion: exchangeDetails.tosAccepted?.etag,
|
||||
content: exchangeTos.termsOfServiceContentType,
|
||||
contentType: exchangeTos.termsOfServiceContentType,
|
||||
currentVersion: exchangeTos.etag,
|
||||
};
|
||||
}
|
||||
|
||||
async function getExchanges(
|
||||
ws: InternalWalletState,
|
||||
): Promise<ExchangesListResponse> {
|
||||
const exchanges: ExchangeListItem[] = [];
|
||||
await ws.db
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.exchangeDetails,
|
||||
x.exchangeTos,
|
||||
x.denominations,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchangeRecords = await tx.exchanges.iter().toArray();
|
||||
for (const r of exchangeRecords) {
|
||||
@ -612,15 +660,12 @@ async function getExchanges(
|
||||
continue;
|
||||
}
|
||||
|
||||
const tos = await getExchangeTosStatusDetails(tx, exchangeDetails);
|
||||
|
||||
exchanges.push({
|
||||
exchangeBaseUrl: r.baseUrl,
|
||||
currency,
|
||||
tos: {
|
||||
acceptedVersion: exchangeDetails.termsOfServiceAcceptedEtag,
|
||||
currentVersion: exchangeDetails.termsOfServiceLastEtag,
|
||||
contentType: exchangeDetails.termsOfServiceContentType,
|
||||
content: exchangeDetails.termsOfServiceText,
|
||||
},
|
||||
tos,
|
||||
paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri),
|
||||
});
|
||||
}
|
||||
@ -634,7 +679,12 @@ async function getExchangeDetailedInfo(
|
||||
): Promise<ExchangeFullDetails> {
|
||||
//TODO: should we use the forceUpdate parameter?
|
||||
const exchange = await ws.db
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
|
||||
.mktx((x) => [
|
||||
x.exchanges,
|
||||
x.exchangeTos,
|
||||
x.exchangeDetails,
|
||||
x.denominations,
|
||||
])
|
||||
.runReadOnly(async (tx) => {
|
||||
const ex = await tx.exchanges.get(exchangeBaseurl);
|
||||
const dp = ex?.detailsPointer;
|
||||
@ -656,6 +706,8 @@ async function getExchangeDetailedInfo(
|
||||
return;
|
||||
}
|
||||
|
||||
const tos = await getExchangeTosStatusDetails(tx, exchangeDetails);
|
||||
|
||||
const denominations: DenominationInfo[] = denominationRecords.map((x) =>
|
||||
DenominationRecord.toDenomInfo(x),
|
||||
);
|
||||
@ -664,12 +716,7 @@ async function getExchangeDetailedInfo(
|
||||
info: {
|
||||
exchangeBaseUrl: ex.baseUrl,
|
||||
currency,
|
||||
tos: {
|
||||
acceptedVersion: exchangeDetails.termsOfServiceAcceptedEtag,
|
||||
currentVersion: exchangeDetails.termsOfServiceLastEtag,
|
||||
contentType: exchangeDetails.termsOfServiceContentType,
|
||||
content: exchangeDetails.termsOfServiceText,
|
||||
},
|
||||
tos,
|
||||
paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri),
|
||||
auditors: exchangeDetails.auditors,
|
||||
wireInfo: exchangeDetails.wireInfo,
|
||||
|
Loading…
Reference in New Issue
Block a user