@reality.eth/contracts 3.2.25 → 3.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/chains/deployments/10/OETH/RealityETH-3.0.json +3 -1
  2. package/chains/deployments/100/XDAI/RealityETH-3.0.json +3 -1
  3. package/chains/deployments/8453/ETH/RealityETH-3.0.json +3 -1
  4. package/chains/supported.json +62 -14
  5. package/generated/chains.json +23 -0
  6. package/generated/contract_token_lookup.json +476 -0
  7. package/generated/contracts.json +9 -3
  8. package/generated/tokens.json +45 -23
  9. package/generated/website-data.js +1 -0
  10. package/package.json +7 -3
  11. package/scripts/generate_chains_json.js +8 -0
  12. package/scripts/generate_contract_token_lookup.js +40 -0
  13. package/scripts/generate_indexer_config.js +111 -0
  14. package/scripts/generate_ponder_config.js +222 -0
  15. package/scripts/generate_website_data.js +68 -0
  16. package/scripts/update_token_prices.js +144 -0
  17. package/tests/python/requirements.txt +0 -4
  18. package/tests/python/test.py +37 -34
  19. package/tests/python/test_erc20.py +27 -25
  20. package/tokens/ARETH.json +3 -2
  21. package/tokens/AVAX.json +2 -1
  22. package/tokens/BNB.json +2 -1
  23. package/tokens/BOND.json +2 -1
  24. package/tokens/CELO.json +3 -2
  25. package/tokens/CTH.json +2 -1
  26. package/tokens/DAOOS.json +2 -1
  27. package/tokens/DEXE.json +2 -1
  28. package/tokens/ETH.json +3 -2
  29. package/tokens/FOX.json +2 -1
  30. package/tokens/GNO.json +4 -3
  31. package/tokens/MATIC.json +2 -1
  32. package/tokens/MONAD.json +3 -2
  33. package/tokens/OETH.json +3 -2
  34. package/tokens/POLK.json +2 -1
  35. package/tokens/SUKU.json +2 -1
  36. package/tokens/SWISE.json +2 -1
  37. package/tokens/TLOS.json +3 -2
  38. package/tokens/TRST.json +2 -1
  39. package/tokens/UBQ.json +2 -1
  40. package/tokens/XDAI.json +3 -2
  41. package/tokens/ZBS.json +2 -1
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Generates packages/ponder/ponder.config.ts from packages/contracts/generated/contracts.json.
3
+ * Chain names are derived from the network_name field in generated/chains.json (populated from
4
+ * chains/supported.json and chainlist.org data).
5
+ *
6
+ * Usage:
7
+ * cd packages/contracts && node scripts/generate_ponder_config.js
8
+ */
9
+
10
+ 'use strict';
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ const projectBase = path.resolve(__dirname, '..');
15
+ const ponderPkg = path.resolve(projectBase, '../ponder');
16
+ const contracts = JSON.parse(fs.readFileSync(path.join(projectBase, 'generated/contracts.json'), 'utf8'));
17
+ const chains = JSON.parse(fs.readFileSync(path.join(projectBase, 'generated/chains.json'), 'utf8'));
18
+
19
+ // Ponder chain name derived from chains.json network_name:
20
+ // lowercase, hyphens/spaces → underscores. Falls back to "chain_{id}".
21
+ function cname(id) {
22
+ const nn = chains[id] && chains[id].network_name;
23
+ if (!nn) return `chain_${id}`;
24
+ return nn.toLowerCase().replace(/[-\s.]+/g, '_');
25
+ }
26
+
27
+ // Polling intervals (ms) keyed by chain ID.
28
+ // Derived from block time, but capped to avoid excessive RPC calls on fast chains.
29
+ const POLL_MS = {
30
+ 1: 12_000,
31
+ 4: 15_000,
32
+ 5: 15_000,
33
+ 8: 30_000,
34
+ 10: 30_000,
35
+ 40: 30_000,
36
+ 56: 3_000,
37
+ 69: 15_000,
38
+ 77: 15_000,
39
+ 97: 3_000,
40
+ 100: 5_000,
41
+ 130: 8_000,
42
+ 137: 15_000,
43
+ 143: 10_000,
44
+ 280: 15_000,
45
+ 300: 30_000,
46
+ 324: 30_000,
47
+ 534353: 15_000,
48
+ 690: 30_000,
49
+ 777: 15_000,
50
+ 1101: 30_000,
51
+ 1301: 10_000,
52
+ 1337702: 15_000,
53
+ 8453: 30_000,
54
+ 10200: 15_000,
55
+ 17000: 30_000,
56
+ 42161: 300_000, // Arbitrum produces blocks very fast; poll slowly to avoid RPC hammering
57
+ 42220: 30_000,
58
+ 43114: 30_000,
59
+ 80001: 15_000,
60
+ 84532: 30_000,
61
+ 421611: 15_000,
62
+ 421613: 30_000,
63
+ 421614: 30_000,
64
+ 11155111: 30_000,
65
+ 11155420: 30_000,
66
+ 88558801: 10_000,
67
+ };
68
+
69
+ const cpoll = id => POLL_MS[id] || 15_000;
70
+ // Format a number with _ as thousands separator (e.g. 12000 → "12_000")
71
+ const fnum = n => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, '_');
72
+
73
+ // Versions to skip entirely (arbitrators, release candidates)
74
+ const SKIP_VERSIONS = new Set(['Arbitrator', 'Arbitrator_RealityETH-2.1', 'RealityETH-2.1-rc1']);
75
+
76
+ // Convert a native version string to a ponder contract name (null = skip)
77
+ function nativePonderName(ver) {
78
+ if (SKIP_VERSIONS.has(ver)) return null;
79
+ const m = ver.match(/^RealityETH-(\d+)\.(\d+)$/);
80
+ return m ? `RealityETH_v${m[1]}_${m[2]}` : null;
81
+ }
82
+
83
+ const isERC20 = ver => ver.startsWith('RealityETH_ERC20-');
84
+
85
+ // ── Collect data ──────────────────────────────────────────────────────────────
86
+
87
+ // native: ponderName → { chainId → [ { address, block } ] }
88
+ // (array because a chain can have multiple tokens for the same version, e.g. Scroll Alpha ETH+SETH)
89
+ const native = {};
90
+ // erc20: chainId → [ { address, block } ]
91
+ const erc20 = {};
92
+ const chainIds = new Set();
93
+
94
+ for (const [cidStr, byToken] of Object.entries(contracts)) {
95
+ const cid = Number(cidStr);
96
+ for (const byVersion of Object.values(byToken)) {
97
+ for (const [ver, data] of Object.entries(byVersion)) {
98
+ if (!data.address) continue;
99
+ if (isERC20(ver)) {
100
+ if (!erc20[cid]) erc20[cid] = [];
101
+ erc20[cid].push({ address: data.address, block: data.block || 0 });
102
+ chainIds.add(cid);
103
+ } else {
104
+ const pn = nativePonderName(ver);
105
+ if (!pn) continue;
106
+ if (!native[pn]) native[pn] = {};
107
+ if (!native[pn][cid]) native[pn][cid] = [];
108
+ native[pn][cid].push({ address: data.address, block: data.block || 0 });
109
+ chainIds.add(cid);
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ // ── Sort order ────────────────────────────────────────────────────────────────
116
+
117
+ // Priority chains come first in output (major production chains)
118
+ const PRIORITY_CHAINS = [1, 100, 10, 8453, 42161, 56, 130, 137, 11155111];
119
+ const sortedCids = [...chainIds].sort((a, b) => {
120
+ const ai = PRIORITY_CHAINS.indexOf(a), bi = PRIORITY_CHAINS.indexOf(b);
121
+ if (ai >= 0 && bi >= 0) return ai - bi;
122
+ if (ai >= 0) return -1;
123
+ if (bi >= 0) return 1;
124
+ return a - b;
125
+ });
126
+
127
+ // Preferred version output order
128
+ const VER_ORDER = ['RealityETH_v3_2', 'RealityETH_v3_0', 'RealityETH_v2_1', 'RealityETH_v2_0'];
129
+ const sortedNative = Object.keys(native).sort((a, b) => {
130
+ const ai = VER_ORDER.indexOf(a), bi = VER_ORDER.indexOf(b);
131
+ if (ai >= 0 && bi >= 0) return ai - bi;
132
+ if (ai >= 0) return -1;
133
+ if (bi >= 0) return 1;
134
+ return a.localeCompare(b);
135
+ });
136
+
137
+ // ── Build output lines ────────────────────────────────────────────────────────
138
+
139
+ const lines = [];
140
+ const p = (...args) => lines.push(...args);
141
+
142
+ p(
143
+ '// AUTO-GENERATED by packages/contracts/scripts/generate_ponder_config.js',
144
+ '// Do not edit by hand — run `cd packages/contracts && npm run generate-ponder-config`',
145
+ 'import { createConfig } from "ponder";',
146
+ 'import type { Abi } from "abitype";',
147
+ 'import rawAbi from "@reality.eth/contracts/abi/solc-0.8.6/RealityETH-3.2.abi.json";',
148
+ 'const abi = rawAbi as unknown as Abi;',
149
+ '',
150
+ );
151
+
152
+ // Use double-quoted strings so ${id} is literal in the TypeScript output
153
+ p(
154
+ "const has = (id: number) => !!process.env[`PONDER_RPC_URL_${id}`];",
155
+ "const rpc = (id: number) => process.env[`PONDER_RPC_URL_${id}`] as string;",
156
+ "const rps = (id: number) => process.env[`PONDER_RPC_MAX_RPS_${id}`] ? { maxRequestsPerSecond: Number(process.env[`PONDER_RPC_MAX_RPS_${id}`]) } : {};",
157
+ '',
158
+ 'export default createConfig({',
159
+ ' chains: {',
160
+ );
161
+
162
+ for (const cid of sortedCids) {
163
+ const n = cname(cid);
164
+ const pi = fnum(cpoll(cid));
165
+ p(` ...(has(${cid}) && { ${n}: { id: ${cid}, rpc: rpc(${cid}), pollingInterval: ${pi}, ...rps(${cid}) } }),`);
166
+ }
167
+
168
+ p(' },', ' contracts: {');
169
+
170
+ // Native contracts
171
+ for (const pn of sortedNative) {
172
+ const chainMap = native[pn];
173
+ const relevantCids = sortedCids.filter(cid => chainMap[cid]);
174
+ if (!relevantCids.length) continue;
175
+
176
+ const guardExpr = relevantCids.length === 1
177
+ ? `has(${relevantCids[0]})`
178
+ : `(${relevantCids.map(c => `has(${c})`).join(' || ')})`;
179
+
180
+ p(` ...(${guardExpr} && { ${pn}: {`);
181
+ p(` abi,`);
182
+ p(` chain: {`);
183
+ for (const cid of relevantCids) {
184
+ const entries = chainMap[cid].sort((a, b) => a.block - b.block);
185
+ const startBlock = entries[0].block;
186
+ const addrVal = entries.length === 1
187
+ ? `"${entries[0].address}"`
188
+ : `[\n ${entries.map(e => `"${e.address}"`).join(',\n ')},\n ]`;
189
+ p(` ...(has(${cid}) && { ${cname(cid)}: { address: ${addrVal}, startBlock: ${startBlock} } }),`);
190
+ }
191
+ p(` },`);
192
+ p(` }}),`);
193
+ p('');
194
+ }
195
+
196
+ // ERC20 contracts, grouped by chain
197
+ for (const cid of sortedCids) {
198
+ if (!erc20[cid]) continue;
199
+ const sorted = [...erc20[cid]].sort((a, b) => a.block - b.block);
200
+ const n = cname(cid);
201
+ const contractName = `RealityETH_ERC20_${n}`;
202
+ const startBlock = sorted[0].block;
203
+ const addrVal = sorted.length === 1
204
+ ? `"${sorted[0].address}"`
205
+ : `[\n ${sorted.map(x => `"${x.address}"`).join(',\n ')},\n ]`;
206
+
207
+ p(` ...(has(${cid}) && { ${contractName}: {`);
208
+ p(` abi,`);
209
+ p(` chain: {`);
210
+ p(` ${n}: { address: ${addrVal}, startBlock: ${startBlock} },`);
211
+ p(` },`);
212
+ p(` }}),`);
213
+ p('');
214
+ }
215
+
216
+ p(' },', '});', '');
217
+
218
+ // ── Write ─────────────────────────────────────────────────────────────────────
219
+
220
+ const outPath = path.join(ponderPkg, 'ponder.config.ts');
221
+ fs.writeFileSync(outPath, lines.join('\n'));
222
+ console.log('Wrote', outPath);
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Bundles all website data files into a single JS file that can be loaded
3
+ * as a <script> tag, enabling the site to run from file:// (IPFS).
4
+ *
5
+ * Usage:
6
+ * node scripts/generate_website_data.js # writes to generated/website-data.js
7
+ * node scripts/generate_website_data.js --install # also copies to packages/frontend/webroot/js/
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const project_base = path.resolve(__dirname, '..');
14
+ const webroot = path.resolve(project_base, '../../packages/frontend/webroot');
15
+ const install = process.argv.includes('--install');
16
+
17
+ const chains = JSON.parse(fs.readFileSync(path.join(project_base, 'generated/chains.json'), 'utf8'));
18
+ const contracts = JSON.parse(fs.readFileSync(path.join(project_base, 'generated/contracts.json'), 'utf8'));
19
+ const factories = JSON.parse(fs.readFileSync(path.join(project_base, 'generated/factories.json'), 'utf8'));
20
+ const tokens = JSON.parse(fs.readFileSync(path.join(project_base, 'generated/tokens.json'), 'utf8'));
21
+ const integrations = JSON.parse(fs.readFileSync(path.join(webroot, 'integrations.json'), 'utf8'));
22
+
23
+ // Flat map: chainId (string) → native token symbol. Covers all chains in chains.json.
24
+ const nativeTokenByChain = {};
25
+ for (const [chainId, chainData] of Object.entries(chains)) {
26
+ const symbol = chainData.nativeCurrency?.symbol;
27
+ if (symbol) nativeTokenByChain[chainId] = symbol;
28
+ }
29
+
30
+ // Flat map: chainId (string) → small bond in wei (as number, safe as IEEE-754 double).
31
+ const smallBondByChain = {};
32
+ for (const [chainId, symbol] of Object.entries(nativeTokenByChain)) {
33
+ const t = tokens[symbol];
34
+ if (t?.small_number != null) smallBondByChain[chainId] = t.small_number;
35
+ }
36
+
37
+ // Flat index: lowercase contract address → metadata. Derived from contracts.json.
38
+ const contractsByAddress = {};
39
+ for (const [chainId, chainContracts] of Object.entries(contracts)) {
40
+ for (const [tokenTicker, tokenVersions] of Object.entries(chainContracts)) {
41
+ const tokenDecimals = tokens[tokenTicker]?.decimals ?? 18;
42
+ for (const [versionName, versionData] of Object.entries(tokenVersions)) {
43
+ if (!versionData.address) continue;
44
+ const majorMatch = versionName.match(/-(\d+)\./);
45
+ contractsByAddress[versionData.address.toLowerCase()] = {
46
+ majorVersion: majorMatch ? parseInt(majorMatch[1]) : null,
47
+ startBlock: versionData.block ?? 0,
48
+ tokenTicker,
49
+ tokenDecimals,
50
+ tokenAddress: versionData.token_address ?? null,
51
+ chainId: parseInt(chainId),
52
+ };
53
+ }
54
+ }
55
+ }
56
+
57
+ const data = { chains, contracts, factories, tokens, integrations, nativeTokenByChain, smallBondByChain, contractsByAddress };
58
+ const output = 'window.RealityWebsiteData = ' + JSON.stringify(data) + ';\n';
59
+
60
+ const generatedPath = path.join(project_base, 'generated/website-data.js');
61
+ fs.writeFileSync(generatedPath, output);
62
+ console.log('Wrote', generatedPath);
63
+
64
+ if (install) {
65
+ const installPath = path.join(webroot, 'js/vendor/website-data.js');
66
+ fs.writeFileSync(installPath, output);
67
+ console.log('Installed to', installPath);
68
+ }
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ // Fetches approximate USD values for all tokens and writes approx_1_usd to each token JSON.
3
+ //
4
+ // approx_1_usd: how many of this token equals ~$1 USD.
5
+ // Used for sorting bonds by USD value: usd_value = bond_in_units / approx_1_usd
6
+ //
7
+ // Testnet-only tokens are valued at 1/1,000,000 of the mainnet token they represent.
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ const TOKENS_DIR = path.join(__dirname, '..', 'tokens');
15
+
16
+ // Maps our token symbol to a CoinGecko coin ID.
17
+ // OETH and ARETH are just ETH on L2 chains — same price.
18
+ const COINGECKO_IDS = {
19
+ ETH: 'ethereum',
20
+ OETH: 'ethereum',
21
+ ARETH: 'ethereum',
22
+ BNB: 'binancecoin',
23
+ GNO: 'gnosis',
24
+ XDAI: 'xdai',
25
+ MATIC: 'matic-network',
26
+ AVAX: 'avalanche-2',
27
+ CELO: 'celo',
28
+ FOX: 'shapeshift-fox-token',
29
+ SWISE: 'stakewise',
30
+ POLK: 'polkamarkets',
31
+ DEXE: 'dexe',
32
+ SUKU: 'suku',
33
+ TRST: 'wetrust',
34
+ UBQ: 'ubiq',
35
+ TLOS: 'telos',
36
+ };
37
+
38
+ // Testnet-only tokens. Value = (mainnet base price) / 1,000,000.
39
+ // The base coin is what they nominally represent for ordering purposes.
40
+ const TESTNET_BASE = {
41
+ BOND: 'ethereum', // arbitrary Sepolia ERC20
42
+ DAOOS: 'ethereum', // dead Rinkeby test token
43
+ MONAD: 'ethereum', // Monad testnet, mainnet not launched
44
+ ZBS: 'ethereum', // dev-chain token
45
+ CTH: 'ethereum', // dev-chain token
46
+ };
47
+
48
+ // Hardcoded fallback prices (USD per token) used when CoinGecko is unavailable.
49
+ // Values are approximate and should be refreshed periodically by running this script.
50
+ const FALLBACKS = {
51
+ ethereum: 3500,
52
+ binancecoin: 650,
53
+ gnosis: 250,
54
+ xdai: 1,
55
+ 'matic-network': 0.45,
56
+ 'avalanche-2': 38,
57
+ celo: 0.60,
58
+ 'shapeshift-fox-token': 0.03,
59
+ stakewise: 0.15,
60
+ polkamarkets: 0.008,
61
+ dexe: 12,
62
+ suku: 0.007,
63
+ wetrust: 0.004,
64
+ ubiq: 0.02,
65
+ telos: 0.06,
66
+ };
67
+
68
+ async function fetchCoinGeckoPrices(ids) {
69
+ const url = 'https://api.coingecko.com/api/v3/simple/price?ids=' + ids.join(',') + '&vs_currencies=usd';
70
+ const res = await fetch(url, {
71
+ headers: { Accept: 'application/json' },
72
+ signal: AbortSignal.timeout(12000),
73
+ });
74
+ if (!res.ok) throw new Error('HTTP ' + res.status);
75
+ return res.json();
76
+ }
77
+
78
+ async function main() {
79
+ const allCgIds = [...new Set([
80
+ ...Object.values(COINGECKO_IDS),
81
+ ...Object.values(TESTNET_BASE),
82
+ ])];
83
+
84
+ let cgPrices = {};
85
+ let liveData = false;
86
+
87
+ console.log('Fetching prices from CoinGecko...');
88
+ try {
89
+ const data = await fetchCoinGeckoPrices(allCgIds);
90
+ cgPrices = data;
91
+ liveData = true;
92
+ console.log('Live prices fetched.\n');
93
+ } catch (err) {
94
+ console.warn('CoinGecko unavailable (' + err.message + '), using hardcoded fallbacks.\n');
95
+ for (const [id, usd] of Object.entries(FALLBACKS)) {
96
+ cgPrices[id] = { usd };
97
+ }
98
+ }
99
+
100
+ function getPrice(cgId) {
101
+ return (cgPrices[cgId] && cgPrices[cgId].usd) || FALLBACKS[cgId] || null;
102
+ }
103
+
104
+ const tokenFiles = fs.readdirSync(TOKENS_DIR).filter(f => f.endsWith('.json')).sort();
105
+
106
+ for (const file of tokenFiles) {
107
+ const symbol = file.replace('.json', '');
108
+ const filePath = path.join(TOKENS_DIR, file);
109
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
110
+
111
+ let priceUsd = null;
112
+ let note = '';
113
+
114
+ if (COINGECKO_IDS[symbol]) {
115
+ const cgId = COINGECKO_IDS[symbol];
116
+ priceUsd = getPrice(cgId);
117
+ note = liveData ? 'live (' + cgId + ')' : 'fallback (' + cgId + ')';
118
+ } else if (TESTNET_BASE[symbol]) {
119
+ const baseId = TESTNET_BASE[symbol];
120
+ const basePrice = getPrice(baseId);
121
+ if (basePrice) {
122
+ priceUsd = basePrice / 1_000_000;
123
+ note = 'testnet 1/1M of ' + baseId + ' ($' + basePrice + ')';
124
+ }
125
+ }
126
+
127
+ if (!priceUsd || priceUsd <= 0) {
128
+ console.warn(' ' + symbol + ': no price found, skipping');
129
+ continue;
130
+ }
131
+
132
+ const approx1Usd = parseFloat((1 / priceUsd).toPrecision(6));
133
+ data.approx_1_usd = approx1Usd;
134
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 4) + '\n');
135
+ console.log(' ' + symbol.padEnd(6) + ' $' + priceUsd.toPrecision(4).padStart(10) + '/token → approx_1_usd = ' + approx1Usd + ' (' + note + ')');
136
+ }
137
+
138
+ console.log('\nDone.');
139
+ if (!liveData) {
140
+ console.log('NOTE: hardcoded fallbacks used. Re-run when network is available for live prices.');
141
+ }
142
+ }
143
+
144
+ main().catch(err => { console.error(err); process.exit(1); });
@@ -4,7 +4,6 @@ asn1crypto==1.5.1
4
4
  async-timeout==4.0.3
5
5
  attrs==23.2.0
6
6
  bitarray==2.9.2
7
- bitcoin==1.1.42
8
7
  cached-property==1.5.2
9
8
  certifi==2023.11.17
10
9
  cffi==1.16.0
@@ -21,7 +20,6 @@ eth-rlp==1.0.0
21
20
  eth-tester==0.10.0b1
22
21
  eth-typing==3.5.2
23
22
  eth-utils==2.3.1
24
- ethereum==2.3.2
25
23
  frozenlist==1.4.1
26
24
  future==0.18.3
27
25
  hexbytes==0.3.1
@@ -41,14 +39,12 @@ py-evm==0.8.0b1
41
39
  pycparser==2.21
42
40
  pycryptodome==3.19.1
43
41
  pyethash==0.1.27
44
- pysha3==1.0.2
45
42
  pyunormalize==15.1.0
46
43
  PyYAML==6.0.1
47
44
  referencing==0.32.1
48
45
  regex==2023.12.25
49
46
  repoze.lru==0.7
50
47
  requests==2.31.0
51
- rlp==3.0.0
52
48
  rpds-py==0.16.2
53
49
  scrypt==0.8.20
54
50
  semantic-version==2.10.0