diff --git a/lib/routes/rss3/index.ts b/lib/routes/rss3/index.ts index 820e36c2b144c9..5c3e136ff03e21 100644 --- a/lib/routes/rss3/index.ts +++ b/lib/routes/rss3/index.ts @@ -1,10 +1,8 @@ -/* eslint-disable default-case */ import { Route, type DataItem } from '@/types'; import { camelcaseKeys } from '@/utils/camelcase-keys'; import ofetch from '@/utils/ofetch'; -import type { Action } from '@rss3/sdk'; -import type { GetRSS3DataMetadata } from './interfaces/metadata'; +import { renderItemActionToHTML } from '@rss3/sdk'; export const route: Route = { path: '/:account/:network?/:tag?', @@ -137,7 +135,7 @@ async function handler(ctx) { title: `${account} activities`, link: 'https://rss3.io', item: data.map((item) => { - const content = parseItemActionToContent(camelcaseKeys(item.actions)); + const content = renderItemActionToHTML(camelcaseKeys(item.actions)); const description = `New ${item.tag} ${item.type} action on ${item.network}

From: ${item.from}
To: ${item.to}`; return { @@ -157,426 +155,3 @@ async function handler(ctx) { }), }; } - -function parseItemActionToContent(actions: Action[]): string | undefined { - if (!actions) { - return; - } - - let joint = ''; - - for (const action of actions) { - const metadata = action.metadata; - if (!metadata) { - continue; - } - const { tag } = action; - switch (tag) { - case 'social': - joint += renderSocialTagContent(action); - break; - case 'collectible': - joint += renderCollectibleTagContent(action); - break; - case 'metaverse': - joint += renderMetaverseTagContent(action); - - break; - case 'exchange': - joint += renderExchange(action); - break; - case 'transaction': - joint += renderTransaction(action); - break; - } - - joint += '
'; - } - - return joint; -} - -const renderTransaction = (action: Action) => { - let joint = ''; - const { type } = action; - const tag = 'transaction'; - switch (type) { - case 'transfer': - case 'burn': - case 'mint': - case 'approval': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Transaction ${type.toUpperCase().at(0) + type.slice(1)}

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

Standard: ${metadata.standard}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Decimals: ${metadata.decimals}

`, - /* html */ `

Address: ${metadata.address}

`, - ]); - break; - } - case 'event': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([/* html */ `

Transaction Event

`, /* html */ `

Block Hash: ${metadata.block.hash}

`, /* html */ `

Transaction Hash: ${metadata.transaction.hash}

`]); - break; - } - case 'bridge': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Transaction Bridge

`, - /* html */ `

Action: ${metadata.action}

`, - /* html */ `

Source Network: ${metadata.sourceNetwork}

`, - /* html */ `

Target Network: ${metadata.targetNetwork}

`, - metadata.token && /* html */ `

Token name: ${metadata.token.name}

`, - metadata.token && /* html */ `

Token Symbol: ${metadata.token.symbol}

`, - metadata.token && /* html */ `

Token Value: ${metadata.token.value}

`, - metadata.token && /* html */ `

Token Address: ${metadata.token.address}

`, - ]); - break; - } - } - - return buildSectionFooterHTML(joint, action); -}; - -const renderExchange = (action: Action) => { - let joint = ''; - const { type } = action; - const tag = 'exchange'; - switch (type) { - case 'liquidity': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Exchange Liquidity

`, - /* html */ `

Action: ${metadata.action}

`, - /* html */ `

- - - - - - - - - - - - - ${metadata.tokens.map( - (token) => /* html */ ` - - - - - - - ` - )} - -
AddressValueNameSymbolDecimalsStandard
${token.address}${token.value}${token.name}${token.symbol}${token.decimals}${token.standard}
-

`, - ]); - break; - } - case 'staking': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Exchange Liquidity

`, - /* html */ `

Action: ${metadata.action}

`, - metadata.token && - /* html */ `

- - Token: -

-

`, - ]); - break; - } - case 'swap': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Exchange Swap

`, - /* html */ metadata.from && `

From: ${metadata.from.address}

`, - /* html */ metadata.to && `

To: ${metadata.to?.address}

`, - ]); - } - } - - return buildSectionFooterHTML(joint, action); -}; - -const renderMetaverseTagContent = (action: Action) => { - let joint = ''; - const { from, to, type } = action; - const tag = 'metaverse'; - switch (type) { - case 'burn': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Metaverse Burn

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - break; - } - case 'trade': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Metaverse Trade

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - break; - } - case 'mint': - { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Metaverse Mint

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - } - break; - case 'transfer': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Metaverse Transfer

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - } - } - - return buildSectionFooterHTML(joint, action); -}; -const renderCollectibleTagContent = (action: Action) => { - let joint = ''; - const { from, to, type } = action; - const tag = 'collectible'; - switch (type) { - case 'approval': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Collectible Approval

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - - break; - } - case 'burn': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Collectible Burn

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - break; - } - case 'trade': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Collectible Trade

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - break; - } - case 'mint': - { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Collectible Mint

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - } - break; - case 'transfer': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html */ `

Collectible Transfer

`, - /* html */ `

Name: ${metadata.name}

`, - /* html */ `

Address: ${metadata.address}

`, - /* html */ `

Symbol: ${metadata.symbol}

`, - /* html */ `

Value: ${metadata.value}

`, - /* html */ `

${from} --> ${to}

`, - ]); - } - } - - return buildSectionFooterHTML(joint, action); -}; - -const renderSocialTagContent = (action: Action) => { - let joint = ''; - const { from, to, platform, type } = action; - const tag = 'social'; - switch (type) { - case 'profile': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - - joint += buildHTML([ - `

Name: ${metadata.name}

`, - `

Handle: ${metadata.handle}

