Skip to content

Instantly share code, notes, and snippets.

@nicovalencia
Created June 1, 2018 05:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicovalencia/476a00568f9ca7fb39cdea7b0ba7326a to your computer and use it in GitHub Desktop.
Save nicovalencia/476a00568f9ca7fb39cdea7b0ba7326a to your computer and use it in GitHub Desktop.
const Web3 = require('web3');
const fetch = require('node-fetch');
const ipfsAPI = require('ipfs-api');
const ipfs = ipfsAPI('localhost', '5002');
const POLLING_INTERVAL = 5000;
const EVENTS = {
Transfer: {}
};
var TOKEN_INDEX_HASH = '';
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
function loadContractInstance({ abiPath, address }) {
return new Promise((resolve, reject) => {
fetch(abiPath).then((resp) => {
return resp.json();
}).then(data => {
let contractInstance = new web3.eth.Contract(data.abi, address);
resolve(contractInstance);
});
});
}
class WorldCupPlayerTokenInterface {
constructor(contractInstance) {
this.instance = contractInstance;
this.getTotalSupply = this.getTotalSupply.bind(this);
this.getTokenIdByIndex = this.getTokenIdByIndex.bind(this);
this.getOwnerOf = this.getOwnerOf.bind(this);
this.getTokenURI = this.getTokenURI.bind(this);
this.getPlayerId = this.getPlayerId.bind(this);
}
async getTotalSupply() {
return new Promise(resolve => {
this.instance.methods.totalSupply().call((error, supply) => {
resolve(supply);
});
});
}
async getTokenIdByIndex(index) {
return new Promise(resolve => {
this.instance.methods.tokenByIndex(index).call((error, tokenId) => {
resolve(tokenId);
});
});
}
async getOwnerOf(tokenId) {
return new Promise(resolve => {
this.instance.methods.ownerOf(tokenId).call((error, owner) => {
resolve(owner);
});
});
}
async getTokenURI(tokenId) {
return new Promise(resolve => {
this.instance.methods.tokenURI(tokenId).call((error, tokenURI) => {
resolve(tokenURI);
});
});
}
async getPlayerId(tokenId) {
return new Promise(resolve => {
this.instance.methods.playerId(tokenId).call((error, playerId) => {
resolve(playerId);
});
});
}
}
async function rebuildTokenIndex({ contractInstance, event }) {
let tokens = {};
let interface = new WorldCupPlayerTokenInterface(contractInstance);
let supply = await interface.getTotalSupply();
let chain = Promise.resolve();
for (let i = 0; i < supply; i++) {
chain = chain.then(() => {
return new Promise(async (resolve, reject) => {
let tokenId = await interface.getTokenIdByIndex(i);
let owner = await interface.getOwnerOf(tokenId);
let tokenURI = await interface.getTokenURI(tokenId);
let playerId = await interface.getPlayerId(tokenId);
tokens[tokenId] = {
owner,
tokenURI,
playerId,
};
resolve();
});
});
}
await chain;
let buffer = Buffer.from(JSON.stringify({
tokens
}));
ipfs.add(buffer, {}, (error, resp) => {
TOKEN_INDEX_HASH = resp[0].hash;
console.log('Rebuilt token index:', TOKEN_INDEX_HASH)
});
}
function pollForEvent({ contractInstance, eventName, processCb }) {
setTimeout(() => pollForEvent(...arguments), POLLING_INTERVAL);
// Have to poll in dev until ganache supports WebSockets transport:
// https://github.com/trufflesuite/ganache-cli/issues/257
contractInstance.getPastEvents(eventName, {
fromBlock: 0,
}, (error, events) => {
events.forEach(event => {
if (!EVENTS[eventName][event.transactionHash]) {
EVENTS[eventName][event.transactionHash] = event;
processCb({ contractInstance, event });
} else {
// console.log('...duplicate event');
}
});
});
}
//TODO: build initial indices, then begin poller:
loadContractInstance({
abiPath: 'http://localhost:3000/abis/WorldCupPlayerToken.json',
address: '0x9a2b051b106f0d3be0a72defcad9799b27a3f46b',
}).then((contractInstance) => {
pollForEvent({
contractInstance,
eventName: 'Transfer',
processCb: rebuildTokenIndex,
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment