mirror of
https://github.com/haveno-dex/haveno-ts.git
synced 2025-02-22 15:39:51 -05:00
support and test taking trades within offer range
This commit is contained in:
parent
2980984850
commit
f256fafa7d
3
dist/HavenoClient.d.ts
vendored
3
dist/HavenoClient.d.ts
vendored
@ -437,9 +437,10 @@ export default class HavenoClient {
|
|||||||
*
|
*
|
||||||
* @param {string} offerId - id of the offer to take
|
* @param {string} offerId - id of the offer to take
|
||||||
* @param {string} paymentAccountId - id of the payment account
|
* @param {string} paymentAccountId - id of the payment account
|
||||||
|
* @param {bigint|undefined} amount - amount the taker chooses to buy or sell within the offer range (default is max offer amount)
|
||||||
* @return {TradeInfo} the initialized trade
|
* @return {TradeInfo} the initialized trade
|
||||||
*/
|
*/
|
||||||
takeOffer(offerId: string, paymentAccountId: string): Promise<TradeInfo>;
|
takeOffer(offerId: string, paymentAccountId: string, amount?: bigint): Promise<TradeInfo>;
|
||||||
/**
|
/**
|
||||||
* Get a trade by id.
|
* Get a trade by id.
|
||||||
*
|
*
|
||||||
|
6
dist/HavenoClient.js
vendored
6
dist/HavenoClient.js
vendored
@ -1021,13 +1021,17 @@ class HavenoClient {
|
|||||||
*
|
*
|
||||||
* @param {string} offerId - id of the offer to take
|
* @param {string} offerId - id of the offer to take
|
||||||
* @param {string} paymentAccountId - id of the payment account
|
* @param {string} paymentAccountId - id of the payment account
|
||||||
|
* @param {bigint|undefined} amount - amount the taker chooses to buy or sell within the offer range (default is max offer amount)
|
||||||
* @return {TradeInfo} the initialized trade
|
* @return {TradeInfo} the initialized trade
|
||||||
*/
|
*/
|
||||||
async takeOffer(offerId, paymentAccountId) {
|
async takeOffer(offerId, paymentAccountId, amount) {
|
||||||
try {
|
try {
|
||||||
const request = new grpc_pb_1.TakeOfferRequest()
|
const request = new grpc_pb_1.TakeOfferRequest()
|
||||||
.setOfferId(offerId)
|
.setOfferId(offerId)
|
||||||
.setPaymentAccountId(paymentAccountId);
|
.setPaymentAccountId(paymentAccountId);
|
||||||
|
if (amount)
|
||||||
|
request.setAmount(amount.toString());
|
||||||
|
HavenoUtils_1.default.log(0, "Taking offer with taker amount: " + amount);
|
||||||
return (await this._tradesClient.takeOffer(request, { password: this._password })).getTrade();
|
return (await this._tradesClient.takeOffer(request, { password: this._password })).getTrade();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
2
dist/HavenoClient.js.map
vendored
2
dist/HavenoClient.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/protobuf/grpc_pb.d.ts
vendored
4
dist/protobuf/grpc_pb.d.ts
vendored
@ -2284,6 +2284,9 @@ export class TakeOfferRequest extends jspb.Message {
|
|||||||
getPaymentAccountId(): string;
|
getPaymentAccountId(): string;
|
||||||
setPaymentAccountId(value: string): TakeOfferRequest;
|
setPaymentAccountId(value: string): TakeOfferRequest;
|
||||||
|
|
||||||
|
getAmount(): string;
|
||||||
|
setAmount(value: string): TakeOfferRequest;
|
||||||
|
|
||||||
serializeBinary(): Uint8Array;
|
serializeBinary(): Uint8Array;
|
||||||
toObject(includeInstance?: boolean): TakeOfferRequest.AsObject;
|
toObject(includeInstance?: boolean): TakeOfferRequest.AsObject;
|
||||||
static toObject(includeInstance: boolean, msg: TakeOfferRequest): TakeOfferRequest.AsObject;
|
static toObject(includeInstance: boolean, msg: TakeOfferRequest): TakeOfferRequest.AsObject;
|
||||||
@ -2296,6 +2299,7 @@ export namespace TakeOfferRequest {
|
|||||||
export type AsObject = {
|
export type AsObject = {
|
||||||
offerId: string,
|
offerId: string,
|
||||||
paymentAccountId: string,
|
paymentAccountId: string,
|
||||||
|
amount: string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
dist/protobuf/grpc_pb.js
vendored
32
dist/protobuf/grpc_pb.js
vendored
@ -20540,7 +20540,8 @@ proto.io.haveno.protobuffer.TakeOfferRequest.prototype.toObject = function(opt_i
|
|||||||
proto.io.haveno.protobuffer.TakeOfferRequest.toObject = function(includeInstance, msg) {
|
proto.io.haveno.protobuffer.TakeOfferRequest.toObject = function(includeInstance, msg) {
|
||||||
var f, obj = {
|
var f, obj = {
|
||||||
offerId: jspb.Message.getFieldWithDefault(msg, 1, ""),
|
offerId: jspb.Message.getFieldWithDefault(msg, 1, ""),
|
||||||
paymentAccountId: jspb.Message.getFieldWithDefault(msg, 2, "")
|
paymentAccountId: jspb.Message.getFieldWithDefault(msg, 2, ""),
|
||||||
|
amount: jspb.Message.getFieldWithDefault(msg, 3, "0")
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeInstance) {
|
if (includeInstance) {
|
||||||
@ -20585,6 +20586,10 @@ proto.io.haveno.protobuffer.TakeOfferRequest.deserializeBinaryFromReader = funct
|
|||||||
var value = /** @type {string} */ (reader.readString());
|
var value = /** @type {string} */ (reader.readString());
|
||||||
msg.setPaymentAccountId(value);
|
msg.setPaymentAccountId(value);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
var value = /** @type {string} */ (reader.readUint64String());
|
||||||
|
msg.setAmount(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reader.skipField();
|
reader.skipField();
|
||||||
break;
|
break;
|
||||||
@ -20628,6 +20633,13 @@ proto.io.haveno.protobuffer.TakeOfferRequest.serializeBinaryToWriter = function(
|
|||||||
f
|
f
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
f = message.getAmount();
|
||||||
|
if (parseInt(f, 10) !== 0) {
|
||||||
|
writer.writeUint64String(
|
||||||
|
3,
|
||||||
|
f
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -20667,6 +20679,24 @@ proto.io.haveno.protobuffer.TakeOfferRequest.prototype.setPaymentAccountId = fun
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optional uint64 amount = 3;
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
proto.io.haveno.protobuffer.TakeOfferRequest.prototype.getAmount = function() {
|
||||||
|
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "0"));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
* @return {!proto.io.haveno.protobuffer.TakeOfferRequest} returns this
|
||||||
|
*/
|
||||||
|
proto.io.haveno.protobuffer.TakeOfferRequest.prototype.setAmount = function(value) {
|
||||||
|
return jspb.Message.setProto3StringIntField(this, 3, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2
dist/utils/HavenoUtils.d.ts
vendored
2
dist/utils/HavenoUtils.d.ts
vendored
@ -86,7 +86,7 @@ export default class HavenoUtils {
|
|||||||
* @param {number|string} amountXmr - amount in XMR to convert to atomic units
|
* @param {number|string} amountXmr - amount in XMR to convert to atomic units
|
||||||
* @return {BigInt} amount in atomic units
|
* @return {BigInt} amount in atomic units
|
||||||
*/
|
*/
|
||||||
static xmrToAtomicUnits(amountXmr: number | string): BigInt;
|
static xmrToAtomicUnits(amountXmr: number | string): bigint;
|
||||||
/**
|
/**
|
||||||
* Convert atomic units to XMR.
|
* Convert atomic units to XMR.
|
||||||
*
|
*
|
||||||
|
@ -157,8 +157,8 @@ const TestConfig = {
|
|||||||
takeOffer: true,
|
takeOffer: true,
|
||||||
awaitFundsToMakeOffer: true,
|
awaitFundsToMakeOffer: true,
|
||||||
direction: "buy", // buy or sell xmr
|
direction: "buy", // buy or sell xmr
|
||||||
amount: BigInt("200000000000"), // amount of xmr to trade (0.2 XMR)
|
offerAmount: BigInt("200000000000"), // amount of xmr to trade (0.2 XMR)
|
||||||
minAmount: undefined,
|
offerMinAmount: undefined,
|
||||||
assetCode: "usd", // counter asset to trade
|
assetCode: "usd", // counter asset to trade
|
||||||
makerPaymentAccountId: undefined,
|
makerPaymentAccountId: undefined,
|
||||||
buyerSecurityDepositPct: 0.15,
|
buyerSecurityDepositPct: 0.15,
|
||||||
@ -219,8 +219,9 @@ interface TradeContext {
|
|||||||
awaitFundsToMakeOffer?: boolean
|
awaitFundsToMakeOffer?: boolean
|
||||||
direction?: string,
|
direction?: string,
|
||||||
assetCode?: string,
|
assetCode?: string,
|
||||||
amount?: bigint,
|
offerAmount?: bigint, // offer amount or max
|
||||||
minAmount?: bigint,
|
offerMinAmount?: bigint,
|
||||||
|
tradeAmount?: bigint, // trade amount within offer range
|
||||||
makerPaymentAccountId?: string,
|
makerPaymentAccountId?: string,
|
||||||
buyerSecurityDepositPct?: number,
|
buyerSecurityDepositPct?: number,
|
||||||
price?: number,
|
price?: number,
|
||||||
@ -924,13 +925,13 @@ test("Can get market depth (CI, sanity check)", async () => {
|
|||||||
expect(marketDepth.getSellDepthList().length).toEqual(0);
|
expect(marketDepth.getSellDepthList().length).toEqual(0);
|
||||||
|
|
||||||
// post offers to buy and sell
|
// post offers to buy and sell
|
||||||
await makeOffer({maker: user1, direction: "buy", amount: BigInt("150000000000"), assetCode: assetCode, price: 17.0});
|
await makeOffer({maker: user1, direction: "buy", offerAmount: BigInt("150000000000"), assetCode: assetCode, price: 17.0});
|
||||||
await makeOffer({maker: user1, direction: "buy", amount: BigInt("150000000000"), assetCode: assetCode, price: 17.2});
|
await makeOffer({maker: user1, direction: "buy", offerAmount: BigInt("150000000000"), assetCode: assetCode, price: 17.2});
|
||||||
await makeOffer({maker: user1, direction: "buy", amount: BigInt("200000000000"), assetCode: assetCode, price: 17.3});
|
await makeOffer({maker: user1, direction: "buy", offerAmount: BigInt("200000000000"), assetCode: assetCode, price: 17.3});
|
||||||
await makeOffer({maker: user1, direction: "buy", amount: BigInt("150000000000"), assetCode: assetCode, price: 17.3});
|
await makeOffer({maker: user1, direction: "buy", offerAmount: BigInt("150000000000"), assetCode: assetCode, price: 17.3});
|
||||||
await makeOffer({maker: user1, direction: "sell", amount: BigInt("300000000000"), assetCode: assetCode, priceMargin: 0.00});
|
await makeOffer({maker: user1, direction: "sell", offerAmount: BigInt("300000000000"), assetCode: assetCode, priceMargin: 0.00});
|
||||||
await makeOffer({maker: user1, direction: "sell", amount: BigInt("300000000000"), assetCode: assetCode, priceMargin: 0.02});
|
await makeOffer({maker: user1, direction: "sell", offerAmount: BigInt("300000000000"), assetCode: assetCode, priceMargin: 0.02});
|
||||||
await makeOffer({maker: user1, direction: "sell", amount: BigInt("400000000000"), assetCode: assetCode, priceMargin: 0.05});
|
await makeOffer({maker: user1, direction: "sell", offerAmount: BigInt("400000000000"), assetCode: assetCode, priceMargin: 0.05});
|
||||||
|
|
||||||
// get user2's market depth
|
// get user2's market depth
|
||||||
await wait(TestConfig.trade.maxTimePeerNoticeMs);
|
await wait(TestConfig.trade.maxTimePeerNoticeMs);
|
||||||
@ -1340,15 +1341,20 @@ test("Can schedule offers with locked funds (CI)", async () => {
|
|||||||
test("Cannot post offer exceeding trade limit (CI, sanity check)", async () => {
|
test("Cannot post offer exceeding trade limit (CI, sanity check)", async () => {
|
||||||
const revolutAccount = await createRevolutPaymentAccount(user1);
|
const revolutAccount = await createRevolutPaymentAccount(user1);
|
||||||
try {
|
try {
|
||||||
await executeTrade({amount: BigInt("2100000000000"), assetCode: "USD", makerPaymentAccountId: revolutAccount.getId(), takeOffer: false});
|
await executeTrade({offerAmount: BigInt("2100000000000"), assetCode: "USD", makerPaymentAccountId: revolutAccount.getId(), takeOffer: false});
|
||||||
throw new Error("Should have rejected posting offer above trade limit")
|
throw new Error("Should have rejected posting offer above trade limit")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
assert(err.message.indexOf("amount is larger than") === 0);
|
assert(err.message.indexOf("amount is larger than") === 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Can complete a trade", async () => {
|
test("Can complete a trade within a range", async () => {
|
||||||
await executeTrade();
|
await executeTrade({
|
||||||
|
price: 150,
|
||||||
|
offerAmount: HavenoUtils.xmrToAtomicUnits(1),
|
||||||
|
offerMinAmount: HavenoUtils.xmrToAtomicUnits(.15),
|
||||||
|
tradeAmount: HavenoUtils.xmrToAtomicUnits(.18)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Can complete trades at the same time (CI, sanity check)", async () => {
|
test("Can complete trades at the same time (CI, sanity check)", async () => {
|
||||||
@ -1548,7 +1554,7 @@ test("Cannot make or take offer with insufficient unlocked funds (CI, sanity che
|
|||||||
else {
|
else {
|
||||||
const tradeAmount = BigInt("250000000000");
|
const tradeAmount = BigInt("250000000000");
|
||||||
await waitForAvailableBalance(tradeAmount * BigInt("2"), user1);
|
await waitForAvailableBalance(tradeAmount * BigInt("2"), user1);
|
||||||
offer = await makeOffer({maker: user1, amount: tradeAmount, awaitFundsToMakeOffer: false});
|
offer = await makeOffer({maker: user1, offerAmount: tradeAmount, awaitFundsToMakeOffer: false});
|
||||||
assert.equal(offer.getState(), "AVAILABLE");
|
assert.equal(offer.getState(), "AVAILABLE");
|
||||||
await wait(TestConfig.trade.walletSyncPeriodMs * 2);
|
await wait(TestConfig.trade.walletSyncPeriodMs * 2);
|
||||||
}
|
}
|
||||||
@ -1598,7 +1604,7 @@ test("Invalidates offers when reserved funds are spent (CI)", async () => {
|
|||||||
// post offer
|
// post offer
|
||||||
await wait(1000);
|
await wait(1000);
|
||||||
const assetCode = getRandomAssetCode();
|
const assetCode = getRandomAssetCode();
|
||||||
const offer: OfferInfo = await makeOffer({maker: user1, assetCode: assetCode, amount: tradeAmount});
|
const offer: OfferInfo = await makeOffer({maker: user1, assetCode: assetCode, offerAmount: tradeAmount});
|
||||||
|
|
||||||
// get key images reserved by offer
|
// get key images reserved by offer
|
||||||
const reservedKeyImages: any[] = [];
|
const reservedKeyImages: any[] = [];
|
||||||
@ -1660,7 +1666,7 @@ test("Can handle unexpected errors during trade initialization", async () => {
|
|||||||
|
|
||||||
// trader 0 posts offer
|
// trader 0 posts offer
|
||||||
HavenoUtils.log(1, "Posting offer");
|
HavenoUtils.log(1, "Posting offer");
|
||||||
let offer = await makeOffer({maker: traders[0], amount: tradeAmount});
|
let offer = await makeOffer({maker: traders[0], offerAmount: tradeAmount});
|
||||||
offer = await traders[0].getMyOffer(offer.getId());
|
offer = await traders[0].getMyOffer(offer.getId());
|
||||||
assert.equal(offer.getState(), "AVAILABLE");
|
assert.equal(offer.getState(), "AVAILABLE");
|
||||||
|
|
||||||
@ -1875,8 +1881,9 @@ function getTradeContexts(numConfigs: number): TradeContext[] {
|
|||||||
|
|
||||||
function tradeContextToString(ctx: TradeContext) {
|
function tradeContextToString(ctx: TradeContext) {
|
||||||
return JSON.stringify(Object.assign({}, ctx, {
|
return JSON.stringify(Object.assign({}, ctx, {
|
||||||
amount: ctx.amount ? ctx.amount.toString() : undefined,
|
offerAmount: ctx.offerAmount ? ctx.offerAmount.toString() : undefined,
|
||||||
minAmount: ctx.minAmount ? ctx.minAmount.toString() : undefined,
|
offerMinAmount: ctx.offerMinAmount ? ctx.offerMinAmount.toString() : undefined,
|
||||||
|
tradeAmount: ctx.tradeAmount ? ctx.tradeAmount.toString() : undefined,
|
||||||
disputeWinnerAmount: ctx.disputeWinnerAmount ? ctx.disputeWinnerAmount.toString() : undefined,
|
disputeWinnerAmount: ctx.disputeWinnerAmount ? ctx.disputeWinnerAmount.toString() : undefined,
|
||||||
arbitrator: ctx.arbitrator ? ctx.arbitrator.getUrl() : undefined,
|
arbitrator: ctx.arbitrator ? ctx.arbitrator.getUrl() : undefined,
|
||||||
maker: ctx.maker ? ctx.maker.getUrl() : undefined,
|
maker: ctx.maker ? ctx.maker.getUrl() : undefined,
|
||||||
@ -1911,7 +1918,7 @@ async function executeTrades(ctxs: TradeContext[], executionCtx?: TradeContext):
|
|||||||
let tradeAmount: bigint|undefined = undefined;
|
let tradeAmount: bigint|undefined = undefined;
|
||||||
const outputCounts = new Map<any, number>();
|
const outputCounts = new Map<any, number>();
|
||||||
for (const ctx of ctxs) {
|
for (const ctx of ctxs) {
|
||||||
if (!tradeAmount || tradeAmount < ctx.amount!) tradeAmount = ctx.amount; // use max amount
|
if (!tradeAmount || tradeAmount < ctx.offerAmount!) tradeAmount = ctx.offerAmount; // use max amount
|
||||||
if (ctx.awaitFundsToMakeOffer && ctx.makeOffer && !ctx.offerId) {
|
if (ctx.awaitFundsToMakeOffer && ctx.makeOffer && !ctx.offerId) {
|
||||||
const wallet = await getWallet(ctx.maker!);
|
const wallet = await getWallet(ctx.maker!);
|
||||||
if (outputCounts.has(wallet)) outputCounts.set(wallet, outputCounts.get(wallet)! + 1);
|
if (outputCounts.has(wallet)) outputCounts.set(wallet, outputCounts.get(wallet)! + 1);
|
||||||
@ -1971,7 +1978,7 @@ async function executeTrade(ctx?: TradeContext): Promise<string> {
|
|||||||
if (!ctx.concurrentTrades) { // already funded
|
if (!ctx.concurrentTrades) { // already funded
|
||||||
if (ctx.awaitFundsToMakeOffer && makingOffer && !ctx.offerId) clientsToFund.push(ctx.maker!);
|
if (ctx.awaitFundsToMakeOffer && makingOffer && !ctx.offerId) clientsToFund.push(ctx.maker!);
|
||||||
if (ctx.awaitFundsToTakeOffer && ctx.takeOffer && !ctx.isOfferTaken) clientsToFund.push(ctx.taker!);
|
if (ctx.awaitFundsToTakeOffer && ctx.takeOffer && !ctx.isOfferTaken) clientsToFund.push(ctx.taker!);
|
||||||
await waitForAvailableBalance(ctx.amount! * BigInt("2"), ...clientsToFund);
|
await waitForAvailableBalance(ctx.offerAmount! * BigInt("2"), ...clientsToFund);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get info before trade
|
// get info before trade
|
||||||
@ -2207,8 +2214,8 @@ async function executeTrade(ctx?: TradeContext): Promise<string> {
|
|||||||
if (!ctx.concurrentTrades) {
|
if (!ctx.concurrentTrades) {
|
||||||
const buyerBalancesAfter = await getBuyer(ctx)!.getBalances();
|
const buyerBalancesAfter = await getBuyer(ctx)!.getBalances();
|
||||||
const sellerBalancesAfter = await getSeller(ctx)!.getBalances();
|
const sellerBalancesAfter = await getSeller(ctx)!.getBalances();
|
||||||
const buyerFee = BigInt(buyerBalancesBefore.getBalance()) + BigInt(buyerBalancesBefore.getReservedOfferBalance()) + BigInt(ctx.offer!.getAmount()) - (BigInt(buyerBalancesAfter.getBalance()) + BigInt(buyerBalancesAfter.getReservedOfferBalance())); // buyer fee = total balance before + offer amount - total balance after
|
const buyerFee = BigInt(buyerBalancesBefore.getBalance()) + BigInt(buyerBalancesBefore.getReservedOfferBalance()) + BigInt(ctx.tradeAmount!) - (BigInt(buyerBalancesAfter.getBalance()) + BigInt(buyerBalancesAfter.getReservedOfferBalance())); // buyer fee = total balance before + trade amount - total balance after
|
||||||
const sellerFee = BigInt(sellerBalancesBefore.getBalance()) + BigInt(sellerBalancesBefore.getReservedOfferBalance()) - BigInt(ctx.offer!.getAmount()) - (BigInt(sellerBalancesAfter.getBalance()) + BigInt(sellerBalancesAfter.getReservedOfferBalance())); // seller fee = total balance before - offer amount - total balance after
|
const sellerFee = BigInt(sellerBalancesBefore.getBalance()) + BigInt(sellerBalancesBefore.getReservedOfferBalance()) - BigInt(ctx.tradeAmount!) - (BigInt(sellerBalancesAfter.getBalance()) + BigInt(sellerBalancesAfter.getReservedOfferBalance())); // seller fee = total balance before - trade amount - total balance after
|
||||||
expect(buyerFee).toBeLessThanOrEqual(TestConfig.maxFee);
|
expect(buyerFee).toBeLessThanOrEqual(TestConfig.maxFee);
|
||||||
expect(buyerFee).toBeGreaterThan(BigInt("0"));
|
expect(buyerFee).toBeGreaterThan(BigInt("0"));
|
||||||
expect(sellerFee).toBeLessThanOrEqual(TestConfig.maxFee);
|
expect(sellerFee).toBeLessThanOrEqual(TestConfig.maxFee);
|
||||||
@ -2270,7 +2277,7 @@ async function makeOffer(ctx?: TradeContext): Promise<OfferInfo> {
|
|||||||
Object.assign(ctx, TestConfig.trade, Object.assign({}, ctx));
|
Object.assign(ctx, TestConfig.trade, Object.assign({}, ctx));
|
||||||
|
|
||||||
// wait for unlocked balance
|
// wait for unlocked balance
|
||||||
if (!ctx.concurrentTrades && ctx.awaitFundsToMakeOffer) await waitForAvailableBalance(ctx.amount! * BigInt("2"), ctx.maker);
|
if (!ctx.concurrentTrades && ctx.awaitFundsToMakeOffer) await waitForAvailableBalance(ctx.offerAmount! * BigInt("2"), ctx.maker);
|
||||||
|
|
||||||
// create payment account if not given // TODO: re-use existing payment account
|
// create payment account if not given // TODO: re-use existing payment account
|
||||||
if (!ctx.makerPaymentAccountId) ctx.makerPaymentAccountId = (await createPaymentAccount(ctx.maker!, ctx.assetCode!)).getId();
|
if (!ctx.makerPaymentAccountId) ctx.makerPaymentAccountId = (await createPaymentAccount(ctx.maker!, ctx.assetCode!)).getId();
|
||||||
@ -2287,14 +2294,14 @@ async function makeOffer(ctx?: TradeContext): Promise<OfferInfo> {
|
|||||||
// post offer
|
// post offer
|
||||||
const offer: OfferInfo = await ctx.maker!.postOffer(
|
const offer: OfferInfo = await ctx.maker!.postOffer(
|
||||||
ctx.direction!,
|
ctx.direction!,
|
||||||
ctx.amount!,
|
ctx.offerAmount!,
|
||||||
ctx.assetCode!,
|
ctx.assetCode!,
|
||||||
ctx.makerPaymentAccountId!,
|
ctx.makerPaymentAccountId!,
|
||||||
ctx.buyerSecurityDepositPct!,
|
ctx.buyerSecurityDepositPct!,
|
||||||
ctx.price,
|
ctx.price,
|
||||||
ctx.priceMargin,
|
ctx.priceMargin,
|
||||||
ctx.triggerPrice,
|
ctx.triggerPrice,
|
||||||
ctx.minAmount);
|
ctx.offerMinAmount);
|
||||||
testOffer(offer, ctx);
|
testOffer(offer, ctx);
|
||||||
|
|
||||||
// offer is included in my offers only
|
// offer is included in my offers only
|
||||||
@ -2336,7 +2343,7 @@ async function takeOffer(ctx: TradeContext): Promise<TradeInfo> {
|
|||||||
expect(takerOffer.getState()).toEqual("UNKNOWN"); // TODO: offer state should be known
|
expect(takerOffer.getState()).toEqual("UNKNOWN"); // TODO: offer state should be known
|
||||||
|
|
||||||
// wait for unlocked balance
|
// wait for unlocked balance
|
||||||
if (ctx.awaitFundsToTakeOffer) await waitForAvailableBalance(ctx.amount! * BigInt("2"), ctx.taker);
|
if (ctx.awaitFundsToTakeOffer) await waitForAvailableBalance(ctx.offerAmount! * BigInt("2"), ctx.taker);
|
||||||
|
|
||||||
// create payment account if not given // TODO: re-use existing payment account
|
// create payment account if not given // TODO: re-use existing payment account
|
||||||
if (!ctx.takerPaymentAccountId) ctx.takerPaymentAccountId = (await createPaymentAccount(ctx.taker!, ctx.assetCode!)).getId();
|
if (!ctx.takerPaymentAccountId) ctx.takerPaymentAccountId = (await createPaymentAccount(ctx.taker!, ctx.assetCode!)).getId();
|
||||||
@ -2351,9 +2358,12 @@ async function takeOffer(ctx: TradeContext): Promise<TradeInfo> {
|
|||||||
const takerBalancesBefore: XmrBalanceInfo = await ctx.taker!.getBalances();
|
const takerBalancesBefore: XmrBalanceInfo = await ctx.taker!.getBalances();
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
HavenoUtils.log(1, "Taking offer " + ctx.offerId);
|
HavenoUtils.log(1, "Taking offer " + ctx.offerId);
|
||||||
const trade = await ctx.taker!.takeOffer(ctx.offerId, ctx.takerPaymentAccountId!);
|
const trade = await ctx.taker!.takeOffer(ctx.offerId, ctx.takerPaymentAccountId!, ctx.tradeAmount);
|
||||||
HavenoUtils.log(1, "Done taking offer " + ctx.offerId + " in " + (Date.now() - startTime) + " ms");
|
HavenoUtils.log(1, "Done taking offer " + ctx.offerId + " in " + (Date.now() - startTime) + " ms");
|
||||||
|
|
||||||
|
// assign expected trade amount
|
||||||
|
if (!ctx.tradeAmount) ctx.tradeAmount = ctx.offerAmount;
|
||||||
|
|
||||||
// test taker's balances after taking trade
|
// test taker's balances after taking trade
|
||||||
if (!ctx.concurrentTrades) {
|
if (!ctx.concurrentTrades) {
|
||||||
const takerBalancesAfter: XmrBalanceInfo = await ctx.taker!.getBalances();
|
const takerBalancesAfter: XmrBalanceInfo = await ctx.taker!.getBalances();
|
||||||
@ -2374,6 +2384,7 @@ async function takeOffer(ctx: TradeContext): Promise<TradeInfo> {
|
|||||||
// taker can get trade
|
// taker can get trade
|
||||||
let fetchedTrade: TradeInfo = await ctx.taker!.getTrade(trade.getTradeId());
|
let fetchedTrade: TradeInfo = await ctx.taker!.getTrade(trade.getTradeId());
|
||||||
assert(GenUtils.arrayContains(["DEPOSITS_PUBLISHED", "DEPOSITS_CONFIRMED", "DEPOSITS_UNLOCKED"], fetchedTrade.getPhase()), "Unexpected trade phase: " + fetchedTrade.getPhase());
|
assert(GenUtils.arrayContains(["DEPOSITS_PUBLISHED", "DEPOSITS_CONFIRMED", "DEPOSITS_UNLOCKED"], fetchedTrade.getPhase()), "Unexpected trade phase: " + fetchedTrade.getPhase());
|
||||||
|
expect(BigInt(fetchedTrade.getAmount())).toEqual(ctx.tradeAmount ? ctx.tradeAmount : ctx.offerAmount);
|
||||||
// TODO: test fetched trade
|
// TODO: test fetched trade
|
||||||
|
|
||||||
// taker is notified of balance change
|
// taker is notified of balance change
|
||||||
|
@ -1046,13 +1046,18 @@ export default class HavenoClient {
|
|||||||
*
|
*
|
||||||
* @param {string} offerId - id of the offer to take
|
* @param {string} offerId - id of the offer to take
|
||||||
* @param {string} paymentAccountId - id of the payment account
|
* @param {string} paymentAccountId - id of the payment account
|
||||||
|
* @param {bigint|undefined} amount - amount the taker chooses to buy or sell within the offer range (default is max offer amount)
|
||||||
* @return {TradeInfo} the initialized trade
|
* @return {TradeInfo} the initialized trade
|
||||||
*/
|
*/
|
||||||
async takeOffer(offerId: string, paymentAccountId: string): Promise<TradeInfo> {
|
async takeOffer(offerId: string,
|
||||||
|
paymentAccountId: string,
|
||||||
|
amount?: bigint): Promise<TradeInfo> {
|
||||||
try {
|
try {
|
||||||
const request = new TakeOfferRequest()
|
const request = new TakeOfferRequest()
|
||||||
.setOfferId(offerId)
|
.setOfferId(offerId)
|
||||||
.setPaymentAccountId(paymentAccountId);
|
.setPaymentAccountId(paymentAccountId);
|
||||||
|
if (amount) request.setAmount(amount.toString());
|
||||||
|
HavenoUtils.log(0, "Taking offer with taker amount: " + amount);
|
||||||
return (await this._tradesClient.takeOffer(request, {password: this._password})).getTrade()!;
|
return (await this._tradesClient.takeOffer(request, {password: this._password})).getTrade()!;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw new HavenoError(e.message, e.code);
|
throw new HavenoError(e.message, e.code);
|
||||||
|
@ -147,7 +147,7 @@ export default class HavenoUtils {
|
|||||||
* @param {number|string} amountXmr - amount in XMR to convert to atomic units
|
* @param {number|string} amountXmr - amount in XMR to convert to atomic units
|
||||||
* @return {BigInt} amount in atomic units
|
* @return {BigInt} amount in atomic units
|
||||||
*/
|
*/
|
||||||
static xmrToAtomicUnits(amountXmr: number|string): BigInt {
|
static xmrToAtomicUnits(amountXmr: number|string): bigint {
|
||||||
if (typeof amountXmr === "number") amountXmr = "" + amountXmr;
|
if (typeof amountXmr === "number") amountXmr = "" + amountXmr;
|
||||||
else if (typeof amountXmr !== "string") throw new Error("Must provide XMR amount as a string or js number to convert to atomic units");
|
else if (typeof amountXmr !== "string") throw new Error("Must provide XMR amount as a string or js number to convert to atomic units");
|
||||||
let decimalDivisor = 1;
|
let decimalDivisor = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user