Skip to content

Commit

Permalink
feat: Buy NFTs to unlock bonus levels
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedvard committed Aug 30, 2022
1 parent 18c97f1 commit c173470
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/gameEvents.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export const RESTART_LEVEL = 'r';
export const START_NEXT_LEVEL = 'snl';
export const ARCADIAN_HEAD_SELECTED = 'ahs';
export const NEAR_TOKENS_ADDED = 'n';
export const NFT_MINT = 'nm';
12 changes: 7 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ const initNear = () => {
const promises = [
nearConnection.nft_tokens_for_owner(nearConnection.accountId),
nearConnection.nft_tokens_by_series(HANG_BY_A_THREAD_SERIES_TESTNET),
nearConnection.getNftCollections(),
];
Promise.all(promises).then(([tokensForOwner, tokensBySeries]) => {
setNftTokens(tokensForOwner, tokensBySeries);
console.log('nft_tokens_for_owner', tokensForOwner);
console.log('nft_tokens_by_series', tokensBySeries);
});

Promise.all(promises).then(
([tokensForOwner, tokensBySeries, collections]) => {
setNftTokens(tokensForOwner, tokensBySeries, collections);
}
);
});
});
};
Expand Down
60 changes: 53 additions & 7 deletions src/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { emit, on } from 'kontra';
import {
LEVEL_COMPLETE,
NEAR_TOKENS_ADDED,
NFT_MINT,
RESTART_LEVEL,
START_LEVEL,
START_NEXT_LEVEL,
} from './gameEvents';
import { fetchArcadianHeads } from './arcadianApi';
import { nftTokensBySeries, setSelectedArcadian } from './store';
import { IPFS_BASE_PATH } from './near/nearConnection';
import { doesOwnNft, getNearLevelId } from './utils';

const overlayIds = ['main', 'bonus', 'levels', 'level-dialog', 'near-levels'];
const levels = 20;
Expand All @@ -38,16 +40,38 @@ const initLevels = () => {
}
};

const initNearLevels = ({ nftTokensBySeries, nftTokensForOwner }) => {
const initNearLevels = ({
nftTokensBySeries,
nftTokensForOwner,
nftCollections,
}) => {
const nearLoadingEl = document.getElementById('loadingNearLevels');
if (nearLoadingEl) nearLoadingEl.remove();
const levelsGridEl = document.getElementById('near-levels-grid');
nftTokensBySeries.forEach((l) => {
nftCollections.forEach((collection) => {
const levelEl = document.createElement('button');
const imgEl = document.createElement('img');
imgEl.setAttribute('src', IPFS_BASE_PATH + l.metadata.media);
levelEl.textContent = l.metadata.title;
const ownsNft = doesOwnNft(collection.token_series_id, nftTokensForOwner);

imgEl.setAttribute('src', IPFS_BASE_PATH + collection.metadata.media);
levelEl.setAttribute('near', 'true');
if (!ownsNft) {
levelEl.setAttribute('disabled', !ownsNft);
}
levelEl.setAttribute('token-series-id', collection.token_series_id);
levelEl.setAttribute('price', collection.price);
levelEl.textContent = collection.metadata.title;
levelEl.appendChild(imgEl);
const mintForPriceEl = document.createElement('span');
if (!ownsNft) {
mintForPriceEl.textContent =
'Buy level for: ' +
(collection.price / Math.pow(10, 24)).toFixed(2) +
' Ⓝ';
} else {
mintForPriceEl.textContent = 'Click to play level';
}
levelEl.appendChild(mintForPriceEl);
levelEl.classList.add('level-item');
levelsGridEl.appendChild(levelEl);
});
Expand Down Expand Up @@ -131,13 +155,31 @@ const onContainerClick = (e) => {

if (classList.contains('close-icon')) {
showOverlay('main');
return;
}
if (classList.contains('level-item')) {

const btn = e.target.closest('button');
if (btn && btn.getAttribute('near')) {
onNearLevelClick(btn);
} else if (classList.contains('level-item')) {
showOverlay();
emit(START_LEVEL, { levelId: +e.target.textContent });
}
};

const onNearLevelClick = (btn) => {
if (btn && btn.getAttribute('disabled') === 'true') {
const token_series_id = btn.getAttribute('token-series-id');
const priceInYoctoNear = btn.getAttribute('price');
emit(NFT_MINT, { token_series_id, priceInYoctoNear });
} else {
showOverlay();
emit(START_LEVEL, {
levelId: getNearLevelId(btn.getAttribute('token-series-id')),
});
}
};

const showOverlay = (id) => {
overlayIds.forEach((o) => {
const overlayEl = document.getElementById(o);
Expand All @@ -158,6 +200,10 @@ const onLevelComplete = () => {
showOverlay('level-dialog');
document.getElementById('nextBtn').focus();
};
const onNearTokensAdded = ({ nftTokensBySeries, nftTokensForOwner }) => {
initNearLevels({ nftTokensBySeries, nftTokensForOwner });
const onNearTokensAdded = ({
nftTokensBySeries,
nftTokensForOwner,
nftCollections,
}) => {
initNearLevels({ nftTokensBySeries, nftTokensForOwner, nftCollections });
};
31 changes: 29 additions & 2 deletions src/near/nearConnection.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { on } from 'kontra';
import { NFT_MINT } from '../gameEvents';
import getConfig from './config';

export const HANG_BY_A_THREAD_SERIES_TESTNET = '2036';
export const MIRRORS_SERIES_TESTNET = '494';
export const PARAS_BASE_PATH_TESTNET =
'https://testnet.paras.id/token/paras-token-v2.testnet::';
export const IPFS_BASE_PATH = 'https://ipfs.fleek.co/ipfs/';
export const PARAS_COLLECTION_API =
'https://api-v3-marketplace-testnet.paras.id/token-series?collection_id=hang-by-a-thread-by-johnonymtestnet';

export class NearConnection {
walletConnection;
Expand All @@ -16,6 +20,7 @@ export class NearConnection {
resolveContract;

constructor() {
this.listenForGameEvents();
this.ready = new Promise((resolve, reject) => {
this.resolveContract = resolve;
});
Expand All @@ -42,11 +47,10 @@ export class NearConnection {
// View methods are read only. They don't modify the state, but usually return some value.
viewMethods: ['nft_tokens_for_owner', 'nft_tokens_by_series'],
// Change methods can modify the state. But you don't receive the returned value when called.
changeMethods: ['setGreeting', 'setScore', 'setName'],
changeMethods: ['nft_mint'],
}
);
this.resolveContract();

return this.walletConnection;
}

Expand All @@ -69,4 +73,27 @@ export class NearConnection {
nft_tokens_by_series(token_series_id) {
return this.contract.nft_tokens_by_series({ token_series_id });
}
nft_mint({ token_series_id, priceInYoctoNear }) {
return this.contract.nft_mint(
{
owner_id: this.accountId,
receiver_id: this.accountId,
token_series_id,
},
'300000000000000',
priceInYoctoNear
);
}
getNftCollections() {
return fetch(PARAS_COLLECTION_API)
.then((res) => res.json())
.then((res) => {
return res.data.results.filter((data) => data.metadata.copies > 0);
});
}
listenForGameEvents() {
on(NFT_MINT, ({ token_series_id, priceInYoctoNear }) =>
this.nft_mint({ token_series_id, priceInYoctoNear })
);
}
}
10 changes: 8 additions & 2 deletions src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const arcadianData = {};
let selectedArcadian = {};
export let nftTokensBySeries = [];
export let nftTokensForOwner = [];
export let nftCollections = [];

export const setGameWidth = (width) => {
gameWidth = width;
Expand All @@ -29,8 +30,13 @@ export const getSelectedArcadian = () => {
return selectedArcadian;
};

export const setNftTokens = (tokensForOwner, tokensBySeries) => {
export const setNftTokens = (tokensForOwner, tokensBySeries, collections) => {
nftTokensForOwner = tokensForOwner;
nftTokensBySeries = tokensBySeries;
emit(NEAR_TOKENS_ADDED, { nftTokensBySeries, nftTokensForOwner });
nftCollections = collections;
emit(NEAR_TOKENS_ADDED, {
nftTokensBySeries,
nftTokensForOwner,
nftCollections,
});
};
7 changes: 7 additions & 0 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ button:disabled {
color: darkgray;
cursor: not-allowed;
}
button:disabled img {
filter: contrast(0.5);
}
button:hover img {
filter: none;
}
.overlay {
position: absolute;
width: 100%;
Expand Down Expand Up @@ -135,6 +141,7 @@ button:disabled {
flex-flow: column;
width: 250px;
height: 300px;
cursor: pointer;
}

#bonus-grid {
Expand Down
16 changes: 16 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,19 @@ export const lineIntersection = (p1, p2, p3, p4) => {
let intersection = Vector(intersectionX, intersectionY);
return intersection;
};

export const doesOwnNft = (seriesId, nftTokensForOwner) => {
const token = nftTokensForOwner.find(
(token) => token.token_id.split(':')[0] === seriesId
);
return !!token;
};

export const getNearLevelId = (tokenSeriesId) => {
switch (tokenSeriesId) {
case '2037':
return 2;
case '2036':
return 3;
}
};

0 comments on commit c173470

Please sign in to comment.