Home Reference Source

packages/polkadot-identicon/lib/index.js

  1. const React = require('react');
  2. const { ReactiveComponent } = require('oo7-react');
  3. const { ss58Decode, ss58Encode } = require('oo7-substrate');
  4. const { blake2b } = require('blakejs');
  5.  
  6. const zero = blake2b(new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
  7.  
  8. const copyToClipboard = str => {
  9. const el = document.createElement('textarea');
  10. el.value = str;
  11. document.body.appendChild(el);
  12. el.select();
  13. document.execCommand('copy');
  14. document.body.removeChild(el);
  15. };
  16.  
  17. export default class Identicon extends ReactiveComponent {
  18. constructor() {
  19. super(["account"]);
  20. }
  21. render() {
  22. let s = 64;
  23. let c = s / 2;
  24. let r = this.props.sixPoint ? s / 2 / 8 * 5 : s / 2 / 4 * 3;
  25. let rroot3o2 = r * Math.sqrt(3) / 2;
  26. let ro2 = r / 2;
  27. let rroot3o4 = r * Math.sqrt(3) / 4;
  28. let ro4 = r / 4;
  29. let r3o4 = r * 3 / 4;
  30.  
  31. let z = s / 64 * 5;
  32. let schema = {
  33. target: { freq: 1, colors: [0, 28, 0, 0, 28, 0, 0, 28, 0, 0, 28, 0, 0, 28, 0, 0, 28, 0, 1] },
  34. cube: { freq: 20, colors: [0, 1, 3, 2, 4, 3, 0, 1, 3, 2, 4, 3, 0, 1, 3, 2, 4, 3, 5] },
  35. quazar: { freq: 16, colors: [1, 2, 3, 1, 2, 4, 5, 5, 4, 1, 2, 3, 1, 2, 4, 5, 5, 4, 0] },
  36. flower: { freq: 32, colors: [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3] },
  37. cyclic: { freq: 32, colors: [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6] },
  38. vmirror: { freq: 128, colors: [0, 1, 2, 3, 4, 5, 3, 4, 2, 0, 1, 6, 7, 8, 9, 7, 8, 6, 10] },
  39. hmirror: { freq: 128, colors: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 8, 6, 7, 5, 3, 4, 2, 11] }
  40. };
  41.  
  42. let total = Object.keys(schema).map(k => schema[k].freq).reduce((a, b) => a + b);
  43. let findScheme = d => {
  44. let cum = 0;
  45. let ks = Object.keys(schema);
  46. for (let i in ks) {
  47. let n = schema[ks[i]].freq;
  48. cum += n;
  49. if (d < cum) {
  50. return schema[ks[i]];
  51. }
  52. }
  53. throw "Impossible";
  54. };
  55.  
  56. let id = typeof this.state.account == 'string' ? ss58Decode(this.state.account) : this.state.account;
  57. if (!(typeof id == 'object' && id && id instanceof Uint8Array && id.length == 32)) {
  58. return React.createElement('svg', {
  59. id: this.props.id,
  60. name: this.props.name,
  61. className: this.props.className,
  62. style: this.props.style,
  63. width: this.props.width || this.props.size,
  64. height: this.props.height || this.props.size,
  65. viewBox: '0 0 64 64'
  66. });
  67. }
  68. let ss58 = ss58Encode(id);
  69. id = Array.from(blake2b(id)).map((x, i) => (x + 256 - zero[i]) % 256);
  70.  
  71. let sat = Math.floor(id[29] * 70 / 256 + 26) % 80 + 30;
  72. let d = Math.floor((id[30] + id[31] * 256) % total);
  73. let scheme = findScheme(d);
  74. let palette = Array.from(id).map((x, i) => {
  75. let b = (x + i % 28 * 58) % 256;
  76. if (b == 0) {
  77. return '#444';
  78. }
  79. if (b == 255) {
  80. return 'transparent';
  81. }
  82. let h = Math.floor(b % 64 * 360 / 64);
  83. let l = [53, 15, 35, 75][Math.floor(b / 64)];
  84. return `hsl(${h}, ${sat}%, ${l}%)`;
  85. });
  86.  
  87. let rot = id[28] % 6 * 3;
  88.  
  89. let colors = scheme.colors.map((_, i) => palette[scheme.colors[i < 18 ? (i + rot) % 18 : 18]]);
  90.  
  91. let i = 0;
  92. return React.createElement(
  93. 'svg',
  94. {
  95. id: this.props.id,
  96. name: this.props.name,
  97. className: this.props.className,
  98. style: this.props.style,
  99. width: this.props.width || this.props.size,
  100. height: this.props.height || this.props.size,
  101. viewBox: '0 0 64 64',
  102. onClick: () => {
  103. copyToClipboard(ss58);this.props.onCopied && this.props.onCopied(ss58);
  104. }
  105. },
  106. React.createElement('circle', { cx: s / 2, cy: s / 2, r: s / 2, fill: '#eee' }),
  107. React.createElement('circle', { cx: c, cy: c - r, r: z, fill: colors[i++] }),
  108. React.createElement('circle', { cx: c, cy: c - ro2, r: z, fill: colors[i++] }),
  109. React.createElement('circle', { cx: c - rroot3o4, cy: c - r3o4, r: z, fill: colors[i++] }),
  110. React.createElement('circle', { cx: c - rroot3o2, cy: c - ro2, r: z, fill: colors[i++] }),
  111. React.createElement('circle', { cx: c - rroot3o4, cy: c - ro4, r: z, fill: colors[i++] }),
  112. React.createElement('circle', { cx: c - rroot3o2, cy: c, r: z, fill: colors[i++] }),
  113. React.createElement('circle', { cx: c - rroot3o2, cy: c + ro2, r: z, fill: colors[i++] }),
  114. React.createElement('circle', { cx: c - rroot3o4, cy: c + ro4, r: z, fill: colors[i++] }),
  115. React.createElement('circle', { cx: c - rroot3o4, cy: c + r3o4, r: z, fill: colors[i++] }),
  116. React.createElement('circle', { cx: c, cy: c + r, r: z, fill: colors[i++] }),
  117. React.createElement('circle', { cx: c, cy: c + ro2, r: z, fill: colors[i++] }),
  118. React.createElement('circle', { cx: c + rroot3o4, cy: c + r3o4, r: z, fill: colors[i++] }),
  119. React.createElement('circle', { cx: c + rroot3o2, cy: c + ro2, r: z, fill: colors[i++] }),
  120. React.createElement('circle', { cx: c + rroot3o4, cy: c + ro4, r: z, fill: colors[i++] }),
  121. React.createElement('circle', { cx: c + rroot3o2, cy: c, r: z, fill: colors[i++] }),
  122. React.createElement('circle', { cx: c + rroot3o2, cy: c - ro2, r: z, fill: colors[i++] }),
  123. React.createElement('circle', { cx: c + rroot3o4, cy: c - ro4, r: z, fill: colors[i++] }),
  124. React.createElement('circle', { cx: c + rroot3o4, cy: c - r3o4, r: z, fill: colors[i++] }),
  125. React.createElement('circle', { cx: c, cy: c, r: z, fill: colors[i++] })
  126. );
  127. }
  128. }