diff --git a/packages/functions/.env b/packages/functions/.env index 11906f1f60..74912f8d9d 100644 --- a/packages/functions/.env +++ b/packages/functions/.env @@ -1,10 +1,10 @@ -ENVIRONMENT="emulator" -WEB3_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEVFMjA3Qzk5YzA2NzkxMDg0QjU5NmU4NkEyMzVGNzFiNTc0NWNkMTIiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njg0Njc4MDQ3NDAsIm5hbWUiOiJERVZfVE9LRU4ifQ.TB2AbWZDMk4WhWIeWKsdEKUReXUh0WUgcHAU5ccb4FA" -JWT_SECRET="mysecret" -ALGOLIA_APPID="UZXKW1YS76" -ALGOLIA_KEY="8bf460848691fae9111b6159867d6bc1" -ENCRYPTION_SALT="sa#asda!2sasd##asad" -IP_INFO_TOKEN="" -XPTOKEN_ID="0x08f800d9e15c1da60c36cb0b2d4a02366ea3e200a65fc071a9e25f09b7fb9e951f0100000000" -XPTOKEN_UID="0xcef8ddcea97a5b82921d1cadbc8ccddcd69341da" -XPTOKEN_GUARDIANID="0x45f8379c44a73fc0ee6ad56acf51bd0f69240af5" \ No newline at end of file +ENVIRONMENT=test +WEB3_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEZCOTFiNTdEN2YzNmVhNjQ4NjQ3ODIyQjJGNGVEOEEyMDZCNERhNjQiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njc0MDYzNzE3NDksIm5hbWUiOiJ0ZXN0IGRldiJ9.88vd8ZmeEle2Xqyc8uEMBOXJqDrFcxxF8gyHuXIjXgk +JWT_SECRET=asdas#@#@xdas31sad +ALGOLIA_APPID=6MPUETJRDB +ALGOLIA_KEY=a75153c20ebe86d31e1fe5874f55dbac +ENCRYPTION_SALT=c4kWxCtNVQ5c2m +IP_INFO_TOKEN='' +XPTOKEN_ID=0x08fe43472f5968c4ccfa7154599e3d9c8df3f2e0b6396cafc2b038f15ee1974e050100000000 +XPTOKEN_UID=0xe71439be7001d2311658ded364e4043a284d16f4 +XPTOKEN_GUARDIANID=0x551fd2c7c7bf356bac194587dab2fcd46420054b \ No newline at end of file diff --git a/packages/functions/Dockerfile b/packages/functions/Dockerfile index 0c94a78230..2a6b2a72d8 100644 --- a/packages/functions/Dockerfile +++ b/packages/functions/Dockerfile @@ -16,6 +16,7 @@ COPY packages/database packages/database COPY packages/interfaces packages/interfaces COPY packages/functions packages/functions COPY package.json ./ +COPY data.proto ./ RUN npm run build:functions diff --git a/packages/functions/deploy.script.ts b/packages/functions/deploy.script.ts index 8536fa09e1..c49400c714 100644 --- a/packages/functions/deploy.script.ts +++ b/packages/functions/deploy.script.ts @@ -18,48 +18,53 @@ fs.appendFileSync( "export PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')\n\n", ); -fs.appendFileSync(file, 'cp packages/functions/Dockerfile ./Dockerfile\n\n'); -fs.appendFileSync(file, 'gcloud builds submit --tag gcr.io/$GOOGLE_CLOUD_PROJECT/functions\n\n'); - -Object.entries({ - ...flattenObject(onRequests), - ...flattenObject(onTriggers), - ...flattenObject(onScheduled), - ...flattenObject(onStorage), -}).forEach(([name, value]) => { - const options = (value as CloudFunctions).runtimeOptions; - - let command = `gcloud run deploy ${name} \\ +const buildImage = () => { + fs.appendFileSync(file, 'cp packages/functions/Dockerfile ./Dockerfile\n\n'); + fs.appendFileSync(file, 'gcloud builds submit --tag gcr.io/$GOOGLE_CLOUD_PROJECT/functions\n\n'); +}; + +const deployServices = () => { + Object.entries({ + ...flattenObject(onRequests), + ...flattenObject(onTriggers), + ...flattenObject(onScheduled), + ...flattenObject(onStorage), + }).forEach(([name, value]) => { + const options = (value as CloudFunctions).runtimeOptions; + + let command = `gcloud run deploy ${name} \\ --image gcr.io/$GOOGLE_CLOUD_PROJECT/functions \\ --allow-unauthenticated \\ --ingress=internal-and-cloud-load-balancing \\ `; - if (options?.region) { - command += ` --region=${options.region} \\\n`; - } - if (options?.timeoutSeconds) { - command += ` --timeout=${options.timeoutSeconds} \\\n`; - } - if (options?.concurrency) { - command += ` --concurrency=${options.concurrency} \\\n`; - } - if (options?.memory) { - command += ` --memory=${options.memory.replace('B', '')} \\\n`; - } - if (options?.minInstances) { - command += ` --min-instances=${options.minInstances} \\\n`; - } - if (options?.cpu) { - command += ` --cpu=${options.cpu} \\\n`; - } - fs.appendFileSync(file, command + ' &\n\n'); -}); - -fs.appendFileSync(file, 'wait\n\n'); - -Object.entries(flattenObject(onStorage)).forEach(([name, value]) => { - const options = (value as CloudFunctions).runtimeOptions; - let command = `if [ -z "$(gcloud eventarc triggers list --filter="name:${name}" --format="value(name)")" ]; then + if (options?.region) { + command += ` --region=${options.region} \\\n`; + } + if (options?.timeoutSeconds) { + command += ` --timeout=${options.timeoutSeconds} \\\n`; + } + if (options?.concurrency) { + command += ` --concurrency=${options.concurrency} \\\n`; + } + if (options?.memory) { + command += ` --memory=${options.memory.replace('B', '')} \\\n`; + } + if (options?.minInstances) { + command += ` --min-instances=${options.minInstances} \\\n`; + } + if (options?.cpu) { + command += ` --cpu=${options.cpu} \\\n`; + } + fs.appendFileSync(file, command + ' &\n\n'); + }); + + fs.appendFileSync(file, 'wait\n\n'); +}; + +const deployStorageTriggers = () => { + Object.entries(flattenObject(onStorage)).forEach(([name, value]) => { + const options = (value as CloudFunctions).runtimeOptions; + let command = `if [ -z "$(gcloud eventarc triggers list --filter="name:${name}" --format="value(name)")" ]; then gcloud eventarc triggers create ${name} \\ --destination-run-service=${name} \\ --destination-run-path="/${name}" \\ @@ -68,48 +73,52 @@ Object.entries(flattenObject(onStorage)).forEach(([name, value]) => { --event-filters="type=google.cloud.storage.object.v1.finalized" \\ --event-filters="bucket=${options.bucket}" \\ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com\nfi &\n\n`; - fs.appendFileSync(file, command); -}); - -const getTriggerType = (type: TriggeredFunctionType) => { - switch (type) { - case TriggeredFunctionType.ON_CREATE: - return 'google.cloud.firestore.document.v1.created'; - case TriggeredFunctionType.ON_UPDATE: - return 'google.cloud.firestore.document.v1.updated'; - case TriggeredFunctionType.ON_WRITE: - return 'google.cloud.firestore.document.v1.written'; - } + fs.appendFileSync(file, command); + }); }; -Object.entries(flattenObject(onTriggers)).forEach(([name, value]) => { - const options = (value as CloudFunctions).runtimeOptions; - const type = (value as TriggeredFunction).type; - const document = (value as TriggeredFunction).document; - let command = `if [ -z "$(gcloud eventarc triggers list --filter="name:${name}" --format="value(name)")" ]; then - gcloud eventarc triggers create ${name} \\ - --location=nam5 \\ - --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com \\ - --destination-run-service=${name} \\ - --destination-run-region=${options.region} \\ - --destination-run-path="/${name}" \\ - --event-filters="database=(default)" \\ - --event-filters="document=${document}" \\ - --event-filters="namespace=(default)" \\ - --event-filters="type=${getTriggerType(type)}" \\ - --event-data-content-type="application/protobuf"\nfi &\n\n`; - fs.appendFileSync(file, command + ''); -}); - -Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { - const command = `if ! gcloud pubsub topics list --format="value(name)" | grep -q "${name}"; then +const deployFirestoreTriggers = () => { + const getTriggerType = (type: TriggeredFunctionType) => { + switch (type) { + case TriggeredFunctionType.ON_CREATE: + return 'google.cloud.firestore.document.v1.created'; + case TriggeredFunctionType.ON_UPDATE: + return 'google.cloud.firestore.document.v1.updated'; + case TriggeredFunctionType.ON_WRITE: + return 'google.cloud.firestore.document.v1.written'; + } + }; + + Object.entries(flattenObject(onTriggers)).forEach(([name, value]) => { + const options = (value as CloudFunctions).runtimeOptions; + const type = (value as TriggeredFunction).type; + const document = (value as TriggeredFunction).document; + let command = `if [ -z "$(gcloud eventarc triggers list --filter="name:${name}" --format="value(name)")" ]; then + gcloud eventarc triggers create ${name} \\ + --location=nam5 \\ + --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com \\ + --destination-run-service=${name} \\ + --destination-run-region=${options.region} \\ + --destination-run-path="/${name}" \\ + --event-filters="database=(default)" \\ + --event-filters-path-pattern="document=${document}" \\ + --event-filters="namespace=(default)" \\ + --event-filters="type=${getTriggerType(type)}" \\ + --event-data-content-type="application/protobuf"\nfi &\n\n`; + fs.appendFileSync(file, command + ''); + }); +}; + +const deployCronTriggers = () => { + Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { + const command = `if ! gcloud pubsub topics list --format="value(name)" | grep -q "${name}"; then gcloud pubsub topics create "${name}"\nfi\n\n`; - fs.appendFileSync(file, command); -}); + fs.appendFileSync(file, command); + }); -Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { - const options = (value as CloudFunctions).runtimeOptions; - const command = `if [ -z "$(gcloud eventarc triggers list --filter="name:${name}" --format="value(name)")" ]; then + Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { + const options = (value as CloudFunctions).runtimeOptions; + const command = `if [ -z "$(gcloud eventarc triggers list --filter="name:${name}" --format="value(name)")" ]; then gcloud eventarc triggers create ${name} \\ --location=us-central1 \\ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com \\ @@ -118,19 +127,26 @@ Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { --destination-run-region=${options.region} \\ --destination-run-path="/${name}" \\ --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished"\nfi &\n\n`; - fs.appendFileSync(file, command); -}); + fs.appendFileSync(file, command); + }); -fs.appendFileSync(file, 'wait\n\n'); + fs.appendFileSync(file, 'wait\n\n'); -Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { - const schedule = (value as ScheduledFunction).schedule; - const command = `if [ -z "$(gcloud scheduler jobs list --filter="name:${name}" --format="value(name)")" ]; then + Object.entries(flattenObject(onScheduled)).forEach(([name, value]) => { + const schedule = (value as ScheduledFunction).schedule; + const command = `if [ -z "$(gcloud scheduler jobs list --filter="name:${name}" --format="value(name)")" ]; then gcloud scheduler jobs create pubsub ${name} \\ --schedule="${schedule}" \\ --topic=projects/$GOOGLE_CLOUD_PROJECT/topics/${name} \\ --message-body="{}"\nfi &\n\n`; - fs.appendFileSync(file, command); -}); + fs.appendFileSync(file, command); + }); + + fs.appendFileSync(file, 'wait\n\n'); +}; -fs.appendFileSync(file, 'wait\n\n'); +buildImage(); +deployServices(); +deployStorageTriggers(); +deployFirestoreTriggers(); +deployCronTriggers(); diff --git a/packages/functions/src/index.express.ts b/packages/functions/src/index.express.ts index b906573ca4..cb89945403 100644 --- a/packages/functions/src/index.express.ts +++ b/packages/functions/src/index.express.ts @@ -34,7 +34,7 @@ Object.entries(flattenObject(onRequests)).forEach(([name, config]) => { // TRIGGERS Object.entries(flattenObject(onTriggers)).forEach(([name, config]) => { - app.post(`/${name}`, app.use(express.raw({ type: 'application/protobuf' })), async (req, res) => { + app.post(`/${name}`, express.raw({ type: 'application/protobuf' }), async (req, res) => { const root = loadSync('./data.proto'); const type = root.lookupType('DocumentEventData'); const decoded = type.decode(req.body); @@ -50,7 +50,7 @@ Object.entries(flattenObject(onTriggers)).forEach(([name, config]) => { ...pathToParts(get(cloudEvent, 'document', '')), }; await (config as TriggeredFunction).handler(event); - res.send(200); + res.sendStatus(200); }); }); @@ -58,7 +58,7 @@ Object.entries(flattenObject(onTriggers)).forEach(([name, config]) => { Object.entries(flattenObject(onScheduled)).forEach(([name, config]) => { app.post(`/${name}`, async (_, res) => { await (config as ScheduledFunction).func(); - res.send(200); + res.sendStatus(200); }); }); @@ -75,7 +75,7 @@ Object.entries(flattenObject(onStorage)).forEach(([name, config]) => { bucket: get(event, 'data.bucket', ''), contentType: get(event, 'data.contentType'), }); - res.send(200); + res.sendStatus(200); }); }); diff --git a/packages/functions/src/runtime/proto/protoToJson.ts b/packages/functions/src/runtime/proto/protoToJson.ts index 64cedc61b6..878cb6336b 100644 --- a/packages/functions/src/runtime/proto/protoToJson.ts +++ b/packages/functions/src/runtime/proto/protoToJson.ts @@ -25,6 +25,8 @@ const protoJsonToJson = (protoJson: { [key: string]: any }) => const valueToJson = (data: { [key: string]: any }): any => { const [type, value] = Object.entries(data)[0]; switch (type) { + case 'nullValue': + return null; case 'booleanValue': case 'integerValue': case 'doubleValue': @@ -34,8 +36,8 @@ const valueToJson = (data: { [key: string]: any }): any => { case 'referenceValue': return value; case 'arrayValue': - return (value.values as any[]).map(valueToJson); + return ((value.values as any[]) || []).map(valueToJson); case 'mapValue': - return protoJsonToJson(value.fields); + return protoJsonToJson(value.fields || {}); } }; diff --git a/packages/interfaces/src/api/base.ts b/packages/interfaces/src/api/base.ts index ac934ec155..6ba799aad0 100644 --- a/packages/interfaces/src/api/base.ts +++ b/packages/interfaces/src/api/base.ts @@ -10,7 +10,7 @@ export enum PublicCollections { PROPOSAL = 'proposal', NOTIFICATION = 'notification', MILESTONE = 'milestone', - MILESTONE_RMS = 'milestone_rms', + MILESTONE_RMS = 'milestone_rms_t2', MILESTONE_SMR = 'milestone_smr', TRANSACTION = 'transaction', BADGES = 'badges', diff --git a/packages/interfaces/src/models/base.ts b/packages/interfaces/src/models/base.ts index 527a0e4c7c..745b9bc436 100644 --- a/packages/interfaces/src/models/base.ts +++ b/packages/interfaces/src/models/base.ts @@ -50,7 +50,7 @@ export enum COL { PROPOSAL = 'proposal', NOTIFICATION = 'notification', MILESTONE = 'milestone', - MILESTONE_RMS = 'milestone_rms', + MILESTONE_RMS = 'milestone_rms_t2', MILESTONE_SMR = 'milestone_smr', TRANSACTION = 'transaction', BADGES = 'badges',