Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
feat: added a unique identifier to the quote within the timestamp met…
Browse files Browse the repository at this point in the history
…adata … (#281)

* Added a unique identifier to the quote within the timestamp metadata field

* Added unit test for affiliate data generation, other nits

* prettier 🤦
  • Loading branch information
alexkroeger authored Jul 31, 2020
1 parent 56f7a90 commit d992563
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const ONE_SECOND_MS = 1000;
export const ONE_MINUTE_MS = ONE_SECOND_MS * 60;
export const TEN_MINUTES_MS = ONE_MINUTE_MS * 10;
export const DEFAULT_VALIDATION_GAS_LIMIT = 10e6;
export const HEX_BASE = 16;

// The number of orders to post to Mesh at one time
export const MESH_ORDERS_BATCH_SIZE = 200;
Expand Down
19 changes: 19 additions & 0 deletions src/utils/number_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const numberUtils = {
// from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
randomNumberInclusive: (minimumSpecified: number, maximumSpecified: number): number => {
const min = Math.ceil(minimumSpecified);
const max = Math.floor(maximumSpecified);
return Math.floor(Math.random() * (max - min + 1)) + min; // The maximum is inclusive and the minimum is inclusive
},
// creates a random hex number of desired length by stringing together
// random integers from 1-15, guaranteeing the
// result is a hex number of the given length
randomHexNumberOfLength: (numberLength: number): string => {
let res = '';
for (let i = 0; i < numberLength; i++) {
// tslint:disable-next-line:custom-no-magic-numbers
res = `${res}${numberUtils.randomNumberInclusive(1, 15).toString(16)}`;
}
return res;
},
};
19 changes: 17 additions & 2 deletions src/utils/service_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
GAS_BURN_REFUND,
GST_DIVISOR,
GST_INTERACTION_COST,
HEX_BASE,
ONE_SECOND_MS,
PERCENTAGE_SIG_DIGITS,
SSTORE_COST,
Expand All @@ -29,6 +30,8 @@ import { GasTokenRefundInfo, GetSwapQuoteResponseLiquiditySource } from '../type
import { orderUtils } from '../utils/order_utils';
import { findTokenDecimalsIfExists } from '../utils/token_metadata_utils';

import { numberUtils } from './number_utils';

export const serviceUtils = {
attributeSwapQuoteOrders(
swapQuote: MarketSellSwapQuote | MarketBuySwapQuote,
Expand Down Expand Up @@ -69,8 +72,20 @@ export const serviceUtils = {
stateMutability: 'view',
type: 'function',
});
const timestamp = new BigNumber(Date.now() / ONE_SECOND_MS).integerValue();
const encodedAffiliateData = affiliateCallDataEncoder.encode([affiliateAddressOrDefault, timestamp]);

// Generate unique identiifer
const timestampInSeconds = new BigNumber(Date.now() / ONE_SECOND_MS).integerValue();
const hexTimestamp = timestampInSeconds.toString(HEX_BASE);
const randomNumber = numberUtils.randomHexNumberOfLength(10);

// Concatenate the hex identifier with the hex timestamp
// In the final encoded call data, this will leave us with a 5-byte ID followed by
// a 4-byte timestamp, and won't break parsers of the timestamp made prior to the
// addition of the ID
const uniqueIdentifier = new BigNumber(`${randomNumber}${hexTimestamp}`, HEX_BASE);

// Encode additional call data and return
const encodedAffiliateData = affiliateCallDataEncoder.encode([affiliateAddressOrDefault, uniqueIdentifier]);
const affiliatedData = `${data}${encodedAffiliateData.slice(2)}`;
return affiliatedData;
},
Expand Down
1 change: 1 addition & 0 deletions test/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export const SYMBOL_TO_ADDRESS: ObjectMap<string> = {
ZRX: ZRX_TOKEN_ADDRESS,
WETH: WETH_TOKEN_ADDRESS,
};
export const AFFILIATE_DATA_SELECTOR = '869584cd';
24 changes: 23 additions & 1 deletion test/service_utils_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'mocha';
import { ZERO } from '../src/constants';
import { serviceUtils } from '../src/utils/service_utils';

import { MAX_INT } from './constants';
import { AFFILIATE_DATA_SELECTOR, MAX_INT } from './constants';

const SUITE_NAME = 'serviceUtils test';

Expand Down Expand Up @@ -68,4 +68,26 @@ describe(SUITE_NAME, () => {
expect(gasTokenGasCost.toNumber()).to.be.eq(0);
});
});
describe('attributeCallData', () => {
it('it returns a reasonable ID and timestamp', () => {
const fakeCallData = '0x0000000000000';
const fakeAffiliate = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
const attributedCallData = serviceUtils.attributeCallData(fakeCallData, fakeAffiliate);
const currentTime = new Date();

// parse out items from call data to ensure they are reasonable values
const selectorPos = attributedCallData.indexOf(AFFILIATE_DATA_SELECTOR);
const affiliateAddress = '0x'.concat(attributedCallData.substring(selectorPos + 32, selectorPos + 72));
const randomId = attributedCallData.substring(selectorPos + 118, selectorPos + 128);
const timestampFromCallDataHex = attributedCallData.substring(selectorPos + 128, selectorPos + 136);
const timestampFromCallData = parseInt(timestampFromCallDataHex, 16);

expect(affiliateAddress).to.be.eq(fakeAffiliate);
// call data timestamp is within 3 seconds of timestamp created during test
expect(timestampFromCallData).to.be.greaterThan(currentTime.getTime() / 1000 - 3);
expect(timestampFromCallData).to.be.lessThan(currentTime.getTime() / 1000 + 3);
// ID is a 10-digit hex number
expect(randomId).to.match(/[0-9A-Fa-f]{10}/);
});
});
});

0 comments on commit d992563

Please sign in to comment.