Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest subquery changes #42

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cc71349
update docker-compose
Douglasacost Nov 8, 2023
48c642e
use npm
Douglasacost Nov 8, 2023
78f2a8a
Add .prettierrc configuration file
Douglasacost Nov 18, 2023
455dbbb
Update log level and disable historical in
Douglasacost Nov 18, 2023
54af4ad
Update dependencies and remove unused code
Douglasacost Nov 18, 2023
64f8390
Refactor collection and item creation logic
Douglasacost Nov 18, 2023
9ed9c27
Delete allocation handler and
Douglasacost Nov 18, 2023
ea76cfd
Fix checkIfExtrinsicExecuteSuccess function call
Douglasacost Nov 18, 2023
202f1b2
Fix bug in login functionality
Douglasacost Nov 18, 2023
06e0985
Update mappings and entities for Pot and
Douglasacost Nov 18, 2023
c33ad74
Add isReward field to BalanceTransfer model
Douglasacost Nov 18, 2023
dbc5a02
Refactor account balance handling and sponsorship functionality
Douglasacost Nov 21, 2023
b8c0778
Update TREASURY_ACCOUNT in
Douglasacost Nov 26, 2023
5bf64cf
Update Pot and Account Quota Fields
Douglasacost Nov 26, 2023
e7a4e45
Add skipTransactions option to runner and remove calls handlers
Douglasacost Nov 26, 2023
7742414
Update dependencies in package.json
Douglasacost Nov 29, 2023
5dfb954
Update dependencies and fix data type conversion
Douglasacost Dec 19, 2023
9c491df
Add feeQuotaBalance and reserveQuotaBalance to AccountPotBalance
Douglasacost Jan 7, 2024
051cea1
Add dependencies and update configuration***
Douglasacost Feb 19, 2024
8bb86e8
Refactor code to improve performance and readability
Douglasacost Mar 22, 2024
7864b7b
Update .gitignore and package.json
Apr 22, 2024
d46e445
Update dwellir rpc name
Apr 29, 2024
1c632e9
Update npm dependencies and configuration
Douglasacost May 23, 2024
979ce71
Merge branch 'feat/composed-index' of github.com:NodleCode/subquery i…
Douglasacost May 28, 2024
5d3fc1c
Update network configuration with new chainId and endpoint. Added new…
Douglasacost May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -5,4 +5,5 @@ node_modules
dist/
src/types

.project-cid
.project-cid
.vscode/
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true
}
7 changes: 4 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ services:
retries: 5

subquery-node:
image: onfinality/subql-node:v1.13.3
image: onfinality/subql-node:v3.4.2
depends_on:
"postgres":
condition: service_healthy
@@ -34,8 +34,9 @@ services:
command:
- -f=/app
- --db-schema=app
- --log-level=debug
- --disable-historical=false
- --log-level=info
- --disable-historical=true
- --unsafe
healthcheck:
test: ["CMD", "curl", "-f", "http://subquery-node:3000/ready"]
interval: 3s
2 changes: 1 addition & 1 deletion docker/pg-Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM postgres:12-alpine
FROM postgres:latest

# Variables needed at runtime to configure postgres and run the initdb scripts
ENV POSTGRES_DB 'postgres'
11,461 changes: 11,461 additions & 0 deletions index.js

Large diffs are not rendered by default.

