Skip to content

Commit

Permalink
Merge branch 'safe-global:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Sascha Ronnie Daoudia authored Feb 19, 2024
2 parents 128f501 + 9b19c81 commit bea6920
Show file tree
Hide file tree
Showing 84 changed files with 4,345 additions and 1,338 deletions.
15 changes: 5 additions & 10 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@
# (default is 259200 [72 hours])
# NOT_FOUND_PRICE_TTL_SECONDS=

# Balances Provider - Valk API
# Chain ids configured to use this provider. (comma-separated numbers)
# (default='')
#FF_VALK_BALANCES_CHAIN_IDS=
# The base Valk API URL to be used.
# (default is https://merlin-api-v1.cf/api/merlin/public if none is set)
#VALK_BASE_URI=
# The API Key to be used. If none is set, balances cannot be retrieved using this provider.
#VALK_API_KEY=

# Balances Provider - Zerion API
# Chain ids configured to use this provider. (comma-separated numbers)
# (default='')
Expand All @@ -32,6 +22,11 @@
# The API Key to be used. If none is set, balances cannot be retrieved using this provider.
#ZERION_API_KEY=

# Relay Provider - Gelato API
# The API key to be used for Gnosis Chain
# FF_RELAY=
# GELATO_API_KEY_GNOSIS_CHAIN=

# The cache TTL for each token price datapoint.
#BALANCES_TTL_SECONDS=

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ lerna-debug.log*

# Database mounted volume
data

# ABIs
/abis
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
/.yarn

# ABIs
/abis
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ WORKDIR /app
COPY --chown=node:node .yarn/releases ./.yarn/releases
COPY --chown=node:node .yarn/patches ./.yarn/patches
COPY --chown=node:node package.json yarn.lock .yarnrc.yml tsconfig*.json ./
COPY --chown=node:node scripts/generate-abis.js ./scripts/generate-abis.js
RUN --mount=type=cache,target=/root/.yarn yarn
COPY --chown=node:node assets ./assets
COPY --chown=node:node migrations ./migrations
Expand All @@ -28,8 +29,9 @@ ARG BUILD_NUMBER
ENV APPLICATION_VERSION=${VERSION} \
APPLICATION_BUILD_NUMBER=${BUILD_NUMBER}

COPY --chown=node:node --from=base /app/abis ./abis
COPY --chown=node:node --from=base /app/node_modules ./node_modules
COPY --chown=node:node --from=base /app/dist ./dist
COPY --chown=node:node --from=base /app/assets ./assets
COPY --chown=node:node --from=base /app/migrations ./migrations
CMD [ "node", "dist/main.js" ]
CMD [ "node", "dist/src/main.js" ]
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "nest build",
"build": "yarn generate-abis && nest build",
"format": "prettier --write .",
"format-check": "prettier --check .",
"generate-abis": "node ./scripts/generate-abis.js",
"postinstall": "yarn generate-abis",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"start:prod": "node dist/src/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"lint-check": "eslint \"{src,apps,libs,test}/**/*.ts\"",
"test": "jest",
Expand All @@ -23,7 +25,6 @@
"test:all:cov": "jest --coverage --config ./test/jest-all.json"
},
"dependencies": {
"@gelatonetwork/relay-sdk": "^5.5.5",
"@nestjs/cli": "^10.3.1",
"@nestjs/common": "^10.3.3",
"@nestjs/config": "^3.1.1",
Expand Down Expand Up @@ -92,6 +93,7 @@
],
"testEnvironment": "node",
"moduleNameMapper": {
"^@/abis/(.*)$": "<rootDir>/../abis/$1",
"^@/(.*)$": "<rootDir>/../src/$1"
},
"globalSetup": "<rootDir>/../test/global-setup.ts"
Expand Down
83 changes: 83 additions & 0 deletions scripts/generate-abis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const fs = require('fs');

/**
* This generates const TypeScript ABIs for each asset in
* `@safe-global/safe-deployments` package for `viem` to infer.
*
* Although it is possible to get a singleton programmatically and
* import the JSON directly, neither is strictly typed.
*
* Once it is possible to import JSON "as const", the deployments
* package should be updated to return the singletons as such.
*
* @see https://github.com/microsoft/TypeScript/issues/32063
*/

