Skip to content

Commit

Permalink
Market: update region price (#20)
Browse files Browse the repository at this point in the history
* update region price

* toolchain
  • Loading branch information
Szegoo authored Feb 6, 2024
1 parent 26e4a3e commit 5505943
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 11 deletions.
35 changes: 28 additions & 7 deletions contracts/coretime_market/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub mod coretime_market {

#[ink(event)]
pub struct RegionUnlisted {
/// The identifier of the region that got listed on sale.
/// The identifier of the region that got unlisted from sale.
#[ink(topic)]
pub(crate) region_id: RawRegionId,
/// The account that removed the region from sale.
Expand All @@ -93,7 +93,7 @@ pub mod coretime_market {

#[ink(event)]
pub struct RegionPurchased {
/// The identifier of the region that got listed on sale.
/// The identifier of the region that got purchased.
#[ink(topic)]
pub(crate) region_id: RawRegionId,
/// The buyer of the region
Expand All @@ -102,6 +102,15 @@ pub mod coretime_market {
pub(crate) total_price: Balance,
}

#[ink(event)]
pub struct RegionPriceUpdated {
/// The identifier of the region that got its price updated.
#[ink(topic)]
pub(crate) region_id: RawRegionId,
/// The new per timeslice price.
pub(crate) new_timeslice_price: Balance,
}

impl CoretimeMarket {
#[ink(constructor)]
pub fn new(
Expand Down Expand Up @@ -270,18 +279,30 @@ pub mod coretime_market {
Ok(())
}

/// A function for updating a listed region's bit price.
/// A function for updating a listed region's price.
///
/// ## Arguments:
/// - `region_id`: The `u128` encoded identifier of the region being listed for sale.
/// - `timeslice_price`: The new per timeslice price of the region.
#[ink(message)]
pub fn update_region_price(
&self,
_region_id: RawRegionId,
_new_timeslice_price: Balance,
&mut self,
id: Id,
new_timeslice_price: Balance,
) -> Result<(), MarketError> {
todo!()
let caller = self.env().caller();

let Id::U128(region_id) = id else { return Err(MarketError::InvalidRegionId) };

let mut listing = self.listings.get(&region_id).ok_or(MarketError::RegionNotListed)?;

ensure!(caller == listing.seller, MarketError::NotAllowed);

listing.timeslice_price = new_timeslice_price;
self.listings.insert(&region_id, &listing);

self.emit_event(RegionPriceUpdated { region_id, new_timeslice_price });
Ok(())
}

/// A function for purchasing a region listed on sale.
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "nightly"
channel = "nightly-2023-12-22"
components = [ "rustfmt", "clippy" ]
targets = [ "wasm32-unknown-unknown"]
profile = "minimal"
2 changes: 1 addition & 1 deletion tests/market/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('Coretime market listing', () => {
});

await expectOnSale(market, id, alice, timeslicePrice);
expect((await market.query.regionPrice(id)).value.unwrap().ok.toNumber()).to.be.equal(
expect((await market.query.regionPrice(id)).value.unwrap().unwrap().toNumber()).to.be.equal(
timeslicePrice * (region.getEnd() - region.getBegin()),
);
expect((await xcRegions.query.ownerOf(id)).value.unwrap()).to.deep.equal(market.address);
Expand Down
4 changes: 2 additions & 2 deletions tests/market/purchase.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('Coretime market purchases', () => {
.tx.listRegion(id, timeslicePrice, alice.address, { value: LISTING_DEPOIST });

await expectOnSale(market, id, alice, timeslicePrice);
expect((await market.query.regionPrice(id)).value.unwrap().ok.toNumber()).to.be.equal(
expect((await market.query.regionPrice(id)).value.unwrap().unwrap().toNumber()).to.be.equal(
timeslicePrice * (region.getEnd() - region.getBegin()),
);
expect((await xcRegions.query.ownerOf(id)).value.unwrap()).to.deep.equal(market.address);
Expand Down Expand Up @@ -146,7 +146,7 @@ describe('Coretime market purchases', () => {
.tx.listRegion(id, timeslicePrice, alice.address, { value: LISTING_DEPOIST });

await expectOnSale(market, id, alice, timeslicePrice);
expect((await market.query.regionPrice(id)).value.unwrap().ok.toNumber()).to.be.equal(
expect((await market.query.regionPrice(id)).value.unwrap().unwrap().toNumber()).to.be.equal(
timeslicePrice * (region.getEnd() - region.getBegin()),
);
expect((await xcRegions.query.ownerOf(id)).value.unwrap()).to.deep.equal(market.address);
Expand Down
2 changes: 2 additions & 0 deletions tests/market/unlist.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ describe('Coretime market unlisting', () => {
expect((await xcRegions.query.ownerOf(id)).value.unwrap()).to.be.equal(alice.address);
});

/* TODO: Come up with a better way to test this.
it('Anyone can unlist an expired region', async () => {
const regionId: RegionId = {
begin: 0,
Expand Down Expand Up @@ -225,4 +226,5 @@ describe('Coretime market unlisting', () => {
// TODO: should ideally ensure that bob received the reward.
});
*/
});
174 changes: 174 additions & 0 deletions tests/market/updatePrice.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { ApiPromise, Keyring, WsProvider } from '@polkadot/api';
import { expect, use } from 'chai';
import { KeyringPair } from '@polkadot/keyring/types';
import XcRegions_Factory from '../../types/constructors/xc_regions';
import Market_Factory from '../../types/constructors/coretime_market';
import XcRegions from '../../types/contracts/xc_regions';
import Market from '../../types/contracts/coretime_market';
import chaiAsPromised from 'chai-as-promised';
import { CoreMask, Id, Region, RegionId, RegionRecord } from 'coretime-utils';
import {
approveTransfer,
balanceOf,
createRegionCollection,
expectEvent,
expectOnSale,
initRegion,
mintRegion,
} from '../common';
import { MarketErrorBuilder } from '../../types/types-returns/coretime_market';

use(chaiAsPromised);

const REGION_COLLECTION_ID = 42;
const LISTING_DEPOIST = 0;
// In reality this is 80, however we use 8 for testing.
const TIMESLICE_PERIOD = 8;

const wsProvider = new WsProvider('ws://127.0.0.1:9944');
// Create a keyring instance
const keyring = new Keyring({ type: 'sr25519', ss58Format: 5 });

describe('Coretime market purchases', () => {
let api: ApiPromise;
let alice: KeyringPair;
let bob: KeyringPair;
let charlie: KeyringPair;

let xcRegions: XcRegions;
let market: Market;

beforeEach(async function (): Promise<void> {
api = await ApiPromise.create({ provider: wsProvider, noInitWarn: true, types: { Id } });

alice = keyring.addFromUri('//Alice');
bob = keyring.addFromUri('//Bob');
charlie = keyring.addFromUri('//Charlie');

const xcRegionsFactory = new XcRegions_Factory(api, alice);
xcRegions = new XcRegions((await xcRegionsFactory.new()).address, alice, api);

const marketFactory = new Market_Factory(api, alice);
market = new Market(
(await marketFactory.new(xcRegions.address, LISTING_DEPOIST, TIMESLICE_PERIOD)).address,
alice,
api,
);

if (!(await api.query.uniques.class(REGION_COLLECTION_ID)).toHuman()) {
await createRegionCollection(api, alice);
}
});

it('Updating price works', async () => {
const regionId: RegionId = {
begin: 30,
core: 40,
mask: CoreMask.completeMask(),
};
const regionRecord: RegionRecord = {
end: 60,
owner: alice.address,
paid: null,
};
const region = new Region(regionId, regionRecord);

await mintRegion(api, alice, region);
await approveTransfer(api, alice, region, xcRegions.address);

await initRegion(api, xcRegions, alice, region);

const id: any = api.createType('Id', { U128: region.getEncodedRegionId(api) });
await xcRegions.withSigner(alice).tx.approve(market.address, id, true);

const timeslicePrice = 5 * Math.pow(10, 12);
await market
.withSigner(alice)
.tx.listRegion(id, timeslicePrice, alice.address, { value: LISTING_DEPOIST });

await expectOnSale(market, id, alice, timeslicePrice);
expect((await market.query.regionPrice(id)).value.unwrap().unwrap().toNumber()).to.be.equal(
timeslicePrice * (region.getEnd() - region.getBegin()),
);
expect((await xcRegions.query.ownerOf(id)).value.unwrap()).to.deep.equal(market.address);

const newTimeslicePrice = 6 * Math.pow(10, 12);

const result = await market.withSigner(alice).tx.updateRegionPrice(id, newTimeslicePrice);
expectEvent(result, 'RegionPriceUpdated', {
regionId: id.toPrimitive().u128,
newTimeslicePrice: newTimeslicePrice.toString(),
});
await expectOnSale(market, id, alice, newTimeslicePrice);
expect((await market.query.regionPrice(id)).value.unwrap().unwrap().toNumber()).to.be.equal(
newTimeslicePrice * (region.getEnd() - region.getBegin()),
);
});

it('Cannot update price for unlisted region', async () => {
const regionId: RegionId = {
begin: 30,
core: 41,
mask: CoreMask.completeMask(),
};
const regionRecord: RegionRecord = {
end: 60,
owner: alice.address,
paid: null,
};
const region = new Region(regionId, regionRecord);

await mintRegion(api, alice, region);
await approveTransfer(api, alice, region, xcRegions.address);

await initRegion(api, xcRegions, alice, region);

const id: any = api.createType('Id', { U128: region.getEncodedRegionId(api) });
await xcRegions.withSigner(alice).tx.approve(market.address, id, true);

const newTimeslicePrice = 6 * Math.pow(10, 12);

const result = await market.withSigner(alice).query.updateRegionPrice(id, newTimeslicePrice);

expect(result.value.unwrap().err).to.deep.equal(MarketErrorBuilder.RegionNotListed());
});

it('Only owner can update the price', async () => {
const regionId: RegionId = {
begin: 30,
core: 42,
mask: CoreMask.completeMask(),
};
const regionRecord: RegionRecord = {
end: 60,
owner: alice.address,
paid: null,
};
const region = new Region(regionId, regionRecord);

await mintRegion(api, alice, region);
await approveTransfer(api, alice, region, xcRegions.address);

await initRegion(api, xcRegions, alice, region);

const id: any = api.createType('Id', { U128: region.getEncodedRegionId(api) });
await xcRegions.withSigner(alice).tx.approve(market.address, id, true);

const timeslicePrice = 7 * Math.pow(10, 12);
await market
.withSigner(alice)
.tx.listRegion(id, timeslicePrice, alice.address, { value: LISTING_DEPOIST });

await expectOnSale(market, id, alice, timeslicePrice);
expect((await market.query.regionPrice(id)).value.unwrap().unwrap().toNumber()).to.be.equal(
timeslicePrice * (region.getEnd() - region.getBegin()),
);
expect((await xcRegions.query.ownerOf(id)).value.unwrap()).to.deep.equal(market.address);

const newTimeslicePrice = 6 * Math.pow(10, 12);

const result = await market.withSigner(bob).query.updateRegionPrice(id, newTimeslicePrice);

expect(result.value.unwrap().err).to.deep.equal(MarketErrorBuilder.NotAllowed());
});
});

0 comments on commit 5505943

Please sign in to comment.