Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Address images (tokens, dapps) as registered via contentHash (when available) #2526

Merged
merged 20 commits into from
Oct 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions js/src/abi/encoder/encoder.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ describe('abi/encoder/Encoder', () => {
});

describe('bytes', () => {
const bytes1 = '1234';
const bytes2 = '10000000000000000000000000000000000000000000000000000000000002';
const bytes3 = '1000000000000000000000000000000000000000000000000000000000000000';
const bytes1 = '0x1234';
const bytes2 = '0x10000000000000000000000000000000000000000000000000000000000002';
const bytes3 = '0x1000000000000000000000000000000000000000000000000000000000000000';

it('encodes fixed bytes', () => {
const token = new Token('fixedBytes', bytes1);
Expand All @@ -215,15 +215,15 @@ describe('abi/encoder/Encoder', () => {
});

it('encodes bytes (two blocks)', () => {
const input = `${bytes3}${bytes3}`;
const input = `${bytes3}${bytes3.slice(-64)}`;
const token = new Token('bytes', input);

expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(0x40)}${padFixedBytes(input)}`);
});

it('encodes two consecutive bytes', () => {
const in1 = '10000000000000000000000000000000000000000000000000000000000002';
const in2 = '0010000000000000000000000000000000000000000000000000000000000002';
const in1 = '0x10000000000000000000000000000000000000000000000000000000000002';
const in2 = '0x0010000000000000000000000000000000000000000000000000000000000002';
const tokens = [new Token('bytes', in1), new Token('bytes', in2)];

expect(Encoder.encode(tokens)).to.equal(`${padU32(0x40)}${padU32(0x80)}${padU32(0x1f)}${padFixedBytes(in1)}${padU32(0x20)}${padFixedBytes(in2)}`);
Expand All @@ -233,7 +233,7 @@ describe('abi/encoder/Encoder', () => {
describe('string', () => {
it('encodes a string', () => {
const string = 'gavofyork';
const stringEnc = padFixedBytes('6761766f66796f726b');
const stringEnc = padFixedBytes('0x6761766f66796f726b');
const token = new Token('string', string);

expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(string.length.toString(16))}${stringEnc}`);
Expand Down Expand Up @@ -272,16 +272,16 @@ describe('abi/encoder/Encoder', () => {

describe('comprehensive test', () => {
it('encodes a complex sequence', () => {
const bytes = '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b';
const bytes = '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b';
const tokens = [new Token('int', 5), new Token('bytes', bytes), new Token('int', 3), new Token('bytes', bytes)];

expect(Encoder.encode(tokens)).to.equal(`${padU32(5)}${padU32(0x80)}${padU32(3)}${padU32(0xe0)}${padU32(0x40)}${bytes}${padU32(0x40)}${bytes}`);
expect(Encoder.encode(tokens)).to.equal(`${padU32(5)}${padU32(0x80)}${padU32(3)}${padU32(0xe0)}${padU32(0x40)}${bytes.substr(2)}${padU32(0x40)}${bytes.substr(2)}`);
});

it('encodes a complex sequence (nested)', () => {
const array = [new Token('int', 5), new Token('int', 6), new Token('int', 7)];
const tokens = [new Token('int', 1), new Token('string', 'gavofyork'), new Token('int', 2), new Token('int', 3), new Token('int', 4), new Token('array', array)];
const stringEnc = padFixedBytes('6761766f66796f726b');
const stringEnc = padFixedBytes('0x6761766f66796f726b');

expect(Encoder.encode(tokens)).to.equal(`${padU32(1)}${padU32(0xc0)}${padU32(2)}${padU32(3)}${padU32(4)}${padU32(0x100)}${padU32(9)}${stringEnc}${padU32(3)}${padU32(5)}${padU32(6)}${padU32(7)}`);
});
Expand Down
33 changes: 17 additions & 16 deletions js/src/abi/util/pad.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,34 @@ export function padU32 (input) {
return `${ZERO_64}${bn.toString(16)}`.slice(-64);
}

export function padBytes (input) {
const length = isArray(input) ? input.length : (`${input}`.length / 2);

return `${padU32(length)}${padFixedBytes(input)}`;
}

export function padFixedBytes (input) {
let sinput;

function stringToBytes (input) {
if (isArray(input)) {
sinput = input.map((code) => code.toString(16)).join('');
return input;
} else if (input.substr(0, 2) === '0x') {
sinput = `${input.substr(2)}`;
return input.substr(2).match(/.{1,2}/g).map((value) => parseInt(value, 16));
} else {
sinput = `${input}`;
return input.split('').map((char) => char.charCodeAt(0));
}
}

export function padBytes (_input) {
const input = stringToBytes(_input);

return `${padU32(input.length)}${padFixedBytes(input)}`;
}

export function padFixedBytes (_input) {
const input = stringToBytes(_input);
const sinput = input.map((code) => `0${code.toString(16)}`.slice(-2)).join('');
const max = Math.floor((sinput.length + 63) / 64) * 64;

return `${sinput}${ZERO_64}`.substr(0, max);
}

export function padString (input) {
const encoded = utf8.encode(input)
const array = utf8.encode(input)
.split('')
.map((char) => char.charCodeAt(0).toString(16))
.join('');
.map((char) => char.charCodeAt(0));

return padBytes(encoded);
return padBytes(array);
}
10 changes: 5 additions & 5 deletions js/src/abi/util/pad.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ describe('abi/util/pad', () => {

describe('padFixedBytes', () => {
it('right pads length < 64 bytes to 64 bytes (string)', () => {
expect(padFixedBytes(SHORT15)).to.equal(LONG15);
expect(padFixedBytes(`0x${SHORT15}`)).to.equal(LONG15);
});

it('right pads length < 64 bytes to 64 bytes (array)', () => {
expect(padFixedBytes(BYTES15)).to.equal(LONG15);
});

it('right pads length > 64 bytes (64 byte multiples)', () => {
expect(padFixedBytes(`${LONG15}${SHORT15}`)).to.equal(`${LONG15}${LONG15}`);
expect(padFixedBytes(`0x${LONG15}${SHORT15}`)).to.equal(`${LONG15}${LONG15}`);
});

it('strips leading 0x when passed in', () => {
Expand All @@ -92,7 +92,7 @@ describe('abi/util/pad', () => {

describe('padBytes', () => {
it('right pads length < 64, adding the length (string)', () => {
const result = padBytes(SHORT15);
const result = padBytes(`0x${SHORT15}`);

expect(result.length).to.equal(128);
expect(result).to.equal(`${padU32(8)}${LONG15}`);
Expand All @@ -106,7 +106,7 @@ describe('abi/util/pad', () => {
});

it('right pads length > 64, adding the length', () => {
const result = padBytes(`${LONG15}${SHORT15}`);
const result = padBytes(`0x${LONG15}${SHORT15}`);

expect(result.length).to.equal(192);
expect(result).to.equal(`${padU32(0x28)}${LONG15}${LONG15}`);
Expand All @@ -118,7 +118,7 @@ describe('abi/util/pad', () => {
const result = padString('gavofyork');

expect(result.length).to.equal(128);
expect(result).to.equal(padBytes('6761766f66796f726b'));
expect(result).to.equal(padBytes('0x6761766f66796f726b'));
});
});
});
2 changes: 2 additions & 0 deletions js/src/dapps/githubhint/Application/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ export default class Application extends Component {
instance.entries
.call({}, [contentHash])
.then(([accountSlashRepo, commit, owner]) => {
console.log('lookupHash', accountSlashRepo, api.util.bytesToHex(commit), owner);

if (owner !== ZERO_ADDRESS) {
this.setState({ contentHashError: contentHash, contentHash: null });
} else {
Expand Down
3 changes: 2 additions & 1 deletion js/src/dapps/tokenreg/Tokens/Token/add-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Dialog, RaisedButton, FlatButton, SelectField, MenuItem } from 'materia
import AddIcon from 'material-ui/svg-icons/content/add';

import InputText from '../../Inputs/Text';
import { ADDRESS_TYPE } from '../../Inputs/validation';

import styles from './token.css';

Expand Down Expand Up @@ -133,7 +134,7 @@ export default class AddMeta extends Component {
<InputText
key={ selectedMeta.value }
floatingLabelText={ `${selectedMeta.label} value` }
hintText={ `The value of the ${selectedMeta.label.toLowerCase()} meta-data` }
hintText={ `The value of the ${selectedMeta.label.toLowerCase()} (${selectedMeta.validation === ADDRESS_TYPE ? 'Address' : 'Url Hint'})` }

validationType={ selectedMeta.validation }
onChange={ this.onChange } />
Expand Down
15 changes: 11 additions & 4 deletions js/src/dapps/tokenreg/Tokens/Token/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ export default class Token extends Component {
metaMined: PropTypes.bool,
isLoading: PropTypes.bool,
isPending: PropTypes.bool,
isOwner: PropTypes.bool,
isTokenOwner: PropTypes.bool,
isTokenOwner: PropTypes.bool.isRequired,

fullWidth: PropTypes.bool
};
Expand Down Expand Up @@ -197,14 +196,20 @@ export default class Token extends Component {
renderIsPending () {
const { isPending } = this.props;

if (!isPending) return null;
if (!isPending) {
return null;
}

return (
<div className={ styles.pending } />
);
}

renderAddMeta () {
if (!this.props.isTokenOwner) {
return null;
}

return (
<AddMeta
handleAddMeta={ this.props.handleAddMeta }
Expand All @@ -214,7 +219,9 @@ export default class Token extends Component {
}

renderUnregister () {
if (!this.props.isOwner) return null;
if (!this.props.isTokenOwner) {
return null;
}

return (
<RaisedButton
Expand Down
29 changes: 7 additions & 22 deletions js/src/dapps/tokenreg/Tokens/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { getTokenTotalSupply } from '../utils';

const { sha3, bytesToHex } = window.parity.api.util;
const { bytesToHex } = window.parity.api.util;

export const SET_TOKENS_LOADING = 'SET_TOKENS_LOADING';
export const setTokensLoading = (isLoading) => ({
Expand Down Expand Up @@ -164,17 +164,15 @@ export const queryTokenMeta = (index, query) => (dispatch, getState) => {
const state = getState();
const contractInstance = state.status.contract.instance;

const key = sha3(query);

const startDate = Date.now();
dispatch(setTokenMetaLoading(index, true));

contractInstance
.meta
.call({}, [ index, key ])
.call({}, [ index, query ])
.then((value) => {
const meta = {
key, query,
query,
value: value.find(v => v !== 0) ? bytesToHex(value) : null
};

Expand All @@ -195,35 +193,22 @@ export const addTokenMeta = (index, key, value) => (dispatch, getState) => {

const state = getState();
const contractInstance = state.status.contract.instance;

const token = state.tokens.tokens.find(t => t.index === index);
const keyHash = sha3(key);

const options = {
from: token.owner
};

let values;

if (key === 'IMG') {
const valueHash = sha3(value);
dispatch(addGithubhintURL(token.owner, valueHash, value));
values = [ index, keyHash, valueHash ];
} else {
values = [ index, keyHash, value ];
}
const options = { from: token.owner };
const values = [ index, key, value ];

contractInstance
.setMeta
.estimateGas(options, values)
.then((gasEstimate) => {
options.gas = gasEstimate.mul(1.2).toFixed(0);
console.log(`transfer: gas estimated as ${gasEstimate.toFixed(0)} setting to ${options.gas}`);
console.log(`addTokenMeta: gas estimated as ${gasEstimate.toFixed(0)} setting to ${options.gas}`);

return contractInstance.setMeta.postTransaction(options, values);
})
.catch((e) => {
console.error(`addTokenMeta #${index} error`, e);
console.error(`addTokenMeta: #${index} error`, e);
});
};

Expand Down
16 changes: 11 additions & 5 deletions js/src/dapps/tokenreg/Tokens/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,31 @@ class TokensContainer extends Component {
isLoading: PropTypes.bool,
tokens: PropTypes.array,
tokenCount: PropTypes.number,
onLoadTokens: PropTypes.func
onLoadTokens: PropTypes.func,
accounts: PropTypes.array
};

componentDidMount () {
this.props.onLoadTokens();
}

render () {
return (<Tokens
{ ...this.props }
/>);
console.log(this.props);
return (
<Tokens
{ ...this.props }
/>
);
}
}

const mapStateToProps = (state) => {
const { list } = state.accounts;
const { isLoading, tokens, tokenCount } = state.tokens;

const { isOwner } = state.status.contract;

return { isLoading, tokens, tokenCount, isOwner };
return { isLoading, tokens, tokenCount, isOwner, accounts: list };
};

const mapDispatchToProps = (dispatch) => {
Expand Down
14 changes: 10 additions & 4 deletions js/src/dapps/tokenreg/Tokens/tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ export default class Tokens extends Component {
handleMetaLookup: PropTypes.func.isRequired,
isOwner: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired,
tokens: PropTypes.array
tokens: PropTypes.array,
accounts: PropTypes.array
};

render () {
const { isLoading, tokens } = this.props;

const loading = isLoading ? (<Loading size={ 2 } />) : null;

return (
Expand All @@ -45,8 +45,14 @@ export default class Tokens extends Component {
}

renderTokens (tokens) {
const { accounts } = this.props;

return tokens.map((token, index) => {
if (!token || !token.tla) return null;
if (!token || !token.tla) {
return null;
}

const isTokenOwner = !!accounts.find((account) => account.address === token.owner);

return (
<Token
Expand All @@ -55,7 +61,7 @@ export default class Tokens extends Component {
handleMetaLookup={ this.props.handleMetaLookup }
handleAddMeta={ this.props.handleAddMeta }
key={ index }
isOwner={ this.props.isOwner } />
isTokenOwner={ isTokenOwner } />
);
});
}
Expand Down
4 changes: 2 additions & 2 deletions js/src/dapps/tokenreg/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import { URL_TYPE, ADDRESS_TYPE } from './Inputs/validation';
import { HEX_TYPE, ADDRESS_TYPE } from './Inputs/validation';

export const metaDataKeys = [
{
label: 'Image',
value: 'IMG',
validation: URL_TYPE
validation: HEX_TYPE
},
{
label: 'Address',
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed js/src/images/contracts/gavcoin-56.png
Binary file not shown.
Binary file added js/src/images/contracts/gavcoin-64x64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed js/src/images/contracts/unknown-56.png
Binary file not shown.
Binary file added js/src/images/contracts/unknown-64x64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading