diff --git a/src/contextualizers/protocol/skyoneer/README.md b/src/contextualizers/protocol/skyoneer/README.md index ad31c459..456edccc 100644 --- a/src/contextualizers/protocol/skyoneer/README.md +++ b/src/contextualizers/protocol/skyoneer/README.md @@ -5,3 +5,4 @@ | PackActivationSource | [0xde1bc6e9164af5a48c45111b811c61f11ce58d91](https://www.onceupon.xyz/0xde1bc6e9164af5a48c45111b811c61f11ce58d91:8453) | Base | | PackActivationDestination | [0x21170f8bd35d0afa8ad55719ce29d6489a8585db](https://www.onceupon.xyz/0x21170f8bd35d0afa8ad55719ce29d6489a8585db:4653) | Gold | | PlotAction | [0xb45805566a842efb6329c11e092158f3e0eddaa2](https://www.onceupon.xyz/0xb45805566a842efb6329c11e092158f3e0eddaa2:4653) | Gold | +| GameEngine | [0xc1e5e0dc7e94f9167ccf983ba26f7c21c83e0a33](https://www.onceupon.xyz/0xc1e5e0dc7e94f9167ccf983ba26f7c21c83e0a33:4653) | Gold | diff --git a/src/contextualizers/protocol/skyoneer/abis/GameEngine.ts b/src/contextualizers/protocol/skyoneer/abis/GameEngine.ts new file mode 100644 index 00000000..319fe837 --- /dev/null +++ b/src/contextualizers/protocol/skyoneer/abis/GameEngine.ts @@ -0,0 +1,35 @@ +const abi = [ + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'receiver', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'tokenAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'tokenAmount', + type: 'uint256', + }, + ], + name: 'SentTokenToAnotherUser', + type: 'event', + }, +] as const; + +export default abi; diff --git a/src/contextualizers/protocol/skyoneer/constants.ts b/src/contextualizers/protocol/skyoneer/constants.ts index 4aab0813..caa7e136 100644 --- a/src/contextualizers/protocol/skyoneer/constants.ts +++ b/src/contextualizers/protocol/skyoneer/constants.ts @@ -1,6 +1,7 @@ import packActivationDestinationAbi from './abis/PackActivationDestination'; import packActivationSourceAbi from './abis/PackActivationSource'; import plotActionAbi from './abis/PlotAction'; +import gameEngineAbi from './abis/GameEngine'; export const PACK_ACTIVATION_DESTINATION_CONTRACT = '0x21170f8bd35d0afa8ad55719ce29d6489a8585db'; @@ -12,7 +13,10 @@ export const Z_GOLD_CONTRACT_ADDRESS = '0x387d73bd8682dceb3327b940213d5de50ee2bba2'; export const PLOT_ACTION_CONTRACT_ADDRESS = '0xb45805566a842efb6329c11e092158f3e0eddaa2'; +export const GAME_ENGINE_CONTRACT_ADDRESS = + '0xc1e5e0dc7e94f9167ccf983ba26f7c21c83e0a33'; export const PACK_ACTIVATION_SOURCE_ABI = packActivationSourceAbi; export const PACK_ACTIVATION_DESTINATION_ABI = packActivationDestinationAbi; export const PLOT_ACTION_ABI = plotActionAbi; +export const GAME_ENGINE_ABI = gameEngineAbi; diff --git a/src/contextualizers/protocol/skyoneer/gameEngine.ts b/src/contextualizers/protocol/skyoneer/gameEngine.ts new file mode 100644 index 00000000..f45430fb --- /dev/null +++ b/src/contextualizers/protocol/skyoneer/gameEngine.ts @@ -0,0 +1,102 @@ +import { + Transaction, + EventLogTopics, + SkyoneerContextActionEnum, + AssetType, +} from '../../../types'; +import { GAME_ENGINE_CONTRACT_ADDRESS, GAME_ENGINE_ABI } from './constants'; +import { decodeLog } from '../../../helpers/utils'; + +export function contextualize(transaction: Transaction): Transaction { + const isGameEngine = detect(transaction); + if (!isGameEngine) return transaction; + + const result = generate(transaction); + return result; +} + +export function detect(transaction: Transaction): boolean { + /** + * There is a degree of overlap between the 'detect' and 'generateContext' functions, + * and while this might seem redundant, maintaining the 'detect' function aligns with + * established patterns in our other modules. This consistency is beneficial, + * and it also serves to decouple the logic, thereby simplifying the testing process + */ + // check logs + if (!transaction.logs) return false; + + for (const log of transaction.logs) { + if (log.address !== GAME_ENGINE_CONTRACT_ADDRESS) continue; + + const decoded = decodeLog(GAME_ENGINE_ABI, log.data, [ + log.topic0, + log.topic1, + log.topic2, + log.topic3, + ] as EventLogTopics); + + if (decoded && decoded.eventName === 'SentTokenToAnotherUser') { + return true; + } + } + + return false; +} + +export function generate(transaction: Transaction): Transaction { + if (!transaction.logs || !transaction.chainId) return transaction; + + let decoded; + for (const log of transaction.logs) { + if (log.address !== GAME_ENGINE_CONTRACT_ADDRESS) continue; + + decoded = decodeLog(GAME_ENGINE_ABI, log.data, [ + log.topic0, + log.topic1, + log.topic2, + log.topic3, + ] as EventLogTopics); + + if (decoded && decoded.eventName === 'SentTokenToAnotherUser') { + break; + } + } + if (!decoded) return transaction; + + // grab variables from decoded event + const sender = decoded.args['sender'] as string; + const receiver = decoded.args['receiver'] as string; + const tokenAddress = decoded.args['tokenAddress'] as string; + const tokenAmount = decoded.args['tokenAmount']; + + transaction.context = { + summaries: { + category: 'PROTOCOL_1', + en: { + title: `Skyoneer`, + default: '[[sender]][[contextAction]][[token]]to[[receiver]]', + }, + }, + variables: { + sender: { + type: 'address', + value: sender, + }, + receiver: { + type: 'address', + value: receiver, + }, + token: { + type: AssetType.ERC20, + token: tokenAddress, + value: tokenAmount.toString(), + }, + contextAction: { + type: 'contextAction', + value: SkyoneerContextActionEnum.TRANSFERRED, + }, + }, + }; + + return transaction; +} diff --git a/src/types/contextAction/protocolContextAction.ts b/src/types/contextAction/protocolContextAction.ts index 70310381..fc864a0b 100644 --- a/src/types/contextAction/protocolContextAction.ts +++ b/src/types/contextAction/protocolContextAction.ts @@ -234,6 +234,7 @@ export enum SkyoneerContextActionEnum { CLEARED_GROWING_CROPS = 'CLEARED_GROWING_CROPS', CLEARED_DEAD_CROPS = 'CLEARED_DEAD_CROPS', PLANTED = 'PLANTED', + TRANSFERRED = 'TRANSFERRED', } export type SkyoneerContextAction = @@ -242,7 +243,8 @@ export type SkyoneerContextAction = | SkyoneerContextActionEnum.HARVESTED | SkyoneerContextActionEnum.CLEARED_GROWING_CROPS | SkyoneerContextActionEnum.CLEARED_DEAD_CROPS - | SkyoneerContextActionEnum.PLANTED; + | SkyoneerContextActionEnum.PLANTED + | SkyoneerContextActionEnum.TRANSFERRED; export enum Protocols { WETH = 'WETH',