PROOF OF SLEEP

Humans sleep.
Machines don't.

748,667 NEAR accounts were active in the first two weeks of October 2026. Only 61,957 were active on at least 5 of those days. 5,771 of them keep a sleep-sized quiet stretch the way a person does.

Try:

0006121800
Sleeps. Never active during the same 9 hours, and active at many other hours across two weeks.
0006121800
Never sleeps. Active in nearly every hour of every day. A program.
0006121800
On a timer. Always the same hour of the day and never anything else.

Three real accounts from NEAR, names removed. Each row is one day; each mark is an hour with at least one transaction, in UTC.

What the test found

We took the first two weeks of every month since January 2021 and looked at when each account signs transactions. Over two weeks, an account passes if it uses at least 6 different hours of the clock, never touches a stretch of 5 to 14 hours in a row, and that stretch is longer than chance would produce.

5,771
accounts passed the sleep test

Out of 61,957 accounts active on at least 5 of those 14 days. This is not a head count: the test misses most verified humans, and some accounts pass by chance.

74%
of transactions came from 340 accounts that never sleep

The other 61,617 regular accounts and the 686,710 occasional ones share the rest.

−95%
accounts passing since Jun 2024

111,138 then. 5,771 now.

84%
of accounts passing are Telegram accounts

Named .near accounts that pass: 585, up from a Jul 2026 low of 235, but far below 9,016 in Jun 2024.

The headline number is mostly not people

Active accounts or actual people?

In the latest window 748,667 accounts were active, but 668,994 of them showed up on only one or two days, up from 60,870 the month before. The count of active accounts swings on bursts like that. The accounts that pass the test barely move with it: monthly changes correlate at 0.19.

101001K10K100K1M10M100M202120222023202420252026748,66761,9575,771
  • Active accounts
  • Active on 5+ of 14 days
  • Passed the sleep test
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/00_account_windows.sql

-- Step 0. One row per account per 14-day window, with its daily rhythm features.
-- Everything else reads this table, so the expensive scan of `transactions` happens once.
-- The filter on block_date is literal: only the sampled days are read and billed.
-- Not partitioned by date on purpose: BigQuery's free tier deletes date partitions older than 60 days.
CREATE OR REPLACE TABLE `your-project.proof_of_sleep.account_windows`
CLUSTER BY window_start, class AS
WITH slots AS (                             -- one row per account, day and hour with activity
  SELECT
    signer_account_id AS account,
    DATE_TRUNC(block_date, MONTH) AS window_start,
    block_date,
    EXTRACT(HOUR FROM block_timestamp_utc) AS hour,
    COUNT(*) AS n_tx
  FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
  WHERE block_date BETWEEN ... -- 70 two-week windows, listed in pipeline/config.py
  GROUP BY 1, 2, 3, 4
),
days AS (                                   -- which hours each active day used
  SELECT
    account, window_start, block_date,
    SUM(n_tx) AS n_tx,
    COUNT(*) AS n_slots,
    BIT_OR(1 << hour) AS day_mask
  FROM slots
  GROUP BY 1, 2, 3
),
accounts AS (                               -- all the hours of the clock the account ever used
  SELECT
    account, window_start,
    SUM(n_tx) AS n_tx,
    COUNT(*) AS n_days,
    SUM(n_slots) AS n_slots,
    BIT_OR(day_mask) AS hour_mask
  FROM days
  GROUP BY 1, 2
),
hours AS (
  SELECT *, ARRAY(SELECT h FROM UNNEST(GENERATE_ARRAY(0, 23)) AS h WHERE (hour_mask >> h) & 1 = 1) AS hs
  FROM accounts
),
gaps AS (                                   -- the longest stretch of hours never used, wrapping past midnight
  SELECT *,
    (SELECT AS STRUCT gap, start_h
     FROM (
       SELECT h AS start_h,
              COALESCE((SELECT MIN(h2) FROM UNNEST(hs) AS h2 WHERE h2 > h), hs[OFFSET(0)] + 24) - h - 1 AS gap
       FROM UNNEST(hs) AS h
     )
     ORDER BY gap DESC, start_h
     LIMIT 1) AS g
  FROM hours
),
classified AS (
  SELECT
    account, window_start, n_tx, n_days, n_slots, hour_mask,
    ARRAY_LENGTH(hs) AS n_hours,
    g.gap AS gap,
    -- middle of the quiet stretch, as a clock hour (UTC)
    (g.start_h + 1 + g.gap / 2) - 24 * FLOOR((g.start_h + 1 + g.gap / 2) / 24) AS mid,
    CASE
      WHEN n_days < 5 THEN 'too_few'
      WHEN g.gap <= 2 AND n_slots / n_days >= 8 THEN 'machine'
      WHEN ARRAY_LENGTH(hs) <= 3 THEN 'timer'
      WHEN g.gap >= 5 AND g.gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(ARRAY_LENGTH(hs))] AND g.gap <= 14 AND ARRAY_LENGTH(hs) >= 6 THEN 'sleeper'
      WHEN g.gap >= 5 AND g.gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(ARRAY_LENGTH(hs))] THEN 'routine'
      ELSE 'unclear'
    END AS class
  FROM gaps
)
SELECT                                      -- accounts seen on 1-2 days are kept only as counts
  IF(n_days >= 3, account, '_light_') AS account,
  window_start,
  COUNT(*) AS accounts,
  SUM(n_tx) AS n_tx,
  n_days,
  SUM(n_slots) AS n_slots,
  IF(n_days >= 3, ANY_VALUE(hour_mask), NULL) AS hour_mask,
  IF(n_days >= 3, ANY_VALUE(n_hours), NULL) AS n_hours,
  IF(n_days >= 3, ANY_VALUE(gap), NULL) AS gap,
  IF(n_days >= 3, ANY_VALUE(mid), NULL) AS mid,
  IF(n_days >= 3, ANY_VALUE(class), 'light') AS class
FROM classified
GROUP BY 1, 2, n_days

sql/01_classes.sql

-- Headline table: how many accounts fall in each class in each 14-day window,
-- and how many transactions each class sent.
SELECT
  window_start,
  class,
  SUM(accounts) AS accounts,
  SUM(n_tx) AS txs
