Skip to content

Instantly share code, notes, and snippets.

View ardislu's full-sized avatar

Ardis Lu ardislu

View GitHub Profile
@ardislu
ardislu / eip-6963.js
Created July 10, 2024 04:16
The minimal JavaScript to select an EIP-6963 wallet as window.ethereum in the DevTools console for quick testing.
// EIP-6963: Multi Injected Provider Discovery
// https://eips.ethereum.org/EIPS/eip-6963
const wallets = [];
window.addEventListener('eip6963:announceProvider', e => wallets.push(e.detail));
window.dispatchEvent(new Event('eip6963:requestProvider'));
console.table(wallets.map(w => w.info.name));
console.log('Wallets have been collected in the \x1B[1;4mwallets\x1B[m object.');
console.log('Basic example to set window.ethereum:\n \x1B[1mwindow.ethereum = wallets[0].provider;\x1B[m');
@ardislu
ardislu / erc-7201.js
Created May 29, 2024 06:13
JavaScript implementation of ERC-7201 ("Namespaced Storage Layout") using noble-hashes.
// JavaScript implementation of ERC-7201 ("Namespaced Storage Layout") using noble-hashes
// https://ercs.ethereum.org/ERCS/erc-7201
// https://github.com/paulmillr/noble-hashes
// import { keccak_256 } from '@noble/hashes/sha3';
const { keccak_256 } = await import('https://esm.sh/@noble/hashes@1.4.0/esm/sha3.js');
function arrToBigInt(arr) {
const hex = `0x${[...arr].map(b => b.toString(16).padStart(2, '0')).join('')}`;
return BigInt(hex);
@ardislu
ardislu / rot13.js
Created May 8, 2024 04:26
Golfed ROT13 in JavaScript.
// Ignores input casing, output will be all lowercase.
const r=s=>s.replace(/[a-z]/gi,c=>(((parseInt(c,36)+3)%26)+10).toString(36));
// r('the quick brown fox jumps over the lazy dog')
// 'gur dhvpx oebja sbk whzcf bire gur ynml qbt'
// r('gur dhvpx oebja sbk whzcf bire gur ynml qbt')
// 'the quick brown fox jumps over the lazy dog'
@ardislu
ardislu / littleEndian64ToBigInt.js
Created April 21, 2024 05:43
Convert a hex string of 8 bytes into a BigInt.
// Converts a hex string of 8 bytes into a BigInt.
// Useful for converting Ethereum's Beacon Deposit Contract get_deposit_count().
// https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa
function littleEndian64ToBigInt(bytes) {
bytes = bytes.replace('0x', '').replaceAll(/\s/g, '');
return new DataView(Uint8Array.from(bytes.matchAll(/.{2}/g), b => parseInt(b, 16)).buffer).getBigUint64(0, true);
}
// Example:
// littleEndian64ToBigInt('0x0519160000000000')
@ardislu
ardislu / erc-7673.js
Last active June 19, 2024 07:14
Minimal JavaScript implementation of ERC-7673.
// Utility functions to convert an Ethereum hexadecimal address to base256emoji and vice versa.
// https://ercs.ethereum.org/ERCS/erc-7673
const toEmoji = [
'🚀', '🪐', '☄', '🛰', '🌌', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', '🌍', '🌏', '🌎',
'🐉', '☀', '💻', '🖥', '💾', '💿', '😂', '❤', '😍', '🤣', '😊', '🙏', '💕', '😭', '😘', '👍',
'😅', '👏', '😁', '🔥', '🥰', '💔', '💖', '💙', '😢', '🤔', '😆', '🙄', '💪', '😉', '☺', '👌',
'🤗', '💜', '😔', '😎', '😇', '🌹', '🤦', '🎉', '💞', '✌', '✨', '🤷', '😱', '😌', '🌸', '🙌',
'😋', '💗', '💚', '😏', '💛', '🙂', '💓', '🤩', '😄', '😀', '🖤', '😃', '💯', '🙈', '👇', '🎶',
'😒', '🤭', '❣', '😜', '💋', '👀', '😪', '😑', '💥', '🙋', '😞', '😩', '😡', '🤪', '👊', '🥳',
@ardislu
ardislu / minimal-endianness.js
Created March 27, 2024 06:27
This is the minimum amount of JavaScript (74 characters) to detect the endianness of a platform.
// The magic number 0xFEFF is selected for familiarity with the commonly-used
// byte-order mark (BOM) character (https://en.wikipedia.org/wiki/Byte_order_mark).
const isLE = new Uint8Array(new Uint16Array([0xFEFF]).buffer)[0] === 0xFF;
// Golfed (-12 characters; 62 total characters):
// const isLE=new Uint8Array(new Uint16Array([256]).buffer)[0]<1;
@ardislu
ardislu / copy-all-code.js
Created February 21, 2024 07:10
Simple script to copy all the code blocks at once from an Etherscan smart contract code page.
// Simple script to copy all the code blocks at once from an Etherscan smart contract code page
// (example: https://etherscan.io/address/0x43506849d7c04f9138d1a2050bbf3a0c054402dd#code).
// Uses a hardcoded CSS selector, must update if Etherscan updates its frontend markup
// (this script was last updated February 2024).
// References:
// 1. Etherscan uses Ace for code blocks (https://ace.c9.io/)
// - API reference: https://ajaxorg.github.io/ace-api-docs/
// 2. Etherscan's "Copy source to clipboard" button is implemented in `copySourceCodeBtn`,
@ardislu
ardislu / erc-55.js
Last active May 29, 2024 05:42
JavaScript implementation of ERC-55 ("Mixed-case checksum address encoding") using noble-hashes.
// JavaScript implementation of ERC-55 ("Mixed-case checksum address encoding") using noble-hashes
// https://ercs.ethereum.org/ERCS/erc-55
// https://github.com/paulmillr/noble-hashes
// import { keccak_256 } from '@noble/hashes/sha3';
const { keccak_256 } = await import('https://esm.sh/@noble/hashes@1.4.0/esm/sha3.js');
function toChecksumAddress(address) {
address = address.toLowerCase().replace('0x', '');
// Hash the address (treat it as UTF-8) and return as a hex string
@ardislu
ardislu / ethereum-address-from-signature.js
Last active September 23, 2023 05:15
This is the minimum amount of JavaScript code to derive an Ethereum address from a signature, using the low-level noble-crypto libraries to minimize dependencies.
import { Signature } from '@noble/secp256k1';
import { keccak_256 } from '@noble/hashes/sha3';
// The message that will be signed
const message = 'Any arbitrary message here. 🏴‍☠️💯😂';
const encodedMessage = new TextEncoder().encode(message);
// Assuming "signature" has been acquired from the user and is in string hex form.
// Note that MetaMask and most other high-level tools will automatically inject the ERC-191 prefix to messages.
// For example, here's the minimal code to request a signature from MetaMask (assuming the below code is run in a frontend):
@ardislu
ardislu / camelCaseToTitleCase.js
Created June 2, 2023 04:35
Simple utility function to convert a camelCase string into Title Case With Spaces for human readability.
/**
* Converts a camelCase string into Title Case With Spaces for human readability.
* @param {string} str - A string in camelCase.
* @returns {string} The input string converted into Title Case With Spaces.
*/
function camelCaseToTitleCase(str) {
str = str[0].toLocaleUpperCase() + str.slice(1);
return str.replaceAll(/([A-Z]+)/g, ' $1').slice(1);
}