mirror of
https://github.com/haveno-dex/haveno-ts.git
synced 2025-01-23 13:11:20 -05:00
test refactor trade state TRADE_COMPLETED to boolean
This commit is contained in:
parent
b1e6257efe
commit
9383f48232
6
dist/protobuf/pb_pb.d.ts
vendored
6
dist/protobuf/pb_pb.d.ts
vendored
@ -6105,6 +6105,9 @@ export class Trade extends jspb.Message {
|
|||||||
getUid(): string;
|
getUid(): string;
|
||||||
setUid(value: string): Trade;
|
setUid(value: string): Trade;
|
||||||
|
|
||||||
|
getIsCompleted(): boolean;
|
||||||
|
setIsCompleted(value: boolean): Trade;
|
||||||
|
|
||||||
serializeBinary(): Uint8Array;
|
serializeBinary(): Uint8Array;
|
||||||
toObject(includeInstance?: boolean): Trade.AsObject;
|
toObject(includeInstance?: boolean): Trade.AsObject;
|
||||||
static toObject(includeInstance: boolean, msg: Trade): Trade.AsObject;
|
static toObject(includeInstance: boolean, msg: Trade): Trade.AsObject;
|
||||||
@ -6143,6 +6146,7 @@ export namespace Trade {
|
|||||||
refundResultState: RefundResultState,
|
refundResultState: RefundResultState,
|
||||||
counterCurrencyExtraData: string,
|
counterCurrencyExtraData: string,
|
||||||
uid: string,
|
uid: string,
|
||||||
|
isCompleted: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum State {
|
export enum State {
|
||||||
@ -6173,7 +6177,6 @@ export namespace Trade {
|
|||||||
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG = 24,
|
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG = 24,
|
||||||
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG = 25,
|
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG = 25,
|
||||||
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG = 26,
|
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG = 26,
|
||||||
TRADE_COMPLETED = 27,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Phase {
|
export enum Phase {
|
||||||
@ -6185,7 +6188,6 @@ export namespace Trade {
|
|||||||
DEPOSITS_UNLOCKED = 5,
|
DEPOSITS_UNLOCKED = 5,
|
||||||
PAYMENT_SENT = 6,
|
PAYMENT_SENT = 6,
|
||||||
PAYMENT_RECEIVED = 7,
|
PAYMENT_RECEIVED = 7,
|
||||||
COMPLETED = 8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PayoutState {
|
export enum PayoutState {
|
||||||
|
38
dist/protobuf/pb_pb.js
vendored
38
dist/protobuf/pb_pb.js
vendored
@ -49227,7 +49227,8 @@ proto.io.haveno.protobuffer.Trade.toObject = function(includeInstance, msg) {
|
|||||||
refundAgentNodeAddress: (f = msg.getRefundAgentNodeAddress()) && proto.io.haveno.protobuffer.NodeAddress.toObject(includeInstance, f),
|
refundAgentNodeAddress: (f = msg.getRefundAgentNodeAddress()) && proto.io.haveno.protobuffer.NodeAddress.toObject(includeInstance, f),
|
||||||
refundResultState: jspb.Message.getFieldWithDefault(msg, 27, 0),
|
refundResultState: jspb.Message.getFieldWithDefault(msg, 27, 0),
|
||||||
counterCurrencyExtraData: jspb.Message.getFieldWithDefault(msg, 28, ""),
|
counterCurrencyExtraData: jspb.Message.getFieldWithDefault(msg, 28, ""),
|
||||||
uid: jspb.Message.getFieldWithDefault(msg, 29, "")
|
uid: jspb.Message.getFieldWithDefault(msg, 29, ""),
|
||||||
|
isCompleted: jspb.Message.getBooleanFieldWithDefault(msg, 30, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeInstance) {
|
if (includeInstance) {
|
||||||
@ -49383,6 +49384,10 @@ proto.io.haveno.protobuffer.Trade.deserializeBinaryFromReader = function(msg, re
|
|||||||
var value = /** @type {string} */ (reader.readString());
|
var value = /** @type {string} */ (reader.readString());
|
||||||
msg.setUid(value);
|
msg.setUid(value);
|
||||||
break;
|
break;
|
||||||
|
case 30:
|
||||||
|
var value = /** @type {boolean} */ (reader.readBool());
|
||||||
|
msg.setIsCompleted(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reader.skipField();
|
reader.skipField();
|
||||||
break;
|
break;
|
||||||
@ -49615,6 +49620,13 @@ proto.io.haveno.protobuffer.Trade.serializeBinaryToWriter = function(message, wr
|
|||||||
f
|
f
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
f = message.getIsCompleted();
|
||||||
|
if (f) {
|
||||||
|
writer.writeBool(
|
||||||
|
30,
|
||||||
|
f
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -49648,8 +49660,7 @@ proto.io.haveno.protobuffer.Trade.State = {
|
|||||||
SELLER_SENT_PAYMENT_RECEIVED_MSG: 23,
|
SELLER_SENT_PAYMENT_RECEIVED_MSG: 23,
|
||||||
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG: 24,
|
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG: 24,
|
||||||
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG: 25,
|
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG: 25,
|
||||||
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG: 26,
|
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG: 26
|
||||||
TRADE_COMPLETED: 27
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49663,8 +49674,7 @@ proto.io.haveno.protobuffer.Trade.Phase = {
|
|||||||
DEPOSITS_CONFIRMED: 4,
|
DEPOSITS_CONFIRMED: 4,
|
||||||
DEPOSITS_UNLOCKED: 5,
|
DEPOSITS_UNLOCKED: 5,
|
||||||
PAYMENT_SENT: 6,
|
PAYMENT_SENT: 6,
|
||||||
PAYMENT_RECEIVED: 7,
|
PAYMENT_RECEIVED: 7
|
||||||
COMPLETED: 8
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50370,6 +50380,24 @@ proto.io.haveno.protobuffer.Trade.prototype.setUid = function(value) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optional bool is_completed = 30;
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
proto.io.haveno.protobuffer.Trade.prototype.getIsCompleted = function() {
|
||||||
|
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 30, false));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} value
|
||||||
|
* @return {!proto.io.haveno.protobuffer.Trade} returns this
|
||||||
|
*/
|
||||||
|
proto.io.haveno.protobuffer.Trade.prototype.setIsCompleted = function(value) {
|
||||||
|
return jspb.Message.setProto3BooleanField(this, 30, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2
dist/protobuf/pb_pb.js.map
vendored
2
dist/protobuf/pb_pb.js.map
vendored
File diff suppressed because one or more lines are too long
@ -264,6 +264,10 @@ class TradeContext {
|
|||||||
return this.buyerOfflineAfterDisputeOpened || this.sellerOfflineAfterDisputeOpened || this.buyerOfflineAfterPaymentSent || this.buyerOfflineAfterTake || this.sellerOfflineAfterTake;
|
return this.buyerOfflineAfterDisputeOpened || this.sellerOfflineAfterDisputeOpened || this.buyerOfflineAfterPaymentSent || this.buyerOfflineAfterTake || this.sellerOfflineAfterTake;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPhase() {
|
||||||
|
return this.isPaymentReceived ? "PAYMENT_RECEIVED" : this.isPaymentSent ? "PAYMENT_SENT" : "DEPOSITS_UNLOCKED";
|
||||||
|
}
|
||||||
|
|
||||||
static init(ctxP: Partial<TradeContext> | undefined): TradeContext {
|
static init(ctxP: Partial<TradeContext> | undefined): TradeContext {
|
||||||
let ctx = ctxP instanceof TradeContext ? ctxP : new TradeContext(ctxP);
|
let ctx = ctxP instanceof TradeContext ? ctxP : new TradeContext(ctxP);
|
||||||
if (!ctx.offerAmount && ctx.tradeAmount) ctx.offerAmount = ctx.tradeAmount;
|
if (!ctx.offerAmount && ctx.tradeAmount) ctx.offerAmount = ctx.tradeAmount;
|
||||||
@ -2432,7 +2436,7 @@ async function executeTrade(ctxP: Partial<TradeContext>): Promise<string> {
|
|||||||
// payout tx is published by buyer (priority) or arbitrator
|
// payout tx is published by buyer (priority) or arbitrator
|
||||||
await wait(ctx.walletSyncPeriodMs);
|
await wait(ctx.walletSyncPeriodMs);
|
||||||
await testTradeState(await ctx.getSeller().havenod!.getTrade(trade.getTradeId()), {phase: "PAYMENT_RECEIVED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: false, isPayoutPublished: true});
|
await testTradeState(await ctx.getSeller().havenod!.getTrade(trade.getTradeId()), {phase: "PAYMENT_RECEIVED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: false, isPayoutPublished: true});
|
||||||
await testTradeState(await ctx.arbitrator.havenod!.getTrade(trade.getTradeId()), {phase: "COMPLETED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: true, isPayoutPublished: true}); // arbitrator trade auto completes
|
await testTradeState(await ctx.arbitrator.havenod!.getTrade(trade.getTradeId()), {phase: "PAYMENT_RECEIVED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: true, isPayoutPublished: true}); // arbitrator trade auto completes
|
||||||
|
|
||||||
// buyer comes online if offline
|
// buyer comes online if offline
|
||||||
if (ctx.buyerOfflineAfterPaymentSent) {
|
if (ctx.buyerOfflineAfterPaymentSent) {
|
||||||
@ -2447,9 +2451,9 @@ async function executeTrade(ctxP: Partial<TradeContext>): Promise<string> {
|
|||||||
|
|
||||||
// test trade completion
|
// test trade completion
|
||||||
await ctx.getBuyer().havenod!.completeTrade(trade.getTradeId());
|
await ctx.getBuyer().havenod!.completeTrade(trade.getTradeId());
|
||||||
await testTradeState(await ctx.getBuyer().havenod!.getTrade(trade.getTradeId()), {phase: "COMPLETED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: true, isPayoutPublished: true});
|
await testTradeState(await ctx.getBuyer().havenod!.getTrade(trade.getTradeId()), {phase: "PAYMENT_RECEIVED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: true, isPayoutPublished: true});
|
||||||
await ctx.getSeller().havenod!.completeTrade(trade.getTradeId());
|
await ctx.getSeller().havenod!.completeTrade(trade.getTradeId());
|
||||||
await testTradeState(await ctx.getSeller().havenod!.getTrade(trade.getTradeId()), {phase: "COMPLETED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: true, isPayoutPublished: true});
|
await testTradeState(await ctx.getSeller().havenod!.getTrade(trade.getTradeId()), {phase: "PAYMENT_RECEIVED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], isCompleted: true, isPayoutPublished: true});
|
||||||
|
|
||||||
// record balances on completion
|
// record balances on completion
|
||||||
if (!ctx.maker.balancesAfterPayout) {
|
if (!ctx.maker.balancesAfterPayout) {
|
||||||
@ -2483,9 +2487,10 @@ async function testTradePayoutUnlock(ctxP: Partial<TradeContext>) {
|
|||||||
let trade = await ctx.arbitrator.havenod!.getTrade(ctx.offerId!);
|
let trade = await ctx.arbitrator.havenod!.getTrade(ctx.offerId!);
|
||||||
if (trade.getPayoutState() !== "PAYOUT_CONFIRMED") await mineToHeight(height + 1);
|
if (trade.getPayoutState() !== "PAYOUT_CONFIRMED") await mineToHeight(height + 1);
|
||||||
await wait(TestConfig.maxWalletStartupMs + ctx.walletSyncPeriodMs * 2);
|
await wait(TestConfig.maxWalletStartupMs + ctx.walletSyncPeriodMs * 2);
|
||||||
if (ctx.getBuyer().havenod) await testTradeState(await ctx.getBuyer().havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"]});
|
const disputeState = ctx.isPaymentReceived ? "NO_DISPUTE" : "DISPUTE_CLOSED";
|
||||||
if (ctx.getSeller().havenod) await testTradeState(await ctx.getSeller().havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"]});
|
if (ctx.getBuyer().havenod) await testTradeState(await ctx.getBuyer().havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), disputeState: disputeState, payoutState: ["PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"]});
|
||||||
await testTradeState(await ctx.arbitrator.havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"]});
|
if (ctx.getSeller().havenod) await testTradeState(await ctx.getSeller().havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), disputeState: disputeState, payoutState: ["PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"]});
|
||||||
|
await testTradeState(await ctx.arbitrator.havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), payoutState: ["PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"]});
|
||||||
let payoutTx = ctx.getBuyer().havenod ? await ctx.getBuyer().havenod?.getXmrTx(payoutTxId) : await ctx.getSeller().havenod?.getXmrTx(payoutTxId);
|
let payoutTx = ctx.getBuyer().havenod ? await ctx.getBuyer().havenod?.getXmrTx(payoutTxId) : await ctx.getSeller().havenod?.getXmrTx(payoutTxId);
|
||||||
expect(payoutTx?.getIsConfirmed());
|
expect(payoutTx?.getIsConfirmed());
|
||||||
|
|
||||||
@ -2494,9 +2499,9 @@ async function testTradePayoutUnlock(ctxP: Partial<TradeContext>) {
|
|||||||
trade = await ctx.arbitrator.havenod!.getTrade(ctx.offerId!);
|
trade = await ctx.arbitrator.havenod!.getTrade(ctx.offerId!);
|
||||||
if (trade.getPayoutState() !== "PAYOUT_UNLOCKED") await mineToHeight(height + 10);
|
if (trade.getPayoutState() !== "PAYOUT_UNLOCKED") await mineToHeight(height + 10);
|
||||||
await wait(TestConfig.maxWalletStartupMs + ctx.walletSyncPeriodMs * 2);
|
await wait(TestConfig.maxWalletStartupMs + ctx.walletSyncPeriodMs * 2);
|
||||||
if (await ctx.getBuyer().havenod) await testTradeState(await ctx.getBuyer().havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_UNLOCKED"]});
|
if (await ctx.getBuyer().havenod) await testTradeState(await ctx.getBuyer().havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), disputeState: disputeState, payoutState: ["PAYOUT_UNLOCKED"]});
|
||||||
if (await ctx.getSeller().havenod) await testTradeState(await ctx.getSeller().havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_UNLOCKED"]});
|
if (await ctx.getSeller().havenod) await testTradeState(await ctx.getSeller().havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), disputeState: disputeState, payoutState: ["PAYOUT_UNLOCKED"]});
|
||||||
await testTradeState(await ctx.arbitrator.havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_UNLOCKED"]});
|
await testTradeState(await ctx.arbitrator.havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), disputeState: disputeState, payoutState: ["PAYOUT_UNLOCKED"]});
|
||||||
payoutTx = ctx.getBuyer().havenod ? await ctx.getBuyer().havenod?.getXmrTx(payoutTxId) : await ctx.getSeller().havenod?.getXmrTx(payoutTxId);
|
payoutTx = ctx.getBuyer().havenod ? await ctx.getBuyer().havenod?.getXmrTx(payoutTxId) : await ctx.getSeller().havenod?.getXmrTx(payoutTxId);
|
||||||
expect(!payoutTx?.getIsLocked());
|
expect(!payoutTx?.getIsLocked());
|
||||||
}
|
}
|
||||||
@ -2508,7 +2513,12 @@ async function testTradeState(trade: TradeInfo, ctx: Partial<TradeContext>) {
|
|||||||
if (ctx.isCompleted !== undefined) expect(trade.getIsCompleted()).toEqual(ctx.isCompleted);
|
if (ctx.isCompleted !== undefined) expect(trade.getIsCompleted()).toEqual(ctx.isCompleted);
|
||||||
if (ctx.isPayoutPublished !== undefined) expect(trade.getIsPayoutPublished()).toEqual(ctx.isPayoutPublished);
|
if (ctx.isPayoutPublished !== undefined) expect(trade.getIsPayoutPublished()).toEqual(ctx.isPayoutPublished);
|
||||||
if (ctx.isPayoutConfirmed !== undefined) expect(trade.getIsPayoutConfirmed()).toEqual(ctx.isPayoutConfirmed);
|
if (ctx.isPayoutConfirmed !== undefined) expect(trade.getIsPayoutConfirmed()).toEqual(ctx.isPayoutConfirmed);
|
||||||
|
if (ctx.isPayoutConfirmed) expect(trade.getIsPayoutPublished()).toEqual(true);
|
||||||
if (ctx.isPayoutUnlocked !== undefined) expect(trade.getIsPayoutUnlocked()).toEqual(ctx.isPayoutUnlocked);
|
if (ctx.isPayoutUnlocked !== undefined) expect(trade.getIsPayoutUnlocked()).toEqual(ctx.isPayoutUnlocked);
|
||||||
|
if (ctx.isPayoutUnlocked) {
|
||||||
|
expect(trade.getIsPayoutConfirmed()).toEqual(true);
|
||||||
|
expect(trade.getIsPayoutPublished()).toEqual(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function makeOffer(ctxP?: Partial<TradeContext>): Promise<OfferInfo> {
|
async function makeOffer(ctxP?: Partial<TradeContext>): Promise<OfferInfo> {
|
||||||
@ -2921,9 +2931,9 @@ async function resolveDispute(ctxP: Partial<TradeContext>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// test trade state
|
// test trade state
|
||||||
if (ctx.getBuyer().havenod) await testTradeState(await ctx.getBuyer().havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], disputeState: "DISPUTE_CLOSED", isCompleted: true, isPayoutPublished: true});
|
if (ctx.getBuyer().havenod) await testTradeState(await ctx.getBuyer().havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], disputeState: "DISPUTE_CLOSED", isCompleted: true, isPayoutPublished: true});
|
||||||
if (ctx.getSeller().havenod) await testTradeState(await ctx.getSeller().havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], disputeState: "DISPUTE_CLOSED", isCompleted: true, isPayoutPublished: true});
|
if (ctx.getSeller().havenod) await testTradeState(await ctx.getSeller().havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], disputeState: "DISPUTE_CLOSED", isCompleted: true, isPayoutPublished: true});
|
||||||
await testTradeState(await ctx.arbitrator.havenod!.getTrade(ctx.offerId!), {phase: "COMPLETED", payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], disputeState: "DISPUTE_CLOSED", isCompleted: true, isPayoutPublished: true});
|
await testTradeState(await ctx.arbitrator.havenod!.getTrade(ctx.offerId!), {phase: ctx.getPhase(), payoutState: ["PAYOUT_PUBLISHED", "PAYOUT_CONFIRMED", "PAYOUT_UNLOCKED"], disputeState: "DISPUTE_CLOSED", isCompleted: true, isPayoutPublished: true});
|
||||||
|
|
||||||
// signing peer has payout tx id on 0 conf (peers must wait for confirmation to see outgoing tx)
|
// signing peer has payout tx id on 0 conf (peers must wait for confirmation to see outgoing tx)
|
||||||
const winnerd = ctx.disputeWinner === DisputeResult.Winner.BUYER ? ctx.getBuyer().havenod : ctx.getSeller().havenod;
|
const winnerd = ctx.disputeWinner === DisputeResult.Winner.BUYER ? ctx.getBuyer().havenod : ctx.getSeller().havenod;
|
||||||
|
Loading…
Reference in New Issue
Block a user