Skip to content

Commit b913469

Browse files
committed
Merge branch 'master' of github.com:wavesplatform/data-service into release/v0.34.0
2 parents 5140017 + e6febfe commit b913469

File tree

10 files changed

+171
-70
lines changed

10 files changed

+171
-70
lines changed

src/daemons/candles/sql/query.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,14 @@ const selectExchanges = pg({ t: 'txs_7' }).select({
6262
height: 't.height',
6363
candle_time: pgRawDateTrunc('t.time_stamp')('minute'),
6464
amount: 't.amount',
65-
price: 't.price',
65+
price: pg.raw(`
66+
CASE WHEN t.tx_version > 2
67+
THEN t.price::numeric
68+
* 10^(select decimals from assets where asset_id = t.price_asset_id)
69+
* 10^(select -decimals from assets where asset_id = t.amount_asset_id)
70+
ELSE t.price::numeric
71+
END
72+
`),
6673
});
6774

6875
/** selectExchangesAfterTimestamp :: Date -> QueryBuilder */

src/daemons/pairs/sql/fillTable.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ const selectExchanges = pg({ t: 'txs_7' })
77
amount_asset_id: 't.amount_asset_id',
88
price_asset_id: 't.price_asset_id',
99
amount: 't.amount',
10-
price: 't.price',
10+
price: pg.raw(`
11+
CASE WHEN t.tx_version > 2
12+
THEN t.price::numeric
13+
* 10^(select decimals from assets where asset_id = t.price_asset_id)
14+
* 10^(select -decimals from assets where asset_id = t.amount_asset_id)
15+
ELSE t.price::numeric
16+
END
17+
`),
1118
time_stamp: 't.time_stamp',
1219
sender: 't.sender',
1320
})

src/services/transactions/burn/repo/sql/query.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const pg = require('knex')({ client: 'pg' });
22

3-
const select = pg({ t: 'txs_6' }).select('*');
3+
const select = pg({ t: 'txs_6' });
44

