Skip to content

Commit cb76a1d

Browse files
authored
fix(api-contracts): correctly decode pallet_revive events (#6181)
* fix: revive events * chore: format
1 parent 3e231e2 commit cb76a1d

File tree

5 files changed

+50
-6
lines changed

5 files changed

+50
-6
lines changed

packages/api-contract/src/Abi/index.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,55 @@ export class Abi {
194194
// earlier version are hoisted to v4
195195
case '4':
196196
return this.#decodeEventV4(record);
197+
case '5':
198+
return this.#decodeEventV5(record);
197199
// Latest
198200
default:
199-
return this.#decodeEventV5(record);
201+
return this.#decodeEventV6(record);
200202
}
201203
}
202204

205+
#decodeEventV6 = (record: EventRecord): DecodedEvent => {
206+
const topics = record.event.data[2] as unknown as { toHex: () => string }[];
207+
// Try to match by signature topic (first topic)
208+
const signatureTopic = topics[0];
209+
const data = record.event.data[1] as Bytes;
210+
211+
if (signatureTopic) {
212+
const event = this.events.find((e) => e.signatureTopic !== undefined && e.signatureTopic !== null && e.signatureTopic === signatureTopic.toHex());
213+
214+
// Early return if event found by signature topic
215+
if (event) {
216+
return event.fromU8a(data);
217+
}
218+
}
219+
220+
// If no event returned yet, it might be anonymous
221+
const amountOfTopics = topics.length;
222+
const potentialEvents = this.events.filter((e) => {
223+
// event can't have a signature topic
224+
if (e.signatureTopic !== null && e.signatureTopic !== undefined) {
225+
return false;
226+
}
227+
228+
// event should have same amount of indexed fields as emitted topics
229+
const amountIndexed = e.args.filter((a) => a.indexed).length;
230+
231+
if (amountIndexed !== amountOfTopics) {
232+
return false;
233+
}
234+
235+
// If all conditions met, it's a potential event
236+
return true;
237+
});
238+
239+
if (potentialEvents.length === 1) {
240+
return potentialEvents[0].fromU8a(data);
241+
}
242+
243+
throw new Error('Unable to determine event');
244+
};
245+
203246
#decodeEventV5 = (record: EventRecord): DecodedEvent => {
204247
// Find event by first topic, which potentially is the signature_topic
205248
const signatureTopic = record.topics[0];

packages/api-contract/src/base/Blueprint.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
8585
: undefined
8686
)
8787
: applyOnEvent(result, ['Instantiated'], ([record]: EventRecord[]) =>
88-
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod)
88+
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod), this._isRevive
8989
)
9090
)
9191
);

packages/api-contract/src/base/Code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export class Code<ApiType extends ApiTypes> extends Base<ApiType> {
110110
: this.api.events.contracts.CodeStored.is(event)
111111
? [new Blueprint<ApiType>(this.api, this.abi, (event as unknown as { data: [AccountId] }).data[0], this._decorateMethod), contract]
112112
: [blueprint, contract],
113-
[undefined, undefined])
113+
[undefined, undefined]), this._isRevive
114114
) || [undefined, undefined]))
115115
);
116116
};

packages/api-contract/src/base/Contract.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
125125
return null;
126126
}
127127
})
128-
.filter((decoded): decoded is DecodedEvent => !!decoded)
128+
.filter((decoded): decoded is DecodedEvent => !!decoded), this._isRevive
129129
))
130130
);
131131
};

packages/api-contract/src/util.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import type { EventRecord } from '@polkadot/types/interfaces';
66

77
type ContractEvents = 'CodeStored' | 'ContractEmitted' | 'ContractExecution' | 'Instantiated';
88

9-
export function applyOnEvent <T> (result: SubmittableResult, types: ContractEvents[], fn: (records: EventRecord[]) => T): T | undefined {
9+
export function applyOnEvent <T> (result: SubmittableResult, types: ContractEvents[], fn: (records: EventRecord[]) => T, isRevive: boolean): T | undefined {
1010
if (result.isInBlock || result.isFinalized) {
11-
const records = result.filterRecords('contracts', types);
11+
const section = isRevive ? 'revive' : 'contracts';
12+
const records = result.filterRecords(section, types);
1213

1314
if (records.length) {
1415
return fn(records);

0 commit comments

Comments
 (0)