31,746 changes: 31,746 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
"publish": "subql publish",
"prepack": "rm -rf dist && npm run build",
"codegen": "./node_modules/.bin/subql codegen",
"start:docker": "docker-compose pull && docker-compose up --remove-orphans"
"start:docker": "docker-compose pull && docker-compose up --remove-orphans -d"
},
"homepage": "https://github.com/NodleCode/subquery",
"repository": "github:NodleCode/subquery",
@@ -19,11 +19,12 @@
"author": "SubQuery Network",
"license": "Apache-2.0",
"devDependencies": {
"@subql/types": "latest",
"@subql/testing": "latest",
"@subql/node": "latest",
"@subql/cli": "latest",
"@polkadot/api": "^10",
"@subql/cli": "^4.2.4",
"@subql/node": "^4.4.1",
"@subql/testing": "^2.1.0",
"@subql/types": "^3.6.0",
"@types/node-fetch": "^2.6.11",
"typescript": "^4.1.3"
},
"exports": {
49 changes: 43 additions & 6 deletions project.yaml
Original file line number Diff line number Diff line change
@@ -5,17 +5,19 @@ runner:
node:
name: "@subql/node"
version: "*"
options:
historical: false
unsafe: true
query:
name: "@subql/query"
version: "*"
description: "Subquery indexer for Nodle network (testnet)."
description: "Subquery indexer for Nodle network."
repository: https://github.com/NodleCode/subquery.git
schema:
file: ./schema.graphql
network:
chainId: "0x97da7ede98d7bad4e36b4d734b6055425a3be036da2a332ea5a7037656427a21"
endpoint: [wss://nodle-parachain.api.onfinality.io/public-ws]
dictionary: https://api.subquery.network/sq/subquery/nodle-parachain-dictionary
endpoint: "wss://nodle-rpc.dwellir.com:443/928f1361-a903-4360-b8ca-4fd786d7214c"
chaintypes:
file: ./dist/chaintypes.js
dataSources:
@@ -74,8 +76,43 @@ dataSources:
filter:
module: balances
method: Transfer
- handler: handleAllocationBatchCall
- handler: handleSponsorshipCreatePotCall
kind: substrate/CallHandler
filter:
module: allocations
method: batch
module: sponsorship
method: createPot
- handler: handleSponsorshipRegisterUsersCall
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually the EventHandlers are a better choice for indexing compared with the CallHandlers. The reason is when the call is nested for example inside a Utility batch, the subquery used to struggle to trace it. Is it still the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True @aliXsed, we had issues with the batch in the past since it handle tons of data (e.x allocations)

Will update this on testnet, for use events instead of calls

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will prepare a new PR when the sponsorship events got updated on mainnet, meanwhile pot indexing is desactivted

kind: substrate/CallHandler
filter:
module: sponsorship
method: registerUsers
- handler: handleSponsorshipRemoveUsersCall
kind: substrate/CallHandler
filter:
module: sponsorship
method: removeUsers
- handler: handleSponsorshipUpdatePotLimitsCall
kind: substrate/CallHandler
filter:
module: sponsorship
method: updatePotLimits
- handler: handleSponsorshipUpdateSponsorshipTypeCall
kind: substrate/CallHandler
filter:
module: sponsorship
method: updateSponsorshipType
- handler: handleSponsorshipUpdateUsersLimitsCall
kind: substrate/CallHandler
filter:
module: sponsorship
method: updateUsersLimits
- handler: handleSponsorshipRemovePotCall
kind: substrate/CallHandler
filter:
module: sponsorship
method: removePot
- handler: handleSponsorshipSponsorForCall
kind: substrate/CallHandler
filter:
module: sponsorship
method: sponsorFor
155 changes: 100 additions & 55 deletions schema.graphql
Original file line number Diff line number Diff line change
@@ -1,69 +1,114 @@
type Collection @entity {
id: ID!
collectionId: String! @index
issuer: String! @index
admin: String! @index
owner: String! @index
freezer: String
metadataCid: String
isDestroyed: Boolean!
createdAt: Float @index
updatedAt: Float @index
items: [Item] @derivedFrom(field: "collection")
id: ID!
collectionId: Float! @index
issuer: String! @index
admin: String! @index
owner: String! @index
freezer: String
metadataCid: String
isDestroyed: Boolean!
createdAt: BigInt @index
updatedAt: BigInt @index
items: [Item] @derivedFrom(field: "collection")
podId: Float @index
}

type Item @entity {
id: ID!
itemId: String! @index
collectionItemKey: String! @index
collection: Collection!
metadataCid: String
isBurned: Boolean!
createdAt: Float @index
updatedAt: Float @index
owner: String
type Item @entity @compositeIndexes(fields: [["owner", "itemId"]]) {
id: ID!
itemId: Float! @index
collectionItemKey: String! @index
collection: Collection!
metadataCid: String
isBurned: Boolean!
createdAt: BigInt @index
updatedAt: BigInt @index
owner: String
podId: Float @index
}

type BalanceTransfer @entity {
id: ID!
from: String! @index
to: String! @index
txHash: String @index
amount: BigInt @index
timestamp: Float @index
blockNumber: BigInt
success: Boolean
type AllBalanceTransfer @entity @compositeIndexes(fields: [["from", "to"]]) {
id: ID!
from: String! @index
to: String! @index
txHash: String @index
amount: BigInt @index
timestamp: BigInt @index
blockNumber: BigInt
}

type AllocationEventData @jsonField {
who: String @index
amount: String
type BalanceTransfer @entity @compositeIndexes(fields: [["from", "to"]]) {
id: ID!
from: String! @index
to: String! @index
txHash: String @index
amount: BigInt @index
timestamp: BigInt @index
blockNumber: BigInt
}

type AllocationEvent @jsonField {
method: String @index
section: String @index
index: String
data: AllocationEventData
type Rewards @entity @compositeIndexes(fields: [["from", "to"]]) {
id: ID!
from: String! @index
to: String! @index
txHash: String @index
amount: BigInt @index
timestamp: BigInt @index
blockNumber: BigInt
}

type Allocations @entity {
id: ID!
txHash: String @index
block: Int @index
data: [AllocationEvent]
success: Boolean
type TransferToTreasury @entity @compositeIndexes(fields: [["from", "to"]]) {
id: ID!
from: String! @index
to: String! @index
txHash: String @index
amount: BigInt @index
timestamp: BigInt @index
blockNumber: BigInt
isAllocation: Boolean @index
}

type UniquesTransfer @entity {
id: ID!
txHash: String @index
block: Int @index
from: String @index
to: String @index
collection: Collection!
item: Item!
fee: BigInt
timestamp: Float @index
success: Boolean
type UniquesTransfer @entity @compositeIndexes(fields: [["from", "to"]]) {
id: ID!
txHash: String @index
block: BigInt @index
from: String @index
to: String @index
collection: Collection!
item: Item!
fee: BigInt
timestamp: BigInt @index
success: Boolean
}

type Pot @entity {
id: ID!
potId: Float! @index
owner: String! @index
feeQuotaBalance: BigInt!
feeQuotaLimit: BigInt!
reserveQuotaBalance: BigInt!
reserveQuotaLimit: BigInt!
sponsorshipType: String!
sponsoredAccounts: [AccountPotBalance] @derivedFrom(field: "pot")
createdAt: BigInt @index
updatedAt: BigInt @index
}

type AccountPotBalance @entity @compositeIndexes(fields: [["pot", "account"]]) {
id: ID!
pot: Pot!
account: Account!
feeQuotaBalance: BigInt!
feeQuotaLimit: BigInt!
reserveQuotaBalance: BigInt!
reserveQuotaLimit: BigInt!
createdAt: BigInt @index
updatedAt: BigInt @index
}

type Account @entity {
id: ID!
potBalance: [AccountPotBalance] @derivedFrom(field: "account")
createdAt: BigInt @index
updatedAt: BigInt @index
}
41 changes: 0 additions & 41 deletions src/handlers/allocation.ts

This file was deleted.

24 changes: 14 additions & 10 deletions src/helpers/verifyUnique.ts
Original file line number Diff line number Diff line change
@@ -19,16 +19,18 @@ export const ensureCollection = async ({
idx,
timestamp,
}: EnsureCollection) => {
const collectionIdString = collectionId.toString();
const collections = await Collection.getByCollectionId(collectionIdString);
const collectionIdAsNumber = Number(collectionId.toString());
const collections = await Collection.getByCollectionId(collectionIdAsNumber);
let collection = collections?.find((c) => !c.isDestroyed);

if (!collection) {
const id = `${collectionIdString}-${blockNumber}-${idx}`;
logger.warn('Collection not found, creating new collection', collectionIdString);
collection = new Collection(id, collectionIdString, '', '', '', false);
collection.createdAt = timestamp.getTime();
const id = `${collectionIdAsNumber}-${blockNumber}-${idx}`;
logger.warn('Collection not found, creating new collection', collectionIdAsNumber);
collection = new Collection(id, collectionIdAsNumber, '', '', '', false);
collection.createdAt = BigInt(timestamp.getTime());
}
collection.createdAt = timestamp.getTime();

collection.updatedAt = BigInt(timestamp.getTime());
return collection;
}

@@ -43,12 +45,14 @@ export const ensureItem = async ({
const itemIdString = itemId.toString();
const items = await Item.getByCollectionItemKey(`${collectionId}-${itemIdString}`);
let item = items?.find((c) => !c.isBurned);

if (!item) {
const id = `${collectionId}-${itemIdString}-${blockNumber}-${idx}`;
logger.warn('Item not found, creating new item', itemIdString);
item = new Item(id, itemIdString, `${collectionId}-${itemIdString}`, collectionFkey, false);
item.createdAt = timestamp.getTime();
item = new Item(id, Number(itemIdString), `${collectionId}-${itemIdString}`, collectionFkey, false);
item.createdAt = BigInt(timestamp.getTime());
}
item.updatedAt = timestamp.getTime();

item.updatedAt = BigInt(timestamp.getTime());
return item;
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "@polkadot/types-augment";
import "@polkadot/api-augment";

export * from "./mappings/mappingAllocationHandler";
export * from "./mappings/mappingSponsorshipHandlers";
export * from "./mappings/mappingUniquesHandlers";
export * from "./mappings/mappingBalancesHandlers";
8 changes: 0 additions & 8 deletions src/mappings/mappingAllocationHandler.ts

This file was deleted.

133 changes: 112 additions & 21 deletions src/mappings/mappingBalancesHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,118 @@
import { SubstrateEvent } from "@subql/types";
import { Balance } from "@polkadot/types/interfaces/runtime";
import { checkIfExtrinsicExecuteSuccess } from "../helpers";
import { BalanceTransfer } from "../types/models";
import { SubstrateEvent } from '@subql/types'
import { Balance } from '@polkadot/types/interfaces/runtime'
import { AllBalanceTransfer, BalanceTransfer, Rewards, TransferToTreasury } from '../types/models'

const REWARD_ACCOUNTS = [
'4jbtsgNhpGAzdEGrKRb7g8Mq4ToNUpBVxeye942tWfG3gcYi',
'4jByf7kvkZ7hGYwGMYhjFYHoLec3zNZ3EKD86PARZDcfnnkD',
'1qnJN7FViy3HZaxZK9tGAA71zxHSBeUweirKqCaox4t8GT7',
'4hyBs59AiVKw4jZ851hmEVzpvxFATxwjvTDi67ziwb4vYDCX',
'4j5pigNy7LAX1dSGZQ7Tc2oms9dzZSEtwQJukSgQ9gAsQ9Fx',
Comment on lines +6 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remind where these addresses come from? you can also put a comment in front of each to remain here.

]

const ALLOCATION_ACCOUNT = '4jbtsgNhpGAzdEGrKRb7g8Mq4ToNUpBVxeye942tWfG3gcYi'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This account has become part of both Rewards and Treasury accounts. What is the logic for that?

const TREASURY_ACCOUNT = [
'4jbtsgNhpGB2vH7xTjpZVzZLy7W4sFyxjvD45x7X1m6BSiGx',
'4jbtsgNhpGB2voF5dZzKQ2tphWLjV48HSkfQwmWqNn3qa4rv',
'4jbtsgNhpGB2voKv8rRSJYTAohbnHE5oVZ4DejZBEQVT5o86',
'4jbtsgNhpGB2NtbdLN3xkB2urHo5JboKkSAjcBM4s3SzQdUt',
'4jbtsgNhpGAzdEGrKRb7g8Mq4ToNUpBVxeye942tWfG3gcYi'
]

const getEntityByTxType = (event: SubstrateEvent) => {
const [from, to, _] = event.event.data
const isReward = REWARD_ACCOUNTS.includes(from.toString())
const isTreasury = TREASURY_ACCOUNT.includes(to.toString())
const result = []

if (isReward) {
result.push(new Rewards(
`${event.block.block.header.number.toNumber()}-${event.idx}`,
'',
''
))
}

if (isTreasury) {
const entity = new TransferToTreasury(
`${event.block.block.header.number.toNumber()}-${event.idx}`,
'',
''
)

entity.isAllocation = from.toString() === ALLOCATION_ACCOUNT

result.push(entity)
}

if (!isReward && !isTreasury) {
result.push(new BalanceTransfer(
`${event.block.block.header.number.toNumber()}-${event.idx}`,
'',
''
))
}

return result
}

export async function handleBalancesTransferEvent(event: SubstrateEvent) {
const from = event.event.data[0];
const to = event.event.data[1];
if(!from || !to) {
logger.error('Some of the from or to address is null', JSON.stringify(event.toHuman()));
return;
const [from, to, amount] = event.event.data
let receiver: string

if (!from || !to) {
logger.error(
'Some of the from or to address is null',
JSON.stringify(event.toHuman())
)
return
}

const amount = event.event.data[2];
let record = new BalanceTransfer(`${event.block.block.header.number.toNumber()}-${event.idx}`, '', '');
record.blockNumber = event.block.block.header.number.toBigInt();
record.from = from.toString();
record.to = to.toString();
record.amount = (amount as Balance).toBigInt();
if (event.extrinsic) {
record.txHash = event.extrinsic.extrinsic.hash.toString();
record.timestamp = event.extrinsic.block.timestamp.getTime();
record.success = checkIfExtrinsicExecuteSuccess(event.extrinsic)

const otherEvents = event.extrinsic?.events?.findIndex(
(item) => item.event.method === 'ContractEmitted'
)

let idWithProposal: string
if (otherEvents && otherEvents !== -1) {
logger.info('ContractEmitted event found')
const payloadDataAddress =
event.extrinsic?.extrinsic?.args[4]?.toString()

const hexReceiver = payloadDataAddress?.split('x')?.pop()
if (hexReceiver) {
logger.info('Receiver address found in payload ' + hexReceiver)
const rawReceiver = Buffer.from(hexReceiver, 'hex').toString()
logger.info('Receiver address in raw format ' + rawReceiver)
receiver = '0x' + rawReceiver.split('x').pop()
logger.info('Receiver address in polkadot format ' + receiver)
}

idWithProposal = `${event.block?.block?.header?.number?.toNumber()}-${event.idx}`
}

return record.save();
let records = getEntityByTxType(event)

const allBalanceTransfer = new AllBalanceTransfer(
`${event.block.block.header.number.toNumber()}-${event.idx}`,
'',
''
)

records.push(
allBalanceTransfer
)

records.forEach(record => {
record.id = idWithProposal || `${event.block.block.header.number.toNumber()}-${event.idx}`
record.blockNumber = event.block.block.header.number.toBigInt()
record.from = from.toString()
record.to = receiver || to.toString()
record.amount = (amount as Balance).toBigInt()
if (event.extrinsic) {
record.txHash = event.extrinsic.extrinsic.hash.toString()
record.timestamp = BigInt(event.extrinsic.block.timestamp.getTime())
}
} )

return Promise.all(records.map(record => record.save()))
}
310 changes: 310 additions & 0 deletions src/mappings/mappingSponsorshipHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
import { SubstrateExtrinsic } from '@subql/types'
import { Balance } from '@polkadot/types/interfaces/runtime'
import { Account, Pot, AccountPotBalance } from '../types'
import { ensureCollection, ensureItem } from '../helpers/verifyUnique'

const createUserObj = (userId: string) => {
const user = new Account(userId)
user.createdAt = BigInt(Date.now())
user.updatedAt = BigInt(Date.now())

return user
}

export async function handleSponsorshipCreatePotCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipCreatePotCall')
if (!extrinsic.success) return

const [potId, sponsorship_type, fee_quota, reserve_quota] =
extrinsic.extrinsic.args

const args = {
pot: potId.toString(),
fee_quota: (fee_quota as Balance).toBigInt(),
reserve_quota: (reserve_quota as Balance).toBigInt(),
sponsorship_type: sponsorship_type.toString(),
}

const owner = extrinsic.extrinsic.signer.toString()
const id = args.pot

const pot = new Pot(
id,
Number(args.pot),
owner,
BigInt(0), // feeQuotaBalance
args.fee_quota, // feeQuotaLimit
BigInt(0), // reserveQuotaBalance
args.reserve_quota, // reserveQuotaLimit
args.sponsorship_type
)

pot.createdAt = BigInt(extrinsic.block.timestamp.getTime())
pot.updatedAt = BigInt(extrinsic.block.timestamp.getTime())

return pot.save()
}

export async function handleSponsorshipRegisterUsersCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipRegisterUsersCall')
if (!extrinsic.success) return

const [potId, users, common_fee_quota, common_reserve_quota] =
extrinsic.extrinsic.args

const args = {
pot: potId.toString(),
users: users.toHuman() as string[],
common_fee_quota: (common_fee_quota as Balance).toBigInt(),
common_reserve_quota: (common_reserve_quota as Balance).toBigInt(),
}

const pot = await Pot.get(args.pot)

if (!pot) {
logger.error('Pot not found')
return
}
logger.debug('Pot found')

await store.bulkCreate(`Account`, args.users.map(createUserObj))

const accounts = args.users

return store.bulkCreate(
`AccountPotBalance`,
accounts.map((userId) => ({
id: `${pot.id}-${userId}`,
potId: pot.id,
accountId: userId,
feeQuotaLimit: args.common_fee_quota,
reserveQuotaLimit: args.common_reserve_quota,
feeQuotaBalance: BigInt(0),
reserveQuotaBalance: BigInt(0),
createdAt: Date.now(),
updatedAt: Date.now(),
}))
)
}

export async function handleSponsorshipRemoveUsersCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipRemoveUsersCall')
if (!extrinsic.success) return

const args = {
pot: extrinsic.extrinsic.args[0].toString(),
users: extrinsic.extrinsic.args[1].toHuman() as string[],
}

const accounts = args.users

return store.bulkRemove(
`AccountPotBalance`,
accounts.map((userId) => `${args.pot}-${userId}`)
)
}

export async function handleSponsorshipUpdatePotLimitsCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipUpdatePotLimitsCall')
if (!extrinsic.success) return

const args = {
pot: extrinsic.extrinsic.args[0].toString(),
new_fee_quota: (extrinsic.extrinsic.args[1] as Balance).toBigInt(),
new_reserve_quota: (extrinsic.extrinsic.args[2] as Balance).toBigInt(),
}

const pot = await Pot.get(args.pot)

if (!pot) return

pot.feeQuotaLimit = args.new_fee_quota
pot.reserveQuotaLimit = args.new_reserve_quota
pot.updatedAt = BigInt(extrinsic.block.timestamp.getTime())

return pot.save()
}

export async function handleSponsorshipUpdateSponsorshipTypeCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipUpdateSponsorshipTypeCall')
if (!extrinsic.success) return

const args = {
pot: extrinsic.extrinsic.args[0].toString(),
sponsorship_type: extrinsic.extrinsic.args[1].toString(),
}

const pot = await Pot.get(args.pot)

if (!pot) return

pot.sponsorshipType = args.sponsorship_type
pot.updatedAt = BigInt(extrinsic.block.timestamp.getTime())

return pot.save()
}

export async function handleSponsorshipUpdateUsersLimitsCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipUpdateUsersLimitsCall')
if (!extrinsic.success) return

const [potId, new_fee_quota, new_reserve_quota, users] =
extrinsic.extrinsic.args

const args = {
pot: potId.toString(),
users: users.toHuman() as string[],
new_fee_quota: (new_fee_quota as Balance).toBigInt(),
new_reserve_quota: (new_reserve_quota as Balance).toBigInt(),
}

const accounts = args.users

const pot = await Pot.get(args.pot)

if (!pot) return

return Promise.all(
accounts.map(async (userId) => {
const userInfo = await api.query.sponsorship
.user(args.pot, userId)
.catch((e) => {})
const apiUserAsHuman = userInfo?.toJSON() as any
const feeQuotaBalance = BigInt(
apiUserAsHuman?.feeQuota?.balance || 0
)
const reserveQuotaBalance = BigInt(
apiUserAsHuman?.reserveQuota?.balance || 0
)
return store.set('AccountPotBalance', `${args.pot}-${userId}`, {
id: `${args.pot}-${userId}`,
accountId: userId,
potId: args.pot,
feeQuotaLimit: args.new_fee_quota,
reserveQuotaLimit: args.new_reserve_quota,
feeQuotaBalance,
reserveQuotaBalance,
updatedAt: BigInt(Date.now()),
} as AccountPotBalance)
})
)
}

export async function handleSponsorshipRemovePotCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipRemovePotCall')
if (!extrinsic.success) return

const args = {
pot: extrinsic.extrinsic.args[0].toString(),
}

// remove AccountPotBalance with potId = args.pot

await store.bulkRemove(
`AccountPotBalance`,
(
await store.getByField(`AccountPotBalance`, 'potId', args.pot)
).map((item) => item.id)
)

return store.remove(`Pot`, args.pot)
}

export async function handleSponsorshipSponsorForCall(
extrinsic: SubstrateExtrinsic
) {
logger.debug('handleSponsorshipSponsorForCall')

const args = {
pot: extrinsic.extrinsic.args[0].toString(),
call: extrinsic.extrinsic.args[1],
}
const pot = await Pot.get(args.pot)

if (!pot) return

const caller = extrinsic.extrinsic.signer.toString()
const potBalance = await AccountPotBalance.get(`${args.pot}-${caller}`)

const call = args.call as any

const isUniqueCreate =
call.method === 'mint' &&
(call.section === 'uniques' || call.section === 'nodleUniques')
const othersEntities = []

if (isUniqueCreate) {
const [collectionId, itemId, owner] = call.args
const idx = extrinsic.idx
const blockNumber = extrinsic.block.block.header.number.toNumber()
const timestamp = extrinsic.block.timestamp

const collection = await ensureCollection({
collectionId,
blockNumber,
idx,
timestamp,
})

const item = await ensureItem({
collectionId,
collectionFkey: collection.id,
itemId,
blockNumber,
idx,
timestamp,
})

item.owner = owner.toString()
item.updatedAt = BigInt(timestamp.getTime())
item.podId = Number(pot.id)
collection.podId = Number(pot.id)
collection.updatedAt = BigInt(timestamp.getTime())

othersEntities.push(collection.save(), item.save())
}

const [apiUser, apiPot] = await Promise.all([
api.query.sponsorship.user(args.pot, caller),
api.query.sponsorship.pot(args.pot),
])

const apiUserAsHuman = apiUser.toJSON() as any

const apiPotAsHuman = apiPot.toJSON() as any

if (potBalance && apiUserAsHuman) {
potBalance.feeQuotaLimit = BigInt(apiUserAsHuman.feeQuota.limit)
potBalance.feeQuotaBalance = BigInt(apiUserAsHuman.feeQuota.balance)
potBalance.reserveQuotaLimit = BigInt(apiUserAsHuman.reserveQuota.limit)
potBalance.reserveQuotaBalance = BigInt(
apiUserAsHuman.reserveQuota.balance
)
potBalance.updatedAt = BigInt(extrinsic.block.timestamp.getTime())
}

if (apiPotAsHuman) {
pot.feeQuotaLimit = BigInt(apiPotAsHuman.feeQuota.limit)
pot.feeQuotaBalance = BigInt(apiPotAsHuman.feeQuota.balance)

pot.reserveQuotaLimit = BigInt(apiPotAsHuman.reserveQuota.limit)
pot.reserveQuotaBalance = BigInt(apiPotAsHuman.reserveQuota.balance)
pot.updatedAt = BigInt(extrinsic.block.timestamp.getTime())
}

return Promise.all([pot.save(), potBalance?.save(), ...othersEntities])
}
497 changes: 256 additions & 241 deletions src/mappings/mappingUniquesHandlers.ts

Large diffs are not rendered by default.

18,978 changes: 8,257 additions & 10,721 deletions yarn.lock

Large diffs are not rendered by default.