FROM `your-project.proof_of_sleep.account_windows`
GROUP BY 1, 2
ORDER BY 1, 2
The numbers as a table
Window (first 14 days of)Active accountsActive on 5+ of 14 daysPassed sleep testNarrow daily routineNever sleepsTransactions
2021-01-015,776253411115122,232
2021-02-0110,024361582111127,800
2021-03-0114,6165011101514185,378
2021-04-0133,1015301163519363,032
2021-05-0129,41192720347114897,225
2021-06-0174,6471,678441562202,045,255
2021-07-0134,3402,425702622652,340,662
2021-08-01118,3683,2249291024403,463,547
2021-09-01354,5235,5221,4851746674,255,286
2021-10-01115,2977,2372,1713394153,518,602
2021-11-01203,66013,2773,3218793604,052,958
2021-12-01261,7686,7821,6275693544,430,472
2022-01-01118,5138,4332,3374075278,673,147
2022-02-0199,80212,1953,8195144657,187,121
2022-03-01138,33110,7363,2675533325,627,966
2022-04-01101,85510,3472,9074584439,689,195
2022-05-0196,43310,5863,05952035214,858,182
2022-06-0171,9439,8932,6855742548,658,237
2022-07-0198,4016,7021,6904662374,665,387
2022-08-0170,6887,8292,0374672524,748,058
2022-09-01365,2226,7841,7773662305,979,219
2022-10-01691,41943,8516,4325,4992147,253,392
2022-11-01632,43726,6504,2383,1952847,985,619
2022-12-01520,49717,2942,7462,1771805,193,085
2023-01-01704,27512,9252,1171,4482025,551,618
2023-02-01578,12031,9673,0173,7052525,795,129
2023-03-01499,58516,0731,7191,6642295,151,534
2023-04-01617,43319,7941,8212,0052035,812,206
2023-05-01471,55910,7831,1921,0131624,580,967
2023-06-01692,94014,9971,2911,4341605,325,806
2023-07-01624,61312,1521,2751,1111665,704,618
2023-08-01636,18013,3221,4831,4381545,776,920
2023-09-012,313,745709,6412,70080,17116519,963,441
2023-10-012,057,855759,8092,94941,58315318,772,803
2023-11-012,494,233873,3169,604225,04517722,517,747
2023-12-013,349,732918,18632,61322,17619349,008,837
2024-01-015,615,3521,011,90829,93825,35971548,534,431
2024-02-017,944,838233,29634,33712,4412,54453,305,841
2024-03-017,725,640650,18492,08016,1814,20376,410,828
2024-04-018,323,407975,85181,75929,6863,436110,351,391
2024-05-018,915,8541,154,35477,10138,9115,00796,481,058
2024-06-0111,046,7011,235,478111,13856,0347,381110,356,866
2024-07-0112,471,3971,089,921110,96546,23711,881107,326,305
2024-08-018,672,206818,71181,33925,9556,85585,249,283
2024-09-014,329,171781,85689,00227,1077,724100,469,324
2024-10-015,356,016838,39487,73547,5806,04299,260,270
2024-11-015,195,904746,34585,94536,7275,179103,099,476
2024-12-014,836,679734,51886,31743,8553,403116,932,645
2025-01-015,195,241679,90882,24548,5144,19291,863,420
2025-02-015,039,854607,62164,99047,2872,40094,677,590
2025-03-01946,585573,85151,89148,5512,10490,011,686
2025-04-011,056,208528,38950,90043,8551,38693,386,190
2025-05-01822,311487,52842,47151,2771,05775,855,417
2025-06-01656,162431,40435,20442,6781,12368,578,879
2025-07-01583,558385,63331,68643,47257061,874,081
2025-08-01597,077390,18430,71743,64947471,626,930
2025-09-01523,074360,13030,17549,15442667,780,040
2025-10-01493,617326,90828,52340,18334765,108,083
2025-11-01450,626295,32726,18038,11139359,853,262
2025-12-01425,592262,23622,80336,91228755,219,350
2026-01-01411,189222,82518,46627,87546650,017,345
2026-02-012,244,069188,98214,52624,98726249,299,409
2026-03-01298,115171,61311,66523,75526346,863,806
2026-04-01271,036156,04612,06924,60120716,022,191
2026-05-01277,674141,33510,23919,49920710,669,214
2026-06-01243,104134,00410,77618,07424912,164,250
2026-07-01204,630121,0958,18918,57920310,745,784
2026-08-01168,71898,4706,90213,8951909,359,512
2026-09-01165,79286,4546,62212,1202289,990,120
2026-10-01748,66761,9575,7717,78134012,162,517

Who actually sends the transactions?

Accounts that never sleep sent 74% of all transactions in the latest window. Of the 100 busiest accounts, 99 are machines and 0 sleep, and those 100 sent 72% of everything. Some of this traffic is relayers acting for other accounts: such delegated actions from accounts that do not themselves look like machines were 13% of all transactions.

0%25%50%75%100%20212022202320242025202674.2%
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/01_classes.sql

-- Headline table: how many accounts fall in each class in each 14-day window,
-- and how many transactions each class sent.
SELECT
  window_start,
  class,
  SUM(accounts) AS accounts,
  SUM(n_tx) AS txs
FROM `your-project.proof_of_sleep.account_windows`
GROUP BY 1, 2
ORDER BY 1, 2

sql/07_concentration.sql

-- How concentrated are transactions? Share of each window's transactions sent by the
-- busiest accounts. Aggregate counts only.
WITH ranked AS (
  SELECT
    window_start,
    n_tx,
    class,
    ROW_NUMBER() OVER (PARTITION BY window_start ORDER BY n_tx DESC, account) AS rnk
  FROM `your-project.proof_of_sleep.account_windows`
  WHERE account != '_light_'
)
SELECT
  window_start,
  SUM(n_tx) AS txs_in_table,
  SUM(IF(rnk <= 10, n_tx, 0)) AS top_10,
  SUM(IF(rnk <= 100, n_tx, 0)) AS top_100,
  SUM(IF(rnk <= 1000, n_tx, 0)) AS top_1000,
  COUNTIF(rnk <= 100 AND class = 'machine') AS top100_machines,
  COUNTIF(rnk <= 100 AND class = 'sleeper') AS top100_sleepers
