aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/stale.yml19
-rw-r--r--packages/contracts/CHANGELOG.json10
-rw-r--r--packages/contracts/contracts/extensions/OrderValidator/OrderValidator.sol2
-rw-r--r--packages/contracts/test/extensions/order_validator.ts13
-rw-r--r--packages/instant/package.json1
-rw-r--r--packages/instant/src/components/erc20_token_selector.tsx2
-rw-r--r--packages/instant/src/components/zero_ex_instant_container.tsx23
-rw-r--r--packages/instant/src/components/zero_ex_instant_provider.tsx1
-rw-r--r--packages/instant/src/redux/analytics_middleware.ts24
-rw-r--r--packages/instant/src/util/analytics.ts28
10 files changed, 106 insertions, 17 deletions
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 000000000..af12c62d5
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,19 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 30
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 7
+# Issues with these labels will never be considered stale
+exemptLabels:
+ - pinned
+ - security
+# Label to use when marking an issue as stale
+staleLabel: stale
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no further activity occurs. Thank you
+ for your contributions.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: >
+ This issue has been automatically closed because no activity occured in 7 days after being marked as stale. If it's still relevant - feel free to reopen. Thank you
+ for your contributions.
diff --git a/packages/contracts/CHANGELOG.json b/packages/contracts/CHANGELOG.json
index 3f57a33d6..00f94c83b 100644
--- a/packages/contracts/CHANGELOG.json
+++ b/packages/contracts/CHANGELOG.json
@@ -1,5 +1,15 @@
[
{
+ "name": "OrderValidator",
+ "version": "1.0.1",
+ "changes": [
+ {
+ "note": "remove `getApproved` check from ERC721 approval query",
+ "pr": 1149
+ }
+ ]
+ },
+ {
"name": "Forwarder",
"version": "1.1.0",
"changes": [
diff --git a/packages/contracts/contracts/extensions/OrderValidator/OrderValidator.sol b/packages/contracts/contracts/extensions/OrderValidator/OrderValidator.sol
index 8bfde3847..3385d35ef 100644
--- a/packages/contracts/contracts/extensions/OrderValidator/OrderValidator.sol
+++ b/packages/contracts/contracts/extensions/OrderValidator/OrderValidator.sol
@@ -148,7 +148,7 @@ contract OrderValidator {
balance = target == owner ? 1 : 0;
// Check if ERC721Proxy is approved to spend tokenId
- bool isApproved = IERC721Token(token).isApprovedForAll(target, assetProxy) || IERC721Token(token).getApproved(tokenId) == assetProxy;
+ bool isApproved = IERC721Token(token).isApprovedForAll(target, assetProxy);
// Set alowance to 1 if ERC721Proxy is approved to spend tokenId
allowance = isApproved ? 1 : 0;
diff --git a/packages/contracts/test/extensions/order_validator.ts b/packages/contracts/test/extensions/order_validator.ts
index 37bd1b0e2..37d7c4c5a 100644
--- a/packages/contracts/test/extensions/order_validator.ts
+++ b/packages/contracts/test/extensions/order_validator.ts
@@ -198,7 +198,7 @@ describe('OrderValidator', () => {
);
expect(newAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
});
- it('should return an allowance of 1 when ERC721Proxy is approved for specific tokenId', async () => {
+ it('should return an allowance of 0 when ERC721Proxy is approved for specific tokenId', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
constants.AWAIT_TRANSACTION_MINED_MS,
@@ -213,7 +213,7 @@ describe('OrderValidator', () => {
makerAddress,
erc721AssetData,
);
- expect(newAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
+ expect(newAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
});
@@ -248,8 +248,9 @@ describe('OrderValidator', () => {
await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
constants.AWAIT_TRANSACTION_MINED_MS,
);
+ const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.approve.sendTransactionAsync(erc721Proxy.address, tokenId, {
+ await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
from: makerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
@@ -311,8 +312,9 @@ describe('OrderValidator', () => {
await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId),
constants.AWAIT_TRANSACTION_MINED_MS,
);
+ const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.approve.sendTransactionAsync(erc721Proxy.address, tokenId, {
+ await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
from: takerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
@@ -465,8 +467,9 @@ describe('OrderValidator', () => {
await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId),
constants.AWAIT_TRANSACTION_MINED_MS,
);
+ const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.approve.sendTransactionAsync(erc721Proxy.address, tokenId, {
+ await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
from: takerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
diff --git a/packages/instant/package.json b/packages/instant/package.json
index d3a85a646..4422dc83f 100644
--- a/packages/instant/package.json
+++ b/packages/instant/package.json
@@ -4,6 +4,7 @@
"engines": {
"node": ">=6.12"
},
+ "private": true,
"description": "0x Instant React Component",
"main": "lib/index.js",
"types": "lib/index.d.ts",
diff --git a/packages/instant/src/components/erc20_token_selector.tsx b/packages/instant/src/components/erc20_token_selector.tsx
index 1b1921acb..0a3d4427a 100644
--- a/packages/instant/src/components/erc20_token_selector.tsx
+++ b/packages/instant/src/components/erc20_token_selector.tsx
@@ -3,6 +3,7 @@ import * as React from 'react';
import { ColorOption } from '../style/theme';
import { ERC20Asset } from '../types';
+import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
import { SearchInput } from './search_input';
@@ -57,6 +58,7 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
this.setState({
searchQuery,
});
+ analytics.trackTokenSelectorSearched(searchQuery);
};
private readonly _isTokenQueryMatch = (token: ERC20Asset): boolean => {
const { searchQuery } = this.state;
diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx
index 47c938472..8a809ee31 100644
--- a/packages/instant/src/components/zero_ex_instant_container.tsx
+++ b/packages/instant/src/components/zero_ex_instant_container.tsx
@@ -11,21 +11,20 @@ import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_
import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading';
import { ColorOption } from '../style/theme';
import { zIndex } from '../style/z_index';
-import { OrderProcessState, SlideAnimationState } from '../types';
+import { SlideAnimationState } from '../types';
+import { analytics, TokenSelectorClosedVia } from '../util/analytics';
import { CSSReset } from './css_reset';
import { SlidingPanel } from './sliding_panel';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
-export interface ZeroExInstantContainerProps {
- orderProcessState: OrderProcessState;
-}
+export interface ZeroExInstantContainerProps {}
export interface ZeroExInstantContainerState {
tokenSelectionPanelAnimationState: SlideAnimationState;
}
-export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantContainerState> {
+export class ZeroExInstantContainer extends React.Component<ZeroExInstantContainerProps, ZeroExInstantContainerState> {
public state = {
tokenSelectionPanelAnimationState: 'none' as SlideAnimationState,
};
@@ -60,9 +59,9 @@ export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantCon
</Flex>
<SlidingPanel
animationState={this.state.tokenSelectionPanelAnimationState}
- onClose={this._handlePanelClose}
+ onClose={this._handlePanelCloseClickedX}
>
- <AvailableERC20TokenSelector onTokenSelect={this._handlePanelClose} />
+ <AvailableERC20TokenSelector onTokenSelect={this._handlePanelCloseAfterChose} />
</SlidingPanel>
<CurrentStandardSlidingPanel />
</Container>
@@ -82,11 +81,19 @@ export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantCon
);
}
private readonly _handleSymbolClick = (): void => {
+ analytics.trackTokenSelectorOpened();
this.setState({
tokenSelectionPanelAnimationState: 'slidIn',
});
};
- private readonly _handlePanelClose = (): void => {
+ private readonly _handlePanelCloseClickedX = (): void => {
+ this._handlePanelClose(TokenSelectorClosedVia.ClickedX);
+ };
+ private readonly _handlePanelCloseAfterChose = (): void => {
+ this._handlePanelClose(TokenSelectorClosedVia.TokenChose);
+ };
+ private readonly _handlePanelClose = (closedVia: TokenSelectorClosedVia): void => {
+ analytics.trackTokenSelectorClosed(closedVia);
this.setState({
tokenSelectionPanelAnimationState: 'slidOut',
});
diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx
index fe34c4466..e006a5a5f 100644
--- a/packages/instant/src/components/zero_ex_instant_provider.tsx
+++ b/packages/instant/src/components/zero_ex_instant_provider.tsx
@@ -131,6 +131,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
this.props.orderSource,
state.providerState,
window,
+ state.selectedAsset,
this.props.affiliateInfo,
),
);
diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts
index 299c2560e..8aa76eb77 100644
--- a/packages/instant/src/redux/analytics_middleware.ts
+++ b/packages/instant/src/redux/analytics_middleware.ts
@@ -53,6 +53,30 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction
).toString();
analytics.addUserProperties({ ethBalanceInUnitAmount });
}
+ break;
+ case ActionTypes.UPDATE_SELECTED_ASSET:
+ const selectedAsset = curState.selectedAsset;
+ if (selectedAsset) {
+ const assetName = selectedAsset.metaData.name;
+ const assetData = selectedAsset.assetData;
+ analytics.trackTokenSelectorChose({
+ assetName,
+ assetData,
+ });
+ analytics.addEventProperties({
+ selectedAssetName: assetName,
+ selectedAssetData: assetData,
+ });
+ }
+ break;
+ case ActionTypes.SET_AVAILABLE_ASSETS:
+ const availableAssets = curState.availableAssets;
+ if (availableAssets) {
+ analytics.addEventProperties({
+ numberAvailableAssets: availableAssets.length,
+ });
+ }
+ break;
}
return nextAction;
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
index cec99dd1b..aa0f37194 100644
--- a/packages/instant/src/util/analytics.ts
+++ b/packages/instant/src/util/analytics.ts
@@ -1,4 +1,4 @@
-import { AffiliateInfo, Network, OrderSource, ProviderState } from '../types';
+import { AffiliateInfo, Asset, Network, OrderSource, ProviderState } from '../types';
import { EventProperties, heapUtil } from './heap';
@@ -20,7 +20,12 @@ enum EventNames {
ACCOUNT_UNLOCK_REQUESTED = 'Account - Unlock Requested',
ACCOUNT_UNLOCK_DENIED = 'Account - Unlock Denied',
ACCOUNT_ADDRESS_CHANGED = 'Account - Address Changed',
+ TOKEN_SELECTOR_OPENED = 'Token Selector - Opened',
+ TOKEN_SELECTOR_CLOSED = 'Token Selector - Closed',
+ TOKEN_SELECTOR_CHOSE = 'Token Selector - Chose',
+ TOKEN_SELECTOR_SEARCHED = 'Token Selector - Searched',
}
+
const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => {
evaluateIfEnabled(() => {
heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventProperties));
@@ -52,8 +57,14 @@ export interface AnalyticsEventOptions {
orderSource?: string;
affiliateAddress?: string;
affiliateFeePercent?: number;
+ numberAvailableAssets?: number;
+ selectedAssetName?: string;
+ selectedAssetData?: string;
+}
+export enum TokenSelectorClosedVia {
+ ClickedX = 'Clicked X',
+ TokenChose = 'Token Chose',
}
-
export const analytics = {
addUserProperties: (properties: AnalyticsUserOptions): void => {
evaluateIfEnabled(() => {
@@ -70,12 +81,13 @@ export const analytics = {
orderSource: OrderSource,
providerState: ProviderState,
window: Window,
+ selectedAsset?: Asset,
affiliateInfo?: AffiliateInfo,
): AnalyticsEventOptions => {
const affiliateAddress = affiliateInfo ? affiliateInfo.feeRecipient : 'none';
const affiliateFeePercent = affiliateInfo ? parseFloat(affiliateInfo.feePercentage.toFixed(4)) : 0;
const orderSourceName = typeof orderSource === 'string' ? orderSource : 'provided';
- return {
+ const eventOptions: AnalyticsEventOptions = {
embeddedHost: window.location.host,
embeddedUrl: window.location.href,
networkId: network,
@@ -85,7 +97,10 @@ export const analytics = {
orderSource: orderSourceName,
affiliateAddress,
affiliateFeePercent,
+ selectedAssetName: selectedAsset ? selectedAsset.metaData.name : 'none',
+ selectedAssetData: selectedAsset ? selectedAsset.assetData : 'none',
};
+ return eventOptions;
},
trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED),
trackAccountLocked: trackingEventFnWithoutPayload(EventNames.ACCOUNT_LOCKED),
@@ -94,4 +109,11 @@ export const analytics = {
trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED),
trackAccountAddressChanged: (address: string) =>
trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }),
+ trackTokenSelectorOpened: trackingEventFnWithoutPayload(EventNames.TOKEN_SELECTOR_OPENED),
+ trackTokenSelectorClosed: (closedVia: TokenSelectorClosedVia) =>
+ trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CLOSED)({ closedVia }),
+ trackTokenSelectorChose: (payload: { assetName: string; assetData: string }) =>
+ trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CHOSE)(payload),
+ trackTokenSelectorSearched: (searchText: string) =>
+ trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_SEARCHED)({ searchText }),
};