Skip to content

Commit 9d020f5

Browse files
authored
Add phone number verification and address association (#19)
* Add mutations for phone number verification * Add phone number normalization * Add Infura API key env var * Add hashed phone number updates/deletes * Add prettier for automatic formatting * Add validation for eth addresses
1 parent 9765db4 commit 9d020f5

31 files changed

+2911
-174
lines changed

.dockerignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
dist
22
node_modules
33
.git
4+
.env

.env.example

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
INFURA_API_KEY=00000000000000000000000000000000
2+
3+
TWILIO_ACCOUNT_SID=0000000000000000000000000000000000
4+
TWILIO_API_KEY=00000000000000000000000000000000
5+
TWILIO_FROM_NUMBER=+12345678900
6+
7+
PRISMA_ENDPOINT=http://localhost:4466
8+
PRISMA_MANAGEMENT_API_SECRET=not-a-secret

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ node_modules
3535

3636
# TypeScript
3737
dist
38+
.env

.graphqlconfig.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
projects:
2+
app:
3+
schemaPath: src/schema.graphql
4+
extensions:
5+
endpoints:
6+
default: http://localhost:4000
7+
database:
8+
schemaPath: src/generated/prisma.graphql
9+
extensions:
10+
prisma: database/prisma.yml
11+
codegen:
12+
- generator: prisma-binding
13+
language: typescript
14+
output:
15+
binding: src/generated/prisma.ts

database/datamodel.graphql

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
type PhoneNumber {
2+
hashedPhoneNumber: String! @unique
3+
address: String!
4+
createdAt: DateTime!
5+
updatedAt: DateTime!
6+
}

database/prisma.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# The endpoint of your Prisma API (deployed to a Prisma Sandbox).
2+
# endpoint: http://localhost:4466
3+
endpoint: ${env:PRISMA_ENDPOINT}
4+
5+
# The file containing the definition of your data model.
6+
datamodel: datamodel.graphql
7+
8+
# Seed your service with initial data based on `seed.graphql`.
9+
seed:
10+
import: seed.graphql
11+
12+
# Download the GraphQL schema of the Prisma API into
13+
# `src/generated/prisma.graphql` (as specfied in `.graphqlconfig.yml`).
14+
# Then generate the corresponding TypeScript definitions into
15+
# `src/generated/prisma.ts` (also specfied in `.graphqlconfig.yml`)
16+
# with `graphql codegen` .
17+
hooks:
18+
post-deploy:
19+
- graphql get-schema --project database
20+
- graphql codegen
21+
22+
# If specified, the `secret` must be used to generate a JWT which is attached
23+
# to the `Authorization` header of HTTP requests made against the Prisma API.
24+
# Info: https://www.prisma.io/docs/reference/prisma-api/concepts-utee3eiquo#authentication
25+
# secret: ${env:PRISMA_SECRET}

database/seed.graphql

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# mutation {
2+
# }

docker-compose.yaml

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
version: '3'
2+
services:
3+
redis:
4+
container_name: redis
5+
image: redis:latest
6+
ports:
7+
- 6379:6379
8+
command:
9+
- redis-server
10+
- --appendonly
11+
- 'yes'
12+
volumes:
13+
- ./tmp/volumes/redis:/data
14+
15+
prisma:
16+
image: prismagraphql/prisma:1.9
17+
ports:
18+
- "4466:4466"
19+
environment:
20+
PRISMA_CONFIG: |
21+
managementApiSecret: not-a-secret
22+
port: 4466
23+
databases:
24+
default:
25+
connector: postgres
26+
host: postgres
27+
port: 5432
28+
user: root
29+
password: prisma
30+
migrations: true
31+
managementSchema: management
32+
database: prisma
33+
links:
34+
- postgres
35+
36+
postgres:
37+
image: postgres:latest
38+
ports:
39+
- "5432:5432"
40+
environment:
41+
POSTGRES_USER: root
42+
POSTGRES_PASSWORD: prisma
43+
volumes:
44+
- ./tmp/volumes/postgres:/var/lib/postgresql/data

package.json

+22-7
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,45 @@
44
"license": "Apache-2.0",
55
"author": "Alex Kern <[email protected]>",
66
"scripts": {
7-
"start": "nodemon -e ts,graphql -x ts-node src/index.ts",
8-
"debug": "nodemon -e ts,graphql -x ts-node --inspect src/index.ts",
7+
"start": "nodemon -e ts,graphql -x ts-node -r dotenv/config src/index.ts",
8+
"debug": "nodemon -e ts,graphql -x ts-node -r dotenv/config --inspect src/index.ts",
99
"playground": "graphql playground",
10-
"dev": "npm-run-all --parallel start playground",
11-
"lint": "tslint -c tslint.json 'src/**/*.ts'",
12-
"check": "tsc --noEmit",
13-
"precommit": "yarn run check && yarn run lint",
10+
"dev": "npm-run-all --parallel dev:redis dev:prisma dev:multi-api playground",
11+
"dev:multi-api": "./scripts/wait-for.sh localhost:6379 -- ./scripts/wait-for.sh localhost:4466 -- yarn run start",
12+
"dev:redis": "docker-compose up redis",
13+
"dev:prisma": "docker-compose up prisma",
14+
"deploy": "npm-run-all --parallel deploy:prisma dev:prisma",
15+
"deploy:prisma": "sleep 5 && yarn prisma deploy",
16+
"lint": "tslint --fix --exclude src/generated/prisma.ts 'src/**/*.ts'",
17+
"check": "tsc --noEmit && tslint --exclude src/generated/prisma.ts 'src/**/*.ts'",
18+
"precommit": "yarn run check",
1419
"docker:build": "docker build -t dsys/eth-explorer:latest .",
1520
"docker:run": "docker run -it dsys/eth-explorer:latest"
1621
},
1722
"dependencies": {
23+
"bluebird": "^3.5.1",
1824
"dataloader": "^1.4.0",
1925
"eth-ens-namehash": "^2.0.8",
2026
"graphql-yoga": "1.14.6",
27+
"libphonenumber-js": "^1.2.15",
28+
"node-fetch": "^2.1.2",
29+
"prisma-binding": "^2.0.2",
30+
"qs": "^6.5.2",
31+
"redis": "^2.8.0",
2132
"web3": "^1.0.0-beta.34"
2233
},
2334
"devDependencies": {
24-
"dotenv": "5.0.1",
35+
"dotenv": "^6.0.0",
2536
"graphql-cli": "2.16.0",
2637
"husky": "^0.14.3",
2738
"nodemon": "1.17.5",
2839
"npm-run-all": "4.1.3",
40+
"prettier": "^1.13.5",
41+
"prisma": "^1.9.0",
2942
"ts-node": "^6.1.0",
3043
"tslint": "^5.10.0",
44+
"tslint-config-prettier": "^1.13.0",
45+
"tslint-plugin-prettier": "^1.3.0",
3146
"typescript": "^2.9.1",
3247
"web3-typescript-typings": "^0.10.2"
3348
}

scripts/wait-for.sh

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/bin/sh
2+
3+
TIMEOUT=15
4+
QUIET=0
5+
6+
echoerr() {
7+
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
8+
}
9+
10+
usage() {
11+
exitcode="$1"
12+
cat << USAGE >&2
13+
Usage:
14+
$cmdname host:port [-t timeout] [-- command args]
15+
-q | --quiet Do not output any status messages
16+
-t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
17+
-- COMMAND ARGS Execute command with args after the test finishes
18+
USAGE
19+
exit "$exitcode"
20+
}
21+
22+
wait_for() {
23+
for i in `seq $TIMEOUT` ; do
24+
nc -z "$HOST" "$PORT" > /dev/null 2>&1
25+
26+
result=$?
27+
if [ $result -eq 0 ] ; then
28+
if [ $# -gt 0 ] ; then
29+
exec "$@"
30+
fi
31+
exit 0
32+
fi
33+
sleep 1
34+
done
35+
echo "Operation timed out" >&2
36+
exit 1
37+
}
38+
39+
while [ $# -gt 0 ]
40+
do
41+
case "$1" in
42+
*:* )
43+
HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
44+
PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
45+
shift 1
46+
;;
47+
-q | --quiet)
48+
QUIET=1
49+
shift 1
50+
;;
51+
-t)
52+
TIMEOUT="$2"
53+
if [ "$TIMEOUT" = "" ]; then break; fi
54+
shift 2
55+
;;
56+
--timeout=*)
57+
TIMEOUT="${1#*=}"
58+
shift 1
59+
;;
60+
--)
61+
shift
62+
break
63+
;;
64+
--help)
65+
usage 0
66+
;;
67+
*)
68+
echoerr "Unknown argument: $1"
69+
usage 1
70+
;;
71+
esac
72+
done
73+
74+
if [ "$HOST" = "" -o "$PORT" = "" ]; then
75+
echoerr "Error: you need to provide a host and port to test."
76+
usage 2
77+
fi
78+
79+
wait_for "$@"

src/context.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1+
import { Prisma } from "./generated/prisma";
12
import { createWeb3Loaders } from "./web3/loaders";
23

34
export interface Context {
4-
req: any;
5+
db: Prisma;
56
loaders: {
6-
web3: any,
7+
web3: any;
78
};
9+
req: any;
810
}
911

10-
export function createContext(req) {
12+
export function createContext(req): Context {
1113
return {
12-
...req,
14+
db: new Prisma({
15+
debug: true, // log all GraphQL queries & mutations sent to the Prisma API
16+
endpoint: process.env.PRISMA_ENDPOINT // the endpoint of the Prisma API (value set in `.env`)
17+
// secret: process.env.PRISMA_SECRET, // only needed if specified in `database/prisma.yml` (value set in `.env`)
18+
}),
1319
loaders: { web3: createWeb3Loaders() },
20+
req
1421
};
1522
}

0 commit comments

Comments
 (0)