FROM ranked
GROUP BY 1
ORDER BY 1
The numbers as a table
WindowNever-sleeping accounts' share of transactionsSleepers' share
2021-01-0162.2%7.5%
2021-02-0155.9%7.2%
2021-03-0121.8%17.4%
2021-04-0137.7%3.6%
2021-05-0155.7%9.5%
2021-06-0162.3%11.2%
2021-07-0158.3%13.1%
2021-08-0162.2%12.4%
2021-09-0152.8%11.0%
2021-10-0137.2%17.2%
2021-11-0145.3%15.2%
2021-12-0154.6%13.1%
2022-01-0173.5%7.5%
2022-02-0166.1%10.7%
2022-03-0157.3%14.4%
2022-04-0173.8%7.6%
2022-05-0182.6%4.8%
2022-06-0181.5%6.5%
2022-07-0169.7%10.4%
2022-08-0168.8%10.9%
2022-09-0159.0%9.2%
2022-10-0151.1%9.3%
2022-11-0162.0%8.7%
2022-12-0159.0%8.3%
2023-01-0155.0%6.3%
2023-02-0154.8%8.9%
2023-03-0158.8%8.9%
2023-04-0151.8%8.6%
2023-05-0155.9%7.6%
2023-06-0151.3%6.3%
2023-07-0146.2%5.5%
2023-08-0149.2%5.6%
2023-09-0143.9%7.5%
2023-10-0137.7%6.6%
2023-11-0139.0%6.3%
2023-12-0123.3%1.9%
2024-01-0140.5%2.2%
2024-02-0156.7%2.4%
2024-03-0153.8%4.7%
2024-04-0162.9%2.7%
2024-05-0158.4%3.1%
2024-06-0155.4%3.7%
2024-07-0158.2%3.6%
2024-08-0164.2%3.4%
2024-09-0174.6%2.7%
2024-10-0174.3%2.7%
2024-11-0176.5%2.3%
2024-12-0179.4%2.0%
2025-01-0177.3%2.3%
2025-02-0180.6%1.7%
2025-03-0185.4%1.3%
2025-04-0186.5%1.3%
2025-05-0186.9%1.2%
2025-06-0187.7%1.1%
2025-07-0187.5%1.2%
2025-08-0189.2%1.1%
2025-09-0189.6%1.0%
2025-10-0190.1%1.0%
2025-11-0190.4%0.9%
2025-12-0191.6%0.8%
2026-01-0192.0%0.7%
2026-02-0189.7%0.6%
2026-03-0193.1%0.5%
2026-04-0165.1%1.5%
2026-05-0177.2%1.9%
2026-06-0181.7%1.6%
2026-07-0182.0%1.4%
2026-08-0183.1%1.3%
2026-09-0186.1%1.2%
2026-10-0174.2%1.2%

Does the test work?

These are checks on our own method, including the one that went against it.

Does the test find real people?

NEAR's I-Am-Human registry holds 5,014 accounts verified as unique humans by a face scan. Of the windows where they were regularly active, 25% pass, against 1.9% of accounts with their days shuffled. So the test does find people, but it misses most of them, and it misses more over time: 33% of verified windows passed in 2023 and 15% in 2026.

Accounts verified as humans by a face scan25.4%
All regular accounts, same windows13.5%
Accounts with each day shuffled around the clock1.9%
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/16_verified.sql

