Skip to content

Commit

Permalink
fix: Wert enhancements (#3066)
Browse files Browse the repository at this point in the history
* fix: Update price extra

* fix: Fetch rarities before opening modal

* fix: Lint

* fix: Update readme
  • Loading branch information
fzavalia authored Mar 28, 2024
1 parent e92d3d1 commit f9527a4
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 97 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ Here are the basic requirements to run the project:
NODE_PATH=src
```

120 changes: 33 additions & 87 deletions src/modules/collection/sagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { sendTransaction } from 'decentraland-dapps/dist/modules/wallet/utils'
import { getChainIdByNetwork } from 'decentraland-dapps/dist/lib/eth'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { getOpenModals } from 'decentraland-dapps/dist/modules/modal/selectors'
import { getProfileOfAddress } from 'decentraland-dapps/dist/modules/profile'
import { config } from 'config'
import { locations } from 'routing/locations'
import { ApprovalFlowModalMetadata, ApprovalFlowModalView } from 'components/Modals/ApprovalFlowModal/ApprovalFlowModal.types'
Expand All @@ -22,8 +21,7 @@ import {
getData as getItemsById,
getPaginationData,
getWalletItems,
getCollectionItems,
getRarities
getCollectionItems
} from 'modules/item/selectors'
import { getName } from 'modules/profile/selectors'
import { buildItemEntity, buildStandardWearableContentHash } from 'modules/item/export'
Expand All @@ -42,7 +40,12 @@ import {
saveMultipleItemsSuccess,
SAVE_ITEM_FAILURE,
SAVE_ITEM_SUCCESS,
setItemsTokenIdRequest
setItemsTokenIdRequest,
fetchRaritiesRequest,
FETCH_RARITIES_SUCCESS,
FETCH_RARITIES_FAILURE,
FetchRaritiesFailureAction,
FetchRaritiesSuccessAction
} from 'modules/item/actions'
import { deployEntitiesFailure, deployEntitiesSuccess } from 'modules/entity/actions'
import {
Expand Down Expand Up @@ -2109,11 +2112,7 @@ describe('when publishing a collection with fiat', () => {
wertEnv = 'dev'
})

describe('when there are no rarities', () => {
beforeEach(() => {
rarities = []
})

describe('when fetching rarities fails', () => {
it('should dispatch a failure action', () => {
return expectSaga(collectionSaga, mockBuilder, mockBuilderClient)
.provide([
Expand All @@ -2122,18 +2121,22 @@ describe('when publishing a collection with fiat', () => {
[call(getChainIdByNetwork, Network.MATIC), ChainId.MATIC_MUMBAI],
[retry(10, 500, mockBuilder.saveTOS, collection, email), undefined],
[call([config, config.get], 'WERT_PUBLISH_FEES_ENV'), wertEnv],
[select(getRarities), rarities]
[put(fetchRaritiesRequest()), undefined],
[
race({ success: take(FETCH_RARITIES_SUCCESS), failure: take(FETCH_RARITIES_FAILURE) }),
{ failure: { payload: { error: 'error' } } as FetchRaritiesFailureAction }
]
])
.dispatch(publishCollectionRequest(collection, items, email, subscribeToNewsletter, paymentMethod))
.put(publishCollectionFailure(collection, items, 'Rarity not found'))
.put(publishCollectionFailure(collection, items, 'Could not fetch rarities: error'))
.silentRun()
})
})

describe('when there is a rarity', () => {
describe('when that rarity does no have prices', () => {
describe('when fetching rarities succeeds', () => {
describe('when there are no rarities', () => {
beforeEach(() => {
rarities = [{} as Rarity]
rarities = []
})

it('should dispatch a failure action', () => {
Expand All @@ -2144,99 +2147,42 @@ describe('when publishing a collection with fiat', () => {
[call(getChainIdByNetwork, Network.MATIC), ChainId.MATIC_MUMBAI],
[retry(10, 500, mockBuilder.saveTOS, collection, email), undefined],
[call([config, config.get], 'WERT_PUBLISH_FEES_ENV'), wertEnv],
[select(getRarities), rarities]
[put(fetchRaritiesRequest()), undefined],
[
race({ success: take(FETCH_RARITIES_SUCCESS), failure: take(FETCH_RARITIES_FAILURE) }),
{ success: { payload: { rarities } } as FetchRaritiesSuccessAction }
]
])
.dispatch(publishCollectionRequest(collection, items, email, subscribeToNewsletter, paymentMethod))
.put(publishCollectionFailure(collection, items, 'Rarity prices not found'))
.put(publishCollectionFailure(collection, items, 'Rarity not found'))
.silentRun()
})
})

describe('when that rarity has MANA prices', () => {
beforeEach(() => {
rarities = [
{
prices: {
MANA: '25000000000000000000'
}
} as Rarity
]
})

describe('when the wert env is dev', () => {
beforeEach(() => {
wertEnv = 'dev'
})

// TODO: Unskip once the success action can be reached.
it.skip('should dispatch the action to open the fiat gateway widget with dev parameters', () => {
return expectSaga(collectionSaga, mockBuilder, mockBuilderClient)
.provide([
[call([mockBuilder, 'fetchCollectionItems'], collection.id), serverItems],
[select(getAddress), from],
[call(getChainIdByNetwork, Network.MATIC), ChainId.MATIC_MUMBAI],
[retry(10, 500, mockBuilder.saveTOS, collection, email), undefined],
[call([config, config.get], 'WERT_PUBLISH_FEES_ENV'), wertEnv],
[select(getRarities), rarities],
[select(getProfileOfAddress, from), undefined]
])
.dispatch(publishCollectionRequest(collection, items, email, subscribeToNewsletter, paymentMethod))
.put.like({
action: {
type: '[Request] Open FIAT Gateway Widget',
payload: {
data: {
partner_id: '01HRRQQ70YK4SP88GHM9A61P6B',
commodity: 'TT',
sc_address: '0xe539E0AED3C1971560517D58277f8dd9aC296281',
origin: 'https://sandbox.wert.io',
network: 'mumbai'
}
}
}
})
.silentRun()
})
})

describe('when the wert env is prod', () => {
describe('when there is a rarity', () => {
describe('when that rarity does no have prices', () => {
beforeEach(() => {
wertEnv = 'prod'
rarities = [{} as Rarity]
})

// TODO: Unskip once the success action can be reached.
it.skip('should dispatch the action to open the fiat gateway widget with prod parameters', () => {
it('should dispatch a failure action', () => {
return expectSaga(collectionSaga, mockBuilder, mockBuilderClient)
.provide([
[call([mockBuilder, 'fetchCollectionItems'], collection.id), serverItems],
[select(getAddress), from],
[call(getChainIdByNetwork, Network.MATIC), ChainId.MATIC_MUMBAI],
[retry(10, 500, mockBuilder.saveTOS, collection, email), undefined],
[call([config, config.get], 'WERT_PUBLISH_FEES_ENV'), wertEnv],
[select(getRarities), rarities],
[select(getProfileOfAddress, from), undefined]
[put(fetchRaritiesRequest()), undefined],
[
race({ success: take(FETCH_RARITIES_SUCCESS), failure: take(FETCH_RARITIES_FAILURE) }),
{ success: { payload: { rarities } } as FetchRaritiesSuccessAction }
]
])
.dispatch(publishCollectionRequest(collection, items, email, subscribeToNewsletter, paymentMethod))
.put.like({
action: {
type: '[Request] Open FIAT Gateway Widget',
payload: {
data: {
partner_id: '01HR4TB274GD2VNZW0VEAXNHW2',
commodity: 'MANA',
sc_address: '0x9D32AaC179153A991e832550d9F96441Ea27763A',
origin: 'https://widget.wert.io',
network: 'polygon'
}
}
}
})
.put(publishCollectionFailure(collection, items, 'Rarity prices not found'))
.silentRun()
})

// TODO: Test the rest of the saga.
// Not included in this PR given that I don't know how to test event channels yet. 👌
// What comes next in the saga are the events emitted from the wert modal for close and success which are handled by the emitter.
})
})
})
Expand Down
29 changes: 24 additions & 5 deletions src/modules/collection/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ import {
SAVE_ITEM_FAILURE,
SET_ITEMS_TOKEN_ID_SUCCESS,
FetchCollectionItemsSuccessAction,
fetchRaritiesRequest
fetchRaritiesRequest,
FETCH_RARITIES_SUCCESS,
FETCH_RARITIES_FAILURE,
FetchRaritiesFailureAction,
FetchRaritiesSuccessAction
} from 'modules/item/actions'
import { areSynced, isValidText, toInitializeItems } from 'modules/item/utils'
import { locations } from 'routing/locations'
Expand All @@ -117,8 +121,7 @@ import {
getCollectionItems,
getWalletItems,
getData as getItemsById,
getPaginationData as getItemPaginationData,
getRarities
getPaginationData as getItemPaginationData
} from 'modules/item/selectors'
import { getName } from 'modules/profile/selectors'
import { buildItemEntity, buildStandardWearableContentHash, hasOldHashedContents } from 'modules/item/export'
Expand Down Expand Up @@ -480,8 +483,24 @@ export function* collectionSaga(legacyBuilderClient: BuilderAPI, client: Builder
const scInputData = new ethers.utils.Interface(manager.abi).encodeFunctionData('createCollection', createCollectionArgs)

// The amount of MANA to be purchased required to publish the collection is determined by the price of the rarities.
// Given that rarities have the same price, we can use the first rarity and multiply it by the amount of items to get the final price.
const rarities: ReturnType<typeof getRarities> = yield select(getRarities)
// Fetch rarities now to keep the price as updated as possible.
yield put(fetchRaritiesRequest())

// Wait for success or failure.
const fetchRaritiesRequestResult: { success: FetchRaritiesSuccessAction; failure: FetchRaritiesFailureAction } = yield race({
success: take(FETCH_RARITIES_SUCCESS),
failure: take(FETCH_RARITIES_FAILURE)
})

// If there is a failure, stop execution.
if (fetchRaritiesRequestResult.failure) {
throw new Error('Could not fetch rarities: ' + fetchRaritiesRequestResult.failure.payload.error)
}

// Get the rarities from the successful response.
// The success action should always be present if the failure action is not, so we don't need to assert it.
const rarities = fetchRaritiesRequestResult.success.payload.rarities
// Given that all rarities have the same price atm, we can just use the first one.
const rarity = rarities[0]

if (!rarity) {
Expand Down
8 changes: 4 additions & 4 deletions src/modules/collection/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ describe('when getting the fiat commodity amount', () => {
unitPrice = '123456789000000000'
})

it('should return 0.12382716', () => {
expect(getFiatGatewayCommodityAmount(unitPrice, items)).toBe(0.12382716)
it('should return 0.12407408', () => {
expect(getFiatGatewayCommodityAmount(unitPrice, items)).toBe(0.12407408)
})
})

Expand All @@ -298,7 +298,7 @@ describe('when getting the fiat commodity amount', () => {
})

it('should return 1', () => {
expect(getFiatGatewayCommodityAmount(unitPrice, items)).toBe(1.003)
expect(getFiatGatewayCommodityAmount(unitPrice, items)).toBe(1.005)
})
})
})
Expand All @@ -314,7 +314,7 @@ describe('when getting the fiat commodity amount', () => {
})

it('should return 10', () => {
expect(getFiatGatewayCommodityAmount(unitPrice, items)).toBe(10.03)
expect(getFiatGatewayCommodityAmount(unitPrice, items)).toBe(10.05)
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion src/modules/collection/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export const toPaginationStats = (collectionPaginationData: CollectionPagination
export const getFiatGatewayCommodityAmount = (unitPrice: string, items: number) => {
const unitPriceWei = ethers.BigNumber.from(unitPrice)
const totalPriceWei = unitPriceWei.mul(items)
const totalPriceEth = Number(ethers.utils.formatEther(totalPriceWei.toString())) * 1.003 // 0.3% extra to safeguard against price fluctuations.
const totalPriceEth = Number(ethers.utils.formatEther(totalPriceWei.toString())) * 1.005 // 0.5% extra to safeguard against price fluctuations.
const factor = Math.pow(10, 8)

// Wert supports up to 8 decimal places.
Expand Down

0 comments on commit f9527a4

Please sign in to comment.