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

feat/collection type #202

Merged
merged 13 commits into from
Jan 23, 2024
4 changes: 3 additions & 1 deletion polkadot.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@
"TransferApproved",
"Transferred"
],
"calls": [],
"calls": [
"update_mint_settings"
],
"storage": [
"Collection",
"ItemMetadataOf"
Expand Down
15 changes: 15 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type CollectionEntity @entity {
updatedAt: DateTime! @index
version: Int!
volume: BigInt! @index
type: CollectionType
settings: CollectionSettings
}

type TokenEntity @entity {
Expand Down Expand Up @@ -88,6 +90,13 @@ type Attribute @jsonField {
value: String!
}

type CollectionSettings @jsonField {
value: String
startBlock: BigInt
endBlock: BigInt
price: BigInt
}

interface EventType {
id: ID!
blockNumber: BigInt
Expand Down Expand Up @@ -136,6 +145,12 @@ enum Interaction {
CHANGEISSUER
}

enum CollectionType {
HolderOf
Issuer
Public
}

type AssetEntity @entity {
id: ID!
name: String
Expand Down
5 changes: 4 additions & 1 deletion src/mappings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { logger } from '@kodadot1/metasquid/logger'
import { Store } from '@subsquid/typeorm-store'
import { STARTING_BLOCK } from '../environment'
import { NFTEntity as NE } from '../model'
import { Asset, NonFungible, Unique } from '../processable'
import { Asset, NonFungible, NonFungibleCall, Unique } from '../processable'
import * as a from './assets'
import * as n from './nfts'
import * as u from './uniques'
Expand Down Expand Up @@ -133,6 +133,9 @@ export async function nfts<T extends SelectedEvent>(item: T, ctx: Context): Prom
case NonFungible.transfer:
await n.handleTokenTransfer(ctx)
break
case NonFungibleCall.updateMintSettings:
await n.handleCollectionMintUpdate(ctx)
break
default:
throw new Error(`Unknown event ${item.name}`)
}
Expand Down
6 changes: 6 additions & 0 deletions src/mappings/nfts/getters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SetAttribute,
SetMetadata,
TransferTokenEvent,
UpdateMintSettings,
} from '../types'

// eslint-disable-next-line unicorn/prefer-module
Expand Down Expand Up @@ -133,3 +134,8 @@ export function getChangeTeamEvent(_ctx: Context): ChangeCollectionTeam {
const ctx = _ctx.event
return proc.getChangeTeamEvent(ctx);
}

export function getUpdateMintCall(_ctx: Context): UpdateMintSettings {
const ctx = _ctx.call
return proc.getUpdateMintCall(ctx);
}
18 changes: 16 additions & 2 deletions src/mappings/nfts/getters/kusama.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { NonFungible } from '../../../processable'
import { nfts as events } from '../../../types/kusama/events'
import { addressOf, unHex } from '../../utils/helper'
import { Event } from '../../utils/types'
import { nfts as calls } from '../../../types/kusama/calls'
import { addressOf, onlyValue, unHex } from '../../utils/helper'
import { Event, Call } from '../../utils/types'
import {
BurnTokenEvent,
BuyTokenEvent,
Expand All @@ -16,6 +17,7 @@ import {
SetAttribute,
SetMetadata,
TransferTokenEvent,
UpdateMintSettings,
} from '../types'

export function getCreateCollectionEvent(ctx: Event): CreateCollectionEvent {
Expand Down Expand Up @@ -334,3 +336,15 @@ export function getChangeTeamEvent(ctx: Event): ChangeCollectionTeam {
freezer: freezer ? addressOf(freezer) : '',
}
}

export function getUpdateMintCall(ctx: Call): UpdateMintSettings {
const call = calls.updateMintSettings

if (call.v9420.is(ctx)) {
const { collection: classId, mintSettings: { mintType, startBlock, endBlock, price } } = call.v9420.decode(ctx)
return { id: classId.toString(), type: mintType, startBlock, endBlock, price }
}

const { collection: classId, mintSettings: { mintType, startBlock, endBlock, price } } = call.v9420.decode(ctx)
return { id: classId.toString(), type: mintType, startBlock, endBlock, price }
}
16 changes: 15 additions & 1 deletion src/mappings/nfts/getters/polkadot.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { logger } from '@kodadot1/metasquid/logger'
import { NonFungible } from '../../../processable'
import { nfts as events } from '../../../types/polkadot/events'
import { nfts as calls } from '../../../types/polkadot/calls'
import { addressOf, unHex } from '../../utils/helper'
import { Event } from '../../utils/types'
import { Event, Call } from '../../utils/types'
import {
BurnTokenEvent,
BuyTokenEvent,
Expand All @@ -17,6 +18,7 @@ import {
SetAttribute,
SetMetadata,
TransferTokenEvent,
UpdateMintSettings,
} from '../types'
import { debug } from '../../utils/logger'

Expand Down Expand Up @@ -338,3 +340,15 @@ export function getChangeTeamEvent(ctx: Event): ChangeCollectionTeam {
freezer: freezer ? addressOf(freezer) : '',
}
}

export function getUpdateMintCall(ctx: Call): UpdateMintSettings {
const call = calls.updateMintSettings

if (call.v9430.is(ctx)) {
const { collection: classId, mintSettings: { mintType, startBlock, endBlock, price } } = call.v9430.decode(ctx)
return { id: classId.toString(), type: mintType, startBlock, endBlock, price }
}

const { collection: classId, mintSettings: { mintType, startBlock, endBlock, price } } = call.v9430.decode(ctx)
return { id: classId.toString(), type: mintType, startBlock, endBlock, price }
}
1 change: 1 addition & 0 deletions src/mappings/nfts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './mint'
export * from './setAttribute'
export * from './setMetadata'
export * from './transfer'
export * from './updateMintSettings'
26 changes: 24 additions & 2 deletions src/mappings/nfts/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MetadataAttribute } from '@kodadot1/metasquid/types'
import { Attribute } from '../../model'
import { ArchiveCall, ArchiveCallWithOptionalValue, MetadataAttribute, Optional } from '@kodadot1/metasquid/types'
import { Attribute, CollectionSettings } from '../../model'
import { createTokenId } from '../utils/types'

export type WithId = {
Expand Down Expand Up @@ -77,6 +77,15 @@ export type ChangeCollectionTeam = WithId & {
freezer: string
}

type MaybeArchiveCall = Pick<ArchiveCall, '__kind'> & { value?: any }

export type UpdateMintSettings = WithId & {
type: MaybeArchiveCall
startBlock: Optional<number>,
endBlock: Optional<number>,
price: Optional<bigint>,
}

export const tokenIdOf = (base: BaseTokenEvent): string => createTokenId(base.collectionId, base.sn)

export function attributeFrom(attribute: MetadataAttribute): Attribute {
Expand All @@ -89,3 +98,16 @@ export function attributeFrom(attribute: MetadataAttribute): Attribute {
}
)
}


export function collectionSettingOf(settings: UpdateMintSettings): CollectionSettings {
return new CollectionSettings(
{},
{
value: String(settings.type.value ?? ''),
startBlock: settings.startBlock,
endBlock: settings.endBlock,
price: settings.price,
}
)
}
24 changes: 24 additions & 0 deletions src/mappings/nfts/updateMintSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getOrFail as get } from '@kodadot1/metasquid/entity'
import { CollectionEntity as CE, CollectionType } from '../../model'
import { unwrap } from '../utils/extract'
import { debug, pending, success } from '../utils/logger'
import { Context } from '../utils/types'
import { getUpdateMintCall } from './getters'
import { collectionSettingOf } from './types'

const OPERATION = 'UPDATE' as any

export async function handleCollectionMintUpdate(context: Context): Promise<void> {
pending(OPERATION, `${context.block.height}`)
const event = unwrap(context, getUpdateMintCall)
debug(OPERATION, event)

const entity = await get(context.store, CE, event.id)

entity.type = event.type.__kind as CollectionType
entity.settings = collectionSettingOf(event)

success(OPERATION, `${event.id} by ${event.caller}`)
await context.store.save(entity)
}

60 changes: 60 additions & 0 deletions src/model/generated/_collectionSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import assert from "assert"
import * as marshal from "./marshal"

export class CollectionSettings {
private _value!: string | undefined | null
private _startBlock!: bigint | undefined | null
private _endBlock!: bigint | undefined | null
private _price!: bigint | undefined | null

constructor(props?: Partial<Omit<CollectionSettings, 'toJSON'>>, json?: any) {
Object.assign(this, props)
if (json != null) {
this._value = json.value == null ? undefined : marshal.string.fromJSON(json.value)
this._startBlock = json.startBlock == null ? undefined : marshal.bigint.fromJSON(json.startBlock)
this._endBlock = json.endBlock == null ? undefined : marshal.bigint.fromJSON(json.endBlock)
this._price = json.price == null ? undefined : marshal.bigint.fromJSON(json.price)
}
}

get value(): string | undefined | null {
return this._value
}

set value(value: string | undefined | null) {
this._value = value
}

get startBlock(): bigint | undefined | null {
return this._startBlock
}

set startBlock(value: bigint | undefined | null) {
this._startBlock = value
}

get endBlock(): bigint | undefined | null {
return this._endBlock
}

set endBlock(value: bigint | undefined | null) {
this._endBlock = value
}

get price(): bigint | undefined | null {
return this._price
}

set price(value: bigint | undefined | null) {
this._price = value
}

toJSON(): object {
return {
value: this.value,
startBlock: this.startBlock == null ? undefined : marshal.bigint.toJSON(this.startBlock),
endBlock: this.endBlock == null ? undefined : marshal.bigint.toJSON(this.endBlock),
price: this.price == null ? undefined : marshal.bigint.toJSON(this.price),
}
}
}
5 changes: 5 additions & 0 deletions src/model/generated/_collectionType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum CollectionType {
HolderOf = "HolderOf",
Issuer = "Issuer",
Public = "Public",
}
8 changes: 8 additions & 0 deletions src/model/generated/collectionEntity.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {Attribute} from "./_attribute"
import {CollectionEvent} from "./collectionEvent.model"
import {MetadataEntity} from "./metadataEntity.model"
import {NFTEntity} from "./nftEntity.model"
import {CollectionType} from "./_collectionType"
import {CollectionSettings} from "./_collectionSettings"

@Entity_()
export class CollectionEntity {
Expand Down Expand Up @@ -102,4 +104,10 @@ export class CollectionEntity {
@Index_()
@Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false})
volume!: bigint

@Column_("varchar", {length: 8, nullable: true})
type!: CollectionType | undefined | null

@Column_("jsonb", {transformer: {to: obj => obj == null ? undefined : obj.toJSON(), from: obj => obj == null ? undefined : new CollectionSettings(undefined, obj)}, nullable: true})
settings!: CollectionSettings | undefined | null
}
2 changes: 2 additions & 0 deletions src/model/generated/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from "./collectionEntity.model"
export * from "./_attribute"
export * from "./_collectionType"
export * from "./_collectionSettings"
export * from "./tokenEntity.model"
export * from "./nftEntity.model"
export * from "./metadataEntity.model"
Expand Down
4 changes: 4 additions & 0 deletions src/processable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ export enum NewNonFungible {
sendTip = 'Nfts.TipSent', // can be used for marking royaltyPaid
}

