polkadot-api 1.17.1 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { getCli, ink, update, remove, generate, add } from '@polkadot-api/cli';
3
3
 
4
- var version = "1.17.1";
4
+ var version = "1.18.0";
5
5
 
6
6
  getCli({
7
7
  add,
@@ -0,0 +1,2 @@
1
+ export * from '@polkadot-api/ws-provider';
2
+ //# sourceMappingURL=ws-provider.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-provider.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,15 +1,14 @@
1
- import { Binary, Blake2256 } from '@polkadot-api/substrate-bindings';
2
- import { lastValueFrom, defer, map, mergeMap, merge, filter, take, ignoreElements, Observable, concat, of, EMPTY, distinctUntilChanged } from 'rxjs';
1
+ import { Binary } from '@polkadot-api/substrate-bindings';
2
+ import { lastValueFrom, mergeMap, defer, map, merge, race, takeWhile, ignoreElements, endWith, filter, take, Observable, concat, of, EMPTY, distinctUntilChanged } from 'rxjs';
3
3
  import '@polkadot-api/observable-client';
4
4
  import '../utils/shareLatest.mjs';
5
- import { toHex, fromHex } from '@polkadot-api/utils';
5
+ import { fromHex } from '@polkadot-api/utils';
6
6
  import { continueWith } from '../utils/continue-with.mjs';
7
7
  import 'rxjs/operators';
8
8
 
9
9
  var __defProp = Object.defineProperty;
10
10
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
11
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
12
- const hashFromTx = (tx) => toHex(Blake2256(fromHex(tx)));
13
12
  const computeState = (analized$, blocks$) => new Observable((observer) => {
14
13
  const analyzedBlocks = /* @__PURE__ */ new Map();
15
14
  let pinnedBlocks;
@@ -106,87 +105,116 @@ class InvalidTxError extends Error {
106
105
  this.error = e;
107
106
  }
108
107
  }
109
- const submit$ = (chainHead, broadcastTx$, tx, emitSign = false) => {
110
- const txHash = hashFromTx(tx);
111
- const getTxEvent = (type, rest) => ({
112
- type,
113
- txHash,
114
- ...rest
115
- });
116
- const pinnedBlocks = chainHead.pinnedBlocks$.state;
117
- const getHeightFromMortality = (mortality) => {
118
- if (!mortality.mortal) return 0;
119
- const { phase, period } = mortality;
120
- const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best).number;
121
- return Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase;
122
- };
123
- const getTipsFromHeight = (height) => {
124
- let tips = [...pinnedBlocks.blocks.values()].filter(
125
- (block) => !block.unpinnable && !block.children.size
126
- );
127
- const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized);
128
- tips = finalized.children ? [finalized, ...tips] : tips;
129
- return tips.filter((x) => x.number >= height);
130
- };
131
- const validateTxAt$ = ({ hash }) => chainHead.validateTx$(hash, tx);
132
- const validate$ = defer(
133
- () => pinnedBlocks.finalizedRuntime.runtime.pipe(
134
- map((r) => r.getMortalityFromTx(tx)),
135
- map(getHeightFromMortality),
136
- map(getTipsFromHeight),
137
- mergeMap(
138
- (blocksToValidate) => merge(...blocksToValidate.map(validateTxAt$)).pipe(
139
- filter(({ success, value }, idx) => {
140
- if (!success && idx === blocksToValidate.length - 1)
141
- throw new InvalidTxError(value);
142
- return success;
143
- }),
144
- take(1)
145
- )
146
- ),
147
- ignoreElements()
148
- )
149
- );
150
- const track$ = new Observable((observer) => {
151
- const subscription = chainHead.trackTx$(tx).subscribe(observer);
152
- subscription.add(
153
- broadcastTx$(tx).subscribe({
154
- error(e) {
155
- observer.error(e);
156
- }
157
- })
108
+ const submit$ = (chainHead, broadcastTx$, tx, emitSign = false) => chainHead.hasher$.pipe(
109
+ mergeMap((hasher) => {
110
+ const txHash = hasher(fromHex(tx));
111
+ const getTxEvent = (type, rest) => ({
112
+ type,
113
+ txHash,
114
+ ...rest
115
+ });
116
+ const pinnedBlocks = chainHead.pinnedBlocks$.state;
117
+ const getHeightFromMortality = (mortality) => {
118
+ if (!mortality.mortal) return 0;
119
+ const { phase, period } = mortality;
120
+ const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best).number;
121
+ return Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase;
122
+ };
123
+ const getTipsFromHeight = (height) => {
124
+ let tips = [...pinnedBlocks.blocks.values()].filter(
125
+ (block) => !block.unpinnable && !block.children.size
126
+ );
127
+ const higherTip = Math.max(...tips.map(({ number }) => number));
128
+ tips = tips.filter(({ number }) => number >= higherTip - 1);
129
+ const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized);
130
+ tips = finalized.children ? [finalized, ...tips] : tips;
131
+ return tips.filter((x) => x.number >= height);
132
+ };
133
+ const validateTxAt$ = ({ hash }) => chainHead.validateTx$(hash, tx);
134
+ const validate$ = defer(
135
+ () => pinnedBlocks.finalizedRuntime.runtime.pipe(
136
+ map((r) => r.getMortalityFromTx(tx)),
137
+ map(getHeightFromMortality),
138
+ map(getTipsFromHeight),
139
+ mergeMap((blocksToValidate) => {
140
+ let err;
141
+ return merge(
142
+ ...blocksToValidate.map(
143
+ (b) => race(
144
+ validateTxAt$(b),
145
+ chainHead.finalized$.pipe(
146
+ takeWhile((finalized) => {
147
+ if (finalized.number < b.number) return true;
148
+ let curr = finalized;
149
+ while (curr.number > b.number) {
150
+ const parent = pinnedBlocks.blocks.get(curr.parent);
151
+ if (!parent) return false;
152
+ curr = parent;
153
+ }
154
+ return curr.hash === finalized.hash;
155
+ }),
156
+ ignoreElements(),
157
+ endWith({ success: null })
158
+ )
159
+ )
160
+ )
161
+ ).pipe(
162
+ filter((v, idx) => {
163
+ if (v.success === false) err ?? (err = new InvalidTxError(v.value));
164
+ if (v.success) return true;
165
+ if (idx === blocksToValidate.length - 1 && err) throw err;
166
+ return false;
167
+ }),
168
+ take(1)
169
+ );
170
+ }),
171
+ ignoreElements()
172
+ )
158
173
  );
159
- return subscription;
160
- });
161
- const bestBlockState$ = computeState(track$, chainHead.pinnedBlocks$).pipe(
162
- map((x) => {
163
- if (!x.found)
174
+ const track$ = new Observable((observer) => {
175
+ const subscription = chainHead.trackTx$(tx).subscribe(observer);
176
+ subscription.add(
177
+ broadcastTx$(tx).subscribe({
178
+ error(e) {
179
+ observer.error(e);
180
+ }
181
+ })
182
+ );
183
+ return subscription;
184
+ });
185
+ const bestBlockState$ = computeState(
186
+ track$,
187
+ chainHead.pinnedBlocks$
188
+ ).pipe(
189
+ map((x) => {
190
+ if (!x.found)
191
+ return getTxEvent("txBestBlocksState", {
192
+ found: false,
193
+ isValid: x.validity?.success !== false
194
+ });
164
195
  return getTxEvent("txBestBlocksState", {
165
- found: false,
166
- isValid: x.validity?.success !== false
196
+ found: true,
197
+ block: {
198
+ index: x.index,
199
+ number: x.number,
200
+ hash: x.hash
201
+ },
202
+ ...getTxSuccessFromSystemEvents(x.events, x.index)
167
203
  });
168
- return getTxEvent("txBestBlocksState", {
169
- found: true,
170
- block: {
171
- index: x.index,
172
- number: x.number,
173
- hash: x.hash
174
- },
175
- ...getTxSuccessFromSystemEvents(x.events, x.index)
176
- });
177
- })
178
- );
179
- return concat(
180
- emitSign ? of(getTxEvent("signed", {})) : EMPTY,
181
- validate$,
182
- of(getTxEvent("broadcasted", {})),
183
- bestBlockState$.pipe(
184
- continueWith(
185
- ({ found, type, ...rest }) => found ? of(getTxEvent("finalized", rest)) : EMPTY
204
+ })
205
+ );
206
+ return concat(
207
+ emitSign ? of(getTxEvent("signed", {})) : EMPTY,
208
+ validate$,
209
+ of(getTxEvent("broadcasted", {})),
210
+ bestBlockState$.pipe(
211
+ continueWith(
212
+ ({ found, type, ...rest }) => found ? of(getTxEvent("finalized", rest)) : EMPTY
213
+ )
186
214
  )
187
- )
188
- );
189
- };
215
+ );
216
+ })
217
+ );
190
218
  const submit = async (chainHead, broadcastTx$, transaction, _at) => lastValueFrom(submit$(chainHead, broadcastTx$, transaction)).then((x) => {
191
219
  if (x.type !== "finalized") throw null;
192
220
  const result = { ...x };
@@ -1 +1 @@
1
- {"version":3,"file":"submit-fns.mjs","sources":["../../../src/tx/submit-fns.ts"],"sourcesContent":["import {\n Binary,\n Blake2256,\n HexString,\n ResultPayload,\n} from \"@polkadot-api/substrate-bindings\"\nimport {\n EMPTY,\n Observable,\n concat,\n defer,\n distinctUntilChanged,\n filter,\n ignoreElements,\n lastValueFrom,\n map,\n merge,\n mergeMap,\n of,\n take,\n} from \"rxjs\"\nimport {\n BlockInfo,\n ChainHead$,\n PinnedBlocks,\n SystemEvent,\n} from \"@polkadot-api/observable-client\"\nimport { AnalyzedBlock } from \"@polkadot-api/observable-client\"\nimport { TxEvent, TxEventsPayload, TxFinalizedPayload } from \"./types\"\nimport { continueWith } from \"@/utils\"\nimport { fromHex, toHex } from \"@polkadot-api/utils\"\n\n// TODO: make it dynamic based on the tx-function of the client\nconst hashFromTx = (tx: HexString) => toHex(Blake2256(fromHex(tx)))\n\nconst computeState = (\n analized$: Observable<AnalyzedBlock>,\n blocks$: Observable<PinnedBlocks>,\n) =>\n new Observable<\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n >((observer) => {\n const analyzedBlocks = new Map<string, AnalyzedBlock>()\n let pinnedBlocks: PinnedBlocks\n let latestState:\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n\n const computeNextState = () => {\n let current: string = pinnedBlocks.best\n let analyzed: AnalyzedBlock | undefined = analyzedBlocks.get(current)\n let analyzedNumber = pinnedBlocks.blocks.get(current)!.number\n\n while (!analyzed) {\n const block = pinnedBlocks.blocks.get(current)\n if (!block) break\n analyzed = analyzedBlocks.get((current = block.parent))\n analyzedNumber--\n }\n\n if (!analyzed) return // this shouldn't happen, though\n\n const isFinalized =\n analyzedNumber <=\n pinnedBlocks.blocks.get(pinnedBlocks.finalized)!.number\n\n const found = analyzed.found.type\n if (found && latestState?.found && latestState.hash === analyzed.hash) {\n if (isFinalized) observer.complete()\n return\n }\n\n observer.next(\n (latestState = analyzed.found.type\n ? {\n found: found as true,\n hash: analyzed.hash,\n number: analyzedNumber,\n index: analyzed.found.index,\n events: analyzed.found.events,\n }\n : {\n found: found as false,\n validity: analyzed.found.validity,\n }),\n )\n\n if (isFinalized) {\n if (found) observer.complete()\n else if (analyzed.found.validity?.success === false)\n observer.error(new InvalidTxError(analyzed.found.validity.value))\n }\n }\n\n const subscription = blocks$\n .pipe(\n distinctUntilChanged(\n (a, b) => a.finalized === b.finalized && a.best === b.best,\n ),\n )\n .subscribe({\n next: (pinned: PinnedBlocks) => {\n pinnedBlocks = pinned\n if (analyzedBlocks.size === 0) return\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n })\n\n subscription.add(\n analized$.subscribe({\n next: (block) => {\n analyzedBlocks.set(block.hash, block)\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n }),\n )\n\n return subscription\n }).pipe(distinctUntilChanged((a, b) => a === b))\n\nconst getTxSuccessFromSystemEvents = (\n systemEvents: Array<SystemEvent>,\n txIdx: number,\n): Omit<TxEventsPayload, \"block\"> => {\n const events = systemEvents\n .filter((x) => x.phase.type === \"ApplyExtrinsic\" && x.phase.value === txIdx)\n .map((x) => ({ ...x.event, topics: x.topics }))\n\n const lastEvent = events[events.length - 1]\n if (\n lastEvent.type === \"System\" &&\n lastEvent.value.type === \"ExtrinsicFailed\"\n ) {\n return {\n ok: false,\n events,\n dispatchError: lastEvent.value.value.dispatch_error,\n }\n }\n\n return { ok: true, events }\n}\n\n/*\ntype TransactionValidityError = Enum<{\n Invalid: Enum<{\n Call: undefined\n Payment: undefined\n Future: undefined\n Stale: undefined\n BadProof: undefined\n AncientBirthBlock: undefined\n ExhaustsResources: undefined\n Custom: number\n BadMandatory: undefined\n MandatoryValidation: undefined\n BadSigner: undefined\n }>\n Unknown: Enum<{\n CannotLookup: undefined\n NoUnsignedValidator: undefined\n Custom: number\n }>\n}>\n*/\nexport class InvalidTxError extends Error {\n error: any // likely to be a `TransactionValidityError`\n constructor(e: any) {\n super(\n JSON.stringify(\n e,\n (_, value) => {\n if (typeof value === \"bigint\") return value.toString()\n return value instanceof Binary ? value.asHex() : value\n },\n 2,\n ),\n )\n this.name = \"InvalidTxError\"\n this.error = e\n }\n}\n\nexport const submit$ = (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n tx: HexString,\n emitSign = false,\n): Observable<TxEvent> => {\n const txHash = hashFromTx(tx)\n const getTxEvent = <\n Type extends TxEvent[\"type\"],\n Rest extends Omit<TxEvent & { type: Type }, \"type\" | \"txHash\">,\n >(\n type: Type,\n rest: Rest,\n ): TxEvent & { type: Type } =>\n ({\n type,\n txHash,\n ...rest,\n }) as any\n\n const pinnedBlocks = chainHead.pinnedBlocks$.state\n const getHeightFromMortality = (\n mortality:\n | {\n mortal: false\n }\n | {\n mortal: true\n period: number\n phase: number\n },\n ) => {\n if (!mortality.mortal) return 0\n const { phase, period } = mortality\n const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best)!.number\n return (\n Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase\n )\n }\n\n const getTipsFromHeight = (height: number): BlockInfo[] => {\n let tips: BlockInfo[] = [...pinnedBlocks.blocks.values()].filter(\n (block) => !block.unpinnable && !block.children.size,\n )\n const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized)!\n tips = finalized.children ? [finalized, ...tips] : tips\n\n return tips.filter((x) => x.number >= height)\n }\n\n const validateTxAt$ = ({ hash }: BlockInfo) => chainHead.validateTx$(hash, tx)\n const validate$: Observable<never> = defer(() =>\n pinnedBlocks.finalizedRuntime.runtime.pipe(\n map((r) => r.getMortalityFromTx(tx)),\n map(getHeightFromMortality),\n map(getTipsFromHeight),\n mergeMap((blocksToValidate) =>\n merge(...blocksToValidate.map(validateTxAt$)).pipe(\n filter(({ success, value }, idx) => {\n if (!success && idx === blocksToValidate.length - 1)\n throw new InvalidTxError(value)\n return success\n }),\n take(1),\n ),\n ),\n ignoreElements(),\n ),\n )\n\n const track$ = new Observable<AnalyzedBlock>((observer) => {\n const subscription = chainHead.trackTx$(tx).subscribe(observer)\n subscription.add(\n broadcastTx$(tx).subscribe({\n error(e) {\n observer.error(e)\n },\n }),\n )\n return subscription\n })\n\n const bestBlockState$ = computeState(track$, chainHead.pinnedBlocks$).pipe(\n map((x) => {\n if (!x.found)\n return getTxEvent(\"txBestBlocksState\", {\n found: false,\n isValid: x.validity?.success !== false,\n })\n\n return getTxEvent(\"txBestBlocksState\", {\n found: true,\n block: {\n index: x.index,\n number: x.number,\n hash: x.hash,\n },\n ...getTxSuccessFromSystemEvents(x.events, x.index),\n })\n }),\n )\n\n return concat(\n emitSign ? of(getTxEvent(\"signed\", {})) : EMPTY,\n validate$,\n of(getTxEvent(\"broadcasted\", {})),\n bestBlockState$.pipe(\n continueWith(({ found, type, ...rest }) =>\n found ? of(getTxEvent(\"finalized\", rest as any)) : EMPTY,\n ),\n ),\n )\n}\n\nexport const submit = async (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n transaction: HexString,\n _at?: HexString,\n): Promise<TxFinalizedPayload> =>\n lastValueFrom(submit$(chainHead, broadcastTx$, transaction)).then((x) => {\n if (x.type !== \"finalized\") throw null\n const result: TxFinalizedPayload = { ...x }\n delete (result as any).type\n return result\n })\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"submit-fns.mjs","sources":["../../../src/tx/submit-fns.ts"],"sourcesContent":["import {\n Binary,\n HexString,\n ResultPayload,\n} from \"@polkadot-api/substrate-bindings\"\nimport {\n EMPTY,\n Observable,\n concat,\n defer,\n distinctUntilChanged,\n endWith,\n filter,\n ignoreElements,\n lastValueFrom,\n map,\n merge,\n mergeMap,\n of,\n race,\n take,\n takeWhile,\n} from \"rxjs\"\nimport {\n BlockInfo,\n ChainHead$,\n PinnedBlocks,\n SystemEvent,\n} from \"@polkadot-api/observable-client\"\nimport { AnalyzedBlock } from \"@polkadot-api/observable-client\"\nimport { TxEvent, TxEventsPayload, TxFinalizedPayload } from \"./types\"\nimport { continueWith } from \"@/utils\"\nimport { fromHex } from \"@polkadot-api/utils\"\n\nconst computeState = (\n analized$: Observable<AnalyzedBlock>,\n blocks$: Observable<PinnedBlocks>,\n) =>\n new Observable<\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n >((observer) => {\n const analyzedBlocks = new Map<string, AnalyzedBlock>()\n let pinnedBlocks: PinnedBlocks\n let latestState:\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n\n const computeNextState = () => {\n let current: string = pinnedBlocks.best\n let analyzed: AnalyzedBlock | undefined = analyzedBlocks.get(current)\n let analyzedNumber = pinnedBlocks.blocks.get(current)!.number\n\n while (!analyzed) {\n const block = pinnedBlocks.blocks.get(current)\n if (!block) break\n analyzed = analyzedBlocks.get((current = block.parent))\n analyzedNumber--\n }\n\n if (!analyzed) return // this shouldn't happen, though\n\n const isFinalized =\n analyzedNumber <=\n pinnedBlocks.blocks.get(pinnedBlocks.finalized)!.number\n\n const found = analyzed.found.type\n if (found && latestState?.found && latestState.hash === analyzed.hash) {\n if (isFinalized) observer.complete()\n return\n }\n\n observer.next(\n (latestState = analyzed.found.type\n ? {\n found: found as true,\n hash: analyzed.hash,\n number: analyzedNumber,\n index: analyzed.found.index,\n events: analyzed.found.events,\n }\n : {\n found: found as false,\n validity: analyzed.found.validity,\n }),\n )\n\n if (isFinalized) {\n if (found) observer.complete()\n else if (analyzed.found.validity?.success === false)\n observer.error(new InvalidTxError(analyzed.found.validity.value))\n }\n }\n\n const subscription = blocks$\n .pipe(\n distinctUntilChanged(\n (a, b) => a.finalized === b.finalized && a.best === b.best,\n ),\n )\n .subscribe({\n next: (pinned: PinnedBlocks) => {\n pinnedBlocks = pinned\n if (analyzedBlocks.size === 0) return\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n })\n\n subscription.add(\n analized$.subscribe({\n next: (block) => {\n analyzedBlocks.set(block.hash, block)\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n }),\n )\n\n return subscription\n }).pipe(distinctUntilChanged((a, b) => a === b))\n\nconst getTxSuccessFromSystemEvents = (\n systemEvents: Array<SystemEvent>,\n txIdx: number,\n): Omit<TxEventsPayload, \"block\"> => {\n const events = systemEvents\n .filter((x) => x.phase.type === \"ApplyExtrinsic\" && x.phase.value === txIdx)\n .map((x) => ({ ...x.event, topics: x.topics }))\n\n const lastEvent = events[events.length - 1]\n if (\n lastEvent.type === \"System\" &&\n lastEvent.value.type === \"ExtrinsicFailed\"\n ) {\n return {\n ok: false,\n events,\n dispatchError: lastEvent.value.value.dispatch_error,\n }\n }\n\n return { ok: true, events }\n}\n\n/*\ntype TransactionValidityError = Enum<{\n Invalid: Enum<{\n Call: undefined\n Payment: undefined\n Future: undefined\n Stale: undefined\n BadProof: undefined\n AncientBirthBlock: undefined\n ExhaustsResources: undefined\n Custom: number\n BadMandatory: undefined\n MandatoryValidation: undefined\n BadSigner: undefined\n }>\n Unknown: Enum<{\n CannotLookup: undefined\n NoUnsignedValidator: undefined\n Custom: number\n }>\n}>\n*/\nexport class InvalidTxError extends Error {\n error: any // likely to be a `TransactionValidityError`\n constructor(e: any) {\n super(\n JSON.stringify(\n e,\n (_, value) => {\n if (typeof value === \"bigint\") return value.toString()\n return value instanceof Binary ? value.asHex() : value\n },\n 2,\n ),\n )\n this.name = \"InvalidTxError\"\n this.error = e\n }\n}\n\nexport const submit$ = (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n tx: HexString,\n emitSign = false,\n): Observable<TxEvent> =>\n chainHead.hasher$.pipe(\n mergeMap((hasher) => {\n const txHash = hasher(fromHex(tx))\n const getTxEvent = <\n Type extends TxEvent[\"type\"],\n Rest extends Omit<TxEvent & { type: Type }, \"type\" | \"txHash\">,\n >(\n type: Type,\n rest: Rest,\n ): TxEvent & { type: Type } =>\n ({\n type,\n txHash,\n ...rest,\n }) as any\n\n const pinnedBlocks = chainHead.pinnedBlocks$.state\n const getHeightFromMortality = (\n mortality:\n | {\n mortal: false\n }\n | {\n mortal: true\n period: number\n phase: number\n },\n ) => {\n if (!mortality.mortal) return 0\n const { phase, period } = mortality\n const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best)!.number\n return (\n Math.floor((Math.max(topNumber, phase) - phase) / period) * period +\n phase\n )\n }\n\n const getTipsFromHeight = (height: number): BlockInfo[] => {\n let tips: BlockInfo[] = [...pinnedBlocks.blocks.values()].filter(\n (block) => !block.unpinnable && !block.children.size,\n )\n const higherTip = Math.max(...tips.map(({ number }) => number))\n // take only tips \"with chance to become canonical\"\n tips = tips.filter(({ number }) => number >= higherTip - 1)\n\n const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized)!\n tips = finalized.children ? [finalized, ...tips] : tips\n\n return tips.filter((x) => x.number >= height)\n }\n\n const validateTxAt$ = ({ hash }: BlockInfo) =>\n chainHead.validateTx$(hash, tx)\n const validate$: Observable<never> = defer(() =>\n pinnedBlocks.finalizedRuntime.runtime.pipe(\n map((r) => r.getMortalityFromTx(tx)),\n map(getHeightFromMortality),\n map(getTipsFromHeight),\n mergeMap((blocksToValidate) => {\n let err: InvalidTxError\n return merge(\n ...blocksToValidate.map((b) =>\n race(\n validateTxAt$(b),\n chainHead.finalized$.pipe(\n takeWhile((finalized) => {\n if (finalized.number < b.number) return true\n let curr = finalized\n while (curr.number > b.number) {\n const parent = pinnedBlocks.blocks.get(curr.parent)\n if (!parent) return false\n curr = parent\n }\n return curr.hash === finalized.hash\n }),\n ignoreElements(),\n endWith({ success: null }),\n ),\n ),\n ),\n ).pipe(\n filter((v, idx) => {\n // save first error\n if (v.success === false) err ??= new InvalidTxError(v.value)\n\n if (v.success) return true\n if (idx === blocksToValidate.length - 1 && err) throw err\n return false\n }),\n take(1),\n )\n }),\n ignoreElements(),\n ),\n )\n\n const track$ = new Observable<AnalyzedBlock>((observer) => {\n const subscription = chainHead.trackTx$(tx).subscribe(observer)\n subscription.add(\n broadcastTx$(tx).subscribe({\n error(e) {\n observer.error(e)\n },\n }),\n )\n return subscription\n })\n\n const bestBlockState$ = computeState(\n track$,\n chainHead.pinnedBlocks$,\n ).pipe(\n map((x) => {\n if (!x.found)\n return getTxEvent(\"txBestBlocksState\", {\n found: false,\n isValid: x.validity?.success !== false,\n })\n\n return getTxEvent(\"txBestBlocksState\", {\n found: true,\n block: {\n index: x.index,\n number: x.number,\n hash: x.hash,\n },\n ...getTxSuccessFromSystemEvents(x.events, x.index),\n })\n }),\n )\n\n return concat(\n emitSign ? of(getTxEvent(\"signed\", {})) : EMPTY,\n validate$,\n of(getTxEvent(\"broadcasted\", {})),\n bestBlockState$.pipe(\n continueWith(({ found, type, ...rest }) =>\n found ? of(getTxEvent(\"finalized\", rest as any)) : EMPTY,\n ),\n ),\n )\n }),\n )\n\nexport const submit = async (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n transaction: HexString,\n _at?: HexString,\n): Promise<TxFinalizedPayload> =>\n lastValueFrom(submit$(chainHead, broadcastTx$, transaction)).then((x) => {\n if (x.type !== \"finalized\") throw null\n const result: TxFinalizedPayload = { ...x }\n delete (result as any).type\n return result\n })\n"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -857,7 +857,6 @@ const getNonce$ = (chainHead, from) => {
857
857
  var __defProp = Object.defineProperty;
858
858
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
859
859
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
860
- const hashFromTx = (tx) => utils.toHex(substrateBindings.Blake2256(utils.fromHex(tx)));
861
860
  const computeState = (analized$, blocks$) => new rxjs.Observable((observer) => {
862
861
  const analyzedBlocks = /* @__PURE__ */ new Map();
863
862
  let pinnedBlocks;
@@ -954,87 +953,116 @@ class InvalidTxError extends Error {
954
953
  this.error = e;
955
954
  }
956
955
  }
957
- const submit$ = (chainHead, broadcastTx$, tx, emitSign = false) => {
958
- const txHash = hashFromTx(tx);
959
- const getTxEvent = (type, rest) => ({
960
- type,
961
- txHash,
962
- ...rest
963
- });
964
- const pinnedBlocks = chainHead.pinnedBlocks$.state;
965
- const getHeightFromMortality = (mortality) => {
966
- if (!mortality.mortal) return 0;
967
- const { phase, period } = mortality;
968
- const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best).number;
969
- return Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase;
970
- };
971
- const getTipsFromHeight = (height) => {
972
- let tips = [...pinnedBlocks.blocks.values()].filter(
973
- (block) => !block.unpinnable && !block.children.size
974
- );
975
- const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized);
976
- tips = finalized.children ? [finalized, ...tips] : tips;
977
- return tips.filter((x) => x.number >= height);
978
- };
979
- const validateTxAt$ = ({ hash }) => chainHead.validateTx$(hash, tx);
980
- const validate$ = rxjs.defer(
981
- () => pinnedBlocks.finalizedRuntime.runtime.pipe(
982
- rxjs.map((r) => r.getMortalityFromTx(tx)),
983
- rxjs.map(getHeightFromMortality),
984
- rxjs.map(getTipsFromHeight),
985
- rxjs.mergeMap(
986
- (blocksToValidate) => rxjs.merge(...blocksToValidate.map(validateTxAt$)).pipe(
987
- rxjs.filter(({ success, value }, idx) => {
988
- if (!success && idx === blocksToValidate.length - 1)
989
- throw new InvalidTxError(value);
990
- return success;
991
- }),
992
- rxjs.take(1)
993
- )
994
- ),
995
- rxjs.ignoreElements()
996
- )
997
- );
998
- const track$ = new rxjs.Observable((observer) => {
999
- const subscription = chainHead.trackTx$(tx).subscribe(observer);
1000
- subscription.add(
1001
- broadcastTx$(tx).subscribe({
1002
- error(e) {
1003
- observer.error(e);
1004
- }
1005
- })
956
+ const submit$ = (chainHead, broadcastTx$, tx, emitSign = false) => chainHead.hasher$.pipe(
957
+ rxjs.mergeMap((hasher) => {
958
+ const txHash = hasher(utils.fromHex(tx));
959
+ const getTxEvent = (type, rest) => ({
960
+ type,
961
+ txHash,
962
+ ...rest
963
+ });
964
+ const pinnedBlocks = chainHead.pinnedBlocks$.state;
965
+ const getHeightFromMortality = (mortality) => {
966
+ if (!mortality.mortal) return 0;
967
+ const { phase, period } = mortality;
968
+ const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best).number;
969
+ return Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase;
970
+ };
971
+ const getTipsFromHeight = (height) => {
972
+ let tips = [...pinnedBlocks.blocks.values()].filter(
973
+ (block) => !block.unpinnable && !block.children.size
974
+ );
975
+ const higherTip = Math.max(...tips.map(({ number }) => number));
976
+ tips = tips.filter(({ number }) => number >= higherTip - 1);
977
+ const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized);
978
+ tips = finalized.children ? [finalized, ...tips] : tips;
979
+ return tips.filter((x) => x.number >= height);
980
+ };
981
+ const validateTxAt$ = ({ hash }) => chainHead.validateTx$(hash, tx);
982
+ const validate$ = rxjs.defer(
983
+ () => pinnedBlocks.finalizedRuntime.runtime.pipe(
984
+ rxjs.map((r) => r.getMortalityFromTx(tx)),
985
+ rxjs.map(getHeightFromMortality),
986
+ rxjs.map(getTipsFromHeight),
987
+ rxjs.mergeMap((blocksToValidate) => {
988
+ let err;
989
+ return rxjs.merge(
990
+ ...blocksToValidate.map(
991
+ (b) => rxjs.race(
992
+ validateTxAt$(b),
993
+ chainHead.finalized$.pipe(
994
+ rxjs.takeWhile((finalized) => {
995
+ if (finalized.number < b.number) return true;
996
+ let curr = finalized;
997
+ while (curr.number > b.number) {
998
+ const parent = pinnedBlocks.blocks.get(curr.parent);
999
+ if (!parent) return false;
1000
+ curr = parent;
1001
+ }
1002
+ return curr.hash === finalized.hash;
1003
+ }),
1004
+ rxjs.ignoreElements(),
1005
+ rxjs.endWith({ success: null })
1006
+ )
1007
+ )
1008
+ )
1009
+ ).pipe(
1010
+ rxjs.filter((v, idx) => {
1011
+ if (v.success === false) err ?? (err = new InvalidTxError(v.value));
1012
+ if (v.success) return true;
1013
+ if (idx === blocksToValidate.length - 1 && err) throw err;
1014
+ return false;
1015
+ }),
1016
+ rxjs.take(1)
1017
+ );
1018
+ }),
1019
+ rxjs.ignoreElements()
1020
+ )
1006
1021
  );
1007
- return subscription;
1008
- });
1009
- const bestBlockState$ = computeState(track$, chainHead.pinnedBlocks$).pipe(
1010
- rxjs.map((x) => {
1011
- if (!x.found)
1022
+ const track$ = new rxjs.Observable((observer) => {
1023
+ const subscription = chainHead.trackTx$(tx).subscribe(observer);
1024
+ subscription.add(
1025
+ broadcastTx$(tx).subscribe({
1026
+ error(e) {
1027
+ observer.error(e);
1028
+ }
1029
+ })
1030
+ );
1031
+ return subscription;
1032
+ });
1033
+ const bestBlockState$ = computeState(
1034
+ track$,
1035
+ chainHead.pinnedBlocks$
1036
+ ).pipe(
1037
+ rxjs.map((x) => {
1038
+ if (!x.found)
1039
+ return getTxEvent("txBestBlocksState", {
1040
+ found: false,
1041
+ isValid: x.validity?.success !== false
1042
+ });
1012
1043
  return getTxEvent("txBestBlocksState", {
1013
- found: false,
1014
- isValid: x.validity?.success !== false
1044
+ found: true,
1045
+ block: {
1046
+ index: x.index,
1047
+ number: x.number,
1048
+ hash: x.hash
1049
+ },
1050
+ ...getTxSuccessFromSystemEvents(x.events, x.index)
1015
1051
  });
1016
- return getTxEvent("txBestBlocksState", {
1017
- found: true,
1018
- block: {
1019
- index: x.index,
1020
- number: x.number,
1021
- hash: x.hash
1022
- },
1023
- ...getTxSuccessFromSystemEvents(x.events, x.index)
1024
- });
1025
- })
1026
- );
1027
- return rxjs.concat(
1028
- emitSign ? rxjs.of(getTxEvent("signed", {})) : rxjs.EMPTY,
1029
- validate$,
1030
- rxjs.of(getTxEvent("broadcasted", {})),
1031
- bestBlockState$.pipe(
1032
- continueWith(
1033
- ({ found, type, ...rest }) => found ? rxjs.of(getTxEvent("finalized", rest)) : rxjs.EMPTY
1052
+ })
1053
+ );
1054
+ return rxjs.concat(
1055
+ emitSign ? rxjs.of(getTxEvent("signed", {})) : rxjs.EMPTY,
1056
+ validate$,
1057
+ rxjs.of(getTxEvent("broadcasted", {})),
1058
+ bestBlockState$.pipe(
1059
+ continueWith(
1060
+ ({ found, type, ...rest }) => found ? rxjs.of(getTxEvent("finalized", rest)) : rxjs.EMPTY
1061
+ )
1034
1062
  )
1035
- )
1036
- );
1037
- };
1063
+ );
1064
+ })
1065
+ );
1038
1066
  const submit = async (chainHead, broadcastTx$, transaction, _at) => rxjs.lastValueFrom(submit$(chainHead, broadcastTx$, transaction)).then((x) => {
1039
1067
  if (x.type !== "finalized") throw null;
1040
1068
  const result = { ...x };