1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.createClass = void 0;
|
4 | const rxjs_1 = require("rxjs");
|
5 | const util_1 = require("@polkadot/util");
|
6 | const index_js_1 = require("../util/index.js");
|
7 | const Result_js_1 = require("./Result.js");
|
8 | function makeEraOptions(api, registry, partialOptions, { header, mortalLength, nonce }) {
|
9 | if (!header) {
|
10 | if (partialOptions.era && !partialOptions.blockHash) {
|
11 | throw new Error('Expected blockHash to be passed alongside non-immortal era options');
|
12 | }
|
13 | if ((0, util_1.isNumber)(partialOptions.era)) {
|
14 |
|
15 |
|
16 | delete partialOptions.era;
|
17 | delete partialOptions.blockHash;
|
18 | }
|
19 | return makeSignOptions(api, partialOptions, { nonce });
|
20 | }
|
21 | return makeSignOptions(api, partialOptions, {
|
22 | blockHash: header.hash,
|
23 | era: registry.createTypeUnsafe('ExtrinsicEra', [{
|
24 | current: header.number,
|
25 | period: partialOptions.era || mortalLength
|
26 | }]),
|
27 | nonce
|
28 | });
|
29 | }
|
30 | function makeSignAndSendOptions(partialOptions, statusCb) {
|
31 | let options = {};
|
32 | if ((0, util_1.isFunction)(partialOptions)) {
|
33 | statusCb = partialOptions;
|
34 | }
|
35 | else {
|
36 | options = (0, util_1.objectSpread)({}, partialOptions);
|
37 | }
|
38 | return [options, statusCb];
|
39 | }
|
40 | function makeSignOptions(api, partialOptions, extras) {
|
41 | return (0, util_1.objectSpread)({ blockHash: api.genesisHash, genesisHash: api.genesisHash }, partialOptions, extras, { runtimeVersion: api.runtimeVersion, signedExtensions: api.registry.signedExtensions, version: api.extrinsicType });
|
42 | }
|
43 | function optionsOrNonce(partialOptions = {}) {
|
44 | return (0, util_1.isBn)(partialOptions) || (0, util_1.isNumber)(partialOptions)
|
45 | ? { nonce: partialOptions }
|
46 | : partialOptions;
|
47 | }
|
48 | function createClass({ api, apiType, blockHash, decorateMethod }) {
|
49 |
|
50 | const ExtrinsicBase = api.registry.createClass('Extrinsic');
|
51 | class Submittable extends ExtrinsicBase {
|
52 | __internal__ignoreStatusCb;
|
53 | __internal__transformResult = (util_1.identity);
|
54 | constructor(registry, extrinsic) {
|
55 | super(registry, extrinsic, { version: api.extrinsicType });
|
56 | this.__internal__ignoreStatusCb = apiType === 'rxjs';
|
57 | }
|
58 | get hasDryRun() {
|
59 | return (0, util_1.isFunction)(api.rpc.system?.dryRun);
|
60 | }
|
61 | get hasPaymentInfo() {
|
62 | return (0, util_1.isFunction)(api.call.transactionPaymentApi?.queryInfo);
|
63 | }
|
64 |
|
65 | dryRun(account, optionsOrHash) {
|
66 | if (!this.hasDryRun) {
|
67 | throw new Error('The system.dryRun RPC call is not available in your environment');
|
68 | }
|
69 | if (blockHash || (0, util_1.isString)(optionsOrHash) || (0, util_1.isU8a)(optionsOrHash)) {
|
70 |
|
71 | return decorateMethod(() => api.rpc.system.dryRun(this.toHex(), blockHash || optionsOrHash));
|
72 | }
|
73 |
|
74 | return decorateMethod(() => this.__internal__observeSign(account, optionsOrHash).pipe((0, rxjs_1.switchMap)(() => api.rpc.system.dryRun(this.toHex()))))();
|
75 | }
|
76 |
|
77 | paymentInfo(account, optionsOrHash) {
|
78 | if (!this.hasPaymentInfo) {
|
79 | throw new Error('The transactionPaymentApi.queryInfo runtime call is not available in your environment');
|
80 | }
|
81 | if (blockHash || (0, util_1.isString)(optionsOrHash) || (0, util_1.isU8a)(optionsOrHash)) {
|
82 |
|
83 | return decorateMethod(() => api.callAt(blockHash || optionsOrHash).pipe((0, rxjs_1.switchMap)((callAt) => {
|
84 | const u8a = this.toU8a();
|
85 | return callAt.transactionPaymentApi.queryInfo(u8a, u8a.length);
|
86 | })));
|
87 | }
|
88 | const [allOptions] = makeSignAndSendOptions(optionsOrHash);
|
89 | const address = (0, index_js_1.isKeyringPair)(account) ? account.address : account.toString();
|
90 |
|
91 | return decorateMethod(() => api.derive.tx.signingInfo(address, allOptions.nonce, allOptions.era).pipe((0, rxjs_1.first)(), (0, rxjs_1.switchMap)((signingInfo) => {
|
92 |
|
93 | const eraOptions = makeEraOptions(api, this.registry, allOptions, signingInfo);
|
94 | const signOptions = makeSignOptions(api, eraOptions, {});
|
95 |
|
96 |
|
97 |
|
98 | const u8a = api.tx(this.toU8a()).signFake(address, signOptions).toU8a();
|
99 | return api.call.transactionPaymentApi.queryInfo(u8a, u8a.length);
|
100 | })))();
|
101 | }
|
102 |
|
103 | send(statusCb) {
|
104 | const isSubscription = api.hasSubscriptions && (this.__internal__ignoreStatusCb || !!statusCb);
|
105 |
|
106 | return decorateMethod(isSubscription
|
107 | ? this.__internal__observeSubscribe
|
108 | : this.__internal__observeSend)(statusCb);
|
109 | }
|
110 | |
111 |
|
112 |
|
113 | signAsync(account, partialOptions) {
|
114 |
|
115 | return decorateMethod(() => this.__internal__observeSign(account, partialOptions).pipe((0, rxjs_1.map)(() => this)))();
|
116 | }
|
117 |
|
118 | signAndSend(account, partialOptions, optionalStatusCb) {
|
119 | const [options, statusCb] = makeSignAndSendOptions(partialOptions, optionalStatusCb);
|
120 | const isSubscription = api.hasSubscriptions && (this.__internal__ignoreStatusCb || !!statusCb);
|
121 |
|
122 | return decorateMethod(() => this.__internal__observeSign(account, options).pipe((0, rxjs_1.switchMap)((info) => isSubscription
|
123 | ? this.__internal__observeSubscribe(info)
|
124 | : this.__internal__observeSend(info)))
|
125 | )(statusCb);
|
126 | }
|
127 |
|
128 | withResultTransform(transform) {
|
129 | this.__internal__transformResult = transform;
|
130 | return this;
|
131 | }
|
132 | __internal__observeSign = (account, partialOptions) => {
|
133 | const address = (0, index_js_1.isKeyringPair)(account) ? account.address : account.toString();
|
134 | const options = optionsOrNonce(partialOptions);
|
135 | return api.derive.tx.signingInfo(address, options.nonce, options.era).pipe((0, rxjs_1.first)(), (0, rxjs_1.mergeMap)(async (signingInfo) => {
|
136 | const eraOptions = makeEraOptions(api, this.registry, options, signingInfo);
|
137 | let updateId = -1;
|
138 | if ((0, index_js_1.isKeyringPair)(account)) {
|
139 | this.sign(account, eraOptions);
|
140 | }
|
141 | else {
|
142 | updateId = await this.__internal__signViaSigner(address, eraOptions, signingInfo.header);
|
143 | }
|
144 | return { options: eraOptions, updateId };
|
145 | }));
|
146 | };
|
147 | __internal__observeStatus = (txHash, status) => {
|
148 | if (!status.isFinalized && !status.isInBlock) {
|
149 | return (0, rxjs_1.of)(this.__internal__transformResult(new Result_js_1.SubmittableResult({
|
150 | status,
|
151 | txHash
|
152 | })));
|
153 | }
|
154 | const blockHash = status.isInBlock
|
155 | ? status.asInBlock
|
156 | : status.asFinalized;
|
157 | return api.derive.tx.events(blockHash).pipe((0, rxjs_1.map)(({ block, events }) => this.__internal__transformResult(new Result_js_1.SubmittableResult({
|
158 | ...(0, index_js_1.filterEvents)(txHash, block, events, status),
|
159 | status,
|
160 | txHash
|
161 | }))), (0, rxjs_1.catchError)((internalError) => (0, rxjs_1.of)(this.__internal__transformResult(new Result_js_1.SubmittableResult({
|
162 | internalError,
|
163 | status,
|
164 | txHash
|
165 | })))));
|
166 | };
|
167 | __internal__observeSend = (info) => {
|
168 | return api.rpc.author.submitExtrinsic(this).pipe((0, rxjs_1.tap)((hash) => {
|
169 | this.__internal__updateSigner(hash, info);
|
170 | }));
|
171 | };
|
172 | __internal__observeSubscribe = (info) => {
|
173 | const txHash = this.hash;
|
174 | return api.rpc.author.submitAndWatchExtrinsic(this).pipe((0, rxjs_1.switchMap)((status) => this.__internal__observeStatus(txHash, status)), (0, rxjs_1.tap)((status) => {
|
175 | this.__internal__updateSigner(status, info);
|
176 | }));
|
177 | };
|
178 | __internal__signViaSigner = async (address, options, header) => {
|
179 | const signer = options.signer || api.signer;
|
180 | if (!signer) {
|
181 | throw new Error('No signer specified, either via api.setSigner or via sign options. You possibly need to pass through an explicit keypair for the origin so it can be used for signing.');
|
182 | }
|
183 | const payload = this.registry.createTypeUnsafe('SignerPayload', [(0, util_1.objectSpread)({}, options, {
|
184 | address,
|
185 | blockNumber: header ? header.number : 0,
|
186 | method: this.method
|
187 | })]);
|
188 | let result;
|
189 | if ((0, util_1.isFunction)(signer.signPayload)) {
|
190 | result = await signer.signPayload(payload.toPayload());
|
191 | }
|
192 | else if ((0, util_1.isFunction)(signer.signRaw)) {
|
193 | result = await signer.signRaw(payload.toRaw());
|
194 | }
|
195 | else {
|
196 | throw new Error('Invalid signer interface, it should implement either signPayload or signRaw (or both)');
|
197 | }
|
198 |
|
199 |
|
200 |
|
201 | super.addSignature(address, result.signature, payload.toPayload());
|
202 | return result.id;
|
203 | };
|
204 | __internal__updateSigner = (status, info) => {
|
205 | if (info && (info.updateId !== -1)) {
|
206 | const { options, updateId } = info;
|
207 | const signer = options.signer || api.signer;
|
208 | if (signer && (0, util_1.isFunction)(signer.update)) {
|
209 | signer.update(updateId, status);
|
210 | }
|
211 | }
|
212 | };
|
213 | }
|
214 | return Submittable;
|
215 | }
|
216 | exports.createClass = createClass;
|