// Path to directory containing JSON assets
const assetsDir = path.join(
process.cwd(),
'node_modules',
'@safe-global',
'safe-deployments',
'dist',
'assets',
);

// Path to directory where ABIs will be written
const outputDir = path.join(process.cwd(), 'abis', 'safe');

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function main() {
// Remove any existing ABIs
try {
fs.rmSync(outputDir, { recursive: true });
} catch {
// Swallow error if directory does not exist (first run)
}

// For each version...
for (const version of fs.readdirSync(assetsDir)) {
const versionOutputDir = path.join(outputDir, version);

fs.mkdirSync(versionOutputDir, { recursive: true });

const versionDir = path.join(assetsDir, version);

// ...parse the ABI for each asset
for (const assetFile of fs.readdirSync(versionDir)) {
// Read the asset JSON
const assetPath = path.join(assetsDir, version, assetFile);
const assetJson = fs.readFileSync(assetPath, 'utf8');

// Parse the asset JSON
const { contractName, abi } = JSON.parse(assetJson);

// Write the ABI to a file
const fileName = `${contractName}.abi.ts`;
const filePath = path.join(versionOutputDir, fileName);

// It is generally better to use the Stream API for larger files
// but as we are storing the JSON in memory, this is likely of
// minimal benefit. As this script runs on build, we need not
// worry too much about performance though.
const stream = fs.createWriteStream(filePath);

// Write formatted ABI to file
stream.write(
'// This file is auto-generated by scripts/generate-abis.js\nexport default ',
);
stream.write(JSON.stringify(abi, null, 2));

// Most important step: assert ABI as readonly
stream.write(' as const;');

stream.end();
}
}

console.log('ABIs generated successfully!');
}

main();
5 changes: 4 additions & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { RootModule } from '@/routes/root/root.module';
import { EmailControllerModule } from '@/routes/email/email.controller.module';
import { AlertsControllerModule } from '@/routes/alerts/alerts.controller.module';
import { RecoveryModule } from '@/routes/recovery/recovery.module';
import { RelayControllerModule } from '@/routes/relay/relay.controller.module';
import { SubscriptionControllerModule } from '@/routes/subscriptions/subscription.module';