-- Outside check. the verified accounts were verified as unique humans by a face scan
-- (NEAR's I-Am-Human soulbound tokens, issuer fractal.i-am-human.near). How do they score?
-- Output is counts by feature, never individual accounts.
SELECT
  window_start,
  gap,
  n_hours,
  n_days,
  n_slots,
  class,
  COUNT(*) AS account_windows
FROM `your-project.proof_of_sleep.account_windows`
WHERE account IN UNNEST([ ... the verified account names, read from the chain by pipeline/pull_verified.py ... ]) AND n_days >= 5
GROUP BY 1, 2, 3, 4, 5, 6
ORDER BY 1, 2, 3, 4, 5, 6
The numbers as a table
ClassSample of all accounts (days not shuffled)Verified humans (account-windows)
sleeper8074,679
routine1,064928
machine38265
timer967316
unclear5,86912,254
Verified windows passing, 202131% of 951
Verified windows passing, 202234% of 3,304
Verified windows passing, 202333% of 3,621
Verified windows passing, 202422% of 6,456
Verified windows passing, 202517% of 3,134
Verified windows passing, 202615% of 976

So how many people is that?

The count of accounts passing is 5,771. How many regular people that implies depends on two rates nobody can measure precisely: how often real people pass, and how often everything else does. Across plausible values the answer runs from about 1,200 to about 34,400, out of 61,957 regular accounts. So this project does not publish a single figure for it.

Non-people pass 2% (shuffled accounts)Non-people pass 5%Non-people pass 9%
Real people pass 25% of the time (all years)19,60013,1001,200
Real people pass 15% of the time (last 12 windows)34,40026,1003,100
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/16_verified.sql

-- Outside check. the verified accounts were verified as unique humans by a face scan
-- (NEAR's I-Am-Human soulbound tokens, issuer fractal.i-am-human.near). How do they score?
-- Output is counts by feature, never individual accounts.
SELECT
  window_start,
  gap,
  n_hours,
  n_days,
  n_slots,
  class,
  COUNT(*) AS account_windows
FROM `your-project.proof_of_sleep.account_windows`
WHERE account IN UNNEST([ ... the verified account names, read from the chain by pipeline/pull_verified.py ... ]) AND n_days >= 5
GROUP BY 1, 2, 3, 4, 5, 6
ORDER BY 1, 2, 3, 4, 5, 6

Could the pattern be chance?

Verified humans go quiet for about 7 hours at a stretch and accounts in general for about 8, close to a night's sleep. The same accounts with each day randomly shifted around the clock peak at 4.

0%5%10%15%036912151821longest quiet stretch, hours
  • Sample of all accounts
  • Verified humans
  • Accounts with days shuffled
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/15_calibration.sql

-- Chance check. About 8,000 randomly chosen accounts from one 14-day window, each as a list
-- of daily activity masks (one 24-bit number per active day). No account names leave BigQuery.
-- pipeline/analyze.py shuffles each day around the clock and re-runs the test on the result.
WITH slots AS (
  SELECT signer_account_id AS account, block_date, EXTRACT(HOUR FROM block_timestamp_utc) AS hour
  FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
  WHERE block_date BETWEEN DATE '2026-10-01' AND DATE '2026-10-14'
  GROUP BY 1, 2, 3
),
daymask AS (
  SELECT account, block_date, BIT_OR(1 << hour) AS m
  FROM slots
  GROUP BY 1, 2
),
acct AS (
  SELECT account, ARRAY_AGG(m ORDER BY block_date) AS ms
  FROM daymask
  GROUP BY 1
  HAVING ARRAY_LENGTH(ms) >= 5
)
SELECT ARRAY_TO_STRING(ARRAY(SELECT FORMAT('%x', m) FROM UNNEST(ms) AS m), ',') AS day_masks
FROM acct
WHERE MOD(ABS(FARM_FINGERPRINT(account)), 100) < 14
The numbers as a table
Longest quiet stretch (hours)Sample of all accountsVerified humansDays shuffled
055257109
1110567355
2144920609
32031,121964
42681,4071,274
55481,7051,272
66501,8771,123
77851,889846
89391,805692
97891,538495
107241,308366
115521,055237
12368757143
13359567103
1426444962
1520031044
1619126124
1720617911
182401629
192401064
20292931
21261472
22229380
23128240

Did they follow their clocks?

When clocks change, people who observe daylight saving should move by an hour. Across 4 clock changes the average move was -0.05 hours in the expected direction (95% interval -0.26 to +0.16). A full one-hour move is ruled out. Either few of these accounts live where clocks change, or they do not follow local time. This data cannot say which.

-1 h+0 h+1 ha full shift would land hereEurope, spring 2026Americas, spring 2026Europe, autumn 2026Americas, autumn 2026
  • How far ordinary weeks drift on their own
  • Each clock change: how far sleepers moved, compared with an Asian control group
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/08_dst.sql

-- Natural experiment: when clocks change, do accounts move with them?
-- 1. Take accounts that pass the sleep test in the 14 days before a clock change.
-- 2. Sort them into regions using only where their quiet stretch sat BEFORE the change.
-- 3. Count when those same accounts were active before and after the change.
-- Placebo events use ordinary dates with no clock change anywhere.
-- Output is counts per event, group, period and hour: never individual accounts.
WITH slots AS (
  SELECT signer_account_id AS account, block_date, EXTRACT(HOUR FROM block_timestamp_utc) AS hour
  FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
  WHERE block_date BETWEEN ... -- days around each clock change, see pipeline/dst_events.py
  GROUP BY 1, 2, 3
),
tagged AS (
  SELECT e.event, IF(s.block_date <= e.pre_end, 'pre', 'post') AS period, s.account, s.block_date, s.hour
  FROM slots AS s
  JOIN UNNEST([ ... the clock-change dates, see pipeline/dst_events.py ... ]) AS e
    ON s.block_date BETWEEN e.pre_start AND e.pre_end
    OR s.block_date BETWEEN e.post_start AND e.post_end
),
days AS (
  SELECT event, period, account, block_date,
         COUNT(*) AS n_slots,
         BIT_OR(1 << hour) AS day_mask,
         ARRAY_AGG(hour) AS hours
  FROM tagged
  GROUP BY 1, 2, 3, 4
),
periods AS (
  SELECT event, period, account,
         COUNT(*) AS n_days,
         SUM(n_slots) AS n_slots,
         BIT_OR(day_mask) AS hour_mask,
         ARRAY_CONCAT_AGG(hours) AS hours
  FROM days
  GROUP BY 1, 2, 3
),
with_hours AS (
  SELECT *, ARRAY(SELECT h FROM UNNEST(GENERATE_ARRAY(0, 23)) AS h WHERE (hour_mask >> h) & 1 = 1) AS hs
  FROM periods
),
features AS (
  SELECT event, period, account, n_days, n_slots, hours, ARRAY_LENGTH(hs) AS n_hours,
    (SELECT AS STRUCT gap, start_h
     FROM (
       SELECT h AS start_h,
              COALESCE((SELECT MIN(h2) FROM UNNEST(hs) AS h2 WHERE h2 > h), hs[OFFSET(0)] + 24) - h - 1 AS gap
       FROM UNNEST(hs) AS h
     )
     ORDER BY gap DESC, start_h
     LIMIT 1) AS g
  FROM with_hours
),
pivoted AS (                                  -- both periods side by side for each account
  SELECT event, account,
    MAX(IF(period = 'pre', n_days, NULL)) AS n_days,
    MAX(IF(period = 'post', n_days, NULL)) AS post_days,
    MAX(IF(period = 'pre', n_slots, NULL)) AS n_slots,
    MAX(IF(period = 'pre', n_hours, NULL)) AS n_hours,
    MAX(IF(period = 'pre', g.gap, NULL)) AS gap,
    MAX(IF(period = 'pre', (g.start_h + 1 + g.gap / 2) - 24 * FLOOR((g.start_h + 1 + g.gap / 2) / 24), NULL)) AS pre_mid,
    ARRAY_CONCAT_AGG(IF(period = 'pre', hours, CAST([] AS ARRAY<INT64>))) AS pre_hours,
    ARRAY_CONCAT_AGG(IF(period = 'post', hours, CAST([] AS ARRAY<INT64>))) AS post_hours
  FROM features
  GROUP BY 1, 2
),
cohort AS (
  SELECT event, pre_hours, post_hours,
    CASE
      WHEN (CASE
      WHEN n_days < 5 THEN 'too_few'
      WHEN gap <= 2 AND n_slots / n_days >= 8 THEN 'machine'
      WHEN n_hours <= 3 THEN 'timer'
      WHEN gap >= 5 AND gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(n_hours)] AND gap <= 14 AND n_hours >= 6 THEN 'sleeper'
      WHEN gap >= 5 AND gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(n_hours)] THEN 'routine'
      ELSE 'unclear'
    END) = 'machine' THEN 'machines'
      WHEN (CASE
      WHEN n_days < 5 THEN 'too_few'
      WHEN gap <= 2 AND n_slots / n_days >= 8 THEN 'machine'
      WHEN n_hours <= 3 THEN 'timer'
      WHEN gap >= 5 AND gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(n_hours)] AND gap <= 14 AND n_hours >= 6 THEN 'sleeper'
      WHEN gap >= 5 AND gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(n_hours)] THEN 'routine'
      ELSE 'unclear'
    END) != 'sleeper' THEN 'drop'
      WHEN pre_mid >= 23 OR pre_mid < 3.5 THEN 'europe'
      WHEN pre_mid >= 6.5 AND pre_mid < 13 THEN 'americas'
      WHEN pre_mid >= 16 AND pre_mid < 23 THEN 'asia'
      ELSE 'in_between'
    END AS grp
  FROM pivoted
  WHERE n_days IS NOT NULL AND post_days >= 3     -- same accounts, active on both sides of the change
)
SELECT event, grp, x.period, x.hour, COUNT(*) AS slots
FROM cohort,
  UNNEST(ARRAY_CONCAT(
    ARRAY(SELECT AS STRUCT 'pre' AS period, h AS hour FROM UNNEST(pre_hours) AS h),
    ARRAY(SELECT AS STRUCT 'post' AS period, h AS hour FROM UNNEST(post_hours) AS h)
  )) AS x
