Skip to content

Commit 6c91854

Browse files
author
Will Pote
committed
Initial commit: 3
1 parent 7276279 commit 6c91854

15 files changed

+7164
-6101
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
node_modules
2+
.env
23
.vscode
34
build
45
cdk.out

README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
# Welcome to your CDK TypeScript project!
1+
# Prerequisites
22

3-
This is a blank project for TypeScript development with CDK.
3+
## API
44

5-
The `cdk.json` file tells the CDK Toolkit how to execute your app.
5+
Create .env file with:
66

7-
## Useful commands
7+
```
8+
ETH_GAS_STATION_INFO_KEY = '...'
9+
JSON_RPC_URL = '...'
10+
```
811

9-
* `npm run build` compile typescript to js
10-
* `npm run watch` watch for changes and compile
11-
* `npm run test` perform the jest unit tests
12-
* `cdk deploy` deploy this stack to your default AWS account/region
13-
* `cdk diff` compare deployed stack with current state
14-
* `cdk synth` emits the synthesized CloudFormation template
12+
## Integ Tests
13+
14+
To run the integ tests you must first deploy the API, then add its url to your .env file.
15+
16+
```
17+
UNISWAP_ROUTING_API= '...'
18+
```

bin/app.ts

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,156 @@
11
#!/usr/bin/env node
2+
import { BuildEnvironmentVariableType } from '@aws-cdk/aws-codebuild';
3+
import * as codepipeline from '@aws-cdk/aws-codepipeline';
4+
import * as codepipeline_actions from '@aws-cdk/aws-codepipeline-actions';
5+
import * as sm from '@aws-cdk/aws-secretsmanager';
6+
import * as cdk from '@aws-cdk/core';
7+
import {
8+
CfnOutput,
9+
Construct,
10+
SecretValue,
11+
Stack,
12+
StackProps,
13+
Stage,
14+
StageProps,
15+
} from '@aws-cdk/core';
16+
import {
17+
CdkPipeline,
18+
CdkStage,
19+
ShellScriptAction,
20+
SimpleSynthAction,
21+
} from '@aws-cdk/pipelines';
22+
import dotenv from 'dotenv';
223
import 'source-map-support/register';
3-
import * as cdk from 'aws-cdk-lib';
424
import { RoutingAPIStack } from './stacks/routing-api-stack';
5-
import dotenv from 'dotenv'
625
dotenv.config();
726