55
const selectFromFiltered = (filtered) =>
66
filtered.select({
Lines changed: 109 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,119 @@
11
import { Task } from 'folktale/concurrency/task';
2-
import { defaultTo, splitEvery, zipWith } from 'ramda';
2+
import { defaultTo, zipObj } from 'ramda';
33
import { AppError } from '../../../errorHandling';
44
import { AssetsService } from '../../assets';
5-
import { ExchangeTx, OrderType } from './repo/types';
5+
import { ExchangeTx, OrderPriceMode, OrderType } from './repo/types';
66

77
const wavesByDefault = defaultTo('WAVES');
88

9-
export const modifyDecimals = (assetsService: AssetsService) => (
10-
txs: ExchangeTx[]
11-
): Task<AppError, ExchangeTx[]> =>
12-
assetsService
13-
.precisions({
14-
ids: txs
15-
.map((tx) => [
16-
wavesByDefault(tx.feeAsset),
17-
wavesByDefault(tx.order1.assetPair.amountAsset),
18-
wavesByDefault(tx.order1.assetPair.priceAsset),
19-
tx.order1.orderType === OrderType.Buy
20-
? wavesByDefault(tx.order1.matcherFeeAssetId)
21-
: wavesByDefault(tx.order2.matcherFeeAssetId),
22-
tx.order1.orderType === OrderType.Sell
23-
? wavesByDefault(tx.order1.matcherFeeAssetId)
24-
: wavesByDefault(tx.order2.matcherFeeAssetId),
25-
wavesByDefault(tx.order1.matcherFeeAssetId),
26-
wavesByDefault(tx.order2.matcherFeeAssetId),
27-
])
28-
.reduce((acc, cur) => acc.concat(cur), []),
29-
})
30-
.map((v: number[]) =>
31-
zipWith(
32-
(
33-
tx,
9+
export const modifyDecimals =
10+
(assetsService: AssetsService) =>
11+
(txs: ExchangeTx[]): Task<AppError, ExchangeTx[]> => {
12+
// extract unique assetIds participating in provided transactions
13+
const participatingAssetIds = Array.from(
14+
txs.reduce(
15+
(assetIds, tx) =>
3416
[
35-
feePrecision,
36-
amountPrecision,
37-
pricePrecision,
38-
buyMatcherFeePrecision,
39-
sellMatcherFeePrecision,
40-
order1MatcherFeePrecision,
41-
order2MatcherFeePrecision,
17+
tx.feeAsset,
18+
tx.order1.assetPair.amountAsset,
19+
tx.order1.assetPair.priceAsset,
20+
tx.order1.matcherFeeAssetId,
21+
tx.order2.matcherFeeAssetId,
4222
]
43-
) => ({
44-
...tx,
45-
fee: tx.fee.shiftedBy(-feePrecision),
46-
amount: tx.amount.shiftedBy(-amountPrecision),
47-
price: tx.price.shiftedBy(-8 - pricePrecision + amountPrecision),
48-
buyMatcherFee: tx.buyMatcherFee.shiftedBy(-buyMatcherFeePrecision),
49-
sellMatcherFee: tx.sellMatcherFee.shiftedBy(-sellMatcherFeePrecision),
50-
order1: {
51-
...tx.order1,
52-
amount: tx.order1.amount.shiftedBy(-amountPrecision),
53-
price: tx.order1.price.shiftedBy(-8 - pricePrecision + amountPrecision),
54-
matcherFee: tx.order1.matcherFee.shiftedBy(-order1MatcherFeePrecision),
55-
},
56-
order2: {
57-
...tx.order2,
58-
amount: tx.order2.amount.shiftedBy(-amountPrecision),
59-
price: tx.order2.price.shiftedBy(-8 - pricePrecision + amountPrecision),
60-
matcherFee: tx.order2.matcherFee.shiftedBy(-order2MatcherFeePrecision),
61-
}
62-
})
63-
,
64-
txs,
65-
splitEvery(v.length / txs.length, v)
23+
.map(wavesByDefault)
24+
.reduce((set, id) => set.add(id), assetIds),
25+
new Set<string>()
6626
)
6727
);
28+
29+
return assetsService
30+
.precisions({ ids: participatingAssetIds })
31+
.map(zipObj(participatingAssetIds))
32+
.map((precisionsMap) => {
33+
const p = (assetId: string | null | undefined): number =>
34+
precisionsMap[wavesByDefault(assetId)];
35+
36+
return txs.map((tx) => {
37+
const feePrecision = p(tx.feeAsset);
38+
39+
const amountAssetPrecision = p(tx.order1.assetPair.amountAsset);
40+
const priceAssetPrecision = p(tx.order1.assetPair.priceAsset);
41+
42+
// exchange v3 support
43+
const txPricePrecision =
44+
!tx.version || tx.version < 3
45+
? 8 + priceAssetPrecision - amountAssetPrecision
46+
: 8;
47+
48+
const order1MatcherFeePrecision = p(tx.order1.matcherFeeAssetId);
49+
// order v4 price mode support
50+
const order1PricePrecision =
51+
tx.order1.version < 4 || tx.order1.priceMode === OrderPriceMode.AssetDecimals
52+
? 8 + priceAssetPrecision - amountAssetPrecision
53+
: 8;
54+
55+
const order2MatcherFeePrecision = p(tx.order2.matcherFeeAssetId);
56+
// order v4 price mode support
57+
const order2PricePrecision =
58+
tx.order2.version < 4 || tx.order2.priceMode === OrderPriceMode.AssetDecimals
59+
? 8 + priceAssetPrecision - amountAssetPrecision
60+
: 8;
61+
62+
const buyMatcherFeePrecision =
63+
tx.order1.orderType === OrderType.Buy
64+
? order1MatcherFeePrecision
65+
: order2MatcherFeePrecision;
66+
67+
const sellMatcherFeePrecision =
68+
tx.order1.orderType === OrderType.Sell
69+
? order1MatcherFeePrecision
70+
: order2MatcherFeePrecision;
71+
72+
console.log(
73+
JSON.stringify({
74+
event: {
75+
name: 'EXCHANGE_TRANSACTION_DECIMALS',
76+
txId: tx.id,
77+
txVersion: tx.version,
78+
amountAssetPrecision,
79+
priceAssetPrecision,
80+
txPricePrecision: txPricePrecision,
81+
txFeePrecision: feePrecision,
82+
buyMatcherFeePrecision,
83+
sellMatcherFeePrecision,
84+
order1Version: tx.order1.version,
85+
order1PriceMode: tx.order1.priceMode,
86+
order1MatcherFeePrecision,
87+
order1PricePrecision,
88+
order2Version: tx.order2.version,
89+
order2PriceMode: tx.order2.priceMode,
90+
order2MatcherFeePrecision,
91+
order2PricePrecision,
92+
},
93+
timestamp: new Date().toISOString(),
94+
})
95+
);
96+
97+
return {
98+
...tx,
99+
fee: tx.fee.shiftedBy(-feePrecision),
100+
amount: tx.amount.shiftedBy(-amountAssetPrecision),
101+
price: tx.price.shiftedBy(-txPricePrecision),
102+
buyMatcherFee: tx.buyMatcherFee.shiftedBy(-buyMatcherFeePrecision),
103+
sellMatcherFee: tx.sellMatcherFee.shiftedBy(-sellMatcherFeePrecision),
104+
order1: {
105+
...tx.order1,
106+
amount: tx.order1.amount.shiftedBy(-amountAssetPrecision),
107+
price: tx.order1.price.shiftedBy(-order1PricePrecision),
108+
matcherFee: tx.order1.matcherFee.shiftedBy(-order1MatcherFeePrecision),
109+
},
110+
order2: {
111+
...tx.order2,
112+
amount: tx.order2.amount.shiftedBy(-amountAssetPrecision),
113+
price: tx.order2.price.shiftedBy(-order2PricePrecision),
114+
matcherFee: tx.order2.matcherFee.shiftedBy(-order2MatcherFeePrecision),
115+
},
116+
};
117+
});
118+
});
119+
};

src/services/transactions/exchange/repo/schema.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Joi } from '../../../../utils/validation';
2-
32
import commonFields from '../../_common/commonFieldsSchemas';
3+
import { OrderPriceMode, OrderType } from './types';
44

55
const orderTypes = (prefix: string) => ({
66
[`${prefix}_id`]: Joi.string()
@@ -11,7 +11,7 @@ const orderTypes = (prefix: string) => ({
1111
.required()
1212
.allow(null),
1313
[`${prefix}_type`]: Joi.string()
14-
.noNullChars()
14+
.valid(OrderType.Buy, OrderType.Sell)
1515
.required(),
1616
[`${prefix}_sender`]: Joi.string()
1717
.base58()
@@ -21,8 +21,8 @@ const orderTypes = (prefix: string) => ({
2121
.required(),
2222
[`${prefix}_signature`]: Joi.string()
2323
.base58()
24-
.allow('')
25-
.required(),
24+
.required()
25+
.allow(""),
2626
[`${prefix}_matcher_fee`]: Joi.object()
2727
.bignumber()
2828
.required(),
@@ -41,6 +41,12 @@ const orderTypes = (prefix: string) => ({
4141
[`${prefix}_matcher_fee_asset_id`]: Joi.string()
4242
.assetId()
4343
.allow(null),
44+
[`${prefix}_eip712signature`]: Joi.string()
45+
.eip712Signature()
46+
.allow(null),
47+
[`${prefix}_price_mode`]: Joi.string()
48+
.valid(OrderPriceMode.AssetDecimals, OrderPriceMode.FixedDecimals)
49+
.allow(null),
4450
});
4551

4652
export const result = Joi.object().keys({

src/services/transactions/exchange/repo/sql/query.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ const columns = {
3737
o1_amount: pg.raw("(t.order1->>'amount')::double precision"),
3838
o1_matcher_fee: pg.raw("(t.order1->>'matcherFee')::double precision"),
3939
o1_matcher_fee_asset_id: pg.raw("t.order1->>'matcherFeeAssetId'"),
40-
40+
o1_price_mode: pg.raw("t.order1->>'priceMode'"),
41+
o1_eip712signature: pg.raw("t.order1->>'eip712Signature'"),
42+
4143
o2_id: pg.raw("t.order2->>'id'"),
4244
o2_version: pg.raw("t.order2->>'version'"),
4345
o2_time_stamp: pg.raw("text_timestamp_cast(t.order2->>'timestamp')"),
@@ -50,6 +52,8 @@ const columns = {
5052
o2_amount: pg.raw("(t.order2->>'amount')::double precision"),
5153
o2_matcher_fee: pg.raw("(t.order2->>'matcherFee')::double precision"),
5254
o2_matcher_fee_asset_id: pg.raw("t.order2->>'matcherFeeAssetId'"),
55+
o2_price_mode: pg.raw("t.order2->>'priceMode'"),
56+
o2_eip712signature: pg.raw("t.order2->>'eip712Signature'"),
5357
};
5458

5559
const select = pg({ t: 'txs_7' });

src/services/transactions/exchange/repo/transformTxInfo.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ExchangeTx, ExchangeTxDbResponse } from './types';
88

99
const createOrder = (prefix: string) => <T extends Record<string, any>>({
1010
[`${prefix}_id`]: id,
11-
[`${prefix}_version`]: version,
11+
[`${prefix}_version`]: versionStr,
1212
[`${prefix}_sender_public_key`]: senderPublicKey,
1313
[`${prefix}_sender`]: sender,
1414
[`${prefix}_type`]: orderType,
@@ -19,12 +19,17 @@ const createOrder = (prefix: string) => <T extends Record<string, any>>({
1919
[`${prefix}_signature`]: signature,
2020
[`${prefix}_matcher_fee`]: matcherFee,
2121
[`${prefix}_matcher_fee_asset_id`]: matcherFeeAssetId,
22+
[`${prefix}_price_mode`]: priceMode,
23+
[`${prefix}_eip712signature`]: eip712Signature,
2224
price_asset: priceAsset,
2325
amount_asset: amountAsset,
2426
sender_public_key: matcherPublicKey,
2527
}: T) => {
26-
const tx = {
28+
const version = parseInt(versionStr) || 1;
29+
30+
const o: any = {
2731
id,
32+
version,
2833
senderPublicKey,
2934
matcherPublicKey,
3035
assetPair: {
@@ -40,7 +45,15 @@ const createOrder = (prefix: string) => <T extends Record<string, any>>({
4045
matcherFee,
4146
signature,
4247
};
43-
return version === '3' ? { ...tx, matcherFeeAssetId } : tx;
48+
49+
if (version > 2) o.matcherFeeAssetId = matcherFeeAssetId;
50+
51+
if (version > 3) {
52+
o.priceMode = priceMode;
53+
o.eip712Signature = eip712Signature;
54+
}
55+
56+
return o;
4457
};
4558

4659
type ExchangeTxFields = {

src/services/transactions/exchange/repo/types.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,19 @@ export type ExchangeTxDbResponse = RawTx & {
3939
o2_matcher_fee_asset_id: string;
4040
};
4141

42+
export enum OrderPriceMode {
43+
AssetDecimals = 'assetDecimals',
44+
FixedDecimals = 'fixedDecimals',
45+
}
46+
4247
export enum OrderType {
4348
Buy = 'buy',
4449
Sell = 'sell',
4550
}
4651

4752
type Order = {
4853
id: string;
49-
version: string;
54+
version: number;
5055
orderType: OrderType;
5156
sender: string;
5257
senderPublicKey: string;
@@ -60,7 +65,9 @@ type Order = {
6065
assetPair: {
6166
amountAsset: string;
6267
priceAsset: string;
63-
}
68+
},
69+
eip712Signature?: string | null;
70+
priceMode?: OrderPriceMode | null;
6471
};
6572

6673
export type ExchangeTx = Tx & {

src/utils/regex.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const interval: RegExp = /^\d+[smhdwMY]$/;
44
export const base58: RegExp = new RegExp(`^${base58Chars}$`);
55
export const assetId: RegExp = new RegExp(`^(?:WAVES|${base58Chars})$`);
66
export const noNullChars: RegExp = /^[^\x00]*$/;
7+
export const eip712Signature: RegExp = /^0x([A-Fa-f0-9])*$/;
78

89
// string doesn't have dangding unescaped slash at the end
910
export const saneForDbLike: RegExp = /^(?:.*[^\\])?(?:\\\\)*$/;

src/utils/validation/joi.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module.exports = rawJoi
3333
base64Prefixed: 'must be a string of "base64:${base64EncodedString}"',
3434
noNullChars: 'must not contain unicode null characters',
3535
saneForDbLike: 'must not end with unescaped slash symbol',
36+
eip712Signature: 'must be a hex-encoded string starting with `0x`',
3637
pair: 'must be a valid pair string',
3738
period: {
3839
value: 'interval must be a valid interval value',
@@ -59,6 +60,9 @@ module.exports = rawJoi
5960
{ regex: regex.saneForDbLike, errorCode: 'string.saneForDbLike' },
6061
{ regex: regex.noNullChars, errorCode: 'string.noNullChars' },
6162
]),
63+
regexRule(joi, 'eip712Signature', [
64+
{ regex: regex.eip712Signature, errorCode: 'string.eip712Signature' },
65+
]),
6266
{
6367
name: 'base64Prefixed',
6468
validate(_, value, state, options) {

0 commit comments

Comments
 (0)