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
39 changes: 39 additions & 0 deletions .github/workflows/create-integrity-file.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Create publish info file

on:
release:
types: [created]
workflow_dispatch:
push:
branches:
- prepare-release

permissions:
contents: read

jobs:
generate-publish-info:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: |
yarn install --frozen-lockfile
yarn build

- name: Run integrity check script
run: |
yarn generate-publish-info

- name: Upload YAML artifact
uses: actions/upload-artifact@v4
with:
name: publish-info
path: ./publish-info

- name: Show YAML output
run: cat ./publish-info/*.yml
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,5 @@ openapi/
yalc.lock
# Local Netlify folder
.netlify

publish-info/
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"test": "FORCE_COLOR=1 lerna run test --stream",
"play": "ts-node ./playground/config/run.ts",
"format": "lerna run format && prettier --write \"playground/**/*.ts\"",
"prepare": "husky"
"prepare": "husky",
"generate-publish-info": "ts-node ./scripts/generate-publish-info.ts"
},
"workspaces": {
"packages": [
Expand Down
2 changes: 1 addition & 1 deletion packages/api-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"yargs": "^17.7.2"
},
"dependencies": {
"@safe-global/protocol-kit": "^4.1.6",
"@safe-global/protocol-kit": "^4.1.7",
"@safe-global/safe-core-sdk-types": "^5.1.0",
"ethers": "^6.13.1",
"node-fetch": "^2.7.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"dependencies": {
"@safe-global/api-kit": "^2.4.6",
"@safe-global/protocol-kit": "^4.1.6",
"@safe-global/protocol-kit": "^4.1.7",
"@web3auth/safeauth-embed": "^0.0.0",
"ethers": "^6.13.1"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/onramp-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"dependencies": {
"@monerium/sdk": "^2.12.0",
"@safe-global/api-kit": "^2.4.6",
"@safe-global/protocol-kit": "^4.1.6",
"@safe-global/protocol-kit": "^4.1.7",
"@safe-global/safe-core-sdk-types": "^5.1.0",
"@stripe/crypto": "^0.0.4",
"@stripe/stripe-js": "^1.54.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol-kit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@safe-global/protocol-kit",
"version": "4.1.6",
"version": "4.1.7",
"description": "SDK that facilitates the interaction with Safe Smart Accounts",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function updateLocalNetworks(networks: NetworkShortName[]) {
const startIndex =
content.indexOf('export const networks: NetworkShortName[] = [') +
'export const networks: NetworkShortName[] = ['.length
const endIndex = content.indexOf(']\n\nif (process.env.TEST_NETWORK ===')
const endIndex = content.indexOf(']\n\ntry {')

const sortedNetworks = networks
.sort((a, b) => Number(a.chainId - b.chainId))
Expand Down
18 changes: 11 additions & 7 deletions packages/protocol-kit/src/contracts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export const PREDETERMINED_SALT_NONCE =
'0xb1073742015cbcf5a3a4d9d1ae33ecf619439710b89475f92e2abd2117e90f90'

const ZKSYNC_MAINNET = 324n
const ZKSYNC_TESTNET = 280n
const ZKSYNC_TESTNET = 300n
const ZKSYNC_LENS = 232n
// For bundle size efficiency we store SafeProxy.sol/GnosisSafeProxy.sol zksync bytecode hash in hex.
// To get the values below we need to:
// 1. Compile Safe smart contracts for zksync
Expand All @@ -52,6 +53,9 @@ const ZKSYNC_SAFE_PROXY_DEPLOYED_BYTECODE: {
} = {
'1.3.0': {
deployedBytecodeHash: '0x0100004124426fb9ebb25e27d670c068e52f9ba631bd383279a188be47e3f86d'
},
'1.4.1': {
deployedBytecodeHash: '0x0100003b6cfa15bd7d1cae1c9c022074524d7785d34859ad0576d8fab4305d4f'
}
}

Expand Down Expand Up @@ -311,10 +315,10 @@ export async function predictSafeAddress({

const from = await safeProxyFactoryContract.getAddress()

// On the zkSync Era chain, the counterfactual deployment address is calculated differently
const isZkSyncEraChain = [ZKSYNC_MAINNET, ZKSYNC_TESTNET].includes(chainId)
if (isZkSyncEraChain) {
const proxyAddress = zkSyncEraCreate2Address(from, safeVersion, salt, input)
// On the zkSync chains, the counterfactual deployment address is calculated differently
const isZkSyncChain = [ZKSYNC_MAINNET, ZKSYNC_TESTNET, ZKSYNC_LENS].includes(chainId)
if (isZkSyncChain) {
const proxyAddress = zkSyncCreate2Address(from, safeVersion, salt, input)

return safeProvider.getChecksummedAddress(proxyAddress)
}
Expand Down Expand Up @@ -348,9 +352,9 @@ export const validateSafeDeploymentConfig = ({ saltNonce }: SafeDeploymentConfig
* @param {Buffer} salt - The salt used for address derivation.
* @param {string} input - Additional input data for the derivation.
*
* @returns {string} The derived zkSync Era address.
* @returns {string} The derived zkSync address.
*/
export function zkSyncEraCreate2Address(
export function zkSyncCreate2Address(
from: string,
safeVersion: SafeVersion,
salt: Buffer,
Expand Down
8 changes: 6 additions & 2 deletions packages/protocol-kit/src/utils/eip-3770/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,10 @@ export const networks: NetworkShortName[] = [
{ chainId: 920637907288165n, shortName: 'kkrt-starknet-sepolia' }
]

if (process.env.TEST_NETWORK === 'hardhat') {
networks.push({ shortName: 'local', chainId: 31337n })
try {
if (process.env.TEST_NETWORK === 'hardhat') {
networks.push({ shortName: 'local', chainId: 31337n })
}
} catch {
// When process is not available we run on a browser environment
}
5 changes: 1 addition & 4 deletions packages/protocol-kit/tests/e2e/utils/setupProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ export function getSafeProviderFromNetwork(
case 'gnosis':
rpcUrl = 'https://rpc.gnosischain.com'
break
case 'goerli':
rpcUrl = 'https://rpc.ankr.com/eth_goerli'
break
case 'sepolia':
rpcUrl = 'https://sepolia.gateway.tenderly.co'
break
case 'mainnet':
rpcUrl = 'https://rpc.ankr.com/eth'
rpcUrl = 'https://ethereum-rpc.publicnode.com'
break
default:
throw new Error('Chain not supported')
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol-kit/tests/e2e/utilsContracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ describe('Contract utils', () => {
)

itif(safeVersionDeployed === '1.3.0')(
'returns the predicted address for Safes deployed on zkSync Era',
'returns the predicted address for Safes deployed on zkSync EVM',
async () => {
const { contractNetworks } = await setupTests()

Expand Down
2 changes: 1 addition & 1 deletion packages/relay-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},
"dependencies": {
"@gelatonetwork/relay-sdk": "^5.5.0",
"@safe-global/protocol-kit": "^4.1.6",
"@safe-global/protocol-kit": "^4.1.7",
"@safe-global/safe-core-sdk-types": "^5.1.0",
"@safe-global/safe-modules-deployments": "^2.2.1",
"ethers": "^6.13.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk-starter-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
},
"dependencies": {
"@safe-global/api-kit": "^2.4.6",
"@safe-global/protocol-kit": "^4.1.6",
"@safe-global/protocol-kit": "^4.1.7",
"@safe-global/relay-kit": "^3.1.1",
"@safe-global/safe-core-sdk-types": "^5.1.0",
"ethers": "^6.13.1"
Expand Down
1 change: 0 additions & 1 deletion playground/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"extends": "../tsconfig.settings.json",
"compilerOptions": {
"composite": true,
"noImplicitThis": false,
"outDir": "dist"
},
Expand Down
118 changes: 118 additions & 0 deletions scripts/generate-publish-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { execFile } from 'child_process'
import * as fs from 'fs'
import * as path from 'path'
import * as yaml from 'yaml'

type PackagePublishInfo = {
id: string
name: string
version: string
size: number
unpackedSize: number
shasum: string
integrity: string
filename: string
entryCount: number
}

type NpmPublishOutput = Record<
string,
PackagePublishInfo & {
files?: string[]
bundled?: unknown[]
}
>

const executeCommand = (command: string, args: string[]): Promise<string> => {
return new Promise((resolve, reject) => {
execFile(command, args, (error, stdout, stderr) => {
if (error) {
return reject(`Error executing command: ${error.message}`)
}

if (stderr) {
console.warn(`Warning during execution: ${stderr}`)
}

resolve(stdout)
})
})
}

const writeToFile = (filePath: string, data: string): Promise<void> => {
return new Promise((resolve, reject) => {
const safeDir = path.join(process.cwd(), 'publish-info')

fs.mkdir(safeDir, { recursive: true, mode: 0o700 }, (err) => {
if (err) return reject(`Directory creation failed: ${err.message}`)

const fullPath = path.join(safeDir, path.basename(filePath))

fs.writeFile(fullPath, data, { mode: 0o600 }, (writeErr) => {
if (writeErr) return reject(`File write failed: ${writeErr.message}`)
resolve()
})
})
})
}

const sanitizePublishOutput = (jsonData: NpmPublishOutput): Record<string, PackagePublishInfo> => {
return Object.fromEntries(
Object.entries(jsonData).map(([pkgName, pkgData]) => {
const { files, bundled, ...cleanData } = pkgData

return [pkgName, cleanData]
})
)
}

const getReadableFilename = (): string => {
try {
const now = new Date()
const pad = (n: number) => n.toString().padStart(2, '0')
const datePart = [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join('-')
const timePart = [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join('-')
const timestamp = `${datePart}_${timePart}`

return `publish-info_${timestamp}.yml`
} catch {
return `publish-info_${Date.now()}.yml`
}
}

const main = async () => {
try {
const projectRoot = path.join(__dirname, '../')
process.chdir(projectRoot)

const stdout = await executeCommand('npm', [
'publish',
'--access',
'public',
'--dry-run',
'--workspaces',
'--json',
'--ignore-scripts'
])

let jsonOutput: NpmPublishOutput
try {
jsonOutput = JSON.parse(stdout) as NpmPublishOutput
} catch (parseError) {
throw new Error(`Error parsing JSON output: ${(parseError as Error).message}`)
}

const cleanedOutput = sanitizePublishOutput(jsonOutput)
const yamlOutput = yaml.stringify(cleanedOutput)

const outputFileName = getReadableFilename()
await writeToFile(outputFileName, yamlOutput)

console.log(`Output stored in ${outputFileName}`)
} catch (error) {
console.error(`Error: ${error instanceof Error ? error.message : error}`)
process.exit(1)
}
}

main()
Loading