adapt to merchant API breaking changes
This commit is contained in:
parent
990b056071
commit
9a412260f3
@ -28,6 +28,7 @@ import {
|
|||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
AmountString,
|
AmountString,
|
||||||
|
codecForMerchantReserveCreateConfirmation,
|
||||||
Configuration,
|
Configuration,
|
||||||
CoreApiResponse,
|
CoreApiResponse,
|
||||||
createEddsaKeyPair,
|
createEddsaKeyPair,
|
||||||
@ -38,6 +39,7 @@ import {
|
|||||||
hash,
|
hash,
|
||||||
j2s,
|
j2s,
|
||||||
Logger,
|
Logger,
|
||||||
|
MerchantReserveCreateConfirmation,
|
||||||
MerchantTemplateAddDetails,
|
MerchantTemplateAddDetails,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
stringToBytes,
|
stringToBytes,
|
||||||
@ -81,7 +83,11 @@ import {
|
|||||||
RemoteWallet,
|
RemoteWallet,
|
||||||
WalletNotificationWaiter,
|
WalletNotificationWaiter,
|
||||||
} from "@gnu-taler/taler-wallet-core/remote";
|
} 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");
|
const logger = new Logger("harness.ts");
|
||||||
|
|
||||||
@ -1568,13 +1574,18 @@ export class MerchantApiClient {
|
|||||||
|
|
||||||
async createTippingReserve(
|
async createTippingReserve(
|
||||||
req: CreateMerchantTippingReserveRequest,
|
req: CreateMerchantTippingReserveRequest,
|
||||||
): Promise<CreateMerchantTippingReserveConfirmation> {
|
): Promise<MerchantReserveCreateConfirmation> {
|
||||||
const url = new URL("private/reserves", this.baseUrl);
|
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(),
|
headers: this.makeAuthHeader(),
|
||||||
});
|
});
|
||||||
// FIXME: validate
|
const respData = readSuccessResponseJsonOrThrow(
|
||||||
return resp.data;
|
resp,
|
||||||
|
codecForMerchantReserveCreateConfirmation(),
|
||||||
|
);
|
||||||
|
return respData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPrivateInstanceInfo(): Promise<any> {
|
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(
|
export async function queryTippingReserves(
|
||||||
merchantService: MerchantServiceInterface,
|
merchantService: MerchantServiceInterface,
|
||||||
instance: string,
|
instance: string,
|
||||||
@ -1773,14 +1769,6 @@ export interface CreateMerchantTippingReserveRequest {
|
|||||||
wire_method: string;
|
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 {
|
export class MerchantService implements MerchantServiceInterface {
|
||||||
static fromExistingConfig(gc: GlobalTestState, name: string) {
|
static fromExistingConfig(gc: GlobalTestState, name: string) {
|
||||||
const cfgFilename = gc.testDir + `/merchant-${name}.conf`;
|
const cfgFilename = gc.testDir + `/merchant-${name}.conf`;
|
||||||
|
@ -213,7 +213,7 @@ deploymentCli
|
|||||||
allowHttp: true,
|
allowHttp: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const paytoUri = addPaytoQueryParams(tipReserveResp.payto_uri, {
|
const paytoUri = addPaytoQueryParams(tipReserveResp.accounts[0].payto_uri, {
|
||||||
message: `tip-reserve ${tipReserveResp.reserve_pub}`,
|
message: `tip-reserve ${tipReserveResp.reserve_pub}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import { defaultCoinConfig } from "../harness/denomStructures.js";
|
|||||||
import {
|
import {
|
||||||
getWireMethodForTest,
|
getWireMethodForTest,
|
||||||
GlobalTestState,
|
GlobalTestState,
|
||||||
|
MerchantApiClient,
|
||||||
MerchantPrivateApi,
|
MerchantPrivateApi,
|
||||||
WalletCli,
|
WalletCli,
|
||||||
} from "../harness/harness.js";
|
} 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 walletTwo = new WalletCli(t, "walletTwo");
|
||||||
const walletThree = new WalletCli(t, "walletThree");
|
const walletThree = new WalletCli(t, "walletThree");
|
||||||
|
|
||||||
@ -147,9 +155,7 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
|
|||||||
// Pay with coin from tipping
|
// Pay with coin from tipping
|
||||||
{
|
{
|
||||||
const mbu = await BankApi.createRandomBankUser(bank);
|
const mbu = await BankApi.createRandomBankUser(bank);
|
||||||
const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
|
const tipReserveResp = await merchantClient.createTippingReserve(
|
||||||
merchant,
|
|
||||||
"default",
|
|
||||||
{
|
{
|
||||||
exchange_url: exchange.baseUrl,
|
exchange_url: exchange.baseUrl,
|
||||||
initial_balance: "TESTKUDOS:10",
|
initial_balance: "TESTKUDOS:10",
|
||||||
@ -158,7 +164,7 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
t.assertDeepEqual(
|
t.assertDeepEqual(
|
||||||
tipReserveResp.payto_uri,
|
tipReserveResp.accounts[0].payto_uri,
|
||||||
exchangeBankAccount.accountPaytoUri,
|
exchangeBankAccount.accountPaytoUri,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import {
|
|||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import {
|
import {
|
||||||
GlobalTestState,
|
GlobalTestState,
|
||||||
|
MerchantApiClient,
|
||||||
MerchantPrivateApi,
|
MerchantPrivateApi,
|
||||||
getWireMethodForTest,
|
getWireMethodForTest,
|
||||||
} from "../harness/harness.js";
|
} from "../harness/harness.js";
|
||||||
@ -40,20 +41,23 @@ export async function runTippingTest(t: GlobalTestState) {
|
|||||||
|
|
||||||
const mbu = await BankApi.createRandomBankUser(bank);
|
const mbu = await BankApi.createRandomBankUser(bank);
|
||||||
|
|
||||||
const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
|
const merchantClient = new MerchantApiClient(
|
||||||
merchant,
|
merchant.makeInstanceBaseUrl("default"),
|
||||||
"default",
|
|
||||||
{
|
{
|
||||||
exchange_url: exchange.baseUrl,
|
method: "external",
|
||||||
initial_balance: "TESTKUDOS:10",
|
|
||||||
wire_method: getWireMethodForTest(),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const tipReserveResp = await merchantClient.createTippingReserve({
|
||||||
|
exchange_url: exchange.baseUrl,
|
||||||
|
initial_balance: "TESTKUDOS:10",
|
||||||
|
wire_method: getWireMethodForTest(),
|
||||||
|
});
|
||||||
|
|
||||||
console.log("tipReserveResp:", tipReserveResp);
|
console.log("tipReserveResp:", tipReserveResp);
|
||||||
|
|
||||||
t.assertDeepEqual(
|
t.assertDeepEqual(
|
||||||
tipReserveResp.payto_uri,
|
tipReserveResp.accounts[0].payto_uri,
|
||||||
exchangeBankAccount.accountPaytoUri,
|
exchangeBankAccount.accountPaytoUri,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@ import {
|
|||||||
TalerProtocolDuration,
|
TalerProtocolDuration,
|
||||||
codecForTimestamp,
|
codecForTimestamp,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp,
|
||||||
|
WireAccount,
|
||||||
|
codecForWireAccount,
|
||||||
|
codecForList,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
export interface MerchantPostOrderRequest {
|
export interface MerchantPostOrderRequest {
|
||||||
@ -75,11 +78,12 @@ export interface MerchantPostOrderResponse {
|
|||||||
token?: ClaimToken;
|
token?: ClaimToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const codecForMerchantPostOrderResponse = (): Codec<MerchantPostOrderResponse> =>
|
export const codecForMerchantPostOrderResponse =
|
||||||
buildCodecForObject<MerchantPostOrderResponse>()
|
(): Codec<MerchantPostOrderResponse> =>
|
||||||
.property("order_id", codecForString())
|
buildCodecForObject<MerchantPostOrderResponse>()
|
||||||
.property("token", codecOptional(codecForString()))
|
.property("order_id", codecForString())
|
||||||
.build("PostOrderResponse");
|
.property("token", codecOptional(codecForString()))
|
||||||
|
.build("PostOrderResponse");
|
||||||
|
|
||||||
export const codecForMerchantRefundDetails = (): Codec<RefundDetails> =>
|
export const codecForMerchantRefundDetails = (): Codec<RefundDetails> =>
|
||||||
buildCodecForObject<RefundDetails>()
|
buildCodecForObject<RefundDetails>()
|
||||||
@ -351,7 +355,6 @@ export interface MerchantTemplateContractDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MerchantTemplateAddDetails {
|
export interface MerchantTemplateAddDetails {
|
||||||
|
|
||||||
// Template ID to use.
|
// Template ID to use.
|
||||||
template_id: string;
|
template_id: string;
|
||||||
|
|
||||||
@ -365,4 +368,19 @@ export interface MerchantTemplateAddDetails {
|
|||||||
|
|
||||||
// Additional information in a separate template.
|
// Additional information in a separate template.
|
||||||
template_contract: MerchantTemplateContractDetails;
|
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");
|
||||||
|
@ -2165,3 +2165,70 @@ export const codecForExchangeRefundSuccessResponse =
|
|||||||
.property("exchange_pub", codecForString())
|
.property("exchange_pub", codecForString())
|
||||||
.property("exchange_sig", codecForString())
|
.property("exchange_sig", codecForString())
|
||||||
.build("ExchangeRefundSuccessResponse");
|
.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");
|
||||||
|
Loading…
Reference in New Issue
Block a user