Skip to content

Commit 4431d7c

Browse files
committed
add: localnet support
1 parent 81f8aa4 commit 4431d7c

File tree

10 files changed

+489
-23
lines changed

10 files changed

+489
-23
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* Localnet configuration for synapse-core
3+
*
4+
* Loads localnet-specific configuration from environment variables.
5+
*/
6+
7+
import type { Address } from 'viem'
8+
9+
/**
10+
* Get environment variable value with Node.js and browser compatibility
11+
*/
12+
function getEnvVar(key: string): string | undefined {
13+
// Node.js environment
14+
if (typeof process !== 'undefined' && process.env != null) {
15+
return process.env[key]
16+
}
17+
// Browser environment (if using build tools like Vite)
18+
// @ts-expect-error - import.meta.env is provided by build tools like Vite
19+
if (typeof import.meta !== 'undefined' && import.meta.env != null) {
20+
// @ts-expect-error - import.meta.env is provided by build tools like Vite
21+
return (import.meta.env as Record<string, string>)[key]
22+
}
23+
return undefined
24+
}
25+
26+
/**
27+
* Localnet chain ID (default: 1414)
28+
*/
29+
export function getLocalnetChainId(): number {
30+
const envValue = getEnvVar('LOCALNET_CHAIN_ID')
31+
if (envValue != null) {
32+
const parsed = Number.parseInt(envValue, 10)
33+
if (!Number.isNaN(parsed)) {
34+
return parsed
35+
}
36+
}
37+
return 1414
38+
}
39+
40+
/**
41+
* Localnet RPC URL (default: http://127.0.0.1:5700/rpc/v1)
42+
*/
43+
export function getLocalnetRpcUrl(): string {
44+
return getEnvVar('LOCALNET_RPC_URL') ?? 'http://127.0.0.1:5700/rpc/v1'
45+
}
46+
47+
/**
48+
* Localnet WebSocket URL (default: ws://127.0.0.1:5700/rpc/v1)
49+
*/
50+
export function getLocalnetWsUrl(): string {
51+
return getEnvVar('LOCALNET_RPC_WS_URL') ?? 'ws://127.0.0.1:5700/rpc/v1'
52+
}
53+
54+
/**
55+
* Localnet block explorer URL (default: http://localhost:8080)
56+
*/
57+
export function getLocalnetBlockExplorerUrl(): string {
58+
return getEnvVar('LOCALNET_BLOCK_EXPLORER_URL') ?? 'http://localhost:8080'
59+
}
60+
61+
/**
62+
* Get localnet contract address from environment
63+
*/
64+
function getRequiredAddress(envVarName: string, contractName: string): Address {
65+
const address = getEnvVar(envVarName)
66+
if (address == null || address === '') {
67+
throw new Error(`${contractName} address not configured for localnet. Set ${envVarName} environment variable.`)
68+
}
69+
if (!address.startsWith('0x') || address.length !== 42) {
70+
throw new Error(`Invalid ${contractName} address in ${envVarName}: ${address}`)
71+
}
72+
return address as Address
73+
}
74+
75+
/**
76+
* Get optional address with default
77+
*/
78+
function getOptionalAddress(envVarName: string, defaultValue: Address): Address {
79+
const address = getEnvVar(envVarName)
80+
if (address != null && address !== '') {
81+
if (!address.startsWith('0x') || address.length !== 42) {
82+
throw new Error(`Invalid address in ${envVarName}: ${address}`)
83+
}
84+
return address as Address
85+
}
86+
return defaultValue
87+
}
88+
89+
export function getLocalnetMulticall3Address(): Address {
90+
return getOptionalAddress('LOCALNET_MULTICALL3_ADDRESS', '0xcA11bde05977b3631167028862bE2a173976CA11')
91+
}
92+
93+
export function getLocalnetUSDFCAddress(): Address {
94+
return getRequiredAddress('LOCALNET_USDFC_ADDRESS', 'USDFC Token')
95+
}
96+
97+
export function getLocalnetUSDFCName(): string {
98+
return getEnvVar('LOCALNET_USDFC_NAME') ?? 'Local USDFC'
99+
}
100+
101+
export function getLocalnetUSDFCSymbol(): string {
102+
return getEnvVar('LOCALNET_USDFC_SYMBOL') ?? 'lUSDFC'
103+
}
104+
105+
export function getLocalnetPaymentsAddress(): Address {
106+
return getRequiredAddress('LOCALNET_PAYMENTS_ADDRESS', 'Payments')
107+
}
108+
109+
export function getLocalnetStorageAddress(): Address {
110+
return getRequiredAddress('LOCALNET_WARM_STORAGE_ADDRESS', 'Warm Storage')
111+
}
112+
113+
export function getLocalnetStorageViewAddress(): Address {
114+
return getRequiredAddress('LOCALNET_STORAGE_VIEW_ADDRESS', 'Storage View')
115+
}
116+
117+
export function getLocalnetSPRegistryAddress(): Address {
118+
return getRequiredAddress('LOCALNET_SP_REGISTRY_ADDRESS', 'Service Provider Registry')
119+
}
120+
121+
export function getLocalnetSessionKeyRegistryAddress(): Address {
122+
return getRequiredAddress('LOCALNET_SESSION_KEY_REGISTRY_ADDRESS', 'Session Key Registry')
123+
}
124+
125+
export function getLocalnetPDPAddress(): Address {
126+
return getRequiredAddress('LOCALNET_PDP_VERIFIER_ADDRESS', 'PDP Verifier')
127+
}

