Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions examples/script-tag/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"root": false,
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"files": {
"ignoreUnknown": true
},
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5",
"semicolons": "asNeeded"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
7 changes: 7 additions & 0 deletions packages/synapse-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@
"./endorsements": {
"types": "./dist/src/endorsements/index.d.ts",
"default": "./dist/src/endorsements/index.js"
},
"./devnet": {
"types": "./dist/src/devnet/index.d.ts",
"default": "./dist/src/devnet/index.js"
}
},
"typesVersions": {
Expand Down Expand Up @@ -150,6 +154,9 @@
],
"endorsements": [
"./dist/src/endorsements/index"
],
"devnet": [
"./dist/src/devnet/index"
]
}
},
Expand Down
121 changes: 121 additions & 0 deletions packages/synapse-core/src/devnet/index.ts
Comment thread
redpanda-f marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* @module @filoz/synapse-core/devnet
*
* Validates and transforms foc-devnet's devnet-info.json into Synapse-compatible configuration.
* See https://github.com/FilOzone/foc-devnet for the export format.
*/

import * as Abis from '../abis/index.ts'
import type { Chain } from '../chains.ts'
import type { VersionedDevnetInfo } from './schema.ts'

/**
* Environment variables generated from devnet info
*/
export interface DevnetEnvVars {
RPC_URL: string
PRIVATE_KEY: string
EVM_ADDRESS: string
NATIVE_ADDRESS: string
MULTICALL3_ADDRESS: string
USDFC_ADDRESS: string
FWSS_PROXY_ADDRESS: string
PDP_VERIFIER_PROXY_ADDRESS: string
SP_REGISTRY_ADDRESS: string
FILECOIN_PAY_ADDRESS: string
ENDORSEMENTS_ADDRESS: string
RUN_ID: string
START_TIME: string
}

/**
* Create a Synapse Chain object from devnet info.
* This is compatible with viem and includes all ABIs needed by the Synapse SDK.
*
* @param devnetInfo - The devnet info from validateDevnetInfo()
* @returns Synapse Chain object with contract ABIs and addresses
*
*/
export function toChain(devnetInfo: VersionedDevnetInfo): Chain {
const { info } = devnetInfo
const contracts = info.contracts

return {
id: 31415926,
name: 'FOC DevNet',
nativeCurrency: {
decimals: 18,
name: 'Filecoin',
symbol: 'FIL',
},
rpcUrls: {
default: { http: [info.lotus.host_rpc_url] },
public: { http: [info.lotus.host_rpc_url] },
},
blockExplorers: {
default: {
name: 'DevNet',
url: 'http://localhost:3000',
},
},
contracts: {
multicall3: {
address: contracts.multicall3_addr as `0x${string}`,
blockCreated: 0,
},
usdfc: {
address: contracts.mockusdfc_addr as `0x${string}`,
abi: Abis.erc20WithPermit,
},
filecoinPay: {
address: contracts.filecoin_pay_v1_addr as `0x${string}`,
abi: Abis.filecoinPay,
},
fwss: {
address: contracts.fwss_service_proxy_addr as `0x${string}`,
abi: Abis.fwss,
},
fwssView: {
address: contracts.fwss_state_view_addr as `0x${string}`,
abi: Abis.fwssView,
},
serviceProviderRegistry: {
address: contracts.service_provider_registry_proxy_addr as `0x${string}`,
abi: Abis.serviceProviderRegistry,
},
sessionKeyRegistry: {
address: contracts.session_key_registry_addr as `0x${string}`,
abi: Abis.sessionKeyRegistry,
},
pdp: {
address: contracts.pdp_verifier_proxy_addr as `0x${string}`,
abi: Abis.pdp,
},
endorsements: {
address: contracts.endorsements_addr as `0x${string}`,
abi: Abis.providerIdSet,
},
},
filbeam: null,
testnet: true,
/**
* Devnet genesis: Set to 0 as placeholder. Epoch<>Date conversions
* will return incorrect results on devnet. Core contract operations
* are unaffected as they use epochs directly.
*/
genesisTimestamp: 0,
}
}

