Skip to content

Commit

Permalink
call setWinner
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemKolodko committed Nov 8, 2024
1 parent f6488af commit 1baf798
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 18 deletions.
113 changes: 107 additions & 6 deletions src/abi/TokenFactory.json
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,30 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "collateralByDay",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down Expand Up @@ -460,6 +484,25 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "creationDate",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "fee",
Expand All @@ -486,6 +529,38 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "day",
"type": "uint256"
}
],
"name": "getWinnerByDay",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxFundingRateInterval",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
Expand Down Expand Up @@ -553,16 +628,36 @@
{
"inputs": [
{
"internalType": "address",
"name": "winnerAddress",
"type": "address"
"internalType": "uint256",
"name": "interval",
"type": "uint256"
}
],
"name": "setMaxFundingRateInterval",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setWinner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "startOfCurrentDay",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tokenImplementation",
Expand Down Expand Up @@ -635,15 +730,21 @@
"type": "function"
},
{
"inputs": [],
"name": "winnerToken",
"outputs": [
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "winners",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
Expand Down
7 changes: 4 additions & 3 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export default () => ({
RPC_URL: process.env.RPC_URL || 'https://a.api.s0.t.hmny.io',
RATE_LIMITER_TTL: parseInt(process.env.RATE_LIMITER_TTL) || 10000,
RATE_LIMITER_LIMIT: parseInt(process.env.RATE_LIMITER_LIMIT) || 20,
PUMP_FUN_CONTRACT_ADDRESS: process.env.PUMP_FUN_CONTRACT_ADDRESS || '',
PUMP_FUN_INITIAL_BLOCK_NUMBER: parseInt(process.env.PUMP_FUN_INITIAL_BLOCK_NUMBER || '0'),
GOOGLE_CLOUD_CONFIG: getGoogleCloudConfig()
TOKEN_FACTORY_ADDRESS: process.env.TOKEN_FACTORY_ADDRESS || '',
INDEXER_INITIAL_BLOCK_NUMBER: parseInt(process.env.INDEXER_INITIAL_BLOCK_NUMBER || '0'),
GOOGLE_CLOUD_CONFIG: getGoogleCloudConfig(),
SERVICE_PRIVATE_KEY: process.env.SERVICE_PRIVATE_KEY || '',
});
60 changes: 51 additions & 9 deletions src/indexer/indexer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import {UserService} from "../user/user.service";
import {DataSource} from "typeorm";
import * as TokenFactoryABI from "../abi/TokenFactory.json";
import {AppService} from "../app.service";
import {Cron, CronExpression} from "@nestjs/schedule";

@Injectable()
export class IndexerService {
private readonly logger = new Logger(IndexerService.name);
private readonly web3: Web3
private readonly accountAddress: string
private readonly tokenFactoryContract: Contract<ContractAbi>
private readonly tokenContract: Contract<ContractAbi>
private readonly blocksIndexingRange = 1000

constructor(
Expand All @@ -25,28 +26,32 @@ export class IndexerService {
private dataSource: DataSource,
) {
const rpcUrl = configService.get('RPC_URL')
const contractAddress = configService.get('PUMP_FUN_CONTRACT_ADDRESS')
const initialBlockNumber = configService.get('PUMP_FUN_INITIAL_BLOCK_NUMBER')
const contractAddress = configService.get('TOKEN_FACTORY_ADDRESS')
const initialBlockNumber = configService.get('INDEXER_INITIAL_BLOCK_NUMBER')

if(!contractAddress) {
this.logger.error(`[PUMP_FUN_CONTRACT_ADDRESS] is missing but required, exit`)
this.logger.error(`[TOKEN_FACTORY_ADDRESS] is missing but required, exit`)
process.exit(1)
}

if(!initialBlockNumber) {
this.logger.error(`[PUMP_FUN_INITIAL_BLOCK_NUMBER] is missing but required, exit`)
this.logger.error(`[INDEXER_INITIAL_BLOCK_NUMBER] is missing but required, exit`)
process.exit(1)
}

this.logger.log(`Starting app service, RPC_URL=${
rpcUrl
}, PUMP_FUN_CONTRACT_ADDRESS=${
}, TOKEN_FACTORY_ADDRESS=${
contractAddress
}, PUMP_FUN_INITIAL_BLOCK_NUMBER=${
}, INDEXER_INITIAL_BLOCK_NUMBER=${
initialBlockNumber
}`)

this.web3 = new Web3(rpcUrl);
const account = this.web3.eth.accounts.privateKeyToAccount(configService.get('SERVICE_PRIVATE_KEY'))
this.accountAddress = account.address
this.web3.eth.accounts.wallet.add(account);
this.logger.log(`Service account address=${account.address}`)
this.tokenFactoryContract = new this.web3.eth.Contract(TokenFactoryABI, contractAddress);
this.bootstrap().then(
() => {
Expand All @@ -62,9 +67,9 @@ export class IndexerService {
where: {}
})
if(!indexerState) {
const blockNumber = +this.configService.get<number>('PUMP_FUN_INITIAL_BLOCK_NUMBER')
const blockNumber = +this.configService.get<number>('INDEXER_INITIAL_BLOCK_NUMBER')
if(!blockNumber) {
this.logger.error('[PUMP_FUN_INITIAL_BLOCK_NUMBER] is empty but required, exit')
this.logger.error('[INDEXER_INITIAL_BLOCK_NUMBER] is empty but required, exit')
process.exit(1)
}
await this.dataSource.manager.insert(IndexerState, {
Expand Down Expand Up @@ -307,4 +312,41 @@ export class IndexerService {

this.eventsTrackingLoop()
}

@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
async callSetWinner() {
let txnHash = ''
let gasFees = 0n

for(let i = 0; i < 3; i++) {
try {
gasFees = await this.tokenFactoryContract.methods
.setWinner()
.estimateGas({ from: this.accountAddress });
const gasPrice = await this.web3.eth.getGasPrice();
const tx = {
from: this.accountAddress,
to: this.configService.get('TOKEN_FACTORY_ADDRESS'),
gas: gasFees,
gasPrice,
data: this.tokenFactoryContract.methods.setWinner().encodeABI(),
};
const signPromise = await this.web3.eth.accounts.signTransaction(tx, this.configService.get('SERVICE_PRIVATE_KEY'));
const sendTxn =
await this.web3.eth.sendSignedTransaction(
signPromise.rawTransaction,
);
txnHash = sendTxn.transactionHash.toString()
break;
} catch (e) {
this.logger.warn(`Failed to send setWinner transaction, attempt: ${(i + 1)} / 3:`, e)
}
}

if(txnHash) {
this.logger.log(`[setWinner] successfully called, transaction hash=${txnHash}, gasFees=${gasFees}`)
} else {
this.logger.error('Failed to call setWinner!')
}
}
}

0 comments on commit 1baf798

Please sign in to comment.