27+
export class RoutingAPIStage extends Stage {
28+
public readonly url: CfnOutput;
29+
30+
constructor(
31+
scope: Construct,
32+
id: string,
33+
props: StageProps & { nodeRPC: string }
34+
) {
35+
super(scope, id, props);
36+
const { nodeRPC } = props;
37+
38+
const { url } = new RoutingAPIStack(this, 'RoutingAPI', { nodeRPC });
39+
this.url = url;
40+
}
41+
}
42+
43+
export class RoutingAPIPipeline extends Stack {
44+
constructor(scope: Construct, id: string, props?: StackProps) {
45+
super(scope, id, props);
46+
47+
const sourceArtifact = new codepipeline.Artifact();
48+
const cloudAssemblyArtifact = new codepipeline.Artifact();
49+
50+
const pipeline = new CdkPipeline(this, 'RoutingAPIPipeline', {
51+
// The pipeline name
52+
pipelineName: 'RoutingAPI',
53+
cloudAssemblyArtifact,
54+
55+
// Where the source can be found
56+
sourceAction: new codepipeline_actions.GitHubSourceAction({
57+
actionName: 'GitHub',
58+
output: sourceArtifact,
59+
oauthToken: SecretValue.secretsManager('github-token-2'),
60+
owner: 'Uniswap',
61+
repo: 'uniswap-routing-api',
62+
branch: 'main',
63+
}),
64+
65+
// Build, Unit Test, and Synth templates.
66+
synthAction: SimpleSynthAction.standardNpmSynth({
67+
sourceArtifact,
68+
cloudAssemblyArtifact,
69+
environmentVariables: {
70+
NPM_TOKEN: {
71+
value: 'npm-private-repo-access-token',
72+
type: BuildEnvironmentVariableType.SECRETS_MANAGER,
73+
},
74+
},
75+
installCommand:
76+
'echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc && npm ci',
77+
buildCommand: 'npm run build',
78+
testCommands: ['npm run test'],
79+
}),
80+
});
81+
82+
// Secrets are stored in secrets manager in the pipeline account. Accounts we deploy to
83+
// have been granted permissions to access secrets via resource policies.
84+
const rpcNodeUrl = sm.Secret.fromSecretAttributes(this, 'RPCNodeUrl', {
85+
secretCompleteArn:
86+
'arn:aws:secretsmanager:us-east-2:644039819003:secret:routing-api-infura-rpc-url-fSmY28',
87+
});
88+
89+
// Beta us-east-2
90+
const betaUsEast2Stage = new RoutingAPIStage(this, 'beta-us-east-2', {
91+
env: { account: '145079444317', region: 'us-east-2' },
92+
nodeRPC: rpcNodeUrl.secretValue.toString(),
93+
});
94+
const betaUsEast2AppStage = pipeline.addApplicationStage(betaUsEast2Stage);
95+
this.addIntegTests(
96+
pipeline,
97+
sourceArtifact,
98+
betaUsEast2Stage,
99+
betaUsEast2AppStage
100+
);
101+
102+
// Prod us-east-2
103+
const prodUsEast2Stage = new RoutingAPIStage(this, 'prod-us-east-2', {
104+
env: { account: '606857263320', region: 'us-east-2' },
105+
nodeRPC: rpcNodeUrl.secretValue.toString(),
106+
});
107+
const prodUsEast2AppStage = pipeline.addApplicationStage(prodUsEast2Stage);
108+
this.addIntegTests(
109+
pipeline,
110+
sourceArtifact,
111+
prodUsEast2Stage,
112+
prodUsEast2AppStage
113+
);
114+
}
115+
116+
private addIntegTests(
117+
pipeline: CdkPipeline,
118+
sourceArtifact: codepipeline.Artifact,
119+
routingAPIStage: RoutingAPIStage,
120+
applicationStage: CdkStage
121+
) {
122+
applicationStage.addActions(
123+
new ShellScriptAction({
124+
actionName: 'IntegrationTests',
125+
additionalArtifacts: [sourceArtifact],
126+
useOutputs: {
127+
UNISWAP_ROUTING_API: pipeline.stackOutput(routingAPIStage.url),
128+
},
129+
environmentVariables: {
130+
NPM_TOKEN: {
131+
value: 'npm-private-repo-access-token',
132+
type: BuildEnvironmentVariableType.SECRETS_MANAGER,
133+
},
134+
},
135+
commands: [
136+
'echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc && npm ci',
137+
'echo "UNISWAP_ROUTING_API=${UNISWAP_ROUTING_API}" > .env',
138+
'npm install',
139+
'npm run integ-test',
140+
],
141+
runOrder: applicationStage.nextSequentialRunOrder(),
142+
})
143+
);
144+
}
145+
}
146+
8147
const app = new cdk.App();
9-
new RoutingAPIStack(app, 'RoutingAPIStack');
148+
149+
// Local dev stack
150+
new RoutingAPIStack(app, 'RoutingAPIStack', {
151+
nodeRPC: process.env.JSON_RPC_URL!,
152+
});
153+
154+
new RoutingAPIPipeline(app, 'RoutingAPIPipelineStack', {
155+
env: { account: '644039819003', region: 'us-east-2' },
156+
});

bin/stacks/routing-api-stack.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
1-
import * as cdk from 'aws-cdk-lib';
2-
import { aws_apigateway, aws_logs } from 'aws-cdk-lib';
3-
import { MethodLoggingLevel } from 'aws-cdk-lib/lib/aws-apigateway';
1+
import * as aws_apigateway from '@aws-cdk/aws-apigateway';
2+
import { MethodLoggingLevel } from '@aws-cdk/aws-apigateway';
3+
import * as aws_logs from '@aws-cdk/aws-logs';
4+
import * as cdk from '@aws-cdk/core';
5+
import { CfnOutput } from '@aws-cdk/core';
46
import { RoutingCachingStack } from './routing-caching-stack';
57
import { RoutingDashboardStack } from './routing-dashboard-stack';
68
import { RoutingLambdaStack } from './routing-lambda-stack';
79