WHERE grp != 'drop'
GROUP BY 1, 2, 3, 4
ORDER BY 1, 2, 3, 4
The numbers as a table
EventDateEurope groupAmericas groupAsia controlMachines
Europe, spring 20262026-03-29-0.4+0.2-0.1-0.6
Americas, spring 20262026-03-08-0.1+0.6-0.1-0.3
Europe, autumn 20262026-10-25+0.1-1.0+0.2+0.3
Americas, autumn 20262026-11-01+0.0+0.3+0.0+0.4
placebo_2026_052026-05-17+0.0-0.3-0.1+0.6
placebo_2026_062026-06-14+0.3+0.2+0.5+0.4
placebo_2026_072026-07-12-0.2+0.2+0.1-0.3
placebo_2026_082026-08-16-0.1-0.7-0.2+0.4

How much depends on the rules?

Changing a rule moves the count a lot, which is one more reason to read it as a measurement of a behaviour and not as a head count.

RuleAccounts passingChangeVerified humans passingShuffled accounts passing
As published5,771+0%25%1.9%
Stricter chance test (p below 0.01)1,994-65%14%0.3%
Uses 8+ hours of the clock3,897-32%22%1.2%
Uses 10+ hours of the clock2,378-59%18%0.8%
Quiet stretch at most 12 hours3,949-32%22%1.4%
Quiet stretch at most 18 hours7,511+30%28%2.0%
Active on 6+ days5,606-3%
Active on 7+ days5,332-8%
No chance test at all30,416+427%
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/06_sensitivity.sql

