V2.1 #21

Merged
eric merged 76 commits from v2.1 into main 2026-11-01 22:07:57 +00:00
2 changed files with 16 additions and 1 deletions
Showing only changes of commit f2bd3e38e2 - Show all commits
+4 -1
View File
@@ -9,7 +9,10 @@ export class StateClient {
private cache: { chainId: string; blocks: TestnetBlock[]; bytes: number } | undefined;
private inFlight: Promise<TestnetSnapshot> | undefined;
private readonly fetcher: typeof fetch;
constructor(fetcher: typeof fetch = fetch) { this.fetcher = fetcher; }
constructor(fetcher: typeof fetch = globalThis.fetch) {
// Browser Web APIs require the Window/global receiver, not this StateClient instance.
this.fetcher = fetcher.bind(globalThis);
}
async json<T>(path: string, signal: AbortSignal): Promise<T> {
const response = await this.fetcher(`/api/${path}`, { cache: 'no-store', redirect: 'error', signal });
if (!/^application\/json(?:\s*;|$)/i.test(response.headers.get('content-type') ?? '') || !response.body) throw new Error('Node must return JSON.');
+12
View File
@@ -6,6 +6,18 @@ import { NETWORK, type TestnetBlock } from '../shared/testnet.ts';
const genesis='0'.repeat(64),chainId='f'.repeat(64);
const block=(height:number,previousHash:string):TestnetBlock=>({ network:NETWORK,chainId,height,
hash:height.toString(16).padStart(64,'0'),previousHash,transactions:[] }) as unknown as TestnetBlock;
test('default browser-style fetch receives the global receiver, not StateClient',async()=>{
const original=globalThis.fetch;
let calls=0;
globalThis.fetch=async function(this:unknown,input:RequestInfo|URL,init?:RequestInit){
assert.equal(this,globalThis,'native browser fetch would throw Illegal invocation for another receiver');
assert.equal(input,'/api/summary');assert.equal(init?.redirect,'error');calls++;
return Response.json({network:NETWORK,chainId,genesis,tip:genesis,height:0,revision:0,
cumulativeWork:'0',pendingTransfers:[],peers:0,algorithm:'RandomX',maturity:2});
};
try{const state=await new StateClient().load();assert.equal(state.tip,genesis);assert.equal(calls,2);}
finally{globalThis.fetch=original;}
});
function fixture(count:number){
const blocks:TestnetBlock[]=[];for(let i=0;i<count;i++)blocks.push(block(i+1,blocks.at(-1)?.hash??genesis));
const calls:string[]=[];