handle multi-coin payments correctly
This commit is contained in:
parent
c51f635673
commit
e5cb59e24d
@ -242,6 +242,12 @@ class PackedArenaObject extends ArenaObject {
|
|||||||
emsc.free(d);
|
emsc.free(d);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
toJson() {
|
||||||
|
// Per default, the json encoding of
|
||||||
|
// packed arena objects is just the crockford encoding.
|
||||||
|
// Subclasses typically want to override this.
|
||||||
|
return this.toCrock();
|
||||||
|
}
|
||||||
loadCrock(s) {
|
loadCrock(s) {
|
||||||
this.alloc();
|
this.alloc();
|
||||||
// We need to get the javascript string
|
// We need to get the javascript string
|
||||||
@ -286,6 +292,14 @@ class AmountNbo extends PackedArenaObject {
|
|||||||
size() {
|
size() {
|
||||||
return 24;
|
return 24;
|
||||||
}
|
}
|
||||||
|
toJson() {
|
||||||
|
let a = new DefaultArena();
|
||||||
|
let am = new Amount(null, a);
|
||||||
|
am.fromNbo(this);
|
||||||
|
let json = am.toJson();
|
||||||
|
a.destroy();
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class EddsaPrivateKey extends PackedArenaObject {
|
class EddsaPrivateKey extends PackedArenaObject {
|
||||||
static create(a) {
|
static create(a) {
|
||||||
@ -468,6 +482,19 @@ class SignatureStruct {
|
|||||||
let ba = new ByteArray(totalSize, buf, a);
|
let ba = new ByteArray(totalSize, buf, a);
|
||||||
return new EccSignaturePurpose(this.purpose(), ba);
|
return new EccSignaturePurpose(this.purpose(), ba);
|
||||||
}
|
}
|
||||||
|
toJson() {
|
||||||
|
let res = {};
|
||||||
|
for (let f of this.fieldTypes()) {
|
||||||
|
let name = f[0];
|
||||||
|
let member = this.members[name];
|
||||||
|
if (!member) {
|
||||||
|
throw Error(format("Member {0} not set", name));
|
||||||
|
}
|
||||||
|
res[name] = member.toJson();
|
||||||
|
}
|
||||||
|
res["purpose"] = this.purpose();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
set(name, value) {
|
set(name, value) {
|
||||||
let typemap = {};
|
let typemap = {};
|
||||||
for (let f of this.fieldTypes()) {
|
for (let f of this.fieldTypes()) {
|
||||||
|
@ -387,6 +387,13 @@ abstract class PackedArenaObject extends ArenaObject {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJson(): any {
|
||||||
|
// Per default, the json encoding of
|
||||||
|
// packed arena objects is just the crockford encoding.
|
||||||
|
// Subclasses typically want to override this.
|
||||||
|
return this.toCrock();
|
||||||
|
}
|
||||||
|
|
||||||
loadCrock(s: string) {
|
loadCrock(s: string) {
|
||||||
this.alloc();
|
this.alloc();
|
||||||
// We need to get the javascript string
|
// We need to get the javascript string
|
||||||
@ -420,7 +427,6 @@ abstract class PackedArenaObject extends ArenaObject {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
hexdump() {
|
hexdump() {
|
||||||
let bytes: string[] = [];
|
let bytes: string[] = [];
|
||||||
for (let i = 0; i < this.size(); i++) {
|
for (let i = 0; i < this.size(); i++) {
|
||||||
@ -441,6 +447,14 @@ class AmountNbo extends PackedArenaObject {
|
|||||||
size() {
|
size() {
|
||||||
return 24;
|
return 24;
|
||||||
}
|
}
|
||||||
|
toJson(): any {
|
||||||
|
let a = new DefaultArena();
|
||||||
|
let am = new Amount(null, a);
|
||||||
|
am.fromNbo(this);
|
||||||
|
let json = am.toJson();
|
||||||
|
a.destroy();
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -673,6 +687,21 @@ abstract class SignatureStruct {
|
|||||||
return new EccSignaturePurpose(this.purpose(), ba);
|
return new EccSignaturePurpose(this.purpose(), ba);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
let res: any = {};
|
||||||
|
for (let f of this.fieldTypes()) {
|
||||||
|
let name = f[0];
|
||||||
|
let member = this.members[name];
|
||||||
|
if (!member) {
|
||||||
|
throw Error(format("Member {0} not set", name));
|
||||||
|
}
|
||||||
|
res[name] = member.toJson();
|
||||||
|
}
|
||||||
|
res["purpose"] = this.purpose();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
protected set(name: string, value: PackedArenaObject) {
|
protected set(name: string, value: PackedArenaObject) {
|
||||||
let typemap: any = {};
|
let typemap: any = {};
|
||||||
for (let f of this.fieldTypes()) {
|
for (let f of this.fieldTypes()) {
|
||||||
|
@ -34,21 +34,24 @@ function signDeposit(db, offer, cds) {
|
|||||||
}
|
}
|
||||||
amountSpent.add(coinSpend);
|
amountSpent.add(coinSpend);
|
||||||
amountRemaining.sub(coinSpend);
|
amountRemaining.sub(coinSpend);
|
||||||
let d = new DepositRequestPS({
|
let newAmount = new Amount(cd.coin.currentAmount);
|
||||||
|
newAmount.sub(coinSpend);
|
||||||
|
cd.coin.currentAmount = newAmount.toJson();
|
||||||
|
let args = {
|
||||||
h_contract: HashCode.fromCrock(offer.H_contract),
|
h_contract: HashCode.fromCrock(offer.H_contract),
|
||||||
h_wire: HashCode.fromCrock(offer.contract.H_wire),
|
h_wire: HashCode.fromCrock(offer.contract.H_wire),
|
||||||
amount_with_fee: new Amount(cd.coin.currentAmount).toNbo(),
|
amount_with_fee: coinSpend.toNbo(),
|
||||||
coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub),
|
coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub),
|
||||||
deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(),
|
deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(),
|
||||||
merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
|
merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
|
||||||
refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
|
refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
|
||||||
timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
|
timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
|
||||||
transaction_id: UInt64.fromNumber(offer.contract.transaction_id),
|
transaction_id: UInt64.fromNumber(offer.contract.transaction_id),
|
||||||
});
|
};
|
||||||
let newAmount = new Amount(cd.coin.currentAmount);
|
let d = new DepositRequestPS(args);
|
||||||
newAmount.sub(coinSpend);
|
console.log("Deposit request #" + ret.length);
|
||||||
cd.coin.currentAmount = newAmount.toJson();
|
console.log("DepositRequestPS: \n", d.toJson());
|
||||||
console.log("DepositRequestPS: ", d.toPurpose().hexdump());
|
console.log("DepositRequestPS sig: \n", d.toPurpose().hexdump());
|
||||||
let coinSig = eddsaSign(d.toPurpose(), EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
|
let coinSig = eddsaSign(d.toPurpose(), EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
|
||||||
.toCrock();
|
.toCrock();
|
||||||
let s = {
|
let s = {
|
||||||
@ -56,7 +59,7 @@ function signDeposit(db, offer, cds) {
|
|||||||
coin_pub: cd.coin.coinPub,
|
coin_pub: cd.coin.coinPub,
|
||||||
ub_sig: cd.coin.denomSig,
|
ub_sig: cd.coin.denomSig,
|
||||||
denom_pub: cd.coin.denomPub,
|
denom_pub: cd.coin.denomPub,
|
||||||
f: amountSpent.toJson(),
|
f: coinSpend.toJson(),
|
||||||
};
|
};
|
||||||
ret.push({ sig: s, updatedCoin: cd.coin });
|
ret.push({ sig: s, updatedCoin: cd.coin });
|
||||||
}
|
}
|
||||||
@ -126,6 +129,7 @@ function getPossibleMintCoins(db, paymentAmount, depositFeeLimit, allowedMints)
|
|||||||
let minAmount = new Amount(paymentAmount);
|
let minAmount = new Amount(paymentAmount);
|
||||||
let accFee = new Amount(coins[0].c.denom.fee_deposit);
|
let accFee = new Amount(coins[0].c.denom.fee_deposit);
|
||||||
let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency);
|
let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency);
|
||||||
|
let usableCoins = [];
|
||||||
nextCoin: for (let i = 0; i < coins.length; i++) {
|
nextCoin: for (let i = 0; i < coins.length; i++) {
|
||||||
let coinAmount = new Amount(coins[i].c.coin.currentAmount);
|
let coinAmount = new Amount(coins[i].c.coin.currentAmount);
|
||||||
let coinFee = coins[i].a;
|
let coinFee = coins[i].a;
|
||||||
@ -138,8 +142,9 @@ function getPossibleMintCoins(db, paymentAmount, depositFeeLimit, allowedMints)
|
|||||||
console.log("too much fees");
|
console.log("too much fees");
|
||||||
continue nextMint;
|
continue nextMint;
|
||||||
}
|
}
|
||||||
|
usableCoins.push(coins[i].c);
|
||||||
if (accAmount.cmp(minAmount) >= 0) {
|
if (accAmount.cmp(minAmount) >= 0) {
|
||||||
ret[key] = m[key];
|
ret[key] = usableCoins;
|
||||||
continue nextMint;
|
continue nextMint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,23 +97,27 @@ function signDeposit(db: IDBDatabase,
|
|||||||
amountSpent.add(coinSpend);
|
amountSpent.add(coinSpend);
|
||||||
amountRemaining.sub(coinSpend);
|
amountRemaining.sub(coinSpend);
|
||||||
|
|
||||||
let d = new DepositRequestPS({
|
let newAmount = new Amount(cd.coin.currentAmount);
|
||||||
|
newAmount.sub(coinSpend);
|
||||||
|
cd.coin.currentAmount = newAmount.toJson();
|
||||||
|
|
||||||
|
let args: DepositRequestPS_Args = {
|
||||||
h_contract: HashCode.fromCrock(offer.H_contract),
|
h_contract: HashCode.fromCrock(offer.H_contract),
|
||||||
h_wire: HashCode.fromCrock(offer.contract.H_wire),
|
h_wire: HashCode.fromCrock(offer.contract.H_wire),
|
||||||
amount_with_fee: new Amount(cd.coin.currentAmount).toNbo(),
|
amount_with_fee: coinSpend.toNbo(),
|
||||||
coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub),
|
coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub),
|
||||||
deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(),
|
deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(),
|
||||||
merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
|
merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
|
||||||
refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
|
refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
|
||||||
timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
|
timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
|
||||||
transaction_id: UInt64.fromNumber(offer.contract.transaction_id),
|
transaction_id: UInt64.fromNumber(offer.contract.transaction_id),
|
||||||
});
|
};
|
||||||
|
|
||||||
let newAmount = new Amount(cd.coin.currentAmount);
|
let d = new DepositRequestPS(args);
|
||||||
newAmount.sub(coinSpend);
|
|
||||||
cd.coin.currentAmount = newAmount.toJson();
|
|
||||||
|
|
||||||
console.log("DepositRequestPS: ", d.toPurpose().hexdump());
|
console.log("Deposit request #" + ret.length);
|
||||||
|
console.log("DepositRequestPS: \n", d.toJson());
|
||||||
|
console.log("DepositRequestPS sig: \n", d.toPurpose().hexdump());
|
||||||
|
|
||||||
let coinSig = eddsaSign(d.toPurpose(),
|
let coinSig = eddsaSign(d.toPurpose(),
|
||||||
EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
|
EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
|
||||||
@ -124,7 +128,7 @@ function signDeposit(db: IDBDatabase,
|
|||||||
coin_pub: cd.coin.coinPub,
|
coin_pub: cd.coin.coinPub,
|
||||||
ub_sig: cd.coin.denomSig,
|
ub_sig: cd.coin.denomSig,
|
||||||
denom_pub: cd.coin.denomPub,
|
denom_pub: cd.coin.denomPub,
|
||||||
f: amountSpent.toJson(),
|
f: coinSpend.toJson(),
|
||||||
};
|
};
|
||||||
ret.push({sig: s, updatedCoin: cd.coin});
|
ret.push({sig: s, updatedCoin: cd.coin});
|
||||||
}
|
}
|
||||||
@ -206,6 +210,7 @@ function getPossibleMintCoins(db: IDBDatabase,
|
|||||||
let minAmount = new Amount(paymentAmount);
|
let minAmount = new Amount(paymentAmount);
|
||||||
let accFee = new Amount(coins[0].c.denom.fee_deposit);
|
let accFee = new Amount(coins[0].c.denom.fee_deposit);
|
||||||
let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency);
|
let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency);
|
||||||
|
let usableCoins: Db.CoinWithDenom[] = [];
|
||||||
nextCoin:
|
nextCoin:
|
||||||
for (let i = 0; i < coins.length; i++) {
|
for (let i = 0; i < coins.length; i++) {
|
||||||
let coinAmount = new Amount(coins[i].c.coin.currentAmount);
|
let coinAmount = new Amount(coins[i].c.coin.currentAmount);
|
||||||
@ -219,8 +224,9 @@ function getPossibleMintCoins(db: IDBDatabase,
|
|||||||
console.log("too much fees");
|
console.log("too much fees");
|
||||||
continue nextMint;
|
continue nextMint;
|
||||||
}
|
}
|
||||||
|
usableCoins.push(coins[i].c);
|
||||||
if (accAmount.cmp(minAmount) >= 0) {
|
if (accAmount.cmp(minAmount) >= 0) {
|
||||||
ret[key] = m[key];
|
ret[key] = usableCoins;
|
||||||
continue nextMint;
|
continue nextMint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user