810
export class RoutingAPIStack extends cdk.Stack {
9-
constructor(parent: cdk.App, name: string, props?: cdk.StackProps) {
11+
public readonly url: CfnOutput;
12+
13+
constructor(
14+
parent: cdk.Construct,
15+
name: string,
16+
props: cdk.StackProps & { nodeRPC: string }
17+
) {
1018
super(parent, name, props);
1119

1220
const { poolCacheBucket, poolCacheKey } = new RoutingCachingStack(
1321
this,
1422
'RoutingCachingStack'
1523
);
1624

25+
const { nodeRPC } = props;
26+
1727
const { routingLambda } = new RoutingLambdaStack(
1828
this,
1929
'RoutingLambdaStack',
20-
{ poolCacheBucket, poolCacheKey }
30+
{ poolCacheBucket, poolCacheKey, nodeRPC }
2131
);
2232

23-
const accessLogGroup = new aws_logs.LogGroup(
24-
this,
25-
'RoutingAPIGAccessLogs'
26-
);
33+
const accessLogGroup = new aws_logs.LogGroup(this, 'RoutingAPIGAccessLogs');
2734

2835
const api = new aws_apigateway.RestApi(this, 'routing-api', {
2936
restApiName: 'Routing API',
3037
deployOptions: {
3138
tracingEnabled: true,
3239
loggingLevel: MethodLoggingLevel.ERROR,
33-
accessLogDestination: new aws_apigateway.LogGroupLogDestination(accessLogGroup),
34-
accessLogFormat: aws_apigateway.AccessLogFormat.jsonWithStandardFields()
40+
accessLogDestination: new aws_apigateway.LogGroupLogDestination(
41+
accessLogGroup
42+
),
43+
accessLogFormat:
44+
aws_apigateway.AccessLogFormat.jsonWithStandardFields(),
3545
},
3646
});
3747

@@ -45,5 +55,9 @@ export class RoutingAPIStack extends cdk.Stack {
4555

4656
const quote = api.root.addResource('quote');
4757
quote.addMethod('POST', lambdaIntegration); // POST /swap
58+
59+
this.url = new CfnOutput(this, 'Url', {
60+
value: api.url,
61+
});
4862
}
4963
}

bin/stacks/routing-caching-stack.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
import * as cdk from 'aws-cdk-lib';
2-
import {
3-
aws_s3,
4-
aws_lambda,
5-
aws_lambda_nodejs,
6-
aws_iam,
7-
aws_events,
8-
aws_events_targets,
9-
Duration,
10-
} from 'aws-cdk-lib';
11-
import { Schedule } from 'aws-cdk-lib/lib/aws-events';
12-
import { Construct } from 'constructs';
1+
import * as aws_events from '@aws-cdk/aws-events';
2+
import * as aws_events_targets from '@aws-cdk/aws-events-targets';
3+
import * as aws_iam from '@aws-cdk/aws-iam';
4+
import * as aws_lambda from '@aws-cdk/aws-lambda';
5+
import * as aws_lambda_nodejs from '@aws-cdk/aws-lambda-nodejs';
6+
import * as aws_s3 from '@aws-cdk/aws-s3';
7+
import * as cdk from '@aws-cdk/core';
8+
import { Construct, Duration } from '@aws-cdk/core';
139
import * as path from 'path';
1410

11+
export interface RoutingCachingStackProps extends cdk.NestedStackProps {
12+
region: string;
13+
}
1514
export class RoutingCachingStack extends cdk.NestedStack {
1615
public readonly poolCacheBucket: aws_s3.Bucket;
1716
public readonly poolCacheKey: string;
@@ -32,6 +31,8 @@ export class RoutingCachingStack extends cdk.NestedStack {
3231
],
3332
});
3433

34+
const region = cdk.Stack.of(this).region;
35+
3536
const poolCachingLambda = new aws_lambda_nodejs.NodejsFunction(
3637
this,
3738
'PoolCacheLambda',
@@ -50,7 +51,7 @@ export class RoutingCachingStack extends cdk.NestedStack {
5051
aws_lambda.LayerVersion.fromLayerVersionArn(
5152
this,
5253
'InsightsLayer',
53-
'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'
54+
`arn:aws:lambda:${region}:580247275435:layer:LambdaInsightsExtension:14`
5455
),
5556
],
5657
tracing: aws_lambda.Tracing.ACTIVE,
@@ -64,7 +65,7 @@ export class RoutingCachingStack extends cdk.NestedStack {
6465
this.poolCacheBucket.grantReadWrite(poolCachingLambda);
6566

6667
new aws_events.Rule(this, 'SchedulePoolCache', {
67-
schedule: Schedule.rate(Duration.minutes(1)),
68+
schedule: aws_events.Schedule.rate(Duration.minutes(1)),
6869
targets: [new aws_events_targets.LambdaFunction(poolCachingLambda)],
6970
});
7071
}

bin/stacks/routing-dashboard-stack.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import * as cdk from 'aws-cdk-lib';
2-
import { aws_cloudwatch, Stack } from 'aws-cdk-lib';
3-
import { Construct } from 'constructs';
1+
import * as aws_cloudwatch from '@aws-cdk/aws-cloudwatch';
2+
import * as cdk from '@aws-cdk/core';
43

54
export const NAMESPACE = 'Uniswap';
65

@@ -9,11 +8,15 @@ export interface RoutingDashboardProps extends cdk.NestedStackProps {
98
}
109

1110
export class RoutingDashboardStack extends cdk.NestedStack {
12-
constructor(scope: Construct, name: string, props: RoutingDashboardProps) {
11+
constructor(
12+
scope: cdk.Construct,
13+
name: string,
14+
props: RoutingDashboardProps
15+
) {
1316
super(scope, name, props);
1417

1518
const { apiName } = props;
16-
const region = Stack.of(this).region;
19+
const region = cdk.Stack.of(this).region;
1720

1821
new aws_cloudwatch.CfnDashboard(this, 'RoutingAPIDashboard', {
1922
dashboardName: 'RoutingDashboard',

0 commit comments

Comments
 (0)