-- How much does the count depend on the thresholds? Recounts sleepers under other choices,
-- changing one rule at a time. Uses the table from step 0, so it costs almost nothing.
WITH t AS (
  SELECT window_start, n_days, n_slots, n_hours, gap, [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(n_hours)] AS c05, [99,99,99,99,19,17,15,14,13,11,10,9,9,8,7,7,6,6,5,5,4,99,99,99,99][OFFSET(n_hours)] AS c01
  FROM `your-project.proof_of_sleep.account_windows`
  WHERE account != '_light_'
)
SELECT
  window_start,
  COUNTIF(n_days >= 5 AND n_hours >= 6 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS base,
  COUNTIF(n_days >= 5 AND n_hours >= 6 AND gap BETWEEN 5 AND 14 AND gap >= c01) AS alpha_01,
  COUNTIF(n_days >= 5 AND n_hours >= 4 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS hours_4,
  COUNTIF(n_days >= 5 AND n_hours >= 8 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS hours_8,
  COUNTIF(n_days >= 5 AND n_hours >= 10 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS hours_10,
  COUNTIF(n_days >= 5 AND n_hours >= 6 AND gap BETWEEN 5 AND 12 AND gap >= c05) AS gap_max_12,
  COUNTIF(n_days >= 5 AND n_hours >= 6 AND gap BETWEEN 5 AND 18 AND gap >= c05) AS gap_max_18,
  COUNTIF(n_days >= 4 AND n_hours >= 6 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS days_4,
  COUNTIF(n_days >= 6 AND n_hours >= 6 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS days_6,
  COUNTIF(n_days >= 7 AND n_hours >= 6 AND gap BETWEEN 5 AND 14 AND gap >= c05) AS days_7,
  COUNTIF(n_days >= 5 AND n_hours >= 6 AND gap BETWEEN 5 AND 14) AS no_chance_test
FROM t
WHERE n_hours IS NOT NULL
GROUP BY 1
ORDER BY 1

Do the raw counts match an independent source?

Plain counts from the raw BigQuery table match NearBlocks, a separate indexer, within 1% on all 70 of 70 windows and on 69 of 69 days for transactions. This chart is the raw daily active accounts for the last 69 days.

050K100K150K200K09-0109-1109-2110-0110-1110-2110-31
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/10_daily_totals.sql

-- Plain daily activity from the raw table, for the most recent stretch of data:
-- transactions, distinct signing accounts, distinct contracts called.
SELECT
  block_date,
  COUNT(*) AS transactions,
  COUNT(DISTINCT signer_account_id) AS active_accounts,
  COUNT(DISTINCT receiver_account_id) AS contracts_called
FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
WHERE block_date BETWEEN DATE '2026-09-01' AND DATE '2026-11-08'
GROUP BY 1
ORDER BY 1
The numbers as a table
DateTransactionsActive accountsContracts calledTx ratio to NearBlocksAccounts ratio
2026-09-01670,52977,13063,6241.00001.0000
2026-09-02659,62277,12763,5261.00001.0000
2026-09-03703,69877,60783,9331.00001.0000
2026-09-04735,46376,04262,1931.00001.0000
2026-09-05674,16274,28860,9371.00001.0000
2026-09-06763,17274,65263,0181.00001.0000
2026-09-07746,04475,71163,4391.00001.0000
2026-09-08704,25471,76863,3121.00001.0000
2026-09-09772,84171,96462,8991.00001.0000
2026-09-10728,73671,15961,6021.00001.0000
2026-09-11846,58270,01462,0631.00001.0000
2026-09-12651,97067,17061,1501.00001.0000
2026-09-13626,44761,50161,6161.00001.0000
2026-09-14706,60049,97258,5321.00001.0000
2026-09-15706,59745,24757,1941.00001.0000
2026-09-16777,08942,51754,7681.00001.0000
2026-09-17840,31444,74957,0701.00001.0000
2026-09-18973,38862,96562,6661.00001.0000
2026-09-19839,38052,39159,7261.00001.0000
2026-09-20846,01357,46657,7991.00001.0000
2026-09-21871,72360,29859,4071.00001.0000
2026-09-22971,95957,79782,6261.00001.0000
2026-09-23869,89256,10558,2101.00001.0000
2026-09-24741,29154,02755,0591.00001.0000
2026-09-25715,46957,30055,8321.00001.0000
2026-09-26603,14354,11853,9251.00001.0000
2026-09-271,217,20963,58966,3801.00001.0000
2026-09-281,129,79361,77177,7701.00001.0000
2026-09-29987,62762,99079,5981.00001.0000
2026-09-30923,52658,74976,0931.00001.0000
2026-10-011,151,49262,10586,3031.00001.0000
2026-10-02868,026118,077134,7711.00001.0000
2026-10-03690,438176,719191,6011.00001.0000
2026-10-04839,450177,196193,9891.00001.0000
2026-10-05865,68195,992140,3621.00001.0000
2026-10-06909,765124,809139,2441.00001.0000
2026-10-07971,068175,774189,5991.00001.0000
2026-10-081,014,85082,44792,5811.00001.0000
2026-10-09680,33253,95063,7611.00001.0000
2026-10-10850,34456,88162,2221.00001.0000
2026-10-111,109,58454,86563,8311.00001.0000
2026-10-12712,62159,16468,1901.00001.0000
2026-10-13731,05455,68564,5101.00001.0000
2026-10-14767,81258,61566,7801.00001.0000
2026-10-15911,98055,50364,8821.00001.0000
2026-10-16658,42754,93665,1181.00001.0000
2026-10-17557,90354,32262,9721.00001.0000
2026-10-18569,73551,81062,0881.00001.0000
2026-10-19607,01953,10772,5531.00001.0000
2026-10-20617,99052,11673,5211.00001.0000
2026-10-21658,78453,91971,2091.00001.0000
2026-10-22547,26751,42349,8381.00001.0000
2026-10-23609,23651,21470,7401.00001.0000
2026-10-24635,43850,17869,7271.00001.0000
2026-10-25550,25049,24556,9871.00001.0000
2026-10-26573,80149,60156,9381.00001.0000
2026-10-27604,32061,85569,7401.00001.0000
2026-10-28520,09649,27357,8391.00001.0000
2026-10-29649,10349,29258,3541.00001.0000
2026-10-30691,42047,34981,7551.00001.0000
2026-10-31502,64946,01966,4531.00001.0000
2026-11-01509,34546,47878,2161.00001.0000
2026-11-02522,35848,06068,2891.00001.0000
2026-11-03597,18972,34382,1381.00001.0000
2026-11-04706,69079,16482,6781.00001.0000
2026-11-05848,79478,56095,5781.00001.0000
2026-11-06717,48478,57493,3461.00001.0000
2026-11-07682,43277,07691,1561.00001.0000
2026-11-08609,50479,18495,7421.00001.0000

Who is left

Who passes the test?

84% of the accounts that pass today are Telegram accounts, and 86% use one game. Named .near accounts peaked at 9,016 in Jun 2024. 4 windows contained large groups of accounts all sleeping in the same few hours, which looks like one program. Those groups are excluded here and listed below.

050K100K150K202120222023202420252026
  • Telegram accounts
  • Other accounts
  • Named .near accounts
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/11_families.sql

-- Who are the accounts that pass the sleep test? Sleepers by account family, with the
-- UTC hour of each sleeper's quiet stretch. A family whose sleepers all sit in the same
-- few hours looks like one program or one place, not a worldwide crowd of people.
WITH labelled AS (
  SELECT
    window_start, n_tx, class, mid,
    CASE
      WHEN REGEXP_CONTAINS(account, r'^[0-9a-f]{64}$') THEN 'implicit'
      WHEN REGEXP_CONTAINS(account, r'^0x[0-9a-f]{40}$') THEN 'eth_implicit'
      WHEN ENDS_WITH(account, '.tg') THEN 'telegram'
      WHEN ENDS_WITH(account, '.kaiching') THEN 'kaiching'
      WHEN ENDS_WITH(account, '.sweat') THEN 'sweat'
      WHEN REGEXP_CONTAINS(account, r'^[^.]+\.near$') THEN 'near_name'
      WHEN ENDS_WITH(account, '.near') THEN 'near_subaccount'
      ELSE 'other'
    END AS family
  FROM `your-project.proof_of_sleep.account_windows`
  WHERE account != '_light_'
)
SELECT
  window_start, family, class,
  IF(class = 'sleeper', CAST(FLOOR(mid) AS INT64), -1) AS mid_hour_utc,
  COUNT(*) AS accounts,
  SUM(n_tx) AS txs
FROM labelled
GROUP BY 1, 2, 3, 4
ORDER BY 1, 2, 3, 4
The numbers as a table
WindowAccount familySleepers removedShare in 3 neighbouring hours
2023-09-01kaiching104,87267%
2023-10-01kaiching79,96953%
2023-11-01kaiching88,20371%
2024-10-01implicit10,41893%

What do these accounts use?

The contracts sleepers use most are the HOT game and its airdrops, then wrapped NEAR, then a long thin tail. By contrast, 99% of the 927,966 transactions sent to intents.near were signed by machines. People using cross-chain swaps usually sign off-chain, so they never appear here.

game.hot.tg4,951
wrap.near803
aggregatedex.near539
firedrop.hot.tg380
17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1359
token.rhealab.near285
usdt.tether-token.near261
intents.near196
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/09_apps.sql

-- What do people on NEAR use? For a set of sample windows: per contract, how many
-- sleepers and how many machines call it, and how many transactions each sends.
WITH tx AS (
  SELECT
    DATE_TRUNC(block_date, MONTH) AS window_start,
    signer_account_id AS account,
    receiver_account_id AS contract,
    COUNT(*) AS n
  FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
  WHERE block_date BETWEEN ... -- sample windows, see pipeline/config.py
  GROUP BY 1, 2, 3
),
joined AS (
  SELECT t.window_start, t.contract, t.account, t.n, COALESCE(a.class, 'light') AS class
  FROM tx AS t
  LEFT JOIN `your-project.proof_of_sleep.account_windows` AS a
    ON a.account = t.account AND a.window_start = t.window_start
),
per_contract AS (
  SELECT
    window_start, contract,
    COUNT(*) AS signers,
    SUM(n) AS txs,
    COUNTIF(class = 'sleeper') AS sleepers,
    SUM(IF(class = 'sleeper', n, 0)) AS sleeper_txs,
    COUNTIF(class = 'machine') AS machines,
    SUM(IF(class = 'machine', n, 0)) AS machine_txs
  FROM joined
  GROUP BY 1, 2
),
ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY window_start ORDER BY sleepers DESC, contract) AS by_sleepers,
    ROW_NUMBER() OVER (PARTITION BY window_start ORDER BY txs DESC, contract) AS by_txs
  FROM per_contract
)
SELECT window_start, contract, signers, txs, sleepers, sleeper_txs, machines, machine_txs, by_sleepers, by_txs
FROM ranked
WHERE (by_sleepers <= 40 OR by_txs <= 40)
  AND NOT REGEXP_CONTAINS(contract, r'^[^.]+\.tg$')   -- a bare .tg name is a person's account, not an app
ORDER BY window_start, by_sleepers
The numbers as a table
ContractSleepersAll signersTransactionsSent by machines
game.hot.tg4,951101,232851,4881%
wrap.near80319,137532,34573%
aggregatedex.near5397,59112,7491%
firedrop.hot.tg3804,40126,5548%
17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a13595,053304,16593%
token.rhealab.near2852,53125,03145%
usdt.tether-token.near2614,27031,68262%
intents.near1963,331927,96699%
nearly-993927.nearlytrade.near1951,81510,13737%
diarhea.nearlytrade.near1741,2295,75437%
ninu-4.nearlytrade.near1581,1595,14435%
dclv2.ref-labs.near1436,40120,65620%

Do they stay?

Of accounts that passed the test in a window since January 2025, 30% were still regularly active a year later, compared with 15% of accounts that never sleep. The most recent cohorts go the other way: in the three latest that can be measured, sleepers held 27% and machines 42%. Windows flagged as a single program are left out.

Kind of account1 month later3 months6 months12 months
Sleepers90%71%54%30%
Narrow daily routine86%69%50%22%
Never sleeps75%54%39%15%
On a timer86%71%55%26%
Can't tell86%69%50%27%
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/05_retention.sql

-- Do accounts come back? For every window and class: of the accounts in that class,
-- how many are seen again (on at least 3 days) 1, 3, 6 and 12 months later.
WITH a AS (
  SELECT account, window_start, class
  FROM `your-project.proof_of_sleep.account_windows`
  WHERE account != '_light_'
),
later AS (
  SELECT account, window_start AS later_start, class AS later_class
  FROM `your-project.proof_of_sleep.account_windows`
  WHERE account != '_light_'
)
SELECT
  a.window_start,
  a.class,
  m AS months_later,
  COUNT(DISTINCT a.account) AS cohort,
  COUNT(DISTINCT later.account) AS seen_again,
  COUNT(DISTINCT IF(later.later_class = 'sleeper', later.account, NULL)) AS seen_again_sleeping
FROM a
CROSS JOIN UNNEST([1, 3, 6, 12]) AS m
LEFT JOIN later
  ON later.account = a.account
  AND later.later_start = DATE_ADD(a.window_start, INTERVAL m MONTH)
WHERE DATE_ADD(a.window_start, INTERVAL m MONTH) <= DATE '2026-10-01'
GROUP BY 1, 2, 3
ORDER BY 1, 2, 3

Where are they?

A sleep midpoint hints at where someone lives. Today's sleepers cluster around UTC+4, UTC+2, UTC+3. This describes the crowd, and nobody can be located precisely from it.

05%10%15%-12-10-8-6-4-2+0+2+4+6+8+10implied UTC offset (hours)
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/04_timezones.sql

-- Where sleepers are on the clock: the UTC hour at the middle of each sleeper's quiet stretch.
-- Rounded down to the hour. Aggregate counts only, never individual accounts.
SELECT
  window_start,
  CAST(FLOOR(mid) AS INT64) AS mid_hour_utc,
  COUNT(*) AS sleepers
FROM `your-project.proof_of_sleep.account_windows`
WHERE class = 'sleeper'
GROUP BY 1, 2
ORDER BY 1, 2

sql/11_families.sql

-- Who are the accounts that pass the sleep test? Sleepers by account family, with the
-- UTC hour of each sleeper's quiet stretch. A family whose sleepers all sit in the same
-- few hours looks like one program or one place, not a worldwide crowd of people.
WITH labelled AS (
  SELECT
    window_start, n_tx, class, mid,
    CASE
      WHEN REGEXP_CONTAINS(account, r'^[0-9a-f]{64}$') THEN 'implicit'
      WHEN REGEXP_CONTAINS(account, r'^0x[0-9a-f]{40}$') THEN 'eth_implicit'
      WHEN ENDS_WITH(account, '.tg') THEN 'telegram'
      WHEN ENDS_WITH(account, '.kaiching') THEN 'kaiching'
      WHEN ENDS_WITH(account, '.sweat') THEN 'sweat'
      WHEN REGEXP_CONTAINS(account, r'^[^.]+\.near$') THEN 'near_name'
      WHEN ENDS_WITH(account, '.near') THEN 'near_subaccount'
      ELSE 'other'
    END AS family
  FROM `your-project.proof_of_sleep.account_windows`
  WHERE account != '_light_'
)
SELECT
  window_start, family, class,
  IF(class = 'sleeper', CAST(FLOOR(mid) AS INT64), -1) AS mid_hour_utc,
  COUNT(*) AS accounts,
  SUM(n_tx) AS txs
FROM labelled
GROUP BY 1, 2, 3, 4
ORDER BY 1, 2, 3, 4
The numbers as a table
Implied UTC offsetSleepers
UTC-1238
UTC-1122
UTC-1023
UTC-947
UTC-842
UTC-758
UTC-664
UTC-567
UTC-4109
UTC-3197
UTC-2197
UTC-1271
UTC+0430
UTC+1502
UTC+2652
UTC+3608
UTC+4675
UTC+5495
UTC+6357
UTC+7377
UTC+8249
UTC+9150
UTC+1099
UTC+1142

Where the people went, and where value went

Are people hidden behind relayers?

Some people never sign anything: a relayer pays the gas and signs for them. Running the same test on those accounts adds 4,203 in the latest window, so the count of accounts that pass is closer to 9,974. That group is shrinking too: it was 12,204 in April 2026.

010K20K30KApr 2026Oct 2026
  • Sleep test passed only through a gas relayer
  • Sleep test passed as a signer
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/12_relayed.sql

-- Humans who never sign. When a relayer pays gas for someone, the relayer signs the transaction
-- and the person only appears as the receiver of a DELEGATE_ACTION. This runs the same sleep test
-- on those people, for the windows in 2026-04-01, 2026-10-01.
WITH acted AS (
  SELECT
    DATE_TRUNC(block_date, MONTH) AS window_start,
    receipt_receiver_account_id AS account,
    block_date,
    EXTRACT(HOUR FROM block_timestamp_utc) AS hour,
    COUNT(*) AS n
  FROM `bigquery-public-data.crypto_near_mainnet_us.receipt_actions`
  WHERE (block_date BETWEEN ... -- see pipeline/config.py) AND action_kind = 'DELEGATE_ACTION'
  GROUP BY 1, 2, 3, 4
),
days AS (
  SELECT window_start, account, block_date, SUM(n) AS n, COUNT(*) AS n_slots, BIT_OR(1 << hour) AS day_mask
  FROM acted
  GROUP BY 1, 2, 3
),
accounts AS (
  SELECT window_start, account, SUM(n) AS n, COUNT(*) AS n_days, SUM(n_slots) AS n_slots, BIT_OR(day_mask) AS hour_mask
  FROM days
  GROUP BY 1, 2
),
hours AS (
  SELECT *, ARRAY(SELECT h FROM UNNEST(GENERATE_ARRAY(0, 23)) AS h WHERE (hour_mask >> h) & 1 = 1) AS hs
  FROM accounts
),
gaps AS (
  SELECT *,
    (SELECT AS STRUCT gap, start_h FROM (
       SELECT h AS start_h,
              COALESCE((SELECT MIN(h2) FROM UNNEST(hs) AS h2 WHERE h2 > h), hs[OFFSET(0)] + 24) - h - 1 AS gap
       FROM UNNEST(hs) AS h) ORDER BY gap DESC, start_h LIMIT 1) AS g
  FROM hours
),
classified AS (
  SELECT window_start, account, n, CASE
      WHEN n_days < 5 THEN 'too_few'
      WHEN g.gap <= 2 AND n_slots / n_days >= 8 THEN 'machine'
      WHEN ARRAY_LENGTH(hs) <= 3 THEN 'timer'
      WHEN g.gap >= 5 AND g.gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(ARRAY_LENGTH(hs))] AND g.gap <= 14 AND ARRAY_LENGTH(hs) >= 6 THEN 'sleeper'
      WHEN g.gap >= 5 AND g.gap >= [99,99,99,20,17,15,13,12,11,10,9,8,7,7,6,6,5,5,4,4,3,3,99,99,99][OFFSET(ARRAY_LENGTH(hs))] THEN 'routine'
      ELSE 'unclear'
    END AS relayed_class
  FROM gaps
)
SELECT
  c.window_start,
  c.relayed_class,
  COALESCE(w.class, 'no_signed_txs') AS signer_class,
  COUNT(*) AS accounts,
  SUM(c.n) AS delegate_actions
FROM classified AS c
LEFT JOIN `your-project.proof_of_sleep.account_windows` AS w
  ON w.account = c.account AND w.window_start = c.window_start
GROUP BY 1, 2, 3
ORDER BY 1, 2, 3
The numbers as a table
WindowPassed as signersPassed, relayed onlyAll relayed accounts
2026-04-0112,06912,2043,508,783
2026-10-015,7714,203369,363

Did value follow the people?

Since January 2025 the number of accounts passing the test fell 93%. Over the same stretch two-week swap volume through NEAR Intents grew from $1.1M to $2B, and the price went from $5.32 to $5.07 after a low of $1.08. More money flows through NEAR while fewer accounts that look like people use it.

1101001K10K100K1M2025-012026-015,771$5.07$2B
  • Accounts passing the sleep test
  • NEAR price
  • NEAR Intents swap volume
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/01_classes.sql

-- Headline table: how many accounts fall in each class in each 14-day window,
-- and how many transactions each class sent.
SELECT
  window_start,
  class,
  SUM(accounts) AS accounts,
  SUM(n_tx) AS txs
FROM `your-project.proof_of_sleep.account_windows`
GROUP BY 1, 2
ORDER BY 1, 2
The numbers as a table
WindowPassed sleep testAverage priceIntents volume in window
2025-01-0182,245$5.32$1.1M
2025-02-0164,990$3.51$5.5M
2025-03-0151,891$2.85$12.7M
2025-04-0150,900$2.27$13.9M
2025-05-0142,471$2.69$23.6M
2025-06-0135,204$2.44$34.3M
2025-07-0131,686$2.28$76M
2025-08-0130,717$2.61$172M
2025-09-0130,175$2.54$198.3M
2025-10-0128,523$2.79$754.7M
2025-11-0126,180$2.38$1.8B
2025-12-0122,803$1.73$929M
2026-01-0118,466$1.71$1.1B
2026-02-0114,526$1.08$1.5B
2026-03-0111,665$1.27$873.4M
2026-04-0112,069$1.29$1B
2026-05-0110,239$1.44$761.3M
2026-06-0110,776$2.21$1.3B
2026-07-018,189$1.93$1.1B
2026-08-016,902$1.65$925.7M
2026-09-016,622$2.22$1.9B
2026-10-015,771$5.07$2B

Does anything lead the price?

Monthly changes in the number of accounts passing the test do not lead the price by 1, 2 or 3 months (best correlation +0.14, p = 0.31). 4 of the 28 tests in this table cross p < 0.05 where about 1.4 are expected by chance, a borderline excess. The strongest result runs the other way: price moves first and active accounts follow one month later.

Signal vs priceprice leads by 3 months21same monthsignal leads by 123
Passed the sleep test-0.05+0.18+0.11+0.30*+0.14+0.01+0.09
Active accounts-0.20+0.02+0.34*+0.02+0.10-0.07-0.13
Transactions-0.05+0.07+0.23+0.31*-0.06-0.23+0.27*
Intents volume+0.33+0.13-0.07-0.11-0.25-0.23-0.30
The query behind this chart

Long lists are shortened here. python -m pipeline.pull_bigquery --print 10 prints any step in full, ready to paste. Steps other than 10 and 15 read the table built by step 00.

sql/01_classes.sql

-- Headline table: how many accounts fall in each class in each 14-day window,
-- and how many transactions each class sent.
SELECT
  window_start,
  class,
  SUM(accounts) AS accounts,
  SUM(n_tx) AS txs
FROM `your-project.proof_of_sleep.account_windows`
GROUP BY 1, 2
ORDER BY 1, 2

What would have to happen

Try your own assumption about the next five years

Over the last 12 windows the number of accounts passing the test has changed by -12.4% a month, roughly halving every 5 months. Move the slider to see where it goes from 5,771.

-accounts in 1 year
-in 3 years
-in 5 years
-growth needed to reach the target below in 5 years

This is arithmetic on one trend, not a forecast. It cannot tell you what a new app launch would do.

What would change my mind

The full thesis is in THESIS.md. These are the numbers to watch.

MeasureTodayWould change my mind
Accounts passing the sleep test5,771above 25,000 for three windows in a row
Named .near accounts that pass585above 3,000
Share of those passing that are Telegram accounts84%below 50%
Accounts that pass only through relayers4,203more than signers, three windows in a row
Never-sleeping accounts' share of transactions74%below 50% while transactions hold up