我如何使用polkadot-js解码基板上的事件帮助?



我在Rust中有一个包管理器Cargo的基本智能合约。在那个智能合约中,我有一些事件是在函数调用时发出的。为了列出这些事件,我在JavaScript中有一个服务,但我不确定如何解码由合约触发的事件,而使用该智能合约在区块链中发生了交易。

我有一个链接,从那里我可以解码https://github.com/polkadot-js/api/blob/f701c398c349159d5afd7344ea38c1d52e4aab56/packages/api-contract/src/Abi/index.ts#L111,但我已经实现了,但我无法解码事件。我把合同和服务贴在这里。

合同

#![cfg_attr(not(feature = "std"), no_std)]
use ink_lang as ink;
#[ink::contract]
mod test {
/// Defines the storage of your contract.
/// Add new fields to the below struct in order
/// to add new static storage fields to your contract.
#[ink(storage)]
pub struct Test {
/// Stores a single `bool` value on the storage.
value: bool,
}
/// Event emitted when a token transfer occurs.
#[ink(event)]
pub struct Transfer {
#[ink(topic)]
from: Option<AccountId>,
#[ink(topic)]
to: Option<AccountId>,
value: Balance,
}
impl Test {
/// Constructor that initializes the `bool` value to the given `init_value`.
#[ink(constructor)]
pub fn new(init_value: bool) -> Self {
Self { value: init_value }
}
/// Constructor that initializes the `bool` value to `false`.
///
/// Constructors can delegate to other constructors.
#[ink(constructor)]
pub fn default() -> Self {
Self::new(Default::default())
}
/// A message that can be called on instantiated contracts.
/// This one flips the value of the stored `bool` from `true`
/// to `false` and vice versa.
#[ink(message)]
pub fn flip(&mut self) {
self.value = !self.value;
Self::env().emit_event(Transfer {
from: None,
to: None,
value: 10000,
});
}
/// Simply returns the current value of our `bool`.
#[ink(message)]
pub fn get(&self) {
Self::env().emit_event(Transfer {
from: None,
to: None,
value: 10000,
});
}
}
/// Unit tests in Rust are normally defined within such a `#[cfg(test)]`
/// module and test functions are marked with a `#[test]` attribute.
/// The below code is technically just normal Rust code.
#[cfg(test)]
mod tests {
/// Imports all the definitions from the outer scope so we can use them here.
use super::*;
/// Imports `ink_lang` so we can use `#[ink::test]`.
use ink_lang as ink;
/// We test if the default constructor does its job.
#[ink::test]
fn default_works() {
let test = Test::default();
assert_eq!(test.get(), false);
}
/// We test a simple use case of our contract.
#[ink::test]
fn it_works() {
let mut test = Test::new(false);
assert_eq!(test.get(), false);
test.flip();
assert_eq!(test.get(), true);
}
}
}

Service.js

const { ApiPromise, WsProvider } = require('@polkadot/api')
const { ContractPromise, Abi } = require('@polkadot/api-contract')
const {
assert,
assertReturn,
compactAddLength,
compactStripLength,
isNumber,
isObject,
isString,
logger,
stringCamelCase,
stringify,
u8aConcat,
u8aToHex,
} = require('@polkadot/util')
// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
const { Keyring } = require('@polkadot/keyring')
const bridgePerr = require('./flipper/examples/test/target/ink/metadata.json')
const Contract_Address_Peer = '5FfwrjcXmWsCZCtzRJPwtPBS3AEnPKJy9c2yEi17mFa5hhS3'
// Acc :- 30 may 11:33
const Peer_Private_key =
'0xb0969cc635d807e6d6bfcb05cad88758c64df2da338050ce2103815653d05606'
const PeerProvider = new WsProvider('ws://127.0.0.1:9944')
// const self = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
const to = '5Gue2tLHMZrfaeX6gDNs8EAPm64mpAnHsWWw5TWhGsb3Fkxo'
const AMOUNT = 1000000000000
async function main() {
const api = await ApiPromise.create({ PeerProvider })
//ed25519 edwards
const keyring = new Keyring({ type: 'ed25519' })
const PeerBridge = new ContractPromise(api, bridgePerr, Contract_Address_Peer)
// The address we are going to query
// Find the actual keypair in the keyring
// const alicePair = keyring.getPair(target)
const userPair = keyring.addFromUri(Peer_Private_key)
console.log('Sending', AMOUNT, 'from', userPair.address, 'to', to)
PeerBridge.tx
.get({
value: 0,
gasLimit: -1,
})
.signAndSend(userPair, ({ events = [], status }) => {
console.log('Transaction status:', status.type)
if (status.isInBlock) {
console.log('Included at block hash', status.asInBlock.toHex())
console.log('Events:')
events.forEach(({ event: { data, method, section }, phase }) => {
console.log(
't',
phase.toString(),
`: ${section}.${method}`,
data.toString(),
)
})
} else if (status.isFinalized) {
console.log('Finalized block hash', status.asFinalized.toHex())
process.exit(0)
}
})
}
main()

日志
Transaction status: Ready
Transaction status: InBlock
Included at block hash 0x20da51303e5e1518e90844be6823f85e51666cc27ee652960d25b65902a97e59
Events:
{"applyExtrinsic":1} : balances.Withdraw ["5Cht6EkuACEXLrF8XBywqZPDCL9AEgSQXS4MB6dwgZAeqCVc",2828033563974]
{"applyExtrinsic":1} : contracts.ContractEmitted ["5DskQxeMsqqueJzauUsbh8xYiiDKR4x7e5Kz29pkCJ1EKmwZ","0x00000010270000000000000000000000000000"]
{"applyExtrinsic":1} : balances.Deposit ["5Cht6EkuACEXLrF8XBywqZPDCL9AEgSQXS4MB6dwgZAeqCVc",1268853627292]
{"applyExtrinsic":1} : balances.Deposit ["5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z",1247343949345]
{"applyExtrinsic":1} : treasury.Deposit [1247343949345]
{"applyExtrinsic":1} : balances.Deposit ["5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY",311835987337]
{"applyExtrinsic":1} : system.ExtrinsicSuccess [{"weight":9072880260,"class":"Normal","paysFee":"Yes"}]
Transaction status: Finalized
Finalized
block hash 0x20da51303e5e1518e90844be6823f85e51666cc27ee652960d25b65902a97e59

如何解决这个问题?

您想要解码来自contractemited的数据。因此,您知道可以将Bytes传递给API上的decodeEvent,这已经完成了一半。

在大多数伪代码中,您需要调整事件检查循环:
const { Abi } = require('@polkadot/api-contract')
events.forEach(({ event, phase }) => {
if (api.events.contracts.ContractEmitted.is(event)) {
// we are dealing with a contract event
const [account_id, contract_evt] = event.data
// decode
const decoded = new Abi(bridgePerr).decodeEvent(contract_evt)
console.log(decoded)
// display results, etc.
...
} else {
// normal/other event logic
}
})

相关内容

  • 没有找到相关文章

最新更新