generated from PolymeshAssociation/typescript-boilerplate
/
createProposal.ts
111 lines (98 loc) · 2.77 KB
/
createProposal.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
102
103
104
105
106
107
108
109
110
111
import { SubmittableExtrinsic } from '@polkadot/api/types';
import { ISubmittableResult } from '@polkadot/types/types';
import BigNumber from 'bignumber.js';
import { PipId, TxTag } from 'polymesh-types/types';
import { Proposal } from '~/api/entities';
import { PolymeshError, PostTransactionValue, Procedure } from '~/base';
import { Context } from '~/context';
import { ErrorCode, Role } from '~/types';
import {
balanceToBigNumber,
findEventRecord,
numberToBalance,
stringToText,
u32ToBigNumber,
} from '~/utils';
export interface CreateProposalParams {
description?: string;
discussionUrl?: string;
bondAmount: BigNumber;
tag: TxTag;
args: unknown[];
}
/**
* @hidden
*/
export const createProposalResolver = (context: Context) => (
receipt: ISubmittableResult
): Proposal => {
const eventRecord = findEventRecord(receipt, 'pips', 'ProposalCreated');
const data = eventRecord.event.data;
const pipId = u32ToBigNumber(data[2] as PipId);
return new Proposal({ pipId: pipId.toNumber() }, context);
};
/**
* @hidden
*/
export async function prepareCreateProposal(
this: Procedure<CreateProposalParams, Proposal>,
args: CreateProposalParams
): Promise<PostTransactionValue<Proposal>> {
const {
context: {
polymeshApi: {
tx,
query: { pips },
},
},
context,
} = this;
const { description, discussionUrl, bondAmount, tag, args: transactionArguments } = args;
const [mod, transaction] = tag.split('.');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const call = ((tx as any)[mod][transaction](...transactionArguments) as SubmittableExtrinsic<
'promise'
>).method;
const [rawMinBond, { free: freeBalance }] = await Promise.all([
pips.minimumProposalDeposit(),
context.accountBalance(),
]);
const minBond = balanceToBigNumber(rawMinBond);
if (freeBalance.lt(bondAmount)) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'Insufficient free balance',
data: {
freeBalance,
},
});
}
if (bondAmount.lt(minBond)) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'Bonded amount must exceed the minimum',
data: {
minBond,
},
});
}
const [proposal] = this.addTransaction(
tx.pips.propose,
{
resolvers: [createProposalResolver(context)],
},
call,
numberToBalance(bondAmount, context),
discussionUrl ? stringToText(discussionUrl, context) : null,
description ? stringToText(description, context) : null,
null // not using beneficiaries for the time being
);
return proposal;
}
/**
* @hidden
*/
export function getRequiredRoles(): Role[] {
return [];
}
export const createProposal = new Procedure(prepareCreateProposal, getRequiredRoles);