Integrate with Reclaim Pallet
Pre-requisite
You need to be familiar with Substrate Framework (opens in a new tab).
At this stage, we assume that you are familiar with the steps at ReactJs.
You can access the code of this walkthrough on Gitlab (opens in a new tab).
Integration with Reclaim Pallet using node template
Please note that pallet_integration_with_reclaim
pallet is an example pallet that represents your pallet which you want to intergrate Reclaim
with.
Clone the Substrate node with reclaim repo.
This Substrate node with reclaim (opens in a new tab) serves as a node template which enables you to use ReclaimVerifier
trait in your pallets.
There are two pallets already configured:
pallet_reclaim
: contains the reclaim logic to verify proofs and implementsReclaimVerifier
.pallet_integration_with_reclaim
: Example pallet that aims to store if the account is verified and usesReclaimVerifier
as an associated type in your palletConfig
.
git clone https://gitlab.reclaimprotocol.org/integrations/onchain/substrate-sdk
cd substrate-sdk
cargo test
Code Discovery (pallet-reclaim/src/traits.rs
)
This file defines the ReclaimVerifier
trait which is an interface for verifying proofs in the Reclaim logic.
use frame_support::dispatch::DispatchResult;
pub trait ReclaimVerifier<Proof> {
fn verify_proof(proof: &Proof) -> DispatchResult;
}
impl<Proof> ReclaimVerifier<Proof> for () {
fn verify_proof(_proof: &Proof) -> DispatchResult {
unimplemented!()
}
Code Discovery (pallet-reclaim/src/lib.rs
)
Examine the core logic of the Reclaim pallet in lib.rs. This includes the implementation of the Reclaim logic, storage items, and the public functions that interact with the blockchain.
- Implements
ReclaimVerifier
impl<T> ReclaimVerifier<Proof> for Pallet<T>
where
T: Config,
{
fn verify_proof(proof: &Proof) -> DispatchResult {
let config = <PReclaimConfig<T>>::get().unwrap();
let epoch_count = config.current_epoch;
let current_epoch = <Epochs<T>>::get(epoch_count);
.....
...
Ok(())
}
}
- Extrinsics for Reclaim Protocol
// For Management. Setup Variables for Reclaim Protocol
pub fn init(origin: OriginFor<T>) -> DispatchResult{
...
}
// For Management. Only callabe by reclaim manager account (initializer account)
pub fn add_epoch(
origin: OriginFor<T>,
witness: BoundedVec<Witness, ConstU32<100>>,
minimum_witness: u128,
) -> DispatchResult{
....
}
// Anyone can call to check if their proofs are valid.
pub fn verify_proof(
origin: OriginFor<T>,
claim_info: ClaimInfo,
signed_claim: SignedClaim,
) -> DispatchResult
Code Discovery (pallet-integration-with-reclaim/src/lib.rs
)
This file illustrates how to use the ReclaimVerifier trait in another pallet, which stores verification status for accounts.
ReclaimVerifier
is added toConfig
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type ReclaimVerifier: ReclaimVerifier<Proof>;
type WeightInfo: WeightInfo;
}
- Storage to persist if an account is verified
pub(super) type AccountVerified<T: Config> = StorageMap<_, Identity, T::AccountId, bool, OptionQuery>;
- Extrinsic to Verify if user's proof is valid and store that user's account is verified
#[pallet::call_index(0)]
#[pallet::weight(<T as pallet::Config>::WeightInfo::verify_user())]
pub fn verify_user(origin: OriginFor<T>, proof: Proof) -> DispatchResult {
let who = ensure_signed(origin)?;
// call `verify_proof`. If verification failed, It will raise `Reclaim` error and revert.
T::ReclaimVerifier::verify_proof(&proof)?;
<AccountVerified<T>>::set(&who, Some(true));
Self::deposit_event(Event::UserVerified { account_id: who });
Ok(())
}
Code Discovery (pallet-integration-with-reclaim/src/mock.rs
)
In mock.rs, set up the testing environment for the integration pallet. This involves configuring mock traits and runtime for unit tests.
impl pallet_reclaim::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Signature = sp_core::ecdsa::Signature;
type PublicKey = sp_core::ecdsa::Public;
type WeightInfo = ();
}
impl pallet_integration_with_reclaim::Config for Test {
type RuntimeEvent = RuntimeEvent;
// ReclaimVerifier assigned to Reclaim Pallet which implements it
type ReclaimVerifier = pallet_reclaim::Pallet<Test>;
type WeightInfo = ();
}
Code Discovery (runtime/src/lib.rs
)
In your runtime's lib.rs, integrate the pallets to the runtime configuration, ensuring they are included in the construct_runtime! macro.
- Implement Configs for Runtime
impl pallet_reclaim::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Signature = sp_core::ecdsa::Signature;
type PublicKey = sp_core::ecdsa::Public;
type WeightInfo = pallet_reclaim::weights::SubstrateWeightInfo<Runtime>;
}
impl pallet_integration_with_reclaim::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ReclaimVerifier = pallet_reclaim::Pallet<Runtime>;
type WeightInfo = pallet_integration_with_reclaim::weights::SubstrateWeightInfo<Runtime>;
}
- Include the pallets in Runtime
construct_runtime!(
pub struct Runtime {
System: frame_system,
Timestamp: pallet_timestamp,
Aura: pallet_aura,
Grandpa: pallet_grandpa,
Balances: pallet_balances,
TransactionPayment: pallet_transaction_payment,
Sudo: pallet_sudo,
Reclaim: pallet_reclaim,
IntegrationWithReclaim: pallet_integration_with_reclaim,
}
);
- Add pallets to benches module
mod benches {
define_benchmarks!(
[frame_benchmarking, BaselineBench::<Runtime>]
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_timestamp, Timestamp]
[pallet_sudo, Sudo]
[pallet_reclaim, Reclaim]
[pallet_integration_with_reclaim, IntegrationWithReclaim]
);
}