adapt to merchant API breaking changes

This commit is contained in:
Florian Dold 2023-05-05 14:56:28 +02:00
parent 990b056071
commit 9a412260f3
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
6 changed files with 130 additions and 47 deletions

View File

@ -28,6 +28,7 @@ import {
AmountJson,
Amounts,
AmountString,
codecForMerchantReserveCreateConfirmation,
Configuration,
CoreApiResponse,
createEddsaKeyPair,
@ -38,6 +39,7 @@ import {
hash,
j2s,
Logger,
MerchantReserveCreateConfirmation,
MerchantTemplateAddDetails,
parsePaytoUri,
stringToBytes,
@ -81,7 +83,11 @@ import {
RemoteWallet,
WalletNotificationWaiter,
} from "@gnu-taler/taler-wallet-core/remote";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
createPlatformHttpLib,
readSuccessResponseJsonOrErrorCode,
readSuccessResponseJsonOrThrow,
} from "@gnu-taler/taler-util/http";
const logger = new Logger("harness.ts");
@ -1568,13 +1574,18 @@ export class MerchantApiClient {
async createTippingReserve(
req: CreateMerchantTippingReserveRequest,
): Promise<CreateMerchantTippingReserveConfirmation> {
): Promise<MerchantReserveCreateConfirmation> {
const url = new URL("private/reserves", this.baseUrl);
const resp = await axios.post(url.href, req, {
const resp = await this.http.fetch(url.href, {
method: "POST",
body: req,
headers: this.makeAuthHeader(),
});
// FIXME: validate
return resp.data;
const respData = readSuccessResponseJsonOrThrow(
resp,
codecForMerchantReserveCreateConfirmation(),
);
return respData;
}
async getPrivateInstanceInfo(): Promise<any> {
@ -1719,21 +1730,6 @@ export namespace MerchantPrivateApi {
};
}
export async function createTippingReserve(
merchantService: MerchantServiceInterface,
instance: string,
req: CreateMerchantTippingReserveRequest,
): Promise<CreateMerchantTippingReserveConfirmation> {
const reqUrl = new URL(
`private/reserves`,
merchantService.makeInstanceBaseUrl(instance),
);
// FIXME: Don't use axios!
const resp = await axios.post(reqUrl.href, req);
// FIXME: validate
return resp.data;
}
export async function queryTippingReserves(
merchantService: MerchantServiceInterface,
instance: string,
@ -1773,14 +1769,6 @@ export interface CreateMerchantTippingReserveRequest {
wire_method: string;
}
export interface CreateMerchantTippingReserveConfirmation {
// Public key identifying the reserve
reserve_pub: string;
// Wire account of the exchange where to transfer the funds
payto_uri: string;
}
export class MerchantService implements MerchantServiceInterface {
static fromExistingConfig(gc: GlobalTestState, name: string) {
const cfgFilename = gc.testDir + `/merchant-${name}.conf`;

View File

@ -213,7 +213,7 @@ deploymentCli
allowHttp: true,
});
const paytoUri = addPaytoQueryParams(tipReserveResp.payto_uri, {
const paytoUri = addPaytoQueryParams(tipReserveResp.accounts[0].payto_uri, {
message: `tip-reserve ${tipReserveResp.reserve_pub}`,
});

View File

@ -26,6 +26,7 @@ import { defaultCoinConfig } from "../harness/denomStructures.js";
import {
getWireMethodForTest,
GlobalTestState,
MerchantApiClient,
MerchantPrivateApi,
WalletCli,
} from "../harness/harness.js";
@ -55,6 +56,13 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
},
);
const merchantClient = new MerchantApiClient(
merchant.makeInstanceBaseUrl("default"),
{
method: "external",
},
);
const walletTwo = new WalletCli(t, "walletTwo");
const walletThree = new WalletCli(t, "walletThree");
@ -147,9 +155,7 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
// Pay with coin from tipping
{
const mbu = await BankApi.createRandomBankUser(bank);
const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
merchant,
"default",
const tipReserveResp = await merchantClient.createTippingReserve(
{
exchange_url: exchange.baseUrl,
initial_balance: "TESTKUDOS:10",
@ -158,7 +164,7 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
);
t.assertDeepEqual(
tipReserveResp.payto_uri,
tipReserveResp.accounts[0].payto_uri,
exchangeBankAccount.accountPaytoUri,
);

View File

@ -24,6 +24,7 @@ import {
} from "@gnu-taler/taler-wallet-core";
import {
GlobalTestState,
MerchantApiClient,
MerchantPrivateApi,
getWireMethodForTest,
} from "../harness/harness.js";
@ -40,20 +41,23 @@ export async function runTippingTest(t: GlobalTestState) {
const mbu = await BankApi.createRandomBankUser(bank);
const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
merchant,
"default",
const merchantClient = new MerchantApiClient(
merchant.makeInstanceBaseUrl("default"),
{
method: "external",
},
);
const tipReserveResp = await merchantClient.createTippingReserve({
exchange_url: exchange.baseUrl,
initial_balance: "TESTKUDOS:10",
wire_method: getWireMethodForTest(),
},
);
});
console.log("tipReserveResp:", tipReserveResp);
t.assertDeepEqual(
tipReserveResp.payto_uri,
tipReserveResp.accounts[0].payto_uri,
exchangeBankAccount.accountPaytoUri,
);

View File

@ -44,6 +44,9 @@ import {
TalerProtocolDuration,
codecForTimestamp,
TalerProtocolTimestamp,
WireAccount,
codecForWireAccount,
codecForList,
} from "@gnu-taler/taler-util";
export interface MerchantPostOrderRequest {
@ -75,7 +78,8 @@ export interface MerchantPostOrderResponse {
token?: ClaimToken;
}
export const codecForMerchantPostOrderResponse = (): Codec<MerchantPostOrderResponse> =>
export const codecForMerchantPostOrderResponse =
(): Codec<MerchantPostOrderResponse> =>
buildCodecForObject<MerchantPostOrderResponse>()
.property("order_id", codecForString())
.property("token", codecOptional(codecForString()))
@ -351,7 +355,6 @@ export interface MerchantTemplateContractDetails {
}
export interface MerchantTemplateAddDetails {
// Template ID to use.
template_id: string;
@ -366,3 +369,18 @@ export interface MerchantTemplateAddDetails {
// Additional information in a separate template.
template_contract: MerchantTemplateContractDetails;
}
export interface MerchantReserveCreateConfirmation {
// Public key identifying the reserve.
reserve_pub: EddsaPublicKeyString;
// Wire accounts of the exchange where to transfer the funds.
accounts: WireAccount[];
}
export const codecForMerchantReserveCreateConfirmation =
(): Codec<MerchantReserveCreateConfirmation> =>
buildCodecForObject<MerchantReserveCreateConfirmation>()
.property("accounts", codecForList(codecForWireAccount()))
.property("reserve_pub", codecForString())
.build("MerchantReserveCreateConfirmation");

View File

@ -2165,3 +2165,70 @@ export const codecForExchangeRefundSuccessResponse =
.property("exchange_pub", codecForString())
.property("exchange_sig", codecForString())
.build("ExchangeRefundSuccessResponse");
export type AccountRestriction =
| RegexAccountRestriction
| DenyAllAccountRestriction;
export interface DenyAllAccountRestriction {
type: "deny";
}
// Accounts interacting with this type of account
// restriction must have a payto://-URI matching
// the given regex.
export interface RegexAccountRestriction {
type: "regex";
// Regular expression that the payto://-URI of the
// partner account must follow. The regular expression
// should follow posix-egrep, but without support for character
// classes, GNU extensions, back-references or intervals. See
// https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html
// for a description of the posix-egrep syntax. Applications
// may support regexes with additional features, but exchanges
// must not use such regexes.
payto_regex: string;
// Hint for a human to understand the restriction
// (that is hopefully easier to comprehend than the regex itself).
human_hint: string;
// Map from IETF BCP 47 language tags to localized
// human hints.
human_hint_i18n?: InternationalizedString;
}
export interface WireAccount {
// payto:// URI identifying the account and wire method
payto_uri: string;
// URI to convert amounts from or to the currency used by
// this wire account of the exchange. Missing if no
// conversion is applicable.
conversion_url?: string;
// Restrictions that apply to bank accounts that would send
// funds to the exchange (crediting this exchange bank account).
// Optional, empty array for unrestricted.
credit_restrictions: AccountRestriction[];
// Restrictions that apply to bank accounts that would receive
// funds from the exchange (debiting this exchange bank account).
// Optional, empty array for unrestricted.
debit_restrictions: AccountRestriction[];
// Signature using the exchange's offline key over
// a TALER_MasterWireDetailsPS
// with purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS.
master_sig: EddsaSignatureString;
}
export const codecForWireAccount = (): Codec<WireAccount> =>
buildCodecForObject<WireAccount>()
.property("conversion_url", codecOptional(codecForString()))
.property("credit_restrictions", codecForList(codecForAny()))
.property("debit_restrictions", codecForList(codecForAny()))
.property("master_sig", codecForString())
.property("payto_uri", codecForString())
.build("WireAccount");