@Module({})
Expand All @@ -48,7 +49,8 @@ export class AppModule implements NestModule {
// into account. The .env file loading is done by the ConfigurationModule
// which is not available at this stage.
static register(configFactory = configuration): DynamicModule {
const isEmailFeatureEnabled = configFactory()['features']['email'];
const { email: isEmailFeatureEnabled, relay: isRelayFeatureEnabled } =
configFactory()['features'];

return {
module: AppModule,
Expand All @@ -75,6 +77,7 @@ export class AppModule implements NestModule {
MessagesModule,
NotificationsModule,
OwnersModule,
...(isRelayFeatureEnabled ? [RelayControllerModule] : []),
RootModule,
SafeAppsModule,
SafesModule,
Expand Down
41 changes: 9 additions & 32 deletions src/config/entities/__tests__/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,6 @@ export default (): ReturnType<typeof configuration> => ({
balances: {
balancesTtlSeconds: faker.number.int(),
providers: {
valk: {
baseUri: faker.internet.url({ appendSlash: false }),
apiKey: faker.string.hexadecimal({ length: 32 }),
chains: {
1: { chainName: faker.string.sample() },
10: { chainName: faker.string.sample() },
100: { chainName: faker.string.sample() },
1101: { chainName: faker.string.sample() },
1313161554: { chainName: faker.string.sample() },
137: { chainName: faker.string.sample() },
324: { chainName: faker.string.sample() },
42161: { chainName: faker.string.sample() },
42220: { chainName: faker.string.sample() },
43114: { chainName: faker.string.sample() },
56: { chainName: faker.string.sample() },
8453: { chainName: faker.string.sample() },
},
currencies: Array.from(
new Set([
...Array.from(
{ length: faker.number.int({ min: 2, max: 5 }) },
() => faker.finance.currencyCode(),
),
'ETH',
'EUR',
'USD',
]),
),
},
zerion: {
baseUri: faker.internet.url({ appendSlash: false }),
apiKey: faker.string.hexadecimal({ length: 32 }),
Expand Down Expand Up @@ -96,7 +67,7 @@ export default (): ReturnType<typeof configuration> => ({
},
email: {
applicationCode: faker.string.alphanumeric(),
baseUri: faker.internet.url({ appendSlash: true }),
baseUri: faker.internet.url({ appendSlash: false }),
apiKey: faker.string.hexadecimal({ length: 32 }),
fromEmail: faker.internet.email(),
fromName: faker.person.fullName(),
Expand All @@ -122,8 +93,8 @@ export default (): ReturnType<typeof configuration> => ({
features: {
richFragments: true,
email: true,
valkBalancesChainIds: ['100'],
zerionBalancesChainIds: ['137'],
relay: true,
},
httpClient: { requestTimeout: faker.number.int() },
log: {
Expand Down Expand Up @@ -211,7 +182,13 @@ export default (): ReturnType<typeof configuration> => ({
host: process.env.REDIS_HOST || 'localhost',
port: process.env.REDIS_PORT || '6379',
},
relay: { limit: faker.number.int({ min: 1 }) },
relay: {
baseUri: faker.internet.url({ appendSlash: false }),
limit: faker.number.int({ min: 1 }),
apiKey: {
100: faker.string.hexadecimal({ length: 32 }),
},
},
safeConfig: {
baseUri: faker.internet.url({ appendSlash: false }),
},
Expand Down
31 changes: 6 additions & 25 deletions src/config/entities/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,6 @@ export default () => ({
balances: {
balancesTtlSeconds: parseInt(process.env.BALANCES_TTL_SECONDS ?? `${300}`),
providers: {
valk: {
baseUri:
process.env.VALK_BASE_URI ||
'https://merlin-api-v1.cf/api/merlin/public',
apiKey: process.env.VALK_API_KEY,
chains: {
1: { chainName: 'eth' },
10: { chainName: 'op' },
56: { chainName: 'bsc' },
100: { chainName: 'xdai' },
137: { chainName: 'matic' },
324: { chainName: 'era' },
1101: { chainName: 'pze' },
8453: { chainName: 'base' },
42161: { chainName: 'arb' },
42220: { chainName: 'celo' },
43114: { chainName: 'avax' },
// 11155111 (Sepolia) is not available on Valk
// 11155111: { chainName: '' },
1313161554: { chainName: 'aurora' },
},
currencies: ['AED', 'AUD', 'CAD', 'EUR', 'GBP', 'INR', 'USD'],
},
zerion: {
baseUri: process.env.ZERION_BASE_URI || 'https://api.zerion.io',
apiKey: process.env.ZERION_API_KEY,
Expand Down Expand Up @@ -148,10 +125,9 @@ export default () => ({
features: {
richFragments: process.env.FF_RICH_FRAGMENTS?.toLowerCase() === 'true',
email: process.env.FF_EMAIL?.toLowerCase() === 'true',
valkBalancesChainIds:
process.env.FF_VALK_BALANCES_CHAIN_IDS?.split(',') ?? [],
zerionBalancesChainIds:
process.env.FF_ZERION_BALANCES_CHAIN_IDS?.split(',') ?? [],
relay: process.env.FF_RELAY?.toLowerCase() === 'true',
},
httpClient: {
// Timeout in milliseconds to be used for the HTTP client.
Expand Down Expand Up @@ -204,7 +180,12 @@ export default () => ({
port: process.env.REDIS_PORT || '6379',
},
relay: {
baseUri:
process.env.RELAY_PROVIDER_API_BASE_URI || 'https://api.gelato.digital',
limit: parseInt(process.env.RELAY_THROTTLE_LIMIT ?? `${5}`),
apiKey: {
100: process.env.GELATO_API_KEY_GNOSIS_CHAIN,
},
},
safeConfig: {
baseUri:
Expand Down
Loading

0 comments on commit bea6920

Please sign in to comment.