export type {
ContractsInfo,
CurioInfo,
DevnetInfoV1,
LotusInfo,
LotusMinerInfo,
UserInfo,
VersionedDevnetInfo,
YugabyteInfo,
} from './schema.ts'
// Re-export schema types and validation for advanced usage
export { validateDevnetInfo } from './schema.ts'
104 changes: 104 additions & 0 deletions packages/synapse-core/src/devnet/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* @module @filoz/synapse-core/devnet/schema
*
* Zod schema for validating DevNet info exports.
*
* This schema validates that all required fields are present with correct
* types in a DevNet info export. Additional or unknown fields may be
* ignored according to Zod's default object parsing behavior. It's used by
* the library to validate the exported devnet-info.json file.
*/

import { z } from 'zod'

const YugabyteInfo = z.object({
web_ui_url: z.string().url(),
master_rpc_port: z.number().int().positive(),
ysql_port: z.number().int().positive(),
})

const CurioInfo = z.object({
provider_id: z.number().int().positive(),
eth_addr: z.string().startsWith('0x'),
native_addr: z.string().min(1),
pdp_service_url: z.string().url(),
container_id: z.string().min(1),
container_name: z.string().min(1),
is_approved: z.boolean(),
is_endorsed: z.boolean(),
yugabyte: YugabyteInfo,
})

const ContractsInfo = z.object({
multicall3_addr: z.string().startsWith('0x'),
mockusdfc_addr: z.string().startsWith('0x'),
fwss_service_proxy_addr: z.string().startsWith('0x'),
fwss_state_view_addr: z.string().startsWith('0x'),
fwss_impl_addr: z.string().startsWith('0x'),
pdp_verifier_proxy_addr: z.string().startsWith('0x'),
pdp_verifier_impl_addr: z.string().startsWith('0x'),
service_provider_registry_proxy_addr: z.string().startsWith('0x'),
service_provider_registry_impl_addr: z.string().startsWith('0x'),
filecoin_pay_v1_addr: z.string().startsWith('0x'),
endorsements_addr: z.string().startsWith('0x'),
session_key_registry_addr: z.string().startsWith('0x'),
})

const UserInfo = z.object({
name: z.string().regex(/^USER_\d+$/),
evm_addr: z.string().startsWith('0x'),
native_addr: z.string().min(1),
private_key_hex: z.string().startsWith('0x'),
})

const LotusInfo = z.object({
host_rpc_url: z.string().url(),
container_id: z.string().min(1),
container_name: z.string().min(1),
})

const LotusMinerInfo = z.object({
container_id: z.string().min(1),
container_name: z.string().min(1),
api_port: z.number().int().positive(),
})

const DevnetInfoV1 = z.object({
run_id: z.string().min(1),
start_time: z.string(),
startup_duration: z.string().min(1),
users: z.array(UserInfo).min(1),
contracts: ContractsInfo,
lotus: LotusInfo,
lotus_miner: LotusMinerInfo,
pdp_sps: z.array(CurioInfo).min(1),
})

export const VersionedDevnetInfo = z.object({
version: z.literal(1),
info: DevnetInfoV1,
})

// Export TypeScript types
export type YugabyteInfo = z.infer<typeof YugabyteInfo>
export type CurioInfo = z.infer<typeof CurioInfo>
export type ContractsInfo = z.infer<typeof ContractsInfo>
export type UserInfo = z.infer<typeof UserInfo>
export type LotusInfo = z.infer<typeof LotusInfo>
export type LotusMinerInfo = z.infer<typeof LotusMinerInfo>
export type DevnetInfoV1 = z.infer<typeof DevnetInfoV1>
export type VersionedDevnetInfo = z.infer<typeof VersionedDevnetInfo>

/**
* Validate DevNet info against schema.
* @param data - The parsed JSON data to validate
* @returns The validated data if successful
* @throws {Error} If validation fails
*/
export function validateDevnetInfo(data: unknown): VersionedDevnetInfo {
try {
return VersionedDevnetInfo.parse(data)
} catch (error) {
throw new Error(`DevNet info schema validation failed: ${error instanceof Error ? error.message : String(error)}`)
}
}
1 change: 1 addition & 0 deletions packages/synapse-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export * as chains from './chains.ts'
export * as endorsements from './endorsements/index.ts'
export * as erc20 from './erc20/index.ts'
export * as errors from './errors/index.ts'

export * as pay from './pay/index.ts'
export * as piece from './piece.ts'
export * as sessionKey from './session-key/index.ts'
Expand Down
Loading