add restricted option to manual withdraw
This commit is contained in:
parent
f16d2e52d5
commit
4491118494
@ -664,7 +664,6 @@ export function hashDenomPub(pub: DenominationPubKey): Uint8Array {
|
|||||||
const hashInputBuf = new ArrayBuffer(pubBuf.length + 4 + 4);
|
const hashInputBuf = new ArrayBuffer(pubBuf.length + 4 + 4);
|
||||||
const uint8ArrayBuf = new Uint8Array(hashInputBuf);
|
const uint8ArrayBuf = new Uint8Array(hashInputBuf);
|
||||||
const dv = new DataView(hashInputBuf);
|
const dv = new DataView(hashInputBuf);
|
||||||
logger.info("age_mask", pub.age_mask);
|
|
||||||
dv.setUint32(0, pub.age_mask ?? 0);
|
dv.setUint32(0, pub.age_mask ?? 0);
|
||||||
dv.setUint32(4, DenomKeyType.toIntTag(pub.cipher));
|
dv.setUint32(4, DenomKeyType.toIntTag(pub.cipher));
|
||||||
uint8ArrayBuf.set(pubBuf, 8);
|
uint8ArrayBuf.set(pubBuf, 8);
|
||||||
@ -680,8 +679,7 @@ export function hashDenomPub(pub: DenominationPubKey): Uint8Array {
|
|||||||
return nacl.hash(uint8ArrayBuf);
|
return nacl.hash(uint8ArrayBuf);
|
||||||
} else {
|
} else {
|
||||||
throw Error(
|
throw Error(
|
||||||
`unsupported cipher (${
|
`unsupported cipher (${(pub as DenominationPubKey).cipher
|
||||||
(pub as DenominationPubKey).cipher
|
|
||||||
}), unable to hash`,
|
}), unable to hash`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ import {
|
|||||||
} from "./time.js";
|
} from "./time.js";
|
||||||
import { codecForAmountString } from "./amounts.js";
|
import { codecForAmountString } from "./amounts.js";
|
||||||
import { strcmp } from "./helpers.js";
|
import { strcmp } from "./helpers.js";
|
||||||
import { Edx25519PublicKey } from "./talerCrypto.js";
|
import { AgeCommitmentProof, Edx25519PublicKey } from "./talerCrypto.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Denomination as found in the /keys response from the exchange.
|
* Denomination as found in the /keys response from the exchange.
|
||||||
@ -954,6 +954,11 @@ export interface CoinDumpJson {
|
|||||||
* Suspended coins are not considered for payments.
|
* Suspended coins are not considered for payments.
|
||||||
*/
|
*/
|
||||||
coin_suspended: boolean;
|
coin_suspended: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the age restriction
|
||||||
|
*/
|
||||||
|
ageCommitmentProof: AgeCommitmentProof | undefined;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,6 +738,7 @@ export const codecForGetExchangeTosRequest = (): Codec<GetExchangeTosRequest> =>
|
|||||||
export interface AcceptManualWithdrawalRequest {
|
export interface AcceptManualWithdrawalRequest {
|
||||||
exchangeBaseUrl: string;
|
exchangeBaseUrl: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
|
restrictAge?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const codecForAcceptManualWithdrawalRequet =
|
export const codecForAcceptManualWithdrawalRequet =
|
||||||
@ -745,6 +746,7 @@ export const codecForAcceptManualWithdrawalRequet =
|
|||||||
buildCodecForObject<AcceptManualWithdrawalRequest>()
|
buildCodecForObject<AcceptManualWithdrawalRequest>()
|
||||||
.property("exchangeBaseUrl", codecForString())
|
.property("exchangeBaseUrl", codecForString())
|
||||||
.property("amount", codecForString())
|
.property("amount", codecForString())
|
||||||
|
.property("restrictAge", codecOptional(codecForNumber()))
|
||||||
.build("AcceptManualWithdrawalRequest");
|
.build("AcceptManualWithdrawalRequest");
|
||||||
|
|
||||||
export interface GetWithdrawalDetailsForAmountRequest {
|
export interface GetWithdrawalDetailsForAmountRequest {
|
||||||
|
@ -775,6 +775,7 @@ advancedCli
|
|||||||
.requiredOption("amount", ["--amount"], clk.STRING, {
|
.requiredOption("amount", ["--amount"], clk.STRING, {
|
||||||
help: "Amount to withdraw",
|
help: "Amount to withdraw",
|
||||||
})
|
})
|
||||||
|
.maybeOption("restrictAge", ["--restrict-age"], clk.INT)
|
||||||
.action(async (args) => {
|
.action(async (args) => {
|
||||||
await withWallet(args, async (wallet) => {
|
await withWallet(args, async (wallet) => {
|
||||||
const exchangeBaseUrl = args.withdrawManually.exchange;
|
const exchangeBaseUrl = args.withdrawManually.exchange;
|
||||||
@ -796,6 +797,7 @@ advancedCli
|
|||||||
{
|
{
|
||||||
amount,
|
amount,
|
||||||
exchangeBaseUrl,
|
exchangeBaseUrl,
|
||||||
|
restrictAge: parseInt(String(args.withdrawManually.restrictAge), 10),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const reservePub = resp.reservePub;
|
const reservePub = resp.reservePub;
|
||||||
|
@ -43,6 +43,20 @@ function fakeAci(current: string, feeDeposit: string): AvailableCoinInfo {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fakeAciWithAgeRestriction(current: string, feeDeposit: string): AvailableCoinInfo {
|
||||||
|
return {
|
||||||
|
availableAmount: a(current),
|
||||||
|
coinPub: "foobar",
|
||||||
|
denomPub: {
|
||||||
|
cipher: DenomKeyType.Rsa,
|
||||||
|
rsa_public_key: "foobar",
|
||||||
|
age_mask: 2446657,
|
||||||
|
},
|
||||||
|
feeDeposit: a(feeDeposit),
|
||||||
|
exchangeBaseUrl: "https://example.com/",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
test("it should be able to pay if merchant takes the fees", (t) => {
|
test("it should be able to pay if merchant takes the fees", (t) => {
|
||||||
const acis: AvailableCoinInfo[] = [
|
const acis: AvailableCoinInfo[] = [
|
||||||
fakeAci("EUR:1.0", "EUR:0.1"),
|
fakeAci("EUR:1.0", "EUR:0.1"),
|
||||||
@ -267,3 +281,31 @@ test("coin selection 9", (t) => {
|
|||||||
);
|
);
|
||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("it should be able to use unrestricted coins for age restricted contract", (t) => {
|
||||||
|
const acis: AvailableCoinInfo[] = [
|
||||||
|
fakeAciWithAgeRestriction("EUR:1.0", "EUR:0.2"),
|
||||||
|
fakeAciWithAgeRestriction("EUR:0.2", "EUR:0.2"),
|
||||||
|
];
|
||||||
|
const res = selectPayCoins({
|
||||||
|
candidates: {
|
||||||
|
candidateCoins: acis,
|
||||||
|
wireFeesPerExchange: {},
|
||||||
|
},
|
||||||
|
contractTermsAmount: a("EUR:1.2"),
|
||||||
|
depositFeeLimit: a("EUR:0.4"),
|
||||||
|
wireFeeLimit: a("EUR:0"),
|
||||||
|
wireFeeAmortization: 1,
|
||||||
|
requiredMinimumAge: 13
|
||||||
|
});
|
||||||
|
if (!res) {
|
||||||
|
t.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t.true(res.coinContributions.length === 2);
|
||||||
|
t.true(
|
||||||
|
Amounts.cmp(Amounts.sum(res.coinContributions).amount, "EUR:1.2") === 0,
|
||||||
|
);
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
@ -454,11 +454,14 @@ async function acceptManualWithdrawal(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
amount: AmountJson,
|
amount: AmountJson,
|
||||||
|
restrictAge?: number,
|
||||||
|
|
||||||
): Promise<AcceptManualWithdrawalResult> {
|
): Promise<AcceptManualWithdrawalResult> {
|
||||||
try {
|
try {
|
||||||
const resp = await createReserve(ws, {
|
const resp = await createReserve(ws, {
|
||||||
amount,
|
amount,
|
||||||
exchange: exchangeBaseUrl,
|
exchange: exchangeBaseUrl,
|
||||||
|
restrictAge
|
||||||
});
|
});
|
||||||
const exchangePaytoUris = await ws.db
|
const exchangePaytoUris = await ws.db
|
||||||
.mktx((x) => ({
|
.mktx((x) => ({
|
||||||
@ -690,6 +693,7 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
|
|||||||
remaining_value: Amounts.stringify(c.currentAmount),
|
remaining_value: Amounts.stringify(c.currentAmount),
|
||||||
withdrawal_reserve_pub: withdrawalReservePub,
|
withdrawal_reserve_pub: withdrawalReservePub,
|
||||||
coin_suspended: c.suspended,
|
coin_suspended: c.suspended,
|
||||||
|
ageCommitmentProof: c.ageCommitmentProof,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -801,6 +805,7 @@ async function dispatchRequestInternal(
|
|||||||
ws,
|
ws,
|
||||||
req.exchangeBaseUrl,
|
req.exchangeBaseUrl,
|
||||||
Amounts.parseOrThrow(req.amount),
|
Amounts.parseOrThrow(req.amount),
|
||||||
|
req.restrictAge
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user