-
Notifications
You must be signed in to change notification settings - Fork 115
/
createChannel.ts
101 lines (86 loc) · 4 KB
/
createChannel.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { ChannelMetadata } from '@joystream/metadata-protobuf'
import { createType } from '@joystream/types'
import { ChannelId } from '@joystream/types/primitives'
import { flags } from '@oclif/command'
import chalk from 'chalk'
import ExitCodes from '../../ExitCodes'
import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
import UploadCommandBase from '../../base/UploadCommandBase'
import { getInputJson } from '../../helpers/InputOutput'
import { asValidatedMetadata, metadataToBytes } from '../../helpers/serialization'
import { ChannelCreationInputSchema } from '../../schemas/ContentDirectory'
import { ChannelCreationInputParameters } from '../../Types'
export default class CreateChannelCommand extends UploadCommandBase {
static description = 'Create channel inside content directory.'
static flags = {
context: ContentDirectoryCommandBase.channelCreationContextFlag,
input: flags.string({
char: 'i',
required: true,
description: `Path to JSON file to use as input`,
}),
...UploadCommandBase.flags,
}
async run(): Promise<void> {
let { context, input } = this.parse(CreateChannelCommand).flags
// Context
if (!context) {
context = await this.promptForChannelCreationContext()
}
const [channelOwner, address] = await this.getChannelOwner(context)
const keypair = await this.getDecodedPair(address)
const channelInput = await getInputJson<ChannelCreationInputParameters>(input, ChannelCreationInputSchema)
const meta = asValidatedMetadata(ChannelMetadata, channelInput)
const { collaborators } = channelInput
if (collaborators) {
await this.validateMemberIdsSet(
collaborators.map(({ memberId }) => memberId),
'collaborator'
)
}
const { coverPhotoPath, avatarPhotoPath } = channelInput
const [resolvedAssets, assetIndices] = await this.resolveAndValidateAssets(
{ coverPhotoPath, avatarPhotoPath },
input
)
meta.coverPhoto = assetIndices.coverPhotoPath
meta.avatarPhoto = assetIndices.avatarPhotoPath
const expectedChannelStateBloatBond = await this.getApi().channelStateBloatBond()
const expectedDataObjectStateBloatBond = await this.getApi().dataObjectStateBloatBond()
const storageBuckets = await this.getApi().selectStorageBucketsForNewChannel()
const distributionBuckets = await this.getApi().selectDistributionBucketsForNewChannel()
const assets = await this.prepareAssetsForExtrinsic(resolvedAssets, 'createChannel')
const channelCreationParameters = createType('PalletContentChannelCreationParametersRecord', {
assets,
expectedChannelStateBloatBond,
expectedDataObjectStateBloatBond,
storageBuckets,
distributionBuckets,
meta: metadataToBytes(ChannelMetadata, meta),
collaborators: new Map(collaborators?.map(({ memberId, permissions }) => [memberId, permissions])),
})
this.jsonPrettyPrint(JSON.stringify({ assets: assets?.toJSON(), metadata: meta, collaborators }))
await this.requireConfirmation('Do you confirm the provided input?', true)
const result = await this.sendAndFollowNamedTx(keypair, 'content', 'createChannel', [
channelOwner,
channelCreationParameters,
])
const channelCreatedEvent = this.getEvent(result, 'content', 'ChannelCreated')
const channelId: ChannelId = channelCreatedEvent.data[0]
const { dataObjects } = channelCreatedEvent.data[1]
this.log(chalk.green(`Channel with id ${chalk.cyanBright(channelId.toString())} successfully created!`))
this.output(channelId.toString())
if (dataObjects.size !== (assets?.objectCreationList.length || 0)) {
this.error('Unexpected number of channel assets in ChannelCreated event!', {
exit: ExitCodes.UnexpectedRuntimeState,
})
}
if (dataObjects.size) {
await this.uploadAssets(
`dynamic:channel:${channelId.toString()}`,
[...dataObjects].map((id, index) => ({ dataObjectId: id, path: resolvedAssets[index].path })),
input
)
}
}
}