@zodiac-os/sdk 1.6.0 → 1.7.0
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.
- package/README.md +18 -27
- package/dist/allow-Dzh6t_l8.mjs.map +1 -1
- package/dist/{api-D6ee2Q2b.mjs → api-CygEDU4N.mjs} +39 -8
- package/dist/api-CygEDU4N.mjs.map +1 -0
- package/dist/cli/config.d.mts +9 -4
- package/dist/cli/config.mjs +6 -3
- package/dist/cli/config.mjs.map +1 -1
- package/dist/cli.mjs +77 -50
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +57 -41
- package/dist/index.mjs +34 -44
- package/dist/index.mjs.map +1 -1
- package/dist/zodiac-os-codegen.d.ts +14 -52
- package/package.json +3 -3
- package/dist/api-D6ee2Q2b.mjs.map +0 -1
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["join"],"sources":["../src/cli/paths.ts","../src/cli/commands/pullOrg.ts","../src/allow/fetch.ts","../src/allow/codegen.ts","../src/cli/commands/pullContracts.ts","../src/cli/run.ts","../src/cli/index.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url'\nimport { join } from 'node:path'\n\n/**\n * Resolve the consumer's `node_modules/.zodiac-os/` directory — the shared\n * home for SDK codegen (`pull-org` emits the importable module here,\n * `pull-contracts` writes `allow.d.ts` alongside it).\n *\n * Prefers walking up from this module's own path when the SDK is installed\n * under a real `node_modules`; falls back to `<cwd>/node_modules` when the\n * SDK is being run from source (dev / linked builds).\n */\nexport function resolveZodiacOsDir(): string {\n const selfPath = fileURLToPath(import.meta.url)\n const match = selfPath.match(/^(.+[/\\\\]node_modules)[/\\\\]/)\n const nodeModules = match ? match[1] : join(process.cwd(), 'node_modules')\n return join(nodeModules, '.zodiac-os')\n}\n","import type { ZodiacConfig } from '../config'\nimport { ApiClient } from '../../api'\nimport { invariant } from '@epic-web/invariant'\nimport {\n ModuleKind,\n Project,\n ScriptTarget,\n VariableDeclarationKind,\n} from 'ts-morph'\nimport { mkdirSync, writeFileSync } from 'fs'\nimport { join } from 'path'\nimport { resolveZodiacOsDir } from '../paths'\n\nconst toLiteral = (value: unknown, indent = 0): string => {\n const pad = ' '.repeat(indent)\n const childPad = ' '.repeat(indent + 1)\n\n if (value === null) return 'null'\n if (typeof value === 'bigint') return `${value}n`\n if (typeof value === 'string') return JSON.stringify(value)\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value)\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]'\n return `[\\n${value.map((v) => `${childPad}${toLiteral(v, indent + 1)}`).join(',\\n')},\\n${pad}]`\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.length === 0) return '{}'\n const props = entries.map(\n ([k, v]) =>\n `${childPad}${/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : JSON.stringify(k)}: ${toLiteral(v, indent + 1)}`\n )\n return `{\\n${props.join(',\\n')},\\n${pad}}`\n }\n return String(value)\n}\n\nexport const pullOrg = async (config: ZodiacConfig) => {\n const client = new ApiClient({\n apiKey: config.apiKey,\n })\n\n const [users, workspaceVaults] = await Promise.all([\n client.listUsers(),\n client.listVaults(),\n ])\n\n const allRawVaults = workspaceVaults.flatMap((ws) => ws.vaults)\n\n const { result: accounts } = await client.resolveConstellation(\n workspaceVaults[0].workspaceId, // can just use any workspace to resolve\n {\n specification: allRawVaults.map((vault) => ({\n type: 'SAFE',\n chain: vault.chain,\n address: vault.address,\n })),\n }\n )\n\n let accountIndex = 0\n const vaultsRecord: Record<string, unknown> = {}\n for (const ws of workspaceVaults) {\n const wsVaults: Record<string, unknown> = {}\n for (const vault of ws.vaults) {\n const account = accounts[accountIndex++]\n invariant(\n account.type === 'SAFE',\n `Expected SAFE account for vault ${vault.id}`\n )\n wsVaults[vault.label] = {\n id: vault.id,\n label: vault.label,\n address: account.address,\n chain: vault.chain,\n threshold: account.threshold,\n owners: [...account.owners],\n modules: [...account.modules],\n }\n }\n vaultsRecord[ws.workspaceName] = {\n workspaceId: ws.workspaceId,\n workspaceName: ws.workspaceName,\n vaults: wsVaults,\n }\n }\n\n const nameCount = new Map<string, number>()\n for (const user of users) {\n nameCount.set(user.fullName, (nameCount.get(user.fullName) ?? 0) + 1)\n }\n\n const usersRecord: Record<string, unknown> = {}\n for (const user of users) {\n const handle =\n nameCount.get(user.fullName)! > 1\n ? `${user.fullName} (${user.id})`\n : user.fullName\n usersRecord[handle] = {\n id: user.id,\n fullName: user.fullName,\n personalSafes: user.personalSafes,\n }\n }\n\n const outDir = resolveZodiacOsDir()\n\n mkdirSync(outDir, { recursive: true })\n\n // Write package.json so .zodiac-os is importable\n writeFileSync(\n join(outDir, 'package.json'),\n JSON.stringify(\n {\n name: '.zodiac-os',\n type: 'module',\n main: 'index.js',\n types: 'index.d.ts',\n },\n null,\n 2\n )\n )\n\n // Use ts-morph to generate TS, then emit JS + d.ts\n const project = new Project({\n compilerOptions: {\n declaration: true,\n module: ModuleKind.ESNext,\n target: ScriptTarget.ESNext,\n outDir,\n },\n useInMemoryFileSystem: true,\n })\n\n const sourceFile = project.createSourceFile('index.ts', '')\n\n sourceFile.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'users',\n initializer: `${toLiteral(usersRecord)} as const`,\n },\n ],\n })\n\n sourceFile.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'vaults',\n initializer: `${toLiteral(vaultsRecord)} as const`,\n },\n ],\n })\n\n const emitResult = sourceFile.getEmitOutput()\n for (const outputFile of emitResult.getOutputFiles()) {\n const filePath = outputFile.getFilePath()\n const fileName = filePath.includes('.d.ts') ? 'index.d.ts' : 'index.js'\n writeFileSync(join(outDir, fileName), outputFile.getText())\n }\n}\n","import { chainIdFor, type ChainPrefix } from './networks'\n\nexport type AbiFragment = Record<string, any>\nexport type Abi = AbiFragment[]\n\n// Returns null on any failure so callers can fall back to a manual ABI file.\nexport async function fetchAbi(\n chainId: number,\n address: `0x${string}`\n): Promise<Abi | null> {\n const url = `https://api.abi.pub/v1/chains/${chainId}/etherscan?module=contract&action=getabi&address=${address}`\n let body: { status?: string; message?: string; result?: string }\n try {\n const resp = await fetch(url)\n if (!resp.ok) return null\n body = (await resp.json()) as typeof body\n } catch {\n return null\n }\n if (body.status !== '1' || typeof body.result !== 'string') return null\n try {\n const parsed = JSON.parse(body.result)\n if (!Array.isArray(parsed) || parsed.length === 0) return null\n return parsed as Abi\n } catch {\n return null\n }\n}\n\nexport const fetchAbiForPrefix = (\n prefix: ChainPrefix,\n address: `0x${string}`\n) => fetchAbi(chainIdFor(prefix), address)\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { walkContracts, readAbi, type ContractNode } from './abi'\nimport type { Abi, AbiFragment } from './fetch'\n\n// Emits named tuple elements per ABI input — this is the reason we don't rely\n// on viem/abitype, which produces unnamed tuples (microsoft/TypeScript#44939).\nexport function generateAllowTypes(\n abisDir: string,\n contractsConfig: Record<string, any>\n): string {\n type Tree = Map<string, Tree | { node: ContractNode; abi: Abi }>\n\n const root: Tree = new Map()\n for (const node of walkContracts(contractsConfig)) {\n const abi = readAbi(abisDir, node)\n if (!abi) continue\n insertIntoTree(root, [node.chain, ...node.segments], { node, abi })\n }\n\n const out: string[] = []\n out.push('// AUTO-GENERATED by `zodiac-os pull-contracts`. Do not edit.')\n out.push('/* eslint-disable */')\n out.push('')\n out.push(\n `import type { FunctionPermission, TargetPermission } from \"zodiac-roles-sdk\";`\n )\n out.push(\n `import type { Scoping, Options, EVERYTHING } from \"@zodiac-os/sdk/allow\";`\n )\n out.push('')\n out.push('declare global {')\n out.push(' interface AllowKit ' + renderTree(root, ' '))\n out.push('}')\n out.push('')\n out.push('export {};')\n out.push('')\n return out.join('\\n')\n}\n\nfunction insertIntoTree(\n tree: Map<string, any>,\n segments: string[],\n leaf: { node: ContractNode; abi: Abi }\n): void {\n const [first, ...rest] = segments\n if (!first) throw new Error('empty segments')\n if (rest.length === 0) {\n tree.set(first, leaf)\n return\n }\n let child = tree.get(first)\n if (!child || child.node) {\n child = new Map()\n tree.set(first, child)\n }\n insertIntoTree(child, rest, leaf)\n}\n\nfunction renderTree(tree: Map<string, any>, indent: string): string {\n const lines: string[] = ['{']\n for (const [key, value] of tree) {\n const safeKey = renderPropKey(key)\n if (value instanceof Map) {\n lines.push(`${indent} ${safeKey}: ${renderTree(value, indent + ' ')};`)\n } else {\n const { node, abi } = value as { node: ContractNode; abi: Abi }\n lines.push(\n `${indent} ${safeKey}: ${renderContractType(node, abi, indent + ' ')};`\n )\n }\n }\n lines.push(`${indent}}`)\n return lines.join('\\n')\n}\n\nfunction renderPropKey(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name)\n}\n\nfunction renderContractType(\n node: ContractNode,\n abi: Abi,\n indent: string\n): string {\n const members: string[] = []\n const seen = new Set<string>()\n members.push(\n `${indent} [EVERYTHING]: (options?: Options) => TargetPermission;`\n )\n for (const fragment of abi) {\n if (fragment.type !== 'function') continue\n if (\n fragment.stateMutability === 'view' ||\n fragment.stateMutability === 'pure'\n ) {\n continue\n }\n const name = fragment.name as string\n if (!name || seen.has(name)) continue\n seen.add(name)\n members.push(renderFunctionSignature(fragment, indent + ' '))\n }\n return ['{', ...members, `${indent}}`].join('\\n')\n}\n\nfunction renderFunctionSignature(\n fragment: AbiFragment,\n indent: string\n): string {\n const name = renderPropKey(fragment.name as string)\n const params: string[] = []\n for (const input of (fragment.inputs as AbiFragment[]) ?? []) {\n const paramName = sanitizeParamName(\n input.name || `arg${params.length}`,\n params.length\n )\n params.push(`${paramName}?: Scoping<${tsTypeFor(input)}>`)\n }\n params.push(`options?: Options`)\n return `${indent}${name}: (${params.join(', ')}) => FunctionPermission;`\n}\n\nfunction sanitizeParamName(name: string, index: number): string {\n const cleaned = name.replace(/[^A-Za-z0-9_$]/g, '_')\n if (!cleaned || /^[0-9]/.test(cleaned)) return `arg${index}`\n // Named tuple element labels can't collide with TS reserved words.\n const reserved = new Set([\n 'function',\n 'class',\n 'new',\n 'number',\n 'string',\n 'object',\n 'boolean',\n 'symbol',\n 'default',\n 'return',\n 'this',\n 'void',\n 'delete',\n 'in',\n 'of',\n 'for',\n 'while',\n 'switch',\n 'case',\n 'if',\n 'else',\n 'null',\n 'true',\n 'false',\n 'undefined',\n 'any',\n 'never',\n 'unknown',\n ])\n return reserved.has(cleaned) ? `_${cleaned}` : cleaned\n}\n\nfunction tsTypeFor(fragment: AbiFragment): string {\n const type = fragment.type as string\n\n const arrayMatch = /^(.*)\\[(\\d*)\\]$/.exec(type)\n if (arrayMatch) {\n const inner: AbiFragment = { ...fragment, type: arrayMatch[1] }\n return `readonly (${tsTypeFor(inner)})[]`\n }\n\n if (type === 'tuple') {\n const components = (fragment.components as AbiFragment[]) ?? []\n if (components.length === 0) return 'Record<string, unknown>'\n const fields = components.map((c, i) => {\n const key = sanitizeParamName(c.name || `f${i}`, i)\n return `${renderPropKey(key)}: ${tsTypeFor(c)}`\n })\n return `{ ${fields.join('; ')} }`\n }\n\n if (type === 'address') return '`0x${string}`'\n if (type === 'bool') return 'boolean'\n if (type === 'string') return 'string'\n if (type === 'bytes') return 'import(\"ethers\").BytesLike'\n if (/^bytes\\d+$/.test(type)) return '`0x${string}`'\n if (/^u?int\\d*$/.test(type)) return 'import(\"ethers\").BigNumberish'\n return 'unknown'\n}\n\nexport function writeGenerated(outFile: string, source: string): void {\n fs.mkdirSync(path.dirname(outFile), { recursive: true })\n fs.writeFileSync(outFile, source, 'utf8')\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { ZodiacConfig } from '../config'\nimport { resolveAbisDir } from '../config'\nimport { resolveZodiacOsDir } from '../paths'\nimport { abiFilePath, walkContracts, writeAbi } from '../../allow/abi'\nimport { fetchAbi } from '../../allow/fetch'\nimport { chainIdFor } from '../../allow/networks'\nimport { generateAllowTypes, writeGenerated } from '../../allow/codegen'\n\ntype Status = 'ok' | 'fetched' | 'missing'\n\nexport const pullContracts = async (config: ZodiacConfig) => {\n if (!config.contracts || Object.keys(config.contracts).length === 0) {\n console.log('No contracts defined in config, skipping.')\n return\n }\n\n const abisDir = resolveAbisDir(config)\n const generatedFile = path.join(resolveZodiacOsDir(), 'allow.d.ts')\n\n let missing = 0\n let fetched = 0\n let existing = 0\n\n for (const node of walkContracts(config.contracts)) {\n const file = abiFilePath(abisDir, node)\n\n if (fs.existsSync(file)) {\n existing++\n report(node.chain, node.segments, node.address, 'ok', file)\n continue\n }\n\n let chainId: number\n try {\n chainId = chainIdFor(node.chain)\n } catch (error) {\n missing++\n report(\n node.chain,\n node.segments,\n node.address,\n 'missing',\n file,\n (error as Error).message\n )\n continue\n }\n\n const abi = await fetchAbi(chainId, node.address)\n if (!abi) {\n missing++\n report(\n node.chain,\n node.segments,\n node.address,\n 'missing',\n file,\n `api.abi.pub returned no ABI for chain ${chainId}`\n )\n continue\n }\n writeAbi(abisDir, node, abi)\n fetched++\n report(node.chain, node.segments, node.address, 'fetched', file)\n }\n\n console.log('')\n console.log(\n `Contracts summary: ${existing} existing, ${fetched} fetched, ${missing} missing.`\n )\n if (missing > 0) {\n console.log('')\n console.log('Missing ABIs must be provided manually. Paste the contract')\n console.log(\n 'ABI JSON at the paths listed above and re-run `zodiac-os pull-contracts`.'\n )\n }\n\n const source = generateAllowTypes(abisDir, config.contracts)\n writeGenerated(generatedFile, source)\n console.log('')\n console.log(`Wrote typings to ${path.relative(process.cwd(), generatedFile)}`)\n\n if (missing > 0) process.exit(1)\n}\n\nfunction report(\n chain: string,\n segments: string[],\n address: string,\n status: Status,\n file: string,\n reason?: string\n) {\n const label = `${chain}.${segments.join('.')}`.padEnd(40, ' ')\n const tag = {\n ok: ' cached ',\n fetched: ' fetched ',\n missing: ' MISSING ',\n }[status]\n const suffix = reason ? ` — ${reason}` : ''\n console.log(`${tag} ${label} ${address}${suffix}`)\n if (status === 'missing') {\n console.log(` → paste ABI at ${file}`)\n }\n}\n","import { Command } from 'commander'\nimport { loadConfig } from './config'\nimport { pullOrg } from './commands/pullOrg'\nimport { pullContracts } from './commands/pullContracts'\n\nexport const run = async (argv: string[] = process.argv) => {\n const program = new Command()\n\n program\n .name('zodiac-os')\n .description('Zodiac OS SDK CLI – pull org data and contract ABIs')\n .version('1.0.0')\n .option(\n '-c, --config <path>',\n 'path to the config file',\n 'zodiac.config.ts'\n )\n\n program\n .command('pull-org')\n .description('Fetch Zodiac users and vaults, generate TypeScript types')\n .action(async (_opts, cmd) => {\n const config = await loadConfig(cmd.optsWithGlobals().config)\n await pullOrg(config)\n })\n\n program\n .command('pull-contracts')\n .description('Fetch contract ABIs, generate typed permissions kit')\n .action(async (_opts, cmd) => {\n const config = await loadConfig(cmd.optsWithGlobals().config)\n await pullContracts(config)\n })\n\n program\n .command('pull')\n .description('Fetch Zodiac org and contracts ABI, generate SDK functions')\n .action(async (_opts, cmd) => {\n const config = await loadConfig(cmd.optsWithGlobals().config)\n await Promise.all([pullOrg(config), pullContracts(config)])\n })\n\n await program.parseAsync(argv)\n}\n","#!/usr/bin/env node\nimport { run } from './run'\n\nrun().then(\n () => {\n process.exit(0)\n },\n (error: unknown) => {\n if (error) console.error(error)\n process.exit(1)\n }\n)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAYA,SAAgB,qBAA6B;CAE3C,MAAM,QADW,cAAc,OAAO,KAAK,IAAI,CACxB,MAAM,8BAA8B;AAE3D,QAAO,KADa,QAAQ,MAAM,KAAK,KAAK,QAAQ,KAAK,EAAE,eAAe,EACjD,aAAa;;;;ACHxC,MAAM,aAAa,OAAgB,SAAS,MAAc;CACxD,MAAM,MAAM,KAAK,OAAO,OAAO;CAC/B,MAAM,WAAW,KAAK,OAAO,SAAS,EAAE;AAExC,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;AAC/C,KAAI,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,MAAM;AAC3D,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAChD,QAAO,OAAO,MAAM;AACtB,KAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,MAAM,KAAK,MAAM,GAAG,WAAW,UAAU,GAAG,SAAS,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,KAAK,IAAI;;AAE/F,KAAI,OAAO,UAAU,UAAU;EAC7B,MAAM,UAAU,OAAO,QAAQ,MAAiC;AAChE,MAAI,QAAQ,WAAW,EAAG,QAAO;AAKjC,SAAO,MAJO,QAAQ,KACnB,CAAC,GAAG,OACH,GAAG,WAAW,6BAA6B,KAAK,EAAE,GAAG,IAAI,KAAK,UAAU,EAAE,CAAC,IAAI,UAAU,GAAG,SAAS,EAAE,GAC1G,CACkB,KAAK,MAAM,CAAC,KAAK,IAAI;;AAE1C,QAAO,OAAO,MAAM;;AAGtB,MAAa,UAAU,OAAO,WAAyB;CACrD,MAAM,SAAS,IAAI,UAAU,EAC3B,QAAQ,OAAO,QAChB,CAAC;CAEF,MAAM,CAAC,OAAO,mBAAmB,MAAM,QAAQ,IAAI,CACjD,OAAO,WAAW,EAClB,OAAO,YAAY,CACpB,CAAC;CAEF,MAAM,eAAe,gBAAgB,SAAS,OAAO,GAAG,OAAO;CAE/D,MAAM,EAAE,QAAQ,aAAa,MAAM,OAAO,qBACxC,gBAAgB,GAAG,aACnB,EACE,eAAe,aAAa,KAAK,WAAW;EAC1C,MAAM;EACN,OAAO,MAAM;EACb,SAAS,MAAM;EAChB,EAAE,EACJ,CACF;CAED,IAAI,eAAe;CACnB,MAAM,eAAwC,EAAE;AAChD,MAAK,MAAM,MAAM,iBAAiB;EAChC,MAAM,WAAoC,EAAE;AAC5C,OAAK,MAAM,SAAS,GAAG,QAAQ;GAC7B,MAAM,UAAU,SAAS;AACzB,aACE,QAAQ,SAAS,QACjB,mCAAmC,MAAM,KAC1C;AACD,YAAS,MAAM,SAAS;IACtB,IAAI,MAAM;IACV,OAAO,MAAM;IACb,SAAS,QAAQ;IACjB,OAAO,MAAM;IACb,WAAW,QAAQ;IACnB,QAAQ,CAAC,GAAG,QAAQ,OAAO;IAC3B,SAAS,CAAC,GAAG,QAAQ,QAAQ;IAC9B;;AAEH,eAAa,GAAG,iBAAiB;GAC/B,aAAa,GAAG;GAChB,eAAe,GAAG;GAClB,QAAQ;GACT;;CAGH,MAAM,4BAAY,IAAI,KAAqB;AAC3C,MAAK,MAAM,QAAQ,MACjB,WAAU,IAAI,KAAK,WAAW,UAAU,IAAI,KAAK,SAAS,IAAI,KAAK,EAAE;CAGvE,MAAM,cAAuC,EAAE;AAC/C,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,SACJ,UAAU,IAAI,KAAK,SAAS,GAAI,IAC5B,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,KAC7B,KAAK;AACX,cAAY,UAAU;GACpB,IAAI,KAAK;GACT,UAAU,KAAK;GACf,eAAe,KAAK;GACrB;;CAGH,MAAM,SAAS,oBAAoB;AAEnC,WAAU,QAAQ,EAAE,WAAW,MAAM,CAAC;AAGtC,eACEA,OAAK,QAAQ,eAAe,EAC5B,KAAK,UACH;EACE,MAAM;EACN,MAAM;EACN,MAAM;EACN,OAAO;EACR,EACD,MACA,EACD,CACF;CAaD,MAAM,aAVU,IAAI,QAAQ;EAC1B,iBAAiB;GACf,aAAa;GACb,QAAQ,WAAW;GACnB,QAAQ,aAAa;GACrB;GACD;EACD,uBAAuB;EACxB,CAAC,CAEyB,iBAAiB,YAAY,GAAG;AAE3D,YAAW,qBAAqB;EAC9B,YAAY;EACZ,iBAAiB,wBAAwB;EACzC,cAAc,CACZ;GACE,MAAM;GACN,aAAa,GAAG,UAAU,YAAY,CAAC;GACxC,CACF;EACF,CAAC;AAEF,YAAW,qBAAqB;EAC9B,YAAY;EACZ,iBAAiB,wBAAwB;EACzC,cAAc,CACZ;GACE,MAAM;GACN,aAAa,GAAG,UAAU,aAAa,CAAC;GACzC,CACF;EACF,CAAC;CAEF,MAAM,aAAa,WAAW,eAAe;AAC7C,MAAK,MAAM,cAAc,WAAW,gBAAgB,CAGlD,eAAcA,OAAK,QAFF,WAAW,aAAa,CACf,SAAS,QAAQ,GAAG,eAAe,WACzB,EAAE,WAAW,SAAS,CAAC;;;;AC9J/D,eAAsB,SACpB,SACA,SACqB;CACrB,MAAM,MAAM,iCAAiC,QAAQ,mDAAmD;CACxG,IAAI;AACJ,KAAI;EACF,MAAM,OAAO,MAAM,MAAM,IAAI;AAC7B,MAAI,CAAC,KAAK,GAAI,QAAO;AACrB,SAAQ,MAAM,KAAK,MAAM;SACnB;AACN,SAAO;;AAET,KAAI,KAAK,WAAW,OAAO,OAAO,KAAK,WAAW,SAAU,QAAO;AACnE,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK,OAAO;AACtC,MAAI,CAAC,MAAM,QAAQ,OAAO,IAAI,OAAO,WAAW,EAAG,QAAO;AAC1D,SAAO;SACD;AACN,SAAO;;;;;AClBX,SAAgB,mBACd,SACA,iBACQ;CAGR,MAAM,uBAAa,IAAI,KAAK;AAC5B,MAAK,MAAM,QAAQ,cAAc,gBAAgB,EAAE;EACjD,MAAM,MAAM,QAAQ,SAAS,KAAK;AAClC,MAAI,CAAC,IAAK;AACV,iBAAe,MAAM,CAAC,KAAK,OAAO,GAAG,KAAK,SAAS,EAAE;GAAE;GAAM;GAAK,CAAC;;CAGrE,MAAM,MAAgB,EAAE;AACxB,KAAI,KAAK,gEAAgE;AACzE,KAAI,KAAK,uBAAuB;AAChC,KAAI,KAAK,GAAG;AACZ,KAAI,KACF,gFACD;AACD,KAAI,KACF,4EACD;AACD,KAAI,KAAK,GAAG;AACZ,KAAI,KAAK,mBAAmB;AAC5B,KAAI,KAAK,0BAA0B,WAAW,MAAM,KAAK,CAAC;AAC1D,KAAI,KAAK,IAAI;AACb,KAAI,KAAK,GAAG;AACZ,KAAI,KAAK,aAAa;AACtB,KAAI,KAAK,GAAG;AACZ,QAAO,IAAI,KAAK,KAAK;;AAGvB,SAAS,eACP,MACA,UACA,MACM;CACN,MAAM,CAAC,OAAO,GAAG,QAAQ;AACzB,KAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iBAAiB;AAC7C,KAAI,KAAK,WAAW,GAAG;AACrB,OAAK,IAAI,OAAO,KAAK;AACrB;;CAEF,IAAI,QAAQ,KAAK,IAAI,MAAM;AAC3B,KAAI,CAAC,SAAS,MAAM,MAAM;AACxB,0BAAQ,IAAI,KAAK;AACjB,OAAK,IAAI,OAAO,MAAM;;AAExB,gBAAe,OAAO,MAAM,KAAK;;AAGnC,SAAS,WAAW,MAAwB,QAAwB;CAClE,MAAM,QAAkB,CAAC,IAAI;AAC7B,MAAK,MAAM,CAAC,KAAK,UAAU,MAAM;EAC/B,MAAM,UAAU,cAAc,IAAI;AAClC,MAAI,iBAAiB,IACnB,OAAM,KAAK,GAAG,OAAO,IAAI,QAAQ,IAAI,WAAW,OAAO,SAAS,KAAK,CAAC,GAAG;OACpE;GACL,MAAM,EAAE,MAAM,QAAQ;AACtB,SAAM,KACJ,GAAG,OAAO,IAAI,QAAQ,IAAI,mBAAmB,MAAM,KAAK,SAAS,KAAK,CAAC,GACxE;;;AAGL,OAAM,KAAK,GAAG,OAAO,GAAG;AACxB,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,cAAc,MAAsB;AAC3C,QAAO,6BAA6B,KAAK,KAAK,GAAG,OAAO,KAAK,UAAU,KAAK;;AAG9E,SAAS,mBACP,MACA,KACA,QACQ;CACR,MAAM,UAAoB,EAAE;CAC5B,MAAM,uBAAO,IAAI,KAAa;AAC9B,SAAQ,KACN,GAAG,OAAO,0DACX;AACD,MAAK,MAAM,YAAY,KAAK;AAC1B,MAAI,SAAS,SAAS,WAAY;AAClC,MACE,SAAS,oBAAoB,UAC7B,SAAS,oBAAoB,OAE7B;EAEF,MAAM,OAAO,SAAS;AACtB,MAAI,CAAC,QAAQ,KAAK,IAAI,KAAK,CAAE;AAC7B,OAAK,IAAI,KAAK;AACd,UAAQ,KAAK,wBAAwB,UAAU,SAAS,KAAK,CAAC;;AAEhE,QAAO;EAAC;EAAK,GAAG;EAAS,GAAG,OAAO;EAAG,CAAC,KAAK,KAAK;;AAGnD,SAAS,wBACP,UACA,QACQ;CACR,MAAM,OAAO,cAAc,SAAS,KAAe;CACnD,MAAM,SAAmB,EAAE;AAC3B,MAAK,MAAM,SAAU,SAAS,UAA4B,EAAE,EAAE;EAC5D,MAAM,YAAY,kBAChB,MAAM,QAAQ,MAAM,OAAO,UAC3B,OAAO,OACR;AACD,SAAO,KAAK,GAAG,UAAU,aAAa,UAAU,MAAM,CAAC,GAAG;;AAE5D,QAAO,KAAK,oBAAoB;AAChC,QAAO,GAAG,SAAS,KAAK,KAAK,OAAO,KAAK,KAAK,CAAC;;AAGjD,SAAS,kBAAkB,MAAc,OAAuB;CAC9D,MAAM,UAAU,KAAK,QAAQ,mBAAmB,IAAI;AACpD,KAAI,CAAC,WAAW,SAAS,KAAK,QAAQ,CAAE,QAAO,MAAM;AAgCrD,QA9BiB,IAAI,IAAI;EACvB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CACc,IAAI,QAAQ,GAAG,IAAI,YAAY;;AAGjD,SAAS,UAAU,UAA+B;CAChD,MAAM,OAAO,SAAS;CAEtB,MAAM,aAAa,kBAAkB,KAAK,KAAK;AAC/C,KAAI,WAEF,QAAO,aAAa,UADO;EAAE,GAAG;EAAU,MAAM,WAAW;EAAI,CAC3B,CAAC;AAGvC,KAAI,SAAS,SAAS;EACpB,MAAM,aAAc,SAAS,cAAgC,EAAE;AAC/D,MAAI,WAAW,WAAW,EAAG,QAAO;AAKpC,SAAO,KAJQ,WAAW,KAAK,GAAG,MAAM;AAEtC,UAAO,GAAG,cADE,kBAAkB,EAAE,QAAQ,IAAI,KAAK,EAAE,CACvB,CAAC,IAAI,UAAU,EAAE;IAC7C,CACiB,KAAK,KAAK,CAAC;;AAGhC,KAAI,SAAS,UAAW,QAAO;AAC/B,KAAI,SAAS,OAAQ,QAAO;AAC5B,KAAI,SAAS,SAAU,QAAO;AAC9B,KAAI,SAAS,QAAS,QAAO;AAC7B,KAAI,aAAa,KAAK,KAAK,CAAE,QAAO;AACpC,KAAI,aAAa,KAAK,KAAK,CAAE,QAAO;AACpC,QAAO;;AAGT,SAAgB,eAAe,SAAiB,QAAsB;AACpE,IAAG,UAAU,KAAK,QAAQ,QAAQ,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,IAAG,cAAc,SAAS,QAAQ,OAAO;;;;AClL3C,MAAa,gBAAgB,OAAO,WAAyB;AAC3D,KAAI,CAAC,OAAO,aAAa,OAAO,KAAK,OAAO,UAAU,CAAC,WAAW,GAAG;AACnE,UAAQ,IAAI,4CAA4C;AACxD;;CAGF,MAAM,UAAU,eAAe,OAAO;CACtC,MAAM,gBAAgB,KAAK,KAAK,oBAAoB,EAAE,aAAa;CAEnE,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,WAAW;AAEf,MAAK,MAAM,QAAQ,cAAc,OAAO,UAAU,EAAE;EAClD,MAAM,OAAO,YAAY,SAAS,KAAK;AAEvC,MAAI,GAAG,WAAW,KAAK,EAAE;AACvB;AACA,UAAO,KAAK,OAAO,KAAK,UAAU,KAAK,SAAS,MAAM,KAAK;AAC3D;;EAGF,IAAI;AACJ,MAAI;AACF,aAAU,WAAW,KAAK,MAAM;WACzB,OAAO;AACd;AACA,UACE,KAAK,OACL,KAAK,UACL,KAAK,SACL,WACA,MACC,MAAgB,QAClB;AACD;;EAGF,MAAM,MAAM,MAAM,SAAS,SAAS,KAAK,QAAQ;AACjD,MAAI,CAAC,KAAK;AACR;AACA,UACE,KAAK,OACL,KAAK,UACL,KAAK,SACL,WACA,MACA,yCAAyC,UAC1C;AACD;;AAEF,WAAS,SAAS,MAAM,IAAI;AAC5B;AACA,SAAO,KAAK,OAAO,KAAK,UAAU,KAAK,SAAS,WAAW,KAAK;;AAGlE,SAAQ,IAAI,GAAG;AACf,SAAQ,IACN,sBAAsB,SAAS,aAAa,QAAQ,YAAY,QAAQ,WACzE;AACD,KAAI,UAAU,GAAG;AACf,UAAQ,IAAI,GAAG;AACf,UAAQ,IAAI,6DAA6D;AACzE,UAAQ,IACN,4EACD;;AAIH,gBAAe,eADA,mBAAmB,SAAS,OAAO,UAAU,CACvB;AACrC,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,oBAAoB,KAAK,SAAS,QAAQ,KAAK,EAAE,cAAc,GAAG;AAE9E,KAAI,UAAU,EAAG,SAAQ,KAAK,EAAE;;AAGlC,SAAS,OACP,OACA,UACA,SACA,QACA,MACA,QACA;CACA,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,IAAI,IAAI;CAC9D,MAAM,MAAM;EACV,IAAI;EACJ,SAAS;EACT,SAAS;EACV,CAAC;CACF,MAAM,SAAS,SAAS,MAAM,WAAW;AACzC,SAAQ,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,SAAS;AAClD,KAAI,WAAW,UACb,SAAQ,IAAI,8BAA8B,OAAO;;;;ACpGrD,MAAa,MAAM,OAAO,OAAiB,QAAQ,SAAS;CAC1D,MAAM,UAAU,IAAI,SAAS;AAE7B,SACG,KAAK,YAAY,CACjB,YAAY,sDAAsD,CAClE,QAAQ,QAAQ,CAChB,OACC,uBACA,2BACA,mBACD;AAEH,SACG,QAAQ,WAAW,CACnB,YAAY,2DAA2D,CACvE,OAAO,OAAO,OAAO,QAAQ;AAE5B,QAAM,QADS,MAAM,WAAW,IAAI,iBAAiB,CAAC,OAAO,CACxC;GACrB;AAEJ,SACG,QAAQ,iBAAiB,CACzB,YAAY,sDAAsD,CAClE,OAAO,OAAO,OAAO,QAAQ;AAE5B,QAAM,cADS,MAAM,WAAW,IAAI,iBAAiB,CAAC,OAAO,CAClC;GAC3B;AAEJ,SACG,QAAQ,OAAO,CACf,YAAY,6DAA6D,CACzE,OAAO,OAAO,OAAO,QAAQ;EAC5B,MAAM,SAAS,MAAM,WAAW,IAAI,iBAAiB,CAAC,OAAO;AAC7D,QAAM,QAAQ,IAAI,CAAC,QAAQ,OAAO,EAAE,cAAc,OAAO,CAAC,CAAC;GAC3D;AAEJ,OAAM,QAAQ,WAAW,KAAK;;;;ACvChC,KAAK,CAAC,WACE;AACJ,SAAQ,KAAK,EAAE;IAEhB,UAAmB;AAClB,KAAI,MAAO,SAAQ,MAAM,MAAM;AAC/B,SAAQ,KAAK,EAAE;EAElB"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["join"],"sources":["../src/cli/commands/pullOrg.ts","../src/allow/fetch.ts","../src/allow/codegen.ts","../src/cli/commands/pullContracts.ts","../src/cli/run.ts","../src/cli/index.ts"],"sourcesContent":["import type { ResolvedConfig } from '../config'\nimport { ApiClient } from '../../api'\nimport { invariant } from '@epic-web/invariant'\nimport { getAddress } from 'ethers'\nimport {\n ModuleKind,\n Project,\n ScriptTarget,\n VariableDeclarationKind,\n} from 'ts-morph'\nimport { mkdirSync, writeFileSync } from 'fs'\nimport { join } from 'path'\nimport { resolveZodiacDir } from '../../paths'\n\nconst toLiteral = (value: unknown, indent = 0): string => {\n const pad = ' '.repeat(indent)\n const childPad = ' '.repeat(indent + 1)\n\n if (value === null) return 'null'\n if (typeof value === 'bigint') return `${value}n`\n if (typeof value === 'string') return JSON.stringify(value)\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value)\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]'\n return `[\\n${value.map((v) => `${childPad}${toLiteral(v, indent + 1)}`).join(',\\n')},\\n${pad}]`\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.length === 0) return '{}'\n const props = entries.map(\n ([k, v]) =>\n `${childPad}${/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : JSON.stringify(k)}: ${toLiteral(v, indent + 1)}`\n )\n return `{\\n${props.join(',\\n')},\\n${pad}}`\n }\n return String(value)\n}\n\nexport const pullOrg = async (config: ResolvedConfig) => {\n const client = new ApiClient({\n apiKey: config.apiKey,\n })\n\n const [users, workspaceAccounts] = await Promise.all([\n client.listUsers(),\n client.listAccounts(),\n ])\n\n // Fetch fresh on-chain state via `resolveConstellation` for every\n // account we can resolve:\n // - `spec` present → pass the stored apply-time node verbatim\n // (deployed nodes match on-chain; undeployed ones derive via\n // CREATE2 from the stored nonce + config).\n // - `vault: true` with no spec → treat as a pre-existing on-chain\n // SAFE (e.g. a workspace vault created outside the\n // constellation-as-code flow). The resolver finds it on-chain.\n // - `vault: false` with no spec → a constituent of a still-pending\n // constellation that's never been deployed. We can't usefully\n // resolve it, so skip; the codegen emits minimal fields.\n const allAccounts = workspaceAccounts.flatMap((ws) => ws.accounts)\n const resolvableAccounts = allAccounts.filter(\n (a) => a.spec != null || a.vault\n )\n const resolved = new Map<\n string,\n Awaited<ReturnType<typeof client.resolveConstellation>>['result'][number]\n >()\n if (resolvableAccounts.length > 0) {\n const response = await client.resolveConstellation(\n workspaceAccounts[0].workspaceId, // any workspace works for the resolve route\n {\n specification: resolvableAccounts.map((account, i) =>\n account.spec != null\n ? account.spec\n : {\n // Synthesize a ref for vault-fallback entries (no stored\n // spec). The /resolve payload requires a ref on every\n // entry; the value isn't used downstream beyond echoing\n // back into the response, so a positional id is fine.\n ref: `vault_${i}` as Lowercase<string>,\n type: 'SAFE',\n chain: account.chain,\n address: account.address,\n }\n ),\n }\n )\n invariant(\n response?.result?.length === resolvableAccounts.length,\n `resolveConstellation returned ${response?.result?.length ?? 0} accounts for ${resolvableAccounts.length} accounts`\n )\n resolvableAccounts.forEach((account, i) => {\n resolved.set(account.id, response.result[i])\n })\n }\n\n // Group accounts by type into separate bracket-access namespaces:\n // `safes`, `rolesMods`, `delays`. This way `eth.safe[...]`\n // IntelliSense only suggests SAFE labels, and the label-collision\n // suffix only kicks in when two accounts **of the same type** share\n // a label.\n const accountsRecord: Record<string, unknown> = {}\n for (const ws of workspaceAccounts) {\n const safes: Record<string, unknown> = {}\n const rolesMods: Record<string, unknown> = {}\n const delays: Record<string, unknown> = {}\n\n const bucketsByType = {\n SAFE: safes,\n ROLES: rolesMods,\n DELAY: delays,\n } as const\n\n type NodeType = 'SAFE' | 'ROLES' | 'DELAY'\n const isNodeType = (type: string): type is NodeType =>\n type === 'SAFE' || type === 'ROLES' || type === 'DELAY'\n\n // Count labels per type so we only suffix within-type collisions.\n const labelCountByType: Record<NodeType, Map<string, number>> = {\n SAFE: new Map(),\n ROLES: new Map(),\n DELAY: new Map(),\n }\n for (const account of ws.accounts) {\n if (!isNodeType(account.type)) continue\n const counts = labelCountByType[account.type]\n counts.set(account.label, (counts.get(account.label) ?? 0) + 1)\n }\n\n for (const account of ws.accounts) {\n if (!isNodeType(account.type)) continue\n const onChain = resolved.get(account.id)\n const counts = labelCountByType[account.type]\n const key =\n (counts.get(account.label) ?? 0) > 1\n ? `${account.label} (${getAddress(account.address)})`\n : account.label\n bucketsByType[account.type][key] = {\n id: account.id,\n label: account.label,\n address: account.address,\n chain: account.chain,\n vault: account.vault,\n ...(onChain?.type === 'SAFE' && {\n threshold: onChain.threshold,\n owners: [...onChain.owners],\n modules: [...onChain.modules],\n }),\n }\n }\n\n accountsRecord[ws.workspaceName] = {\n workspaceId: ws.workspaceId,\n workspaceName: ws.workspaceName,\n safes,\n rolesMods,\n delays,\n }\n }\n\n const nameCount = new Map<string, number>()\n for (const user of users) {\n nameCount.set(user.fullName, (nameCount.get(user.fullName) ?? 0) + 1)\n }\n\n const usersRecord: Record<string, unknown> = {}\n for (const user of users) {\n const handle =\n nameCount.get(user.fullName)! > 1\n ? `${user.fullName} (${user.id})`\n : user.fullName\n usersRecord[handle] = {\n id: user.id,\n fullName: user.fullName,\n personalSafes: user.personalSafes,\n }\n }\n\n const outDir = resolveZodiacDir(config.rootDir)\n\n mkdirSync(outDir, { recursive: true })\n\n // Pin CJS so `require()` works regardless of the parent package.json's type\n writeFileSync(\n join(outDir, 'package.json'),\n JSON.stringify(\n {\n type: 'commonjs',\n main: 'index.js',\n types: 'index.d.ts',\n },\n null,\n 2\n )\n )\n\n // Use ts-morph to generate TS, then emit JS + d.ts\n const project = new Project({\n compilerOptions: {\n declaration: true,\n module: ModuleKind.CommonJS,\n target: ScriptTarget.ESNext,\n outDir,\n },\n useInMemoryFileSystem: true,\n })\n\n const sourceFile = project.createSourceFile('index.ts', '')\n\n sourceFile.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'users',\n initializer: `${toLiteral(usersRecord)} as const`,\n },\n ],\n })\n\n sourceFile.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'accounts',\n initializer: `${toLiteral(accountsRecord)} as const`,\n },\n ],\n })\n\n const emitResult = sourceFile.getEmitOutput()\n for (const outputFile of emitResult.getOutputFiles()) {\n const filePath = outputFile.getFilePath()\n const fileName = filePath.includes('.d.ts') ? 'index.d.ts' : 'index.js'\n let contents = outputFile.getText()\n // Augment the SDK's global `ZodiacGeneratedCodegen` interface so\n // `constellation()`'s default type parameter picks up these literal\n // shapes automatically.\n if (fileName === 'index.d.ts') {\n contents += `\ndeclare global {\n interface ZodiacGeneratedCodegen {\n users: typeof users;\n accounts: typeof accounts;\n }\n}\n`\n }\n writeFileSync(join(outDir, fileName), contents)\n }\n}\n","import { chainIdFor, type ChainPrefix } from './networks'\n\nexport type AbiFragment = Record<string, any>\nexport type Abi = AbiFragment[]\n\n// Returns null on any failure so callers can fall back to a manual ABI file.\nexport async function fetchAbi(\n chainId: number,\n address: `0x${string}`\n): Promise<Abi | null> {\n const url = `https://api.abi.pub/v1/chains/${chainId}/etherscan?module=contract&action=getabi&address=${address}`\n let body: { status?: string; message?: string; result?: string }\n try {\n const resp = await fetch(url)\n if (!resp.ok) return null\n body = (await resp.json()) as typeof body\n } catch {\n return null\n }\n if (body.status !== '1' || typeof body.result !== 'string') return null\n try {\n const parsed = JSON.parse(body.result)\n if (!Array.isArray(parsed) || parsed.length === 0) return null\n return parsed as Abi\n } catch {\n return null\n }\n}\n\nexport const fetchAbiForPrefix = (\n prefix: ChainPrefix,\n address: `0x${string}`\n) => fetchAbi(chainIdFor(prefix), address)\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { walkContracts, readAbi, type ContractNode } from './abi'\nimport type { Abi, AbiFragment } from './fetch'\n\n// Emits named tuple elements per ABI input — this is the reason we don't rely\n// on viem/abitype, which produces unnamed tuples (microsoft/TypeScript#44939).\nexport function generateAllowTypes(\n abisDir: string,\n contractsConfig: Record<string, any>\n): string {\n type Tree = Map<string, Tree | { node: ContractNode; abi: Abi }>\n\n const root: Tree = new Map()\n for (const node of walkContracts(contractsConfig)) {\n const abi = readAbi(abisDir, node)\n if (!abi) continue\n insertIntoTree(root, [node.chain, ...node.segments], { node, abi })\n }\n\n const out: string[] = []\n out.push('// AUTO-GENERATED by `zodiac-os pull-contracts`. Do not edit.')\n out.push('/* eslint-disable */')\n out.push('')\n out.push(\n `import type { FunctionPermission, TargetPermission } from \"zodiac-roles-sdk\";`\n )\n out.push(\n `import type { Scoping, Options, EVERYTHING } from \"@zodiac-os/sdk/allow\";`\n )\n out.push('')\n out.push('declare global {')\n out.push(' interface AllowKit ' + renderTree(root, ' '))\n out.push('}')\n out.push('')\n out.push('export {};')\n out.push('')\n return out.join('\\n')\n}\n\nfunction insertIntoTree(\n tree: Map<string, any>,\n segments: string[],\n leaf: { node: ContractNode; abi: Abi }\n): void {\n const [first, ...rest] = segments\n if (!first) throw new Error('empty segments')\n if (rest.length === 0) {\n tree.set(first, leaf)\n return\n }\n let child = tree.get(first)\n if (!child || child.node) {\n child = new Map()\n tree.set(first, child)\n }\n insertIntoTree(child, rest, leaf)\n}\n\nfunction renderTree(tree: Map<string, any>, indent: string): string {\n const lines: string[] = ['{']\n for (const [key, value] of tree) {\n const safeKey = renderPropKey(key)\n if (value instanceof Map) {\n lines.push(`${indent} ${safeKey}: ${renderTree(value, indent + ' ')};`)\n } else {\n const { node, abi } = value as { node: ContractNode; abi: Abi }\n lines.push(\n `${indent} ${safeKey}: ${renderContractType(node, abi, indent + ' ')};`\n )\n }\n }\n lines.push(`${indent}}`)\n return lines.join('\\n')\n}\n\nfunction renderPropKey(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name)\n}\n\nfunction renderContractType(\n node: ContractNode,\n abi: Abi,\n indent: string\n): string {\n const members: string[] = []\n const seen = new Set<string>()\n members.push(\n `${indent} [EVERYTHING]: (options?: Options) => TargetPermission;`\n )\n for (const fragment of abi) {\n if (fragment.type !== 'function') continue\n if (\n fragment.stateMutability === 'view' ||\n fragment.stateMutability === 'pure'\n ) {\n continue\n }\n const name = fragment.name as string\n if (!name || seen.has(name)) continue\n seen.add(name)\n members.push(renderFunctionSignature(fragment, indent + ' '))\n }\n return ['{', ...members, `${indent}}`].join('\\n')\n}\n\nfunction renderFunctionSignature(\n fragment: AbiFragment,\n indent: string\n): string {\n const name = renderPropKey(fragment.name as string)\n const params: string[] = []\n for (const input of (fragment.inputs as AbiFragment[]) ?? []) {\n const paramName = sanitizeParamName(\n input.name || `arg${params.length}`,\n params.length\n )\n params.push(`${paramName}?: Scoping<${tsTypeFor(input)}>`)\n }\n params.push(`options?: Options`)\n return `${indent}${name}: (${params.join(', ')}) => FunctionPermission;`\n}\n\nfunction sanitizeParamName(name: string, index: number): string {\n const cleaned = name.replace(/[^A-Za-z0-9_$]/g, '_')\n if (!cleaned || /^[0-9]/.test(cleaned)) return `arg${index}`\n // Named tuple element labels can't collide with TS reserved words.\n const reserved = new Set([\n 'function',\n 'class',\n 'new',\n 'number',\n 'string',\n 'object',\n 'boolean',\n 'symbol',\n 'default',\n 'return',\n 'this',\n 'void',\n 'delete',\n 'in',\n 'of',\n 'for',\n 'while',\n 'switch',\n 'case',\n 'if',\n 'else',\n 'null',\n 'true',\n 'false',\n 'undefined',\n 'any',\n 'never',\n 'unknown',\n ])\n return reserved.has(cleaned) ? `_${cleaned}` : cleaned\n}\n\nfunction tsTypeFor(fragment: AbiFragment): string {\n const type = fragment.type as string\n\n const arrayMatch = /^(.*)\\[(\\d*)\\]$/.exec(type)\n if (arrayMatch) {\n const inner: AbiFragment = { ...fragment, type: arrayMatch[1] }\n return `readonly (${tsTypeFor(inner)})[]`\n }\n\n if (type === 'tuple') {\n const components = (fragment.components as AbiFragment[]) ?? []\n if (components.length === 0) return 'Record<string, unknown>'\n const fields = components.map((c, i) => {\n const key = sanitizeParamName(c.name || `f${i}`, i)\n return `${renderPropKey(key)}: ${tsTypeFor(c)}`\n })\n return `{ ${fields.join('; ')} }`\n }\n\n if (type === 'address') return '`0x${string}`'\n if (type === 'bool') return 'boolean'\n if (type === 'string') return 'string'\n if (type === 'bytes') return 'import(\"ethers\").BytesLike'\n if (/^bytes\\d+$/.test(type)) return '`0x${string}`'\n if (/^u?int\\d*$/.test(type)) return 'import(\"ethers\").BigNumberish'\n return 'unknown'\n}\n\nexport function writeGenerated(outFile: string, source: string): void {\n fs.mkdirSync(path.dirname(outFile), { recursive: true })\n fs.writeFileSync(outFile, source, 'utf8')\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { ResolvedConfig } from '../config'\nimport { resolveAbisDir } from '../config'\nimport { resolveZodiacDir } from '../../paths'\nimport { abiFilePath, walkContracts, writeAbi } from '../../allow/abi'\nimport { fetchAbi } from '../../allow/fetch'\nimport { chainIdFor } from '../../allow/networks'\nimport { generateAllowTypes, writeGenerated } from '../../allow/codegen'\n\ntype Status = 'ok' | 'fetched' | 'missing'\n\nexport const pullContracts = async (config: ResolvedConfig) => {\n if (!config.contracts || Object.keys(config.contracts).length === 0) {\n console.log('No contracts defined in config, skipping.')\n return\n }\n\n const abisDir = resolveAbisDir(config)\n const generatedFile = path.join(\n resolveZodiacDir(config.rootDir),\n 'allow.d.ts'\n )\n\n let missing = 0\n let fetched = 0\n let existing = 0\n\n for (const node of walkContracts(config.contracts)) {\n const file = abiFilePath(abisDir, node)\n\n if (fs.existsSync(file)) {\n existing++\n report(node.chain, node.segments, node.address, 'ok', file)\n continue\n }\n\n let chainId: number\n try {\n chainId = chainIdFor(node.chain)\n } catch (error) {\n missing++\n report(\n node.chain,\n node.segments,\n node.address,\n 'missing',\n file,\n (error as Error).message\n )\n continue\n }\n\n const abi = await fetchAbi(chainId, node.address)\n if (!abi) {\n missing++\n report(\n node.chain,\n node.segments,\n node.address,\n 'missing',\n file,\n `api.abi.pub returned no ABI for chain ${chainId}`\n )\n continue\n }\n writeAbi(abisDir, node, abi)\n fetched++\n report(node.chain, node.segments, node.address, 'fetched', file)\n }\n\n console.log('')\n console.log(\n `Contracts summary: ${existing} existing, ${fetched} fetched, ${missing} missing.`\n )\n if (missing > 0) {\n console.log('')\n console.log('Missing ABIs must be provided manually. Paste the contract')\n console.log(\n 'ABI JSON at the paths listed above and re-run `zodiac-os pull-contracts`.'\n )\n }\n\n const source = generateAllowTypes(abisDir, config.contracts)\n writeGenerated(generatedFile, source)\n console.log('')\n console.log(`Wrote typings to ${path.relative(process.cwd(), generatedFile)}`)\n\n if (missing > 0) process.exit(1)\n}\n\nfunction report(\n chain: string,\n segments: string[],\n address: string,\n status: Status,\n file: string,\n reason?: string\n) {\n const label = `${chain}.${segments.join('.')}`.padEnd(40, ' ')\n const tag = {\n ok: ' cached ',\n fetched: ' fetched ',\n missing: ' MISSING ',\n }[status]\n const suffix = reason ? ` — ${reason}` : ''\n console.log(`${tag} ${label} ${address}${suffix}`)\n if (status === 'missing') {\n console.log(` → paste ABI at ${file}`)\n }\n}\n","import { Command } from 'commander'\nimport { loadConfig } from './config'\nimport { pullOrg } from './commands/pullOrg'\nimport { pullContracts } from './commands/pullContracts'\n\nexport const run = async (argv: string[] = process.argv) => {\n const program = new Command()\n\n program\n .name('zodiac-os')\n .description('Zodiac OS SDK CLI – pull org data and contract ABIs')\n .version('1.0.0')\n .option(\n '-c, --config <path>',\n 'path to the config file',\n 'zodiac.config.ts'\n )\n\n program\n .command('pull-org')\n .description('Fetch Zodiac users and vaults, generate TypeScript types')\n .action(async (_opts, cmd) => {\n const config = await loadConfig(cmd.optsWithGlobals().config)\n await pullOrg(config)\n })\n\n program\n .command('pull-contracts')\n .description('Fetch contract ABIs, generate typed permissions kit')\n .action(async (_opts, cmd) => {\n const config = await loadConfig(cmd.optsWithGlobals().config)\n await pullContracts(config)\n })\n\n program\n .command('pull')\n .description('Fetch Zodiac org and contracts ABI, generate SDK functions')\n .action(async (_opts, cmd) => {\n const config = await loadConfig(cmd.optsWithGlobals().config)\n await Promise.all([pullOrg(config), pullContracts(config)])\n })\n\n await program.parseAsync(argv)\n}\n","#!/usr/bin/env node\nimport { run } from './run'\n\nrun().then(\n () => {\n process.exit(0)\n },\n (error: unknown) => {\n if (error) console.error(error)\n process.exit(1)\n }\n)\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/// <reference path="./zodiac-os-codegen.d.ts" />
|
|
2
2
|
import { a as EVERYTHING, c as Scoping, i as ConditionFunction, l as TargetPermission, n as ChainPrefix, o as FunctionPermission, s as Options, u as buildAllowKit } from "./index-DTBaxN7b.mjs";
|
|
3
3
|
import { Annotation, Permission, PermissionSet, c, forAll } from "zodiac-roles-sdk";
|
|
4
|
-
import { Address, ApplyConstellationPayload, ApplyConstellationResult, ChainId,
|
|
5
|
-
import * as ZodiacOsCodegen from ".zodiac-os";
|
|
4
|
+
import { Address, ApplyConstellationPayload, ApplyConstellationResult, ChainId, ListAccountsResult, ListUsersResult, ResolveConstellationPayload, ResolveConstellationResult } from "@zodiac-os/api-types";
|
|
6
5
|
import { UUID } from "crypto";
|
|
7
6
|
|
|
8
7
|
//#region src/types.d.ts
|
|
@@ -22,7 +21,7 @@ type AllowanceSpec = RealBigints<ApiAllowanceSpec>;
|
|
|
22
21
|
//#region src/constellation.d.ts
|
|
23
22
|
/**
|
|
24
23
|
* A role definition keyed by role name. Permissions are expanded into
|
|
25
|
-
* `{ targets, annotations }` via `processPermissions` at `
|
|
24
|
+
* `{ targets, annotations }` via `processPermissions` at `push()` time.
|
|
26
25
|
*/
|
|
27
26
|
type RoleDef = {
|
|
28
27
|
members: readonly AddressOrRef[];
|
|
@@ -37,31 +36,34 @@ type User = {
|
|
|
37
36
|
active: boolean;
|
|
38
37
|
}>;
|
|
39
38
|
};
|
|
40
|
-
type
|
|
39
|
+
type Account = {
|
|
41
40
|
id: UUID;
|
|
42
41
|
label: string;
|
|
43
42
|
address: Lowercase<Address>;
|
|
44
|
-
chain: ChainId;
|
|
45
|
-
|
|
46
|
-
owners: readonly string[];
|
|
47
|
-
modules: readonly string[];
|
|
43
|
+
chain: ChainId; /** True for accounts promoted to a workspace vault. */
|
|
44
|
+
vault: boolean;
|
|
48
45
|
};
|
|
49
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Accounts grouped by node type within a workspace. Per-type maps keep
|
|
48
|
+
* bracket-accessor namespaces separate: a SAFE and a ROLES mod sharing a
|
|
49
|
+
* label don't collide, and `eth.safe[...]` IntelliSense doesn't suggest
|
|
50
|
+
* ROLES mod labels (and vice versa).
|
|
51
|
+
*/
|
|
52
|
+
type WorkspaceAccounts = {
|
|
50
53
|
workspaceId: UUID;
|
|
51
54
|
workspaceName: string;
|
|
52
|
-
|
|
55
|
+
safes: Readonly<Record<string, Account>>;
|
|
56
|
+
rolesMods: Readonly<Record<string, Account>>;
|
|
57
|
+
delays: Readonly<Record<string, Account>>;
|
|
53
58
|
};
|
|
54
59
|
/** Shape of the codegen data produced by `zodiac-os pull-org`. */
|
|
55
60
|
type CodegenData = {
|
|
56
61
|
users: Readonly<Record<string, User>>;
|
|
57
|
-
|
|
58
|
-
};
|
|
59
|
-
type GeneratedCodegen = {
|
|
60
|
-
users: typeof ZodiacOsCodegen.users;
|
|
61
|
-
vaults: typeof ZodiacOsCodegen.vaults;
|
|
62
|
+
accounts: Readonly<Record<string, WorkspaceAccounts>>;
|
|
62
63
|
};
|
|
64
|
+
type GeneratedCodegen = ZodiacGeneratedCodegen extends CodegenData ? ZodiacGeneratedCodegen : CodegenData;
|
|
63
65
|
type ConstellationOpts<C extends CodegenData> = {
|
|
64
|
-
/** Workspace to scope
|
|
66
|
+
/** Workspace to scope accounts and roles to. */workspace: keyof C['accounts'] & string; /** Human-readable label for this constellation. */
|
|
65
67
|
label: string; /** Target chain for all nodes in this constellation. */
|
|
66
68
|
chain: ChainId;
|
|
67
69
|
};
|
|
@@ -69,7 +71,8 @@ type ConstellationInternalOpts<C extends CodegenData> = {
|
|
|
69
71
|
/** Injected codegen data (used for testing). */codegen?: C;
|
|
70
72
|
};
|
|
71
73
|
type Prettify<T> = { readonly [K in keyof T]: T[K] } & {};
|
|
72
|
-
type
|
|
74
|
+
type SafeEntries<C extends CodegenData, W extends keyof C['accounts']> = C['accounts'][W]['safes'];
|
|
75
|
+
type RolesEntries<C extends CodegenData, W extends keyof C['accounts']> = C['accounts'][W]['rolesMods'];
|
|
73
76
|
type NodeType = 'SAFE' | 'ROLES' | 'DELAY';
|
|
74
77
|
/** A reference to a node used in `owners`, `modules`, `target`, etc. */
|
|
75
78
|
type NodeRef = Readonly<{
|
|
@@ -102,10 +105,12 @@ type RolesNode = NodeBase & Readonly<{
|
|
|
102
105
|
owner?: AddressOrRef; /** The account that calls will be executed from. */
|
|
103
106
|
avatar?: AddressOrRef; /** MultiSend contract addresses for batched transactions. */
|
|
104
107
|
multisend?: readonly Address[]; /** Role definitions configured on this modifier. */
|
|
105
|
-
roles?: Record<string, RoleDef>;
|
|
106
|
-
allowances
|
|
108
|
+
roles?: Record<string, RoleDef>;
|
|
109
|
+
/** Spending allowances configured on this modifier. Either an array or
|
|
110
|
+
* a Record keyed by name — both forms carry the same allowance specs. */
|
|
111
|
+
allowances?: readonly AllowanceSpec[] | Record<string, AllowanceSpec>;
|
|
107
112
|
}>;
|
|
108
|
-
/** Any complete node that can be passed to `
|
|
113
|
+
/** Any complete node that can be passed to `push()`. */
|
|
109
114
|
type ConstellationNode = SafeNode | RolesNode;
|
|
110
115
|
type NewSafeProps = {
|
|
111
116
|
/** Deployment nonce for CREATE2 address derivation. */nonce: bigint; /** Number of owner signatures required to execute a transaction. */
|
|
@@ -115,23 +120,26 @@ type NewSafeProps = {
|
|
|
115
120
|
vault?: boolean;
|
|
116
121
|
};
|
|
117
122
|
type NewRolesProps = {
|
|
118
|
-
/** Deployment nonce for CREATE2 address derivation.
|
|
123
|
+
/** Deployment nonce for CREATE2 address derivation. */nonce: bigint; /** The safe that this roles modifier controls. Defaults to the new safe with the same label, when one exists. */
|
|
119
124
|
target?: AddressOrRef; /** The account that calls will be executed from. Defaults to `target` value */
|
|
120
125
|
avatar?: AddressOrRef; /** The account that is allowed to update the configuration of the Roles Mod. Defaults to `target` value */
|
|
121
126
|
owner?: AddressOrRef; /** MultiSend contract addresses for batched transactions. Defaults to `['0x38869bf66a61cf6bdb996a6ae40d5853fd43b526', '0x9641d764fc13c8b624c04430c7356c1c7c8102e2']` */
|
|
122
127
|
multisend?: readonly Address[]; /** Role definitions to configure on this modifier. */
|
|
123
|
-
roles?: Record<string, RoleDef>;
|
|
124
|
-
allowances
|
|
128
|
+
roles?: Record<string, RoleDef>;
|
|
129
|
+
/** Spending allowances to configure on this modifier. Either an array or
|
|
130
|
+
* a Record keyed by name — both forms carry the same allowance specs. */
|
|
131
|
+
allowances?: readonly AllowanceSpec[] | Record<string, AllowanceSpec>;
|
|
125
132
|
};
|
|
126
|
-
type
|
|
133
|
+
type ExistingNodeAccessor<Type extends string, K extends string, E, Ch extends ChainId, NP extends Record<string, any>> = Readonly<Prettify<E & {
|
|
127
134
|
type: Type;
|
|
128
135
|
label: K;
|
|
129
136
|
chain: Ch;
|
|
130
|
-
}>> & (<O extends { [P in Exclude<keyof
|
|
137
|
+
}>> & (<O extends { [P in Exclude<keyof E & string, 'id' | 'label'>]?: any } & Partial<NP> = {}>(overrides?: { [P in Exclude<keyof E & string, 'id' | 'label'>]?: any } & Partial<NP> & O) => Readonly<Prettify<Omit<E, keyof O> & O & Partial<NP> & {
|
|
131
138
|
type: Type;
|
|
132
139
|
label: K;
|
|
133
140
|
chain: Ch;
|
|
134
|
-
}>>)
|
|
141
|
+
}>>);
|
|
142
|
+
type NewNodeAccessor<Type extends string, Ch extends ChainId, NP extends Record<string, any>> = Readonly<Prettify<{
|
|
135
143
|
type: Type;
|
|
136
144
|
label: string;
|
|
137
145
|
chain: Ch;
|
|
@@ -139,27 +147,35 @@ type EntityAccessor<Type extends string, Entries extends Record<string, any>, Ch
|
|
|
139
147
|
type: Type;
|
|
140
148
|
label: string;
|
|
141
149
|
chain: Ch;
|
|
142
|
-
}>>)
|
|
150
|
+
}>>);
|
|
151
|
+
type EntityAccessor<Type extends string, Entries extends Record<string, any>, Ch extends ChainId = ChainId, NP extends Record<string, any> = Record<string, any>> = { readonly [K in keyof Entries & string]: ExistingNodeAccessor<Type, K, Entries[K], Ch, NP> } & {
|
|
152
|
+
readonly [key: string]: NewNodeAccessor<Type, Ch, NP>;
|
|
153
|
+
};
|
|
143
154
|
type UserAccessor<C extends CodegenData, Ch extends number> = { readonly [K in keyof C['users'] & string]: C['users'][K]['personalSafes'][Ch]['address'] };
|
|
144
|
-
type ConstellationResult<C extends CodegenData, W extends keyof C['
|
|
145
|
-
/** Access existing safes by label or create new ones with a new label.
|
|
146
|
-
|
|
155
|
+
type ConstellationResult<C extends CodegenData, W extends keyof C['accounts'] = keyof C['accounts'], Ch extends ChainId = ChainId> = {
|
|
156
|
+
/** Access existing safes by label or create new ones with a new label.
|
|
157
|
+
* Only SAFE-typed accounts are suggested in IntelliSense. */
|
|
158
|
+
safe: EntityAccessor<'SAFE', SafeEntries<C, W>, Ch, NewSafeProps>;
|
|
159
|
+
/** Access existing roles modifiers by label or create new ones with a
|
|
160
|
+
* new label. Only ROLES-typed accounts are suggested in IntelliSense. */
|
|
161
|
+
roles: EntityAccessor<'ROLES', RolesEntries<C, W>, Ch, NewRolesProps>; /** Resolve a user's personal safe address on the constellation's chain. */
|
|
147
162
|
user: UserAccessor<C, Ch>;
|
|
148
163
|
};
|
|
149
164
|
/** @internal */
|
|
150
165
|
/**
|
|
151
166
|
* Creates a constellation scoped to a workspace and chain.
|
|
152
167
|
*
|
|
153
|
-
* Use bracket access to reference existing vaults
|
|
168
|
+
* Use bracket access to reference existing accounts (vaults and other
|
|
169
|
+
* applied constellation nodes) or define new ones:
|
|
154
170
|
* ```ts
|
|
155
171
|
* const eth = constellation({ workspace: 'GG', label: 'my constellation', chain: 1 })
|
|
156
172
|
*
|
|
157
|
-
* const dao = eth.safe['GG DAO'] // existing
|
|
173
|
+
* const dao = eth.safe['GG DAO'] // existing account ref
|
|
158
174
|
* const roles = eth.roles['GG DAO'] // existing roles ref
|
|
159
175
|
* const newSafe = eth.safe['New Safe']({ nonce: 0n, threshold: 2, owners: [...], modules: [...] })
|
|
160
176
|
* ```
|
|
161
177
|
*/
|
|
162
|
-
declare function constellation<const C extends CodegenData = GeneratedCodegen, const W extends keyof C['
|
|
178
|
+
declare function constellation<const C extends CodegenData = GeneratedCodegen, const W extends keyof C['accounts'] & string = keyof C['accounts'] & string, const Ch extends ChainId = ChainId>(opts: ConstellationOpts<C> & {
|
|
163
179
|
workspace: W;
|
|
164
180
|
chain: Ch;
|
|
165
181
|
}, internal?: ConstellationInternalOpts<C>): ConstellationResult<C, W, Ch>;
|
|
@@ -185,7 +201,7 @@ declare class ApiClient {
|
|
|
185
201
|
}?: Options$1);
|
|
186
202
|
protected postJson(endpoint: string, payload: unknown): Promise<any>;
|
|
187
203
|
protected get(endpoint: string): Promise<any>;
|
|
188
|
-
|
|
204
|
+
listAccounts(): Promise<ListAccountsResult>;
|
|
189
205
|
listUsers(): Promise<ListUsersResult>;
|
|
190
206
|
/**
|
|
191
207
|
* Applies an accounts specification to Zodiac OS.
|
|
@@ -197,12 +213,12 @@ declare class ApiClient {
|
|
|
197
213
|
resolveConstellation(workspaceId: UUID, payload: ResolveConstellationPayload): Promise<ResolveConstellationResult>;
|
|
198
214
|
}
|
|
199
215
|
//#endregion
|
|
200
|
-
//#region src/
|
|
201
|
-
type
|
|
216
|
+
//#region src/push.d.ts
|
|
217
|
+
type PushOpts = {
|
|
202
218
|
/** API client instance. Defaults to a client configured from environment variables. */api?: ApiClient;
|
|
203
219
|
};
|
|
204
220
|
/**
|
|
205
|
-
* Resolves node references and
|
|
221
|
+
* Resolves node references and pushes the constellation specification to the API.
|
|
206
222
|
*
|
|
207
223
|
*
|
|
208
224
|
* ```ts
|
|
@@ -210,12 +226,12 @@ type ApplyOpts = {
|
|
|
210
226
|
* const dao = eth.safe['GG DAO']
|
|
211
227
|
* const roles = eth.roles['New Roles']({ nonce: 0n, target: dao, owner: dao, avatar: dao })
|
|
212
228
|
*
|
|
213
|
-
* await
|
|
229
|
+
* await push([dao, roles])
|
|
214
230
|
* ```
|
|
215
231
|
*/
|
|
216
|
-
declare function
|
|
232
|
+
declare function push(nodes: ConstellationNode[] | {
|
|
217
233
|
[key: string]: ConstellationNode;
|
|
218
|
-
}, opts?:
|
|
234
|
+
}, opts?: PushOpts): Promise<ApplyConstellationResult[]>;
|
|
219
235
|
//#endregion
|
|
220
|
-
export { type ChainPrefix, type ConditionFunction, EVERYTHING, type FunctionPermission, type Options, type Scoping, type TargetPermission,
|
|
236
|
+
export { type ChainPrefix, type ConditionFunction, EVERYTHING, type FunctionPermission, type Options, type Scoping, type TargetPermission, buildAllowKit, c, constellation, forAll, push };
|
|
221
237
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,73 +1,64 @@
|
|
|
1
|
-
import { t as ApiClient } from "./api-
|
|
1
|
+
import { n as resolveZodiacDir, t as ApiClient } from "./api-CygEDU4N.mjs";
|
|
2
2
|
import { n as EVERYTHING, t as buildAllowKit } from "./allow-Dzh6t_l8.mjs";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
import { invariant } from "@epic-web/invariant";
|
|
5
5
|
import { c, forAll, processPermissions } from "zodiac-roles-sdk";
|
|
6
6
|
//#region src/constellation.ts
|
|
7
7
|
function loadCodegen() {
|
|
8
|
-
return createRequire(import.meta.url)(
|
|
8
|
+
return createRequire(import.meta.url)(resolveZodiacDir());
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* Creates a constellation scoped to a workspace and chain.
|
|
12
12
|
*
|
|
13
|
-
* Use bracket access to reference existing vaults
|
|
13
|
+
* Use bracket access to reference existing accounts (vaults and other
|
|
14
|
+
* applied constellation nodes) or define new ones:
|
|
14
15
|
* ```ts
|
|
15
16
|
* const eth = constellation({ workspace: 'GG', label: 'my constellation', chain: 1 })
|
|
16
17
|
*
|
|
17
|
-
* const dao = eth.safe['GG DAO'] // existing
|
|
18
|
+
* const dao = eth.safe['GG DAO'] // existing account ref
|
|
18
19
|
* const roles = eth.roles['GG DAO'] // existing roles ref
|
|
19
20
|
* const newSafe = eth.safe['New Safe']({ nonce: 0n, threshold: 2, owners: [...], modules: [...] })
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
23
|
function constellation(opts, internal) {
|
|
23
24
|
const codegen = internal?.codegen ?? loadCodegen();
|
|
24
|
-
const ws = codegen.
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
const ws = codegen.accounts[opts.workspace];
|
|
26
|
+
const safesByLabel = {};
|
|
27
|
+
const rolesByLabel = {};
|
|
28
|
+
if (ws) {
|
|
29
|
+
for (const [label, account] of Object.entries(ws.safes)) safesByLabel[label] = account;
|
|
30
|
+
for (const [label, account] of Object.entries(ws.rolesMods)) rolesByLabel[label] = account;
|
|
31
|
+
}
|
|
27
32
|
const meta = {
|
|
28
33
|
label: opts.label,
|
|
29
34
|
chain: opts.chain,
|
|
30
35
|
workspaceId: ws?.workspaceId ?? ""
|
|
31
36
|
};
|
|
32
|
-
const newSafes = /* @__PURE__ */ new Map();
|
|
33
37
|
function makeNodeRef(data) {
|
|
34
|
-
|
|
38
|
+
return Object.freeze({
|
|
35
39
|
...data,
|
|
36
40
|
chain: opts.chain,
|
|
37
41
|
_constellation: meta
|
|
38
42
|
});
|
|
39
|
-
if (ref.type === "SAFE" && typeof ref.label === "string") newSafes.set(ref.label, ref);
|
|
40
|
-
return ref;
|
|
41
43
|
}
|
|
42
|
-
function entityAccessor(registry, type
|
|
44
|
+
function entityAccessor(registry, type) {
|
|
43
45
|
const cache = /* @__PURE__ */ new Map();
|
|
44
46
|
return new Proxy({}, { get(_target, name) {
|
|
45
47
|
if (typeof name !== "string") return void 0;
|
|
46
48
|
const cached = cache.get(name);
|
|
47
49
|
if (cached) return cached;
|
|
48
50
|
const existing = registry[name];
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
avatar: canonicalSafe,
|
|
57
|
-
...overrides,
|
|
58
|
-
label: name
|
|
59
|
-
});
|
|
60
|
-
return makeNodeRef({
|
|
61
|
-
type,
|
|
62
|
-
...existing || {},
|
|
63
|
-
...overrides,
|
|
64
|
-
label: name
|
|
65
|
-
});
|
|
66
|
-
};
|
|
51
|
+
const specLabel = existing?.label ?? name;
|
|
52
|
+
const fn = (overrides) => makeNodeRef({
|
|
53
|
+
type,
|
|
54
|
+
...existing || {},
|
|
55
|
+
...overrides,
|
|
56
|
+
label: specLabel
|
|
57
|
+
});
|
|
67
58
|
Object.assign(fn, {
|
|
68
59
|
type,
|
|
69
60
|
...existing || {},
|
|
70
|
-
label:
|
|
61
|
+
label: specLabel,
|
|
71
62
|
chain: opts.chain,
|
|
72
63
|
_constellation: meta
|
|
73
64
|
});
|
|
@@ -84,21 +75,16 @@ function constellation(opts, internal) {
|
|
|
84
75
|
return personalSafe.address;
|
|
85
76
|
} });
|
|
86
77
|
}
|
|
87
|
-
const safe = entityAccessor(vaultsByLabel, "SAFE");
|
|
88
78
|
return {
|
|
89
|
-
safe,
|
|
90
|
-
roles: entityAccessor(
|
|
91
|
-
const invoked = newSafes.get(name);
|
|
92
|
-
if (invoked) return invoked;
|
|
93
|
-
if (name in vaultsByLabel) return safe[name];
|
|
94
|
-
}),
|
|
79
|
+
safe: entityAccessor(safesByLabel, "SAFE"),
|
|
80
|
+
roles: entityAccessor(rolesByLabel, "ROLES"),
|
|
95
81
|
user: userAccessor()
|
|
96
82
|
};
|
|
97
83
|
}
|
|
98
84
|
//#endregion
|
|
99
|
-
//#region src/
|
|
85
|
+
//#region src/push.ts
|
|
100
86
|
/**
|
|
101
|
-
* Resolves node references and
|
|
87
|
+
* Resolves node references and pushes the constellation specification to the API.
|
|
102
88
|
*
|
|
103
89
|
*
|
|
104
90
|
* ```ts
|
|
@@ -106,10 +92,10 @@ function constellation(opts, internal) {
|
|
|
106
92
|
* const dao = eth.safe['GG DAO']
|
|
107
93
|
* const roles = eth.roles['New Roles']({ nonce: 0n, target: dao, owner: dao, avatar: dao })
|
|
108
94
|
*
|
|
109
|
-
* await
|
|
95
|
+
* await push([dao, roles])
|
|
110
96
|
* ```
|
|
111
97
|
*/
|
|
112
|
-
async function
|
|
98
|
+
async function push(nodes, opts) {
|
|
113
99
|
const api = opts?.api ?? new ApiClient();
|
|
114
100
|
const refs = deriveRefs(nodes);
|
|
115
101
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -171,6 +157,10 @@ async function nodeToSpec(node, refs) {
|
|
|
171
157
|
spec.roles = await expandRoles(value, refs);
|
|
172
158
|
continue;
|
|
173
159
|
}
|
|
160
|
+
if (node.type === "ROLES" && key === "allowances" && value != null && !Array.isArray(value)) {
|
|
161
|
+
spec.allowances = resolveRefs(Object.values(value), refs);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
174
164
|
spec[key] = resolveRefs(value, refs);
|
|
175
165
|
}
|
|
176
166
|
spec.ref = refs.byIdentity.get(node);
|
|
@@ -191,7 +181,7 @@ async function expandRoles(roles, refs) {
|
|
|
191
181
|
function resolveRefs(value, refs) {
|
|
192
182
|
if (isConstellationNode(value)) {
|
|
193
183
|
const ref = refs.byIdentity.get(value) ?? refs.byLabel.get(labelKey(value));
|
|
194
|
-
invariant(ref != null, `Node "${value.label}" is referenced not included in the
|
|
184
|
+
invariant(ref != null, `Node "${value.label}" is referenced not included in the push() call`);
|
|
195
185
|
return `$${ref}`;
|
|
196
186
|
}
|
|
197
187
|
if (Array.isArray(value)) return value.map((v) => resolveRefs(v, refs));
|
|
@@ -221,6 +211,6 @@ function isConstellationNode(value) {
|
|
|
221
211
|
return false;
|
|
222
212
|
}
|
|
223
213
|
//#endregion
|
|
224
|
-
export { EVERYTHING,
|
|
214
|
+
export { EVERYTHING, buildAllowKit, c, constellation, forAll, push };
|
|
225
215
|
|
|
226
216
|
//# sourceMappingURL=index.mjs.map
|