packages/synapse-sdk/src/filbeam/service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ export class FilBeamService {
5959
}
6060

6161
private _validateNetworkType(network: FilecoinNetworkType) {
62-
if (network === 'mainnet' || network === 'calibration') return
62+
if (network === 'mainnet' || network === 'calibration' || network === 'localnet') return
6363

6464
throw createError(
6565
'FilBeamService',
6666
'validateNetworkType',
67-
'Unsupported network type: Only Filecoin mainnet and calibration networks are supported.'
67+
'Unsupported network type: Only Filecoin mainnet, calibration, and localnet networks are supported.'
6868
)
6969
}
7070

packages/synapse-sdk/src/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
* ```
1010
*/
1111

12+
export {
13+
ADD_PIECES_TYPEHASH,
14+
CREATE_DATA_SET_TYPEHASH,
15+
DELETE_DATA_SET_TYPEHASH,
16+
PDP_PERMISSION_NAMES,
17+
PDP_PERMISSIONS,
18+
SCHEDULE_PIECE_REMOVALS_TYPEHASH,
19+
SessionKey,
20+
} from './session/key.ts'
1221
export { Synapse } from './synapse.ts'
1322
export * from './types.ts'
1423
export * from './utils/constants.ts'

packages/synapse-sdk/src/synapse.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,10 @@ export class Synapse {
119119
}
120120

121121
// Final network validation
122-
if (network !== 'mainnet' && network !== 'calibration') {
123-
throw new Error(`Invalid network: ${String(network)}. Only 'mainnet' and 'calibration' are supported.`)
122+
if (network !== 'mainnet' && network !== 'calibration' && network !== 'localnet') {
123+
throw new Error(
124+
`Invalid network: ${String(network)}. Only 'mainnet', 'calibration', and 'localnet' are supported.`
125+
)
124126
}
125127

126128
// Create Warm Storage service with initialized addresses
@@ -321,7 +323,13 @@ export class Synapse {
321323
* @returns The numeric chain ID
322324
*/
323325
getChainId(): number {
324-
return this._network === 'mainnet' ? CHAIN_IDS.mainnet : CHAIN_IDS.calibration
326+
if (this._network === 'mainnet') {
327+
return CHAIN_IDS.mainnet
328+
} else if (this._network === 'calibration') {
329+
return CHAIN_IDS.calibration
330+
} else {
331+
return CHAIN_IDS.localnet
332+
}
325333
}
326334

327335
/**

packages/synapse-sdk/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export type ServiceProvider = string
2222
/**
2323
* Supported Filecoin network types
2424
*/
25-
export type FilecoinNetworkType = 'mainnet' | 'calibration'
25+
export type FilecoinNetworkType = 'mainnet' | 'calibration' | 'localnet'
2626

2727
/**
2828
* Token identifier for balance queries

packages/synapse-sdk/src/utils/constants.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ import * as Abis from '@filoz/synapse-core/abis'
66
import { MAX_UPLOAD_SIZE as CORE_MAX_UPLOAD_SIZE } from '@filoz/synapse-core/piece'
77
import { erc20Abi, multicall3Abi } from 'viem'
88
import type { FilecoinNetworkType } from '../types.ts'
9+
import {
10+
getLocalnetChainId,
11+
getLocalnetMulticall3Address,
12+
getLocalnetRpcUrl,
13+
getLocalnetUSDFCAddress,
14+
getLocalnetWarmStorageAddress,
15+
getLocalnetWsUrl,
16+
} from './localnet-config.ts'
917

1018
/**
1119
* Token identifiers
@@ -21,6 +29,7 @@ export const TOKENS = {
2129
export const CHAIN_IDS: Record<FilecoinNetworkType, number> = {
2230
mainnet: 314,
2331
calibration: 314159,
32+
localnet: getLocalnetChainId(),
2433
} as const
2534

2635
/**
@@ -130,6 +139,10 @@ export const GENESIS_TIMESTAMPS: Record<FilecoinNetworkType, number> = {
130139
* Calibration testnet genesis: November 1, 2022 18:13:00 UTC
131140
*/
132141
calibration: 1667326380,
142+
/**
143+
* Localnet genesis: Use current time as localnet is ephemeral
144+
*/
145+
localnet: Math.floor(Date.now() / 1000),
133146
} as const
134147

135148
/**
@@ -314,6 +327,10 @@ export const RPC_URLS: Record<FilecoinNetworkType, { http: string; websocket: st
314327
http: 'https://api.calibration.node.glif.io/rpc/v1',
315328
websocket: 'wss://wss.calibration.node.glif.io/apigw/lotus/rpc/v1',
316329
},
330+
localnet: {
331+
http: getLocalnetRpcUrl(),
332+
websocket: getLocalnetWsUrl(),
333+
},
317334
} as const
318335

319336
/**
@@ -327,6 +344,9 @@ export const CONTRACT_ADDRESSES = {
327344
WARM_STORAGE: {
328345
mainnet: '0x8408502033C418E1bbC97cE9ac48E5528F371A9f',
329346
calibration: '0x02925630df557F957f70E112bA06e50965417CA0',
347+
get localnet() {
348+
return getLocalnetWarmStorageAddress()
349+
},
330350
} as const satisfies Record<FilecoinNetworkType, string>,
331351

332352
/**
@@ -336,10 +356,16 @@ export const CONTRACT_ADDRESSES = {
336356
MULTICALL3: {
337357
mainnet: '0xcA11bde05977b3631167028862bE2a173976CA11',
338358
calibration: '0xcA11bde05977b3631167028862bE2a173976CA11',
359+
get localnet() {
360+
return getLocalnetMulticall3Address()
361+
},
339362
} as const satisfies Record<FilecoinNetworkType, string>,
340363

341364
USDFC: {
342365
mainnet: '0x80B98d3aa09ffff255c3ba4A241111Ff1262F045',
343366
calibration: '0xb3042734b608a1B16e9e86B374A3f3e389B4cDf0',
367+
get localnet() {
368+
return getLocalnetUSDFCAddress()
369+
},
344370
} as const satisfies Record<FilecoinNetworkType, string>,
345371
} as const

0 commit comments

Comments
 (0)