diff options
author | Steve Klebanoff <steve.klebanoff@gmail.com> | 2018-11-28 02:24:12 +0800 |
---|---|---|
committer | Steve Klebanoff <steve.klebanoff@gmail.com> | 2018-11-28 02:24:12 +0800 |
commit | 4ebc561986d2d46c8b888dfffe2728b47db34959 (patch) | |
tree | 2b1059c274338f58b23994044a2aec2d3d76eafe | |
parent | e08fb72cf10f5260966e4dfd84873c326ff4ea61 (diff) | |
parent | d23fd23e912ef2ca646048e2df70e2c016ce9986 (diff) | |
download | dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.tar dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.tar.gz dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.tar.bz2 dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.tar.lz dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.tar.xz dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.tar.zst dexon-0x-contracts-4ebc561986d2d46c8b888dfffe2728b47db34959.zip |
Merge branch 'development' into feature/instant/stable-css-classes
-rw-r--r-- | .github/stale.yml | 19 | ||||
-rw-r--r-- | packages/contracts/CHANGELOG.json | 10 | ||||
-rw-r--r-- | packages/contracts/contracts/extensions/OrderValidator/OrderValidator.sol | 2 | ||||
-rw-r--r-- | packages/contracts/test/extensions/order_validator.ts | 13 | ||||
-rw-r--r-- | packages/instant/package.json | 1 | ||||
-rw-r--r-- | packages/instant/src/components/erc20_token_selector.tsx | 2 | ||||
-rw-r--r-- | packages/instant/src/components/zero_ex_instant_container.tsx | 23 | ||||
-rw-r--r-- | packages/instant/src/components/zero_ex_instant_provider.tsx | 1 | ||||
-rw-r--r-- | packages/instant/src/redux/analytics_middleware.ts | 24 | ||||
-rw-r--r-- | packages/instant/src/util/analytics.ts | 28 |
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 }), }; |