export enum NonFungibleCall {
updateMintSettings = 'Nfts.update_mint_settings',
}

export enum Asset {
create = 'Assets.Created',
destroy = 'Assets.Destroyed',
Expand Down
1 change: 1 addition & 0 deletions src/types/kusama/calls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as nfts from './nfts/calls'
1 change: 1 addition & 0 deletions src/types/kusama/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export * as v9270 from './v9270'
export * as v9420 from './v9420'
export * as v9430 from './v9430'
export * as events from './events'
export * as calls from './calls'
export * as storage from './storage'
24 changes: 24 additions & 0 deletions src/types/kusama/nfts/calls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {sts, Block, Bytes, Option, Result, CallType, RuntimeCtx} from '../support'
import * as v9420 from '../v9420'

export const updateMintSettings = {
name: 'Nfts.update_mint_settings',
/**
* Update mint settings.
*
* Origin must be either `ForceOrigin` or `Signed` and the sender should be the Issuer
* of the `collection`.
*
* - `collection`: The identifier of the collection to change.
* - `mint_settings`: The new mint settings.
*
* Emits `CollectionMintSettingsUpdated` event when successful.
*/
v9420: new CallType(
'Nfts.update_mint_settings',
sts.struct({
collection: sts.number(),
mintSettings: v9420.MintSettings,
})
),
}
Loading