`, - `

Bio: ${metadata.bio}

`, - `

Platform: ${platform}

`, - metadata.imageUri && `${metadata.name}`, - ]); - break; - } - case 'mint': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([`

Social Mint

`, `

Title: ${metadata.title}

`, `

${from} --> ${to}

`]); - break; - } - case 'delete': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([`

Social Delete

`, `

Title: ${metadata.title}

`]); - break; - } - case 'post': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html*/ `

Social Post

`, - /* html*/ `

Title: ${metadata.title}

`, - /* html*/ `

Author: ${metadata.handle}

`, - /* html*/ `

Content:

${metadata.body}

`, - /* html*/ `

Platform: ${platform}

`, - ]); - break; - } - case 'comment': { - const metadata = extractMetadata(tag, type, action); - if (!metadata) { - break; - } - joint += buildHTML([ - /* html*/ `

Social Comment

`, - /* html*/ `

Comment Anchor:${metadata.handle}

`, - metadata.target && /* html*/ `

Comment Target: ${metadata.target.title || metadata.targetUrl}

`, - ]); - - break; - } - case 'reward': - case 'revise': - case 'proxy': - case 'share': - break; - } - - return joint; -}; - -function extractMetadata(_tag: T1, _type: T2, data: any): GetRSS3DataMetadata | null { - const metadata = data.metadata; - if (!metadata) { - return null; - } - return camelcaseKeys(data.metadata) as GetRSS3DataMetadata; -} - -function buildHTML(arr: (string | boolean | undefined | null)[]): string { - return arr.filter(Boolean).join('\n'); -} - -const buildSectionFooterHTML = (string: string, action: Action) => - buildHTML([ - string, - !!action.platform && `

Platform: ${action.platform}

`, - - /* html */ `

Related URLs: -

  • ${action.relatedUrls.map((url) => `${url}`).join('
  • ')}

`, - ]); diff --git a/package.json b/package.json index fad5b866483ddc..b8a8fc62b83570 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@opentelemetry/sdk-trace-base": "1.26.0", "@opentelemetry/semantic-conventions": "1.27.0", "@postlight/parser": "2.2.3", - "@rss3/sdk": "0.0.13", + "@rss3/sdk": "0.0.15", "@scalar/hono-api-reference": "0.5.143", "@sentry/node": "7.116.0", "@tonyrl/rand-user-agent": "2.0.76", @@ -197,4 +197,4 @@ "engines": { "node": ">=22" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0ade8dedd89a1..678071c28a72e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,8 +42,8 @@ importers: specifier: 2.2.3 version: 2.2.3 '@rss3/sdk': - specifier: 0.0.13 - version: 0.0.13 + specifier: 0.0.15 + version: 0.0.15 '@scalar/hono-api-reference': specifier: 0.5.143 version: 0.5.143(hono@4.5.10) @@ -1745,14 +1745,14 @@ packages: cpu: [x64] os: [win32] - '@rss3/api-core@0.0.13': - resolution: {integrity: sha512-5CRVS0FpCZ8YiS/ttHM0ZxPxM05+WkcEPE7a5klX9NvULbDCISdpYQkiUkdVjZw+hPD7MCtlvBc9tFqTQKojJw==} + '@rss3/api-core@0.0.15': + resolution: {integrity: sha512-+3sTJqmWAVWFvOLHVtb9kht7jPDcz/icUa46AqWNsaXVBrTdkhq+UEnjtbNp/TYAJfxNxL//0LGCVd9EaWZjXA==} - '@rss3/api-utils@0.0.13': - resolution: {integrity: sha512-ucN9myX/E0DlA3Q+KkpCD/HwpB6fQSMlaHqRhDDV3tuyYrQnP/PjRKpGibx1Sz2x519SJNnsfyDL931H00iDJA==} + '@rss3/api-utils@0.0.15': + resolution: {integrity: sha512-j3uyM5wcNdlCOQb17BxYO/wnl9XwgnzOKqqnbL8IYr/BTJp2d30zgno3F4xZiiIGJm5fAwISNkIcPZhcs/DfBw==} - '@rss3/sdk@0.0.13': - resolution: {integrity: sha512-5QcC9NeMiKeay/H1JEGlG2ZtmKhZxlyLTA5f6dcIdGZUrSNk4DCM/J+8u0ED73bMQupi6xnUm+dIJdn6A1kHyA==} + '@rss3/sdk@0.0.15': + resolution: {integrity: sha512-refr0jRJ422G0kO3vU+S3D/6rXTVDAG/thiZYtg68FVuJc7OMmmiPrrRKf/8X/gOTa3BWsUNpyHRnEFNdJa09w==} '@scalar/hono-api-reference@0.5.143': resolution: {integrity: sha512-Rojp75Ma2HB2uUsmOQqsB6mJG8ydg1FB8ful3W8rhrahNZv76zK/wXmNl9B9OsK6AFIf8a7/kZuXMrAoHfHBSA==} @@ -7283,20 +7283,20 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.21.2': optional: true - '@rss3/api-core@0.0.13': + '@rss3/api-core@0.0.15': dependencies: openapi-fetch: 0.11.3 ts-case-convert: 2.0.7 type-fest: 4.26.0 - '@rss3/api-utils@0.0.13': + '@rss3/api-utils@0.0.15': dependencies: - '@rss3/api-core': 0.0.13 + '@rss3/api-core': 0.0.15 - '@rss3/sdk@0.0.13': + '@rss3/sdk@0.0.15': dependencies: - '@rss3/api-core': 0.0.13 - '@rss3/api-utils': 0.0.13 + '@rss3/api-core': 0.0.15 + '@rss3/api-utils': 0.0.15 '@scalar/hono-api-reference@0.5.143(hono@